dom/camera/GonkRecorder.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /*
     2  * Copyright (C) 2009 The Android Open Source Project
     3  * Copyright (C) 2013 Mozilla Foundation
     4  *
     5  * Licensed under the Apache License, Version 2.0 (the "License");
     6  * you may not use this file except in compliance with the License.
     7  * You may obtain a copy of the License at
     8  *
     9  *      http://www.apache.org/licenses/LICENSE-2.0
    10  *
    11  * Unless required by applicable law or agreed to in writing, software
    12  * distributed under the License is distributed on an "AS IS" BASIS,
    13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  * See the License for the specific language governing permissions and
    15  * limitations under the License.
    16  */
    18 #include "nsDebug.h"
    19 #define DOM_CAMERA_LOG_LEVEL        3
    20 #include "CameraCommon.h"
    21 #include "GonkCameraSource.h"
    22 #include "GonkRecorder.h"
    24 #define RE_LOGD(fmt, ...) DOM_CAMERA_LOGA("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
    25 #define RE_LOGV(fmt, ...) DOM_CAMERA_LOGI("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
    26 #define RE_LOGI(fmt, ...) DOM_CAMERA_LOGI("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
    27 #define RE_LOGW(fmt, ...) DOM_CAMERA_LOGW("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
    28 #define RE_LOGE(fmt, ...) DOM_CAMERA_LOGE("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
    30 #include <binder/IPCThreadState.h>
    31 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
    32 # include <media/openmax/OMX_Audio.h>
    33 #endif
    34 #include <media/stagefright/foundation/ADebug.h>
    35 #include <media/stagefright/AudioSource.h>
    36 #include <media/stagefright/AMRWriter.h>
    37 #include <media/stagefright/AACWriter.h>
    38 #include <media/stagefright/MPEG2TSWriter.h>
    39 #include <media/stagefright/MPEG4Writer.h>
    40 #include <media/stagefright/MediaDefs.h>
    41 #include <media/stagefright/MetaData.h>
    42 #include <media/stagefright/OMXClient.h>
    43 #include <media/stagefright/OMXCodec.h>
    44 #include <media/MediaProfiles.h>
    46 #include <utils/Errors.h>
    47 #include <sys/types.h>
    48 #include <ctype.h>
    49 #include <unistd.h>
    51 #include <cutils/properties.h>
    52 #include <system/audio.h>
    54 #define RES_720P (720 * 1280)
    55 namespace android {
    57 GonkRecorder::GonkRecorder()
    58     : mWriter(NULL),
    59       mOutputFd(-1),
    60       mAudioSource(AUDIO_SOURCE_CNT),
    61       mVideoSource(VIDEO_SOURCE_LIST_END),
    62       mStarted(false) {
    64     RE_LOGV("Constructor");
    65     reset();
    66 }
    68 GonkRecorder::~GonkRecorder() {
    69     RE_LOGV("Destructor");
    70     stop();
    71 }
    73 status_t GonkRecorder::init() {
    74     RE_LOGV("init");
    75     return OK;
    76 }
    78 status_t GonkRecorder::setAudioSource(audio_source_t as) {
    79     RE_LOGV("setAudioSource: %d", as);
    80     if (as < AUDIO_SOURCE_DEFAULT ||
    81         as >= AUDIO_SOURCE_CNT) {
    82         RE_LOGE("Invalid audio source: %d", as);
    83         return BAD_VALUE;
    84     }
    86     if (as == AUDIO_SOURCE_DEFAULT) {
    87         mAudioSource = AUDIO_SOURCE_MIC;
    88     } else {
    89         mAudioSource = as;
    90     }
    92     return OK;
    93 }
    95 status_t GonkRecorder::setVideoSource(video_source vs) {
    96     RE_LOGV("setVideoSource: %d", vs);
    97     if (vs < VIDEO_SOURCE_DEFAULT ||
    98         vs >= VIDEO_SOURCE_LIST_END) {
    99         RE_LOGE("Invalid video source: %d", vs);
   100         return BAD_VALUE;
   101     }
   103     if (vs == VIDEO_SOURCE_DEFAULT) {
   104         mVideoSource = VIDEO_SOURCE_CAMERA;
   105     } else {
   106         mVideoSource = vs;
   107     }
   109     return OK;
   110 }
   112 status_t GonkRecorder::setOutputFormat(output_format of) {
   113     RE_LOGV("setOutputFormat: %d", of);
   114     if (of < OUTPUT_FORMAT_DEFAULT ||
   115         of >= OUTPUT_FORMAT_LIST_END) {
   116         RE_LOGE("Invalid output format: %d", of);
   117         return BAD_VALUE;
   118     }
   120     if (of == OUTPUT_FORMAT_DEFAULT) {
   121         mOutputFormat = OUTPUT_FORMAT_THREE_GPP;
   122     } else {
   123         mOutputFormat = of;
   124     }
   126     return OK;
   127 }
   129 status_t GonkRecorder::setAudioEncoder(audio_encoder ae) {
   130     RE_LOGV("setAudioEncoder: %d", ae);
   131     if (ae < AUDIO_ENCODER_DEFAULT ||
   132         ae >= AUDIO_ENCODER_LIST_END) {
   133         RE_LOGE("Invalid audio encoder: %d", ae);
   134         return BAD_VALUE;
   135     }
   137     if (ae == AUDIO_ENCODER_DEFAULT) {
   138         mAudioEncoder = AUDIO_ENCODER_AMR_NB;
   139     } else {
   140         mAudioEncoder = ae;
   141     }
   143     return OK;
   144 }
   146 status_t GonkRecorder::setVideoEncoder(video_encoder ve) {
   147     RE_LOGV("setVideoEncoder: %d", ve);
   148     if (ve < VIDEO_ENCODER_DEFAULT ||
   149         ve >= VIDEO_ENCODER_LIST_END) {
   150         RE_LOGE("Invalid video encoder: %d", ve);
   151         return BAD_VALUE;
   152     }
   154     if (ve == VIDEO_ENCODER_DEFAULT) {
   155         mVideoEncoder = VIDEO_ENCODER_H263;
   156     } else {
   157         mVideoEncoder = ve;
   158     }
   160     return OK;
   161 }
   163 status_t GonkRecorder::setVideoSize(int width, int height) {
   164     RE_LOGV("setVideoSize: %dx%d", width, height);
   165     if (width <= 0 || height <= 0) {
   166         RE_LOGE("Invalid video size: %dx%d", width, height);
   167         return BAD_VALUE;
   168     }
   170     // Additional check on the dimension will be performed later
   171     mVideoWidth = width;
   172     mVideoHeight = height;
   174     return OK;
   175 }
   177 status_t GonkRecorder::setVideoFrameRate(int frames_per_second) {
   178     RE_LOGV("setVideoFrameRate: %d", frames_per_second);
   179     if ((frames_per_second <= 0 && frames_per_second != -1) ||
   180         frames_per_second > 120) {
   181         RE_LOGE("Invalid video frame rate: %d", frames_per_second);
   182         return BAD_VALUE;
   183     }
   185     // Additional check on the frame rate will be performed later
   186     mFrameRate = frames_per_second;
   188     return OK;
   189 }
   191 status_t GonkRecorder::setOutputFile(const char *path) {
   192     RE_LOGE("setOutputFile(const char*) must not be called");
   193     // We don't actually support this at all, as the media_server process
   194     // no longer has permissions to create files.
   196     return -EPERM;
   197 }
   199 status_t GonkRecorder::setOutputFile(int fd, int64_t offset, int64_t length) {
   200     RE_LOGV("setOutputFile: %d, %lld, %lld", fd, offset, length);
   201     // These don't make any sense, do they?
   202     CHECK_EQ(offset, 0ll);
   203     CHECK_EQ(length, 0ll);
   205     if (fd < 0) {
   206         RE_LOGE("Invalid file descriptor: %d", fd);
   207         return -EBADF;
   208     }
   210     if (mOutputFd >= 0) {
   211         ::close(mOutputFd);
   212     }
   213     mOutputFd = dup(fd);
   215     return OK;
   216 }
   218 // Attempt to parse an int64 literal optionally surrounded by whitespace,
   219 // returns true on success, false otherwise.
   220 static bool safe_strtoi64(const char *s, int64_t *val) {
   221     char *end;
   223     // It is lame, but according to man page, we have to set errno to 0
   224     // before calling strtoll().
   225     errno = 0;
   226     *val = strtoll(s, &end, 10);
   228     if (end == s || errno == ERANGE) {
   229         return false;
   230     }
   232     // Skip trailing whitespace
   233     while (isspace(*end)) {
   234         ++end;
   235     }
   237     // For a successful return, the string must contain nothing but a valid
   238     // int64 literal optionally surrounded by whitespace.
   240     return *end == '\0';
   241 }
   243 // Return true if the value is in [0, 0x007FFFFFFF]
   244 static bool safe_strtoi32(const char *s, int32_t *val) {
   245     int64_t temp;
   246     if (safe_strtoi64(s, &temp)) {
   247         if (temp >= 0 && temp <= 0x007FFFFFFF) {
   248             *val = static_cast<int32_t>(temp);
   249             return true;
   250         }
   251     }
   252     return false;
   253 }
   255 // Trim both leading and trailing whitespace from the given string.
   256 static void TrimString(String8 *s) {
   257     size_t num_bytes = s->bytes();
   258     const char *data = s->string();
   260     size_t leading_space = 0;
   261     while (leading_space < num_bytes && isspace(data[leading_space])) {
   262         ++leading_space;
   263     }
   265     size_t i = num_bytes;
   266     while (i > leading_space && isspace(data[i - 1])) {
   267         --i;
   268     }
   270     s->setTo(String8(&data[leading_space], i - leading_space));
   271 }
   273 status_t GonkRecorder::setParamAudioSamplingRate(int32_t sampleRate) {
   274     RE_LOGV("setParamAudioSamplingRate: %d", sampleRate);
   275     if (sampleRate <= 0) {
   276         RE_LOGE("Invalid audio sampling rate: %d", sampleRate);
   277         return BAD_VALUE;
   278     }
   280     // Additional check on the sample rate will be performed later.
   281     mSampleRate = sampleRate;
   282     return OK;
   283 }
   285 status_t GonkRecorder::setParamAudioNumberOfChannels(int32_t channels) {
   286     RE_LOGV("setParamAudioNumberOfChannels: %d", channels);
   287     if (channels <= 0 || channels >= 3) {
   288         RE_LOGE("Invalid number of audio channels: %d", channels);
   289         return BAD_VALUE;
   290     }
   292     // Additional check on the number of channels will be performed later.
   293     mAudioChannels = channels;
   294     return OK;
   295 }
   297 status_t GonkRecorder::setParamAudioEncodingBitRate(int32_t bitRate) {
   298     RE_LOGV("setParamAudioEncodingBitRate: %d", bitRate);
   299     if (bitRate <= 0) {
   300         RE_LOGE("Invalid audio encoding bit rate: %d", bitRate);
   301         return BAD_VALUE;
   302     }
   304     // The target bit rate may not be exactly the same as the requested.
   305     // It depends on many factors, such as rate control, and the bit rate
   306     // range that a specific encoder supports. The mismatch between the
   307     // the target and requested bit rate will NOT be treated as an error.
   308     mAudioBitRate = bitRate;
   309     return OK;
   310 }
   312 status_t GonkRecorder::setParamVideoEncodingBitRate(int32_t bitRate) {
   313     RE_LOGV("setParamVideoEncodingBitRate: %d", bitRate);
   314     if (bitRate <= 0) {
   315         RE_LOGE("Invalid video encoding bit rate: %d", bitRate);
   316         return BAD_VALUE;
   317     }
   319     // The target bit rate may not be exactly the same as the requested.
   320     // It depends on many factors, such as rate control, and the bit rate
   321     // range that a specific encoder supports. The mismatch between the
   322     // the target and requested bit rate will NOT be treated as an error.
   323     mVideoBitRate = bitRate;
   324     return OK;
   325 }
   327 // Always rotate clockwise, and only support 0, 90, 180 and 270 for now.
   328 status_t GonkRecorder::setParamVideoRotation(int32_t degrees) {
   329     RE_LOGV("setParamVideoRotation: %d", degrees);
   330     if (degrees < 0 || degrees % 90 != 0) {
   331         RE_LOGE("Unsupported video rotation angle: %d", degrees);
   332         return BAD_VALUE;
   333     }
   334     mRotationDegrees = degrees % 360;
   335     return OK;
   336 }
   338 status_t GonkRecorder::setParamMaxFileDurationUs(int64_t timeUs) {
   339     RE_LOGV("setParamMaxFileDurationUs: %lld us", timeUs);
   341     // This is meant for backward compatibility for MediaRecorder.java
   342     if (timeUs <= 0) {
   343         RE_LOGW("Max file duration is not positive: %lld us. Disabling duration limit.", timeUs);
   344         timeUs = 0; // Disable the duration limit for zero or negative values.
   345     } else if (timeUs <= 100000LL) {  // XXX: 100 milli-seconds
   346         RE_LOGE("Max file duration is too short: %lld us", timeUs);
   347         return BAD_VALUE;
   348     }
   350     if (timeUs <= 15 * 1000000LL) {
   351         RE_LOGW("Target duration (%lld us) too short to be respected", timeUs);
   352     }
   353     mMaxFileDurationUs = timeUs;
   354     return OK;
   355 }
   357 status_t GonkRecorder::setParamMaxFileSizeBytes(int64_t bytes) {
   358     RE_LOGV("setParamMaxFileSizeBytes: %lld bytes", bytes);
   360     // This is meant for backward compatibility for MediaRecorder.java
   361     if (bytes <= 0) {
   362         RE_LOGW("Max file size is not positive: %lld bytes. "
   363              "Disabling file size limit.", bytes);
   364         bytes = 0; // Disable the file size limit for zero or negative values.
   365     } else if (bytes <= 1024) {  // XXX: 1 kB
   366         RE_LOGE("Max file size is too small: %lld bytes", bytes);
   367         return BAD_VALUE;
   368     }
   370     if (bytes <= 100 * 1024) {
   371         RE_LOGW("Target file size (%lld bytes) is too small to be respected", bytes);
   372     }
   374     if (bytes >= 0xffffffffLL) {
   375         RE_LOGW("Target file size (%lld bytes) too large to be respected, clipping to 4GB", bytes);
   376         bytes = 0xffffffffLL;
   377     }
   379     mMaxFileSizeBytes = bytes;
   380     return OK;
   381 }
   383 status_t GonkRecorder::setParamInterleaveDuration(int32_t durationUs) {
   384     RE_LOGV("setParamInterleaveDuration: %d", durationUs);
   385     if (durationUs <= 500000) {           //  500 ms
   386         // If interleave duration is too small, it is very inefficient to do
   387         // interleaving since the metadata overhead will count for a significant
   388         // portion of the saved contents
   389         RE_LOGE("Audio/video interleave duration is too small: %d us", durationUs);
   390         return BAD_VALUE;
   391     } else if (durationUs >= 10000000) {  // 10 seconds
   392         // If interleaving duration is too large, it can cause the recording
   393         // session to use too much memory since we have to save the output
   394         // data before we write them out
   395         RE_LOGE("Audio/video interleave duration is too large: %d us", durationUs);
   396         return BAD_VALUE;
   397     }
   398     mInterleaveDurationUs = durationUs;
   399     return OK;
   400 }
   402 // If seconds <  0, only the first frame is I frame, and rest are all P frames
   403 // If seconds == 0, all frames are encoded as I frames. No P frames
   404 // If seconds >  0, it is the time spacing (seconds) between 2 neighboring I frames
   405 status_t GonkRecorder::setParamVideoIFramesInterval(int32_t seconds) {
   406     RE_LOGV("setParamVideoIFramesInterval: %d seconds", seconds);
   407     mIFramesIntervalSec = seconds;
   408     return OK;
   409 }
   411 status_t GonkRecorder::setParam64BitFileOffset(bool use64Bit) {
   412     RE_LOGV("setParam64BitFileOffset: %s",
   413         use64Bit? "use 64 bit file offset": "use 32 bit file offset");
   414     mUse64BitFileOffset = use64Bit;
   415     return OK;
   416 }
   418 status_t GonkRecorder::setParamVideoCameraId(int32_t cameraId) {
   419     RE_LOGV("setParamVideoCameraId: %d", cameraId);
   420     if (cameraId < 0) {
   421         return BAD_VALUE;
   422     }
   423     mCameraId = cameraId;
   424     return OK;
   425 }
   427 status_t GonkRecorder::setParamTrackTimeStatus(int64_t timeDurationUs) {
   428     RE_LOGV("setParamTrackTimeStatus: %lld", timeDurationUs);
   429     if (timeDurationUs < 20000) {  // Infeasible if shorter than 20 ms?
   430         RE_LOGE("Tracking time duration too short: %lld us", timeDurationUs);
   431         return BAD_VALUE;
   432     }
   433     mTrackEveryTimeDurationUs = timeDurationUs;
   434     return OK;
   435 }
   437 status_t GonkRecorder::setParamVideoEncoderProfile(int32_t profile) {
   438     RE_LOGV("setParamVideoEncoderProfile: %d", profile);
   440     // Additional check will be done later when we load the encoder.
   441     // For now, we are accepting values defined in OpenMAX IL.
   442     mVideoEncoderProfile = profile;
   443     return OK;
   444 }
   446 status_t GonkRecorder::setParamVideoEncoderLevel(int32_t level) {
   447     RE_LOGV("setParamVideoEncoderLevel: %d", level);
   449     // Additional check will be done later when we load the encoder.
   450     // For now, we are accepting values defined in OpenMAX IL.
   451     mVideoEncoderLevel = level;
   452     return OK;
   453 }
   455 status_t GonkRecorder::setParamMovieTimeScale(int32_t timeScale) {
   456     RE_LOGV("setParamMovieTimeScale: %d", timeScale);
   458     // The range is set to be the same as the audio's time scale range
   459     // since audio's time scale has a wider range.
   460     if (timeScale < 600 || timeScale > 96000) {
   461         RE_LOGE("Time scale (%d) for movie is out of range [600, 96000]", timeScale);
   462         return BAD_VALUE;
   463     }
   464     mMovieTimeScale = timeScale;
   465     return OK;
   466 }
   468 status_t GonkRecorder::setParamVideoTimeScale(int32_t timeScale) {
   469     RE_LOGV("setParamVideoTimeScale: %d", timeScale);
   471     // 60000 is chosen to make sure that each video frame from a 60-fps
   472     // video has 1000 ticks.
   473     if (timeScale < 600 || timeScale > 60000) {
   474         RE_LOGE("Time scale (%d) for video is out of range [600, 60000]", timeScale);
   475         return BAD_VALUE;
   476     }
   477     mVideoTimeScale = timeScale;
   478     return OK;
   479 }
   481 status_t GonkRecorder::setParamAudioTimeScale(int32_t timeScale) {
   482     RE_LOGV("setParamAudioTimeScale: %d", timeScale);
   484     // 96000 Hz is the highest sampling rate support in AAC.
   485     if (timeScale < 600 || timeScale > 96000) {
   486         RE_LOGE("Time scale (%d) for audio is out of range [600, 96000]", timeScale);
   487         return BAD_VALUE;
   488     }
   489     mAudioTimeScale = timeScale;
   490     return OK;
   491 }
   493 status_t GonkRecorder::setParamGeoDataLongitude(
   494     int64_t longitudex10000) {
   496     if (longitudex10000 > 1800000 || longitudex10000 < -1800000) {
   497         return BAD_VALUE;
   498     }
   499     mLongitudex10000 = longitudex10000;
   500     return OK;
   501 }
   503 status_t GonkRecorder::setParamGeoDataLatitude(
   504     int64_t latitudex10000) {
   506     if (latitudex10000 > 900000 || latitudex10000 < -900000) {
   507         return BAD_VALUE;
   508     }
   509     mLatitudex10000 = latitudex10000;
   510     return OK;
   511 }
   513 status_t GonkRecorder::setParameter(
   514         const String8 &key, const String8 &value) {
   515     RE_LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
   516     if (key == "max-duration") {
   517         int64_t max_duration_ms;
   518         if (safe_strtoi64(value.string(), &max_duration_ms)) {
   519             return setParamMaxFileDurationUs(1000LL * max_duration_ms);
   520         }
   521     } else if (key == "max-filesize") {
   522         int64_t max_filesize_bytes;
   523         if (safe_strtoi64(value.string(), &max_filesize_bytes)) {
   524             return setParamMaxFileSizeBytes(max_filesize_bytes);
   525         }
   526     } else if (key == "interleave-duration-us") {
   527         int32_t durationUs;
   528         if (safe_strtoi32(value.string(), &durationUs)) {
   529             return setParamInterleaveDuration(durationUs);
   530         }
   531     } else if (key == "param-movie-time-scale") {
   532         int32_t timeScale;
   533         if (safe_strtoi32(value.string(), &timeScale)) {
   534             return setParamMovieTimeScale(timeScale);
   535         }
   536     } else if (key == "param-use-64bit-offset") {
   537         int32_t use64BitOffset;
   538         if (safe_strtoi32(value.string(), &use64BitOffset)) {
   539             return setParam64BitFileOffset(use64BitOffset != 0);
   540         }
   541     } else if (key == "param-geotag-longitude") {
   542         int64_t longitudex10000;
   543         if (safe_strtoi64(value.string(), &longitudex10000)) {
   544             return setParamGeoDataLongitude(longitudex10000);
   545         }
   546     } else if (key == "param-geotag-latitude") {
   547         int64_t latitudex10000;
   548         if (safe_strtoi64(value.string(), &latitudex10000)) {
   549             return setParamGeoDataLatitude(latitudex10000);
   550         }
   551     } else if (key == "param-track-time-status") {
   552         int64_t timeDurationUs;
   553         if (safe_strtoi64(value.string(), &timeDurationUs)) {
   554             return setParamTrackTimeStatus(timeDurationUs);
   555         }
   556     } else if (key == "audio-param-sampling-rate") {
   557         int32_t sampling_rate;
   558         if (safe_strtoi32(value.string(), &sampling_rate)) {
   559             return setParamAudioSamplingRate(sampling_rate);
   560         }
   561     } else if (key == "audio-param-number-of-channels") {
   562         int32_t number_of_channels;
   563         if (safe_strtoi32(value.string(), &number_of_channels)) {
   564             return setParamAudioNumberOfChannels(number_of_channels);
   565         }
   566     } else if (key == "audio-param-encoding-bitrate") {
   567         int32_t audio_bitrate;
   568         if (safe_strtoi32(value.string(), &audio_bitrate)) {
   569             return setParamAudioEncodingBitRate(audio_bitrate);
   570         }
   571     } else if (key == "audio-param-time-scale") {
   572         int32_t timeScale;
   573         if (safe_strtoi32(value.string(), &timeScale)) {
   574             return setParamAudioTimeScale(timeScale);
   575         }
   576     } else if (key == "video-param-encoding-bitrate") {
   577         int32_t video_bitrate;
   578         if (safe_strtoi32(value.string(), &video_bitrate)) {
   579             return setParamVideoEncodingBitRate(video_bitrate);
   580         }
   581     } else if (key == "video-param-rotation-angle-degrees") {
   582         int32_t degrees;
   583         if (safe_strtoi32(value.string(), &degrees)) {
   584             return setParamVideoRotation(degrees);
   585         }
   586     } else if (key == "video-param-i-frames-interval") {
   587         int32_t seconds;
   588         if (safe_strtoi32(value.string(), &seconds)) {
   589             return setParamVideoIFramesInterval(seconds);
   590         }
   591     } else if (key == "video-param-encoder-profile") {
   592         int32_t profile;
   593         if (safe_strtoi32(value.string(), &profile)) {
   594             return setParamVideoEncoderProfile(profile);
   595         }
   596     } else if (key == "video-param-encoder-level") {
   597         int32_t level;
   598         if (safe_strtoi32(value.string(), &level)) {
   599             return setParamVideoEncoderLevel(level);
   600         }
   601     } else if (key == "video-param-camera-id") {
   602         int32_t cameraId;
   603         if (safe_strtoi32(value.string(), &cameraId)) {
   604             return setParamVideoCameraId(cameraId);
   605         }
   606     } else if (key == "video-param-time-scale") {
   607         int32_t timeScale;
   608         if (safe_strtoi32(value.string(), &timeScale)) {
   609             return setParamVideoTimeScale(timeScale);
   610         }
   611     } else {
   612         RE_LOGE("setParameter: failed to find key %s", key.string());
   613     }
   614     return BAD_VALUE;
   615 }
   617 status_t GonkRecorder::setParameters(const String8 &params) {
   618     RE_LOGV("setParameters: %s", params.string());
   619     const char *cparams = params.string();
   620     const char *key_start = cparams;
   621     for (;;) {
   622         const char *equal_pos = strchr(key_start, '=');
   623         if (equal_pos == NULL) {
   624             RE_LOGE("Parameters %s miss a value", cparams);
   625             return BAD_VALUE;
   626         }
   627         String8 key(key_start, equal_pos - key_start);
   628         TrimString(&key);
   629         if (key.length() == 0) {
   630             RE_LOGE("Parameters %s contains an empty key", cparams);
   631             return BAD_VALUE;
   632         }
   633         const char *value_start = equal_pos + 1;
   634         const char *semicolon_pos = strchr(value_start, ';');
   635         String8 value;
   636         if (semicolon_pos == NULL) {
   637             value.setTo(value_start);
   638         } else {
   639             value.setTo(value_start, semicolon_pos - value_start);
   640         }
   641         if (setParameter(key, value) != OK) {
   642             return BAD_VALUE;
   643         }
   644         if (semicolon_pos == NULL) {
   645             break;  // Reaches the end
   646         }
   647         key_start = semicolon_pos + 1;
   648     }
   649     return OK;
   650 }
   652 status_t GonkRecorder::setListener(const sp<IMediaRecorderClient> &listener) {
   653     mListener = listener;
   655     return OK;
   656 }
   658 status_t GonkRecorder::setClientName(const String16& clientName) {
   659     mClientName = clientName;
   661     return OK;
   662 }
   664 status_t GonkRecorder::prepare() {
   665     if (mVideoSource != VIDEO_SOURCE_LIST_END && mVideoEncoder != VIDEO_ENCODER_LIST_END &&
   666         mVideoHeight && mVideoWidth &&  // Video recording
   667         (mVideoHeight * mVideoWidth >= RES_720P)) {
   668         // TODO: Above check needs to be updated when mMaxFileDurationUs is set from camera app
   669         RE_LOGV("Video is high resolution so setting 64-bit file offsets");
   670         setParam64BitFileOffset(true);
   671     }
   672     return OK;
   673 }
   675 status_t GonkRecorder::start() {
   676     CHECK_GE(mOutputFd, 0);
   678     // Get UID here for permission checking
   679     mClientUid = IPCThreadState::self()->getCallingUid();
   680     if (mWriter != NULL) {
   681         RE_LOGE("File writer is not avaialble");
   682         return UNKNOWN_ERROR;
   683     }
   685     status_t status = OK;
   687     switch (mOutputFormat) {
   688         case OUTPUT_FORMAT_DEFAULT:
   689         case OUTPUT_FORMAT_THREE_GPP:
   690         case OUTPUT_FORMAT_MPEG_4:
   691             status = startMPEG4Recording();
   692             break;
   694         case OUTPUT_FORMAT_AMR_NB:
   695         case OUTPUT_FORMAT_AMR_WB:
   696             status = startAMRRecording();
   697             break;
   699 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
   700         case OUTPUT_FORMAT_AAC_ADIF:
   701         case OUTPUT_FORMAT_AAC_ADTS:
   702             status = startAACRecording();
   703             break;
   704 #endif
   706         case OUTPUT_FORMAT_RTP_AVP:
   707             status = startRTPRecording();
   708             break;
   710         case OUTPUT_FORMAT_MPEG2TS:
   711             status = startMPEG2TSRecording();
   712             break;
   714         default:
   715             RE_LOGE("Unsupported output file format: %d", mOutputFormat);
   716             status = UNKNOWN_ERROR;
   717             break;
   718     }
   720     if ((status == OK) && (!mStarted)) {
   721         mStarted = true;
   722     }
   724     return status;
   725 }
   727 sp<MediaSource> GonkRecorder::createAudioSource() {
   728     sp<AudioSource> audioSource =
   729         new AudioSource(
   730                 mAudioSource,
   731                 mSampleRate,
   732                 mAudioChannels);
   734     status_t err = audioSource->initCheck();
   736     if (err != OK) {
   737         RE_LOGE("audio source is not initialized");
   738         return NULL;
   739     }
   741     sp<MetaData> encMeta = new MetaData;
   742     const char *mime;
   743     switch (mAudioEncoder) {
   744         case AUDIO_ENCODER_AMR_NB:
   745         case AUDIO_ENCODER_DEFAULT:
   746             mime = MEDIA_MIMETYPE_AUDIO_AMR_NB;
   747             break;
   748         case AUDIO_ENCODER_AMR_WB:
   749             mime = MEDIA_MIMETYPE_AUDIO_AMR_WB;
   750             break;
   751 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
   752         case AUDIO_ENCODER_AAC:
   753             mime = MEDIA_MIMETYPE_AUDIO_AAC;
   754             encMeta->setInt32(kKeyAACProfile, OMX_AUDIO_AACObjectLC);
   755             break;
   756         case AUDIO_ENCODER_HE_AAC:
   757             mime = MEDIA_MIMETYPE_AUDIO_AAC;
   758             encMeta->setInt32(kKeyAACProfile, OMX_AUDIO_AACObjectHE);
   759             break;
   760         case AUDIO_ENCODER_AAC_ELD:
   761             mime = MEDIA_MIMETYPE_AUDIO_AAC;
   762             encMeta->setInt32(kKeyAACProfile, OMX_AUDIO_AACObjectELD);
   763             break;
   764 #endif
   765         default:
   766             RE_LOGE("Unknown audio encoder: %d", mAudioEncoder);
   767             return NULL;
   768     }
   769     encMeta->setCString(kKeyMIMEType, mime);
   771     int32_t maxInputSize;
   772     CHECK(audioSource->getFormat()->findInt32(
   773                 kKeyMaxInputSize, &maxInputSize));
   775     encMeta->setInt32(kKeyMaxInputSize, maxInputSize);
   776     encMeta->setInt32(kKeyChannelCount, mAudioChannels);
   777     encMeta->setInt32(kKeySampleRate, mSampleRate);
   778     encMeta->setInt32(kKeyBitRate, mAudioBitRate);
   779     if (mAudioTimeScale > 0) {
   780         encMeta->setInt32(kKeyTimeScale, mAudioTimeScale);
   781     }
   783     // OMXClient::connect() always returns OK and abort's fatally if
   784     // it can't connect.
   785     OMXClient client;
   786     // CHECK_EQ causes an abort if the given condition fails.
   787     CHECK_EQ(client.connect(), (status_t)OK);
   788     sp<MediaSource> audioEncoder =
   789         OMXCodec::Create(client.interface(), encMeta,
   790                          true /* createEncoder */, audioSource);
   791     mAudioSourceNode = audioSource;
   793     return audioEncoder;
   794 }
   796 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
   797 status_t GonkRecorder::startAACRecording() {
   798     // FIXME:
   799     // Add support for OUTPUT_FORMAT_AAC_ADIF
   800     CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_AAC_ADTS);
   802     CHECK(mAudioEncoder == AUDIO_ENCODER_AAC ||
   803           mAudioEncoder == AUDIO_ENCODER_HE_AAC ||
   804           mAudioEncoder == AUDIO_ENCODER_AAC_ELD);
   805     CHECK(mAudioSource != AUDIO_SOURCE_CNT);
   807     mWriter = new AACWriter(mOutputFd);
   808     status_t status = startRawAudioRecording();
   809     if (status != OK) {
   810         mWriter.clear();
   811         mWriter = NULL;
   812     }
   814     return status;
   815 }
   816 #endif
   818 status_t GonkRecorder::startAMRRecording() {
   819     CHECK(mOutputFormat == OUTPUT_FORMAT_AMR_NB ||
   820           mOutputFormat == OUTPUT_FORMAT_AMR_WB);
   822     if (mOutputFormat == OUTPUT_FORMAT_AMR_NB) {
   823         if (mAudioEncoder != AUDIO_ENCODER_DEFAULT &&
   824             mAudioEncoder != AUDIO_ENCODER_AMR_NB) {
   825             RE_LOGE("Invalid encoder %d used for AMRNB recording",
   826                     mAudioEncoder);
   827             return BAD_VALUE;
   828         }
   829     } else {  // mOutputFormat must be OUTPUT_FORMAT_AMR_WB
   830         if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
   831             RE_LOGE("Invlaid encoder %d used for AMRWB recording",
   832                     mAudioEncoder);
   833             return BAD_VALUE;
   834         }
   835     }
   837     mWriter = new AMRWriter(mOutputFd);
   838     status_t status = startRawAudioRecording();
   839     if (status != OK) {
   840         mWriter.clear();
   841         mWriter = NULL;
   842     }
   843     return status;
   844 }
   846 status_t GonkRecorder::startRawAudioRecording() {
   847     if (mAudioSource >= AUDIO_SOURCE_CNT) {
   848         RE_LOGE("Invalid audio source: %d", mAudioSource);
   849         return BAD_VALUE;
   850     }
   852     status_t status = BAD_VALUE;
   853     if (OK != (status = checkAudioEncoderCapabilities())) {
   854         return status;
   855     }
   857     sp<MediaSource> audioEncoder = createAudioSource();
   858     if (audioEncoder == NULL) {
   859         return UNKNOWN_ERROR;
   860     }
   862     CHECK(mWriter != 0);
   863     mWriter->addSource(audioEncoder);
   865     if (mMaxFileDurationUs != 0) {
   866         mWriter->setMaxFileDuration(mMaxFileDurationUs);
   867     }
   868     if (mMaxFileSizeBytes != 0) {
   869         mWriter->setMaxFileSize(mMaxFileSizeBytes);
   870     }
   871     mWriter->setListener(mListener);
   872     mWriter->start();
   874     return OK;
   875 }
   877 status_t GonkRecorder::startRTPRecording() {
   878     return INVALID_OPERATION;
   879 }
   881 status_t GonkRecorder::startMPEG2TSRecording() {
   882     CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_MPEG2TS);
   884     sp<MediaWriter> writer = new MPEG2TSWriter(mOutputFd);
   886     if (mAudioSource != AUDIO_SOURCE_CNT) {
   887 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
   888         if (mAudioEncoder != AUDIO_ENCODER_AAC &&
   889             mAudioEncoder != AUDIO_ENCODER_HE_AAC &&
   890             mAudioEncoder != AUDIO_ENCODER_AAC_ELD) {
   891             return ERROR_UNSUPPORTED;
   892         }
   893 #endif
   894         status_t err = setupAudioEncoder(writer);
   896         if (err != OK) {
   897             return err;
   898         }
   899     }
   901     if (mVideoSource < VIDEO_SOURCE_LIST_END) {
   902         if (mVideoEncoder != VIDEO_ENCODER_H264) {
   903             return ERROR_UNSUPPORTED;
   904         }
   906         sp<MediaSource> mediaSource;
   907         status_t err = setupMediaSource(&mediaSource);
   908         if (err != OK) {
   909             return err;
   910         }
   912         sp<MediaSource> encoder;
   913         err = setupVideoEncoder(mediaSource, mVideoBitRate, &encoder);
   915         if (err != OK) {
   916             return err;
   917         }
   919         writer->addSource(encoder);
   920     }
   922     if (mMaxFileDurationUs != 0) {
   923         writer->setMaxFileDuration(mMaxFileDurationUs);
   924     }
   926     if (mMaxFileSizeBytes != 0) {
   927         writer->setMaxFileSize(mMaxFileSizeBytes);
   928     }
   930     mWriter = writer;
   932     return mWriter->start();
   933 }
   935 void GonkRecorder::clipVideoFrameRate() {
   936     RE_LOGV("clipVideoFrameRate: encoder %d", mVideoEncoder);
   937     int minFrameRate = mEncoderProfiles->getVideoEncoderParamByName(
   938                         "enc.vid.fps.min", mVideoEncoder);
   939     int maxFrameRate = mEncoderProfiles->getVideoEncoderParamByName(
   940                         "enc.vid.fps.max", mVideoEncoder);
   941     if (mFrameRate < minFrameRate && minFrameRate != -1) {
   942         RE_LOGW("Intended video encoding frame rate (%d fps) is too small"
   943              " and will be set to (%d fps)", mFrameRate, minFrameRate);
   944         mFrameRate = minFrameRate;
   945     } else if (mFrameRate > maxFrameRate && maxFrameRate != -1) {
   946         RE_LOGW("Intended video encoding frame rate (%d fps) is too large"
   947              " and will be set to (%d fps)", mFrameRate, maxFrameRate);
   948         mFrameRate = maxFrameRate;
   949     }
   950 }
   952 void GonkRecorder::clipVideoBitRate() {
   953     RE_LOGV("clipVideoBitRate: encoder %d", mVideoEncoder);
   954     int minBitRate = mEncoderProfiles->getVideoEncoderParamByName(
   955                         "enc.vid.bps.min", mVideoEncoder);
   956     int maxBitRate = mEncoderProfiles->getVideoEncoderParamByName(
   957                         "enc.vid.bps.max", mVideoEncoder);
   958     if (mVideoBitRate < minBitRate && minBitRate != -1) {
   959         RE_LOGW("Intended video encoding bit rate (%d bps) is too small"
   960              " and will be set to (%d bps)", mVideoBitRate, minBitRate);
   961         mVideoBitRate = minBitRate;
   962     } else if (mVideoBitRate > maxBitRate && maxBitRate != -1) {
   963         RE_LOGW("Intended video encoding bit rate (%d bps) is too large"
   964              " and will be set to (%d bps)", mVideoBitRate, maxBitRate);
   965         mVideoBitRate = maxBitRate;
   966     }
   967 }
   969 void GonkRecorder::clipVideoFrameWidth() {
   970     RE_LOGV("clipVideoFrameWidth: encoder %d", mVideoEncoder);
   971     int minFrameWidth = mEncoderProfiles->getVideoEncoderParamByName(
   972                         "enc.vid.width.min", mVideoEncoder);
   973     int maxFrameWidth = mEncoderProfiles->getVideoEncoderParamByName(
   974                         "enc.vid.width.max", mVideoEncoder);
   975     if (mVideoWidth < minFrameWidth && minFrameWidth != -1) {
   976         RE_LOGW("Intended video encoding frame width (%d) is too small"
   977              " and will be set to (%d)", mVideoWidth, minFrameWidth);
   978         mVideoWidth = minFrameWidth;
   979     } else if (mVideoWidth > maxFrameWidth && maxFrameWidth != -1) {
   980         RE_LOGW("Intended video encoding frame width (%d) is too large"
   981              " and will be set to (%d)", mVideoWidth, maxFrameWidth);
   982         mVideoWidth = maxFrameWidth;
   983     }
   984 }
   986 status_t GonkRecorder::checkVideoEncoderCapabilities() {
   988     // Dont clip for time lapse capture as encoder will have enough
   989     // time to encode because of slow capture rate of time lapse.
   990     clipVideoBitRate();
   991     clipVideoFrameRate();
   992     clipVideoFrameWidth();
   993     clipVideoFrameHeight();
   994     setDefaultProfileIfNecessary();
   995     return OK;
   996 }
   998 // Set to use AVC baseline profile if the encoding parameters matches
   999 // CAMCORDER_QUALITY_LOW profile; this is for the sake of MMS service.
  1000 void GonkRecorder::setDefaultProfileIfNecessary() {
  1001     RE_LOGV("setDefaultProfileIfNecessary");
  1003     camcorder_quality quality = CAMCORDER_QUALITY_LOW;
  1005     int64_t durationUs   = mEncoderProfiles->getCamcorderProfileParamByName(
  1006                                 "duration", mCameraId, quality) * 1000000LL;
  1008     int fileFormat       = mEncoderProfiles->getCamcorderProfileParamByName(
  1009                                 "file.format", mCameraId, quality);
  1011     int videoCodec       = mEncoderProfiles->getCamcorderProfileParamByName(
  1012                                 "vid.codec", mCameraId, quality);
  1014     int videoBitRate     = mEncoderProfiles->getCamcorderProfileParamByName(
  1015                                 "vid.bps", mCameraId, quality);
  1017     int videoFrameRate   = mEncoderProfiles->getCamcorderProfileParamByName(
  1018                                 "vid.fps", mCameraId, quality);
  1020     int videoFrameWidth  = mEncoderProfiles->getCamcorderProfileParamByName(
  1021                                 "vid.width", mCameraId, quality);
  1023     int videoFrameHeight = mEncoderProfiles->getCamcorderProfileParamByName(
  1024                                 "vid.height", mCameraId, quality);
  1026     int audioCodec       = mEncoderProfiles->getCamcorderProfileParamByName(
  1027                                 "aud.codec", mCameraId, quality);
  1029     int audioBitRate     = mEncoderProfiles->getCamcorderProfileParamByName(
  1030                                 "aud.bps", mCameraId, quality);
  1032     int audioSampleRate  = mEncoderProfiles->getCamcorderProfileParamByName(
  1033                                 "aud.hz", mCameraId, quality);
  1035     int audioChannels    = mEncoderProfiles->getCamcorderProfileParamByName(
  1036                                 "aud.ch", mCameraId, quality);
  1038     if (durationUs == mMaxFileDurationUs &&
  1039         fileFormat == mOutputFormat &&
  1040         videoCodec == mVideoEncoder &&
  1041         videoBitRate == mVideoBitRate &&
  1042         videoFrameRate == mFrameRate &&
  1043         videoFrameWidth == mVideoWidth &&
  1044         videoFrameHeight == mVideoHeight &&
  1045         audioCodec == mAudioEncoder &&
  1046         audioBitRate == mAudioBitRate &&
  1047         audioSampleRate == mSampleRate &&
  1048         audioChannels == mAudioChannels) {
  1049         if (videoCodec == VIDEO_ENCODER_H264) {
  1050             RE_LOGI("Force to use AVC baseline profile");
  1051             setParamVideoEncoderProfile(OMX_VIDEO_AVCProfileBaseline);
  1056 status_t GonkRecorder::checkAudioEncoderCapabilities() {
  1057     clipAudioBitRate();
  1058     clipAudioSampleRate();
  1059     clipNumberOfAudioChannels();
  1060     return OK;
  1063 void GonkRecorder::clipAudioBitRate() {
  1064     RE_LOGV("clipAudioBitRate: encoder %d", mAudioEncoder);
  1066     int minAudioBitRate =
  1067             mEncoderProfiles->getAudioEncoderParamByName(
  1068                 "enc.aud.bps.min", mAudioEncoder);
  1069     if (minAudioBitRate != -1 && mAudioBitRate < minAudioBitRate) {
  1070         RE_LOGW("Intended audio encoding bit rate (%d) is too small"
  1071             " and will be set to (%d)", mAudioBitRate, minAudioBitRate);
  1072         mAudioBitRate = minAudioBitRate;
  1075     int maxAudioBitRate =
  1076             mEncoderProfiles->getAudioEncoderParamByName(
  1077                 "enc.aud.bps.max", mAudioEncoder);
  1078     if (maxAudioBitRate != -1 && mAudioBitRate > maxAudioBitRate) {
  1079         RE_LOGW("Intended audio encoding bit rate (%d) is too large"
  1080             " and will be set to (%d)", mAudioBitRate, maxAudioBitRate);
  1081         mAudioBitRate = maxAudioBitRate;
  1085 void GonkRecorder::clipAudioSampleRate() {
  1086     RE_LOGV("clipAudioSampleRate: encoder %d", mAudioEncoder);
  1088     int minSampleRate =
  1089             mEncoderProfiles->getAudioEncoderParamByName(
  1090                 "enc.aud.hz.min", mAudioEncoder);
  1091     if (minSampleRate != -1 && mSampleRate < minSampleRate) {
  1092         RE_LOGW("Intended audio sample rate (%d) is too small"
  1093             " and will be set to (%d)", mSampleRate, minSampleRate);
  1094         mSampleRate = minSampleRate;
  1097     int maxSampleRate =
  1098             mEncoderProfiles->getAudioEncoderParamByName(
  1099                 "enc.aud.hz.max", mAudioEncoder);
  1100     if (maxSampleRate != -1 && mSampleRate > maxSampleRate) {
  1101         RE_LOGW("Intended audio sample rate (%d) is too large"
  1102             " and will be set to (%d)", mSampleRate, maxSampleRate);
  1103         mSampleRate = maxSampleRate;
  1107 void GonkRecorder::clipNumberOfAudioChannels() {
  1108     RE_LOGV("clipNumberOfAudioChannels: encoder %d", mAudioEncoder);
  1110     int minChannels =
  1111             mEncoderProfiles->getAudioEncoderParamByName(
  1112                 "enc.aud.ch.min", mAudioEncoder);
  1113     if (minChannels != -1 && mAudioChannels < minChannels) {
  1114         RE_LOGW("Intended number of audio channels (%d) is too small"
  1115             " and will be set to (%d)", mAudioChannels, minChannels);
  1116         mAudioChannels = minChannels;
  1119     int maxChannels =
  1120             mEncoderProfiles->getAudioEncoderParamByName(
  1121                 "enc.aud.ch.max", mAudioEncoder);
  1122     if (maxChannels != -1 && mAudioChannels > maxChannels) {
  1123         RE_LOGW("Intended number of audio channels (%d) is too large"
  1124             " and will be set to (%d)", mAudioChannels, maxChannels);
  1125         mAudioChannels = maxChannels;
  1129 void GonkRecorder::clipVideoFrameHeight() {
  1130     RE_LOGV("clipVideoFrameHeight: encoder %d", mVideoEncoder);
  1131     int minFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
  1132                         "enc.vid.height.min", mVideoEncoder);
  1133     int maxFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
  1134                         "enc.vid.height.max", mVideoEncoder);
  1135     if (minFrameHeight != -1 && mVideoHeight < minFrameHeight) {
  1136         RE_LOGW("Intended video encoding frame height (%d) is too small"
  1137              " and will be set to (%d)", mVideoHeight, minFrameHeight);
  1138         mVideoHeight = minFrameHeight;
  1139     } else if (maxFrameHeight != -1 && mVideoHeight > maxFrameHeight) {
  1140         RE_LOGW("Intended video encoding frame height (%d) is too large"
  1141              " and will be set to (%d)", mVideoHeight, maxFrameHeight);
  1142         mVideoHeight = maxFrameHeight;
  1146 // Set up the appropriate MediaSource depending on the chosen option
  1147 status_t GonkRecorder::setupMediaSource(
  1148                       sp<MediaSource> *mediaSource) {
  1149     if (mVideoSource == VIDEO_SOURCE_DEFAULT
  1150             || mVideoSource == VIDEO_SOURCE_CAMERA) {
  1151         sp<GonkCameraSource> cameraSource;
  1152         status_t err = setupCameraSource(&cameraSource);
  1153         if (err != OK) {
  1154             return err;
  1156         *mediaSource = cameraSource;
  1157     } else if (mVideoSource == VIDEO_SOURCE_GRALLOC_BUFFER) {
  1158         return BAD_VALUE;
  1159     } else {
  1160         return INVALID_OPERATION;
  1162     return OK;
  1165 status_t GonkRecorder::setupCameraSource(
  1166         sp<GonkCameraSource> *cameraSource) {
  1167     status_t err = OK;
  1168     if ((err = checkVideoEncoderCapabilities()) != OK) {
  1169         return err;
  1171     Size videoSize;
  1172     videoSize.width = mVideoWidth;
  1173     videoSize.height = mVideoHeight;
  1174     bool useMeta = true;
  1175     char value[PROPERTY_VALUE_MAX];
  1176     if (property_get("debug.camcorder.disablemeta", value, NULL) &&
  1177             atoi(value)) {
  1178       useMeta = false;
  1181     *cameraSource = GonkCameraSource::Create(
  1182                 mCameraHw, videoSize, mFrameRate, useMeta);
  1183     if (*cameraSource == NULL) {
  1184         return UNKNOWN_ERROR;
  1187     if ((*cameraSource)->initCheck() != OK) {
  1188         (*cameraSource).clear();
  1189         *cameraSource = NULL;
  1190         return NO_INIT;
  1193     // When frame rate is not set, the actual frame rate will be set to
  1194     // the current frame rate being used.
  1195     if (mFrameRate == -1) {
  1196         int32_t frameRate = 0;
  1197         CHECK ((*cameraSource)->getFormat()->findInt32(
  1198                     kKeyFrameRate, &frameRate));
  1199         RE_LOGI("Frame rate is not explicitly set. Use the current frame "
  1200              "rate (%d fps)", frameRate);
  1201         mFrameRate = frameRate;
  1204     CHECK(mFrameRate != -1);
  1206     mIsMetaDataStoredInVideoBuffers =
  1207         (*cameraSource)->isMetaDataStoredInVideoBuffers();
  1209     return OK;
  1212 status_t GonkRecorder::setupVideoEncoder(
  1213         sp<MediaSource> cameraSource,
  1214         int32_t videoBitRate,
  1215         sp<MediaSource> *source) {
  1216     source->clear();
  1218     sp<MetaData> enc_meta = new MetaData;
  1219     enc_meta->setInt32(kKeyBitRate, videoBitRate);
  1220     enc_meta->setInt32(kKeyFrameRate, mFrameRate);
  1222     switch (mVideoEncoder) {
  1223         case VIDEO_ENCODER_H263:
  1224             enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
  1225             break;
  1227         case VIDEO_ENCODER_MPEG_4_SP:
  1228             enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
  1229             break;
  1231         case VIDEO_ENCODER_H264:
  1232             enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
  1233             break;
  1235         default:
  1236             CHECK(!"Should not be here, unsupported video encoding.");
  1237             break;
  1240     sp<MetaData> meta = cameraSource->getFormat();
  1242     int32_t width, height, stride, sliceHeight, colorFormat;
  1243     CHECK(meta->findInt32(kKeyWidth, &width));
  1244     CHECK(meta->findInt32(kKeyHeight, &height));
  1245     CHECK(meta->findInt32(kKeyStride, &stride));
  1246     CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight));
  1247     CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));
  1249     enc_meta->setInt32(kKeyWidth, width);
  1250     enc_meta->setInt32(kKeyHeight, height);
  1251     enc_meta->setInt32(kKeyIFramesInterval, mIFramesIntervalSec);
  1252     enc_meta->setInt32(kKeyStride, stride);
  1253     enc_meta->setInt32(kKeySliceHeight, sliceHeight);
  1254     enc_meta->setInt32(kKeyColorFormat, colorFormat);
  1255     if (mVideoTimeScale > 0) {
  1256         enc_meta->setInt32(kKeyTimeScale, mVideoTimeScale);
  1258     if (mVideoEncoderProfile != -1) {
  1259         enc_meta->setInt32(kKeyVideoProfile, mVideoEncoderProfile);
  1261     if (mVideoEncoderLevel != -1) {
  1262         enc_meta->setInt32(kKeyVideoLevel, mVideoEncoderLevel);
  1265     // OMXClient::connect() always returns OK and abort's fatally if
  1266     // it can't connect.
  1267     OMXClient client;
  1268     // CHECK_EQ causes an abort if the given condition fails.
  1269     CHECK_EQ(client.connect(), (status_t)OK);
  1271     uint32_t encoder_flags = 0;
  1272     if (mIsMetaDataStoredInVideoBuffers) {
  1273 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
  1274         encoder_flags |= OMXCodec::kStoreMetaDataInVideoBuffers;
  1275 #else
  1276         encoder_flags |= OMXCodec::kHardwareCodecsOnly;
  1277         encoder_flags |= OMXCodec::kStoreMetaDataInVideoBuffers;
  1278         encoder_flags |= OMXCodec::kOnlySubmitOneInputBufferAtOneTime;
  1279 #endif
  1282     sp<MediaSource> encoder = OMXCodec::Create(
  1283             client.interface(), enc_meta,
  1284             true /* createEncoder */, cameraSource,
  1285             NULL, encoder_flags);
  1286     if (encoder == NULL) {
  1287         RE_LOGW("Failed to create the encoder");
  1288         // When the encoder fails to be created, we need
  1289         // release the camera source due to the camera's lock
  1290         // and unlock mechanism.
  1291         cameraSource->stop();
  1292         return UNKNOWN_ERROR;
  1295     *source = encoder;
  1297     return OK;
  1300 status_t GonkRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) {
  1301     status_t status = BAD_VALUE;
  1302     if (OK != (status = checkAudioEncoderCapabilities())) {
  1303         return status;
  1306     switch(mAudioEncoder) {
  1307         case AUDIO_ENCODER_AMR_NB:
  1308         case AUDIO_ENCODER_AMR_WB:
  1309 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
  1310         case AUDIO_ENCODER_AAC:
  1311         case AUDIO_ENCODER_HE_AAC:
  1312         case AUDIO_ENCODER_AAC_ELD:
  1313 #endif
  1314             break;
  1316         default:
  1317             RE_LOGE("Unsupported audio encoder: %d", mAudioEncoder);
  1318             return UNKNOWN_ERROR;
  1321     sp<MediaSource> audioEncoder = createAudioSource();
  1322     if (audioEncoder == NULL) {
  1323         return UNKNOWN_ERROR;
  1326     writer->addSource(audioEncoder);
  1327     return OK;
  1330 status_t GonkRecorder::setupMPEG4Recording(
  1331         int outputFd,
  1332         int32_t videoWidth, int32_t videoHeight,
  1333         int32_t videoBitRate,
  1334         int32_t *totalBitRate,
  1335         sp<MediaWriter> *mediaWriter) {
  1336     mediaWriter->clear();
  1337     *totalBitRate = 0;
  1338     status_t err = OK;
  1339     sp<MediaWriter> writer = new MPEG4Writer(outputFd);
  1341     if (mVideoSource < VIDEO_SOURCE_LIST_END) {
  1343         sp<MediaSource> mediaSource;
  1344         err = setupMediaSource(&mediaSource);
  1345         if (err != OK) {
  1346             return err;
  1349         sp<MediaSource> encoder;
  1350         err = setupVideoEncoder(mediaSource, videoBitRate, &encoder);
  1351         if (err != OK) {
  1352             return err;
  1355         writer->addSource(encoder);
  1356         *totalBitRate += videoBitRate;
  1359     // Audio source is added at the end if it exists.
  1360     // This help make sure that the "recoding" sound is suppressed for
  1361     // camcorder applications in the recorded files.
  1362     if (mAudioSource != AUDIO_SOURCE_CNT) {
  1363         err = setupAudioEncoder(writer);
  1364         if (err != OK) return err;
  1365         *totalBitRate += mAudioBitRate;
  1368     if (mInterleaveDurationUs > 0) {
  1369         reinterpret_cast<MPEG4Writer *>(writer.get())->
  1370             setInterleaveDuration(mInterleaveDurationUs);
  1372     if (mLongitudex10000 > -3600000 && mLatitudex10000 > -3600000) {
  1373         reinterpret_cast<MPEG4Writer *>(writer.get())->
  1374             setGeoData(mLatitudex10000, mLongitudex10000);
  1376     if (mMaxFileDurationUs != 0) {
  1377         writer->setMaxFileDuration(mMaxFileDurationUs);
  1379     if (mMaxFileSizeBytes != 0) {
  1380         writer->setMaxFileSize(mMaxFileSizeBytes);
  1383     mStartTimeOffsetMs = mEncoderProfiles->getStartTimeOffsetMs(mCameraId);
  1384     if (mStartTimeOffsetMs > 0) {
  1385         reinterpret_cast<MPEG4Writer *>(writer.get())->
  1386             setStartTimeOffsetMs(mStartTimeOffsetMs);
  1389     writer->setListener(mListener);
  1390     *mediaWriter = writer;
  1391     return OK;
  1394 void GonkRecorder::setupMPEG4MetaData(int64_t startTimeUs, int32_t totalBitRate,
  1395         sp<MetaData> *meta) {
  1396     (*meta)->setInt64(kKeyTime, startTimeUs);
  1397     (*meta)->setInt32(kKeyFileType, mOutputFormat);
  1398     (*meta)->setInt32(kKeyBitRate, totalBitRate);
  1399     (*meta)->setInt32(kKey64BitFileOffset, mUse64BitFileOffset);
  1400     if (mMovieTimeScale > 0) {
  1401         (*meta)->setInt32(kKeyTimeScale, mMovieTimeScale);
  1403     if (mTrackEveryTimeDurationUs > 0) {
  1404         (*meta)->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs);
  1407     char value[PROPERTY_VALUE_MAX];
  1408     if (property_get("debug.camcorder.rotation", value, 0) > 0 && atoi(value) >= 0) {
  1409         mRotationDegrees = atoi(value);
  1410         RE_LOGI("Setting rotation to %d", mRotationDegrees );
  1413     if (mRotationDegrees != 0) {
  1414         (*meta)->setInt32(kKeyRotation, mRotationDegrees);
  1418 status_t GonkRecorder::startMPEG4Recording() {
  1419     int32_t totalBitRate;
  1420     status_t err = setupMPEG4Recording(
  1421             mOutputFd, mVideoWidth, mVideoHeight,
  1422             mVideoBitRate, &totalBitRate, &mWriter);
  1423     if (err != OK) {
  1424         return err;
  1427     //systemTime() doesn't give correct time because
  1428     //HAVE_POSIX_CLOCKS is not defined for utils/Timers.cpp
  1429     //so, using clock_gettime directly
  1430 #include <time.h>
  1431     struct timespec t;
  1432     clock_gettime(CLOCK_MONOTONIC, &t);
  1433     int64_t startTimeUs = int64_t(t.tv_sec)*1000000000LL + t.tv_nsec;
  1434     startTimeUs = startTimeUs / 1000;
  1435     sp<MetaData> meta = new MetaData;
  1436     setupMPEG4MetaData(startTimeUs, totalBitRate, &meta);
  1438     err = mWriter->start(meta.get());
  1439     if (err != OK) {
  1440         return err;
  1443     return OK;
  1446 status_t GonkRecorder::pause() {
  1447     RE_LOGV("pause");
  1448     if (mWriter == NULL) {
  1449         return UNKNOWN_ERROR;
  1451     mWriter->pause();
  1453     if (mStarted) {
  1454         mStarted = false;
  1458     return OK;
  1461 status_t GonkRecorder::stop() {
  1462     RE_LOGV("stop");
  1463     status_t err = OK;
  1465     if (mWriter != NULL) {
  1466         err = mWriter->stop();
  1467         mWriter.clear();
  1470     if (mOutputFd >= 0) {
  1471         ::close(mOutputFd);
  1472         mOutputFd = -1;
  1475     if (mStarted) {
  1476         mStarted = false;
  1480     return err;
  1483 status_t GonkRecorder::close() {
  1484     RE_LOGV("close");
  1485     stop();
  1487     return OK;
  1490 status_t GonkRecorder::reset() {
  1491     RE_LOGV("reset");
  1492     stop();
  1494     // No audio or video source by default
  1495     mAudioSource = AUDIO_SOURCE_CNT;
  1496     mVideoSource = VIDEO_SOURCE_LIST_END;
  1498     // Default parameters
  1499     mOutputFormat  = OUTPUT_FORMAT_THREE_GPP;
  1500     mAudioEncoder  = AUDIO_ENCODER_AMR_NB;
  1501     mVideoEncoder  = VIDEO_ENCODER_H263;
  1502     mVideoWidth    = 176;
  1503     mVideoHeight   = 144;
  1504     mFrameRate     = -1;
  1505     mVideoBitRate  = 192000;
  1506     mSampleRate    = 8000;
  1507     mAudioChannels = 1;
  1508     mAudioBitRate  = 12200;
  1509     mInterleaveDurationUs = 0;
  1510     mIFramesIntervalSec = 1;
  1511     mAudioSourceNode = 0;
  1512     mUse64BitFileOffset = false;
  1513     mMovieTimeScale  = -1;
  1514     mAudioTimeScale  = -1;
  1515     mVideoTimeScale  = -1;
  1516     mCameraId        = 0;
  1517     mStartTimeOffsetMs = -1;
  1518     mVideoEncoderProfile = -1;
  1519     mVideoEncoderLevel   = -1;
  1520     mMaxFileDurationUs = 0;
  1521     mMaxFileSizeBytes = 0;
  1522     mTrackEveryTimeDurationUs = 0;
  1523     mIsMetaDataStoredInVideoBuffers = false;
  1524     mEncoderProfiles = MediaProfiles::getInstance();
  1525     mRotationDegrees = 0;
  1526     mLatitudex10000 = -3600000;
  1527     mLongitudex10000 = -3600000;
  1529     mOutputFd = -1;
  1530     mCameraHw.clear();
  1531     //TODO: May need to register a listener eventually
  1532     //if someone is interested in recorder events for now
  1533     //default to no listener registered
  1534     mListener = NULL;
  1536     return OK;
  1539 status_t GonkRecorder::getMaxAmplitude(int *max) {
  1540     RE_LOGV("getMaxAmplitude");
  1542     if (max == NULL) {
  1543         RE_LOGE("Null pointer argument");
  1544         return BAD_VALUE;
  1547     if (mAudioSourceNode != 0) {
  1548         *max = mAudioSourceNode->getMaxAmplitude();
  1549     } else {
  1550         *max = 0;
  1553     return OK;
  1556 status_t GonkRecorder::dump(
  1557         int fd, const Vector<String16>& args) const {
  1558     RE_LOGV("dump");
  1559     const size_t SIZE = 256;
  1560     char buffer[SIZE];
  1561     String8 result;
  1562     if (mWriter != 0) {
  1563         mWriter->dump(fd, args);
  1564     } else {
  1565         snprintf(buffer, SIZE, "   No file writer\n");
  1566         result.append(buffer);
  1568     snprintf(buffer, SIZE, "   Recorder: %p\n", this);
  1569     snprintf(buffer, SIZE, "   Output file (fd %d):\n", mOutputFd);
  1570     result.append(buffer);
  1571     snprintf(buffer, SIZE, "     File format: %d\n", mOutputFormat);
  1572     result.append(buffer);
  1573     snprintf(buffer, SIZE, "     Max file size (bytes): %lld\n", mMaxFileSizeBytes);
  1574     result.append(buffer);
  1575     snprintf(buffer, SIZE, "     Max file duration (us): %lld\n", mMaxFileDurationUs);
  1576     result.append(buffer);
  1577     snprintf(buffer, SIZE, "     File offset length (bits): %d\n", mUse64BitFileOffset? 64: 32);
  1578     result.append(buffer);
  1579     snprintf(buffer, SIZE, "     Interleave duration (us): %d\n", mInterleaveDurationUs);
  1580     result.append(buffer);
  1581     snprintf(buffer, SIZE, "     Progress notification: %lld us\n", mTrackEveryTimeDurationUs);
  1582     result.append(buffer);
  1583     snprintf(buffer, SIZE, "   Audio\n");
  1584     result.append(buffer);
  1585     snprintf(buffer, SIZE, "     Source: %d\n", mAudioSource);
  1586     result.append(buffer);
  1587     snprintf(buffer, SIZE, "     Encoder: %d\n", mAudioEncoder);
  1588     result.append(buffer);
  1589     snprintf(buffer, SIZE, "     Bit rate (bps): %d\n", mAudioBitRate);
  1590     result.append(buffer);
  1591     snprintf(buffer, SIZE, "     Sampling rate (hz): %d\n", mSampleRate);
  1592     result.append(buffer);
  1593     snprintf(buffer, SIZE, "     Number of channels: %d\n", mAudioChannels);
  1594     result.append(buffer);
  1595     snprintf(buffer, SIZE, "     Max amplitude: %d\n", mAudioSourceNode == 0? 0: mAudioSourceNode->getMaxAmplitude());
  1596     result.append(buffer);
  1597     snprintf(buffer, SIZE, "   Video\n");
  1598     result.append(buffer);
  1599     snprintf(buffer, SIZE, "     Source: %d\n", mVideoSource);
  1600     result.append(buffer);
  1601     snprintf(buffer, SIZE, "     Camera Id: %d\n", mCameraId);
  1602     result.append(buffer);
  1603     snprintf(buffer, SIZE, "     Camera object address: %p\n", mCameraHw.get());
  1604     result.append(buffer);
  1605     snprintf(buffer, SIZE, "     Start time offset (ms): %d\n", mStartTimeOffsetMs);
  1606     result.append(buffer);
  1607     snprintf(buffer, SIZE, "     Encoder: %d\n", mVideoEncoder);
  1608     result.append(buffer);
  1609     snprintf(buffer, SIZE, "     Encoder profile: %d\n", mVideoEncoderProfile);
  1610     result.append(buffer);
  1611     snprintf(buffer, SIZE, "     Encoder level: %d\n", mVideoEncoderLevel);
  1612     result.append(buffer);
  1613     snprintf(buffer, SIZE, "     I frames interval (s): %d\n", mIFramesIntervalSec);
  1614     result.append(buffer);
  1615     snprintf(buffer, SIZE, "     Frame size (pixels): %dx%d\n", mVideoWidth, mVideoHeight);
  1616     result.append(buffer);
  1617     snprintf(buffer, SIZE, "     Frame rate (fps): %d\n", mFrameRate);
  1618     result.append(buffer);
  1619     snprintf(buffer, SIZE, "     Bit rate (bps): %d\n", mVideoBitRate);
  1620     result.append(buffer);
  1621     ::write(fd, result.string(), result.size());
  1622     return OK;
  1625 status_t GonkRecorder::setCamera(const sp<GonkCameraHardware>& aCameraHw) {
  1626   mCameraHw = aCameraHw;
  1627   return OK;
  1630 }  // namespace android

mercurial