Home | History | Annotate | Download | only in libmediaplayerservice
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 //#define LOG_NDEBUG 0
     18 #define LOG_TAG "StagefrightRecorder"
     19 #include <inttypes.h>
     20 #include <utils/Log.h>
     21 
     22 #include "WebmWriter.h"
     23 #include "StagefrightRecorder.h"
     24 
     25 #include <algorithm>
     26 
     27 #include <android/hardware/ICamera.h>
     28 
     29 #include <binder/IPCThreadState.h>
     30 #include <binder/IServiceManager.h>
     31 
     32 #include <media/IMediaPlayerService.h>
     33 #include <media/MediaAnalyticsItem.h>
     34 #include <media/stagefright/foundation/ABuffer.h>
     35 #include <media/stagefright/foundation/ADebug.h>
     36 #include <media/stagefright/foundation/AMessage.h>
     37 #include <media/stagefright/foundation/ALooper.h>
     38 #include <media/stagefright/ACodec.h>
     39 #include <media/stagefright/AudioSource.h>
     40 #include <media/stagefright/AMRWriter.h>
     41 #include <media/stagefright/AACWriter.h>
     42 #include <media/stagefright/CameraSource.h>
     43 #include <media/stagefright/CameraSourceTimeLapse.h>
     44 #include <media/stagefright/MPEG2TSWriter.h>
     45 #include <media/stagefright/MPEG4Writer.h>
     46 #include <media/stagefright/MediaDefs.h>
     47 #include <media/stagefright/MetaData.h>
     48 #include <media/stagefright/MediaCodecSource.h>
     49 #include <media/stagefright/PersistentSurface.h>
     50 #include <media/MediaProfiles.h>
     51 #include <camera/CameraParameters.h>
     52 
     53 #include <utils/Errors.h>
     54 #include <sys/types.h>
     55 #include <ctype.h>
     56 #include <unistd.h>
     57 
     58 #include <system/audio.h>
     59 
     60 #include "ARTPWriter.h"
     61 
     62 namespace android {
     63 
     64 static const float kTypicalDisplayRefreshingRate = 60.f;
     65 // display refresh rate drops on battery saver
     66 static const float kMinTypicalDisplayRefreshingRate = kTypicalDisplayRefreshingRate / 2;
     67 static const int kMaxNumVideoTemporalLayers = 8;
     68 
     69 // key for media statistics
     70 static const char *kKeyRecorder = "recorder";
     71 // attrs for media statistics
     72 // NB: these are matched with public Java API constants defined
     73 // in frameworks/base/media/java/android/media/MediaRecorder.java
     74 // These must be kept synchronized with the constants there.
     75 static const char *kRecorderAudioBitrate = "android.media.mediarecorder.audio-bitrate";
     76 static const char *kRecorderAudioChannels = "android.media.mediarecorder.audio-channels";
     77 static const char *kRecorderAudioSampleRate = "android.media.mediarecorder.audio-samplerate";
     78 static const char *kRecorderAudioTimescale = "android.media.mediarecorder.audio-timescale";
     79 static const char *kRecorderCaptureFps = "android.media.mediarecorder.capture-fps";
     80 static const char *kRecorderCaptureFpsEnable = "android.media.mediarecorder.capture-fpsenable";
     81 static const char *kRecorderFrameRate = "android.media.mediarecorder.frame-rate";
     82 static const char *kRecorderHeight = "android.media.mediarecorder.height";
     83 static const char *kRecorderMovieTimescale = "android.media.mediarecorder.movie-timescale";
     84 static const char *kRecorderRotation = "android.media.mediarecorder.rotation";
     85 static const char *kRecorderVideoBitrate = "android.media.mediarecorder.video-bitrate";
     86 static const char *kRecorderVideoIframeInterval = "android.media.mediarecorder.video-iframe-interval";
     87 static const char *kRecorderVideoLevel = "android.media.mediarecorder.video-encoder-level";
     88 static const char *kRecorderVideoProfile = "android.media.mediarecorder.video-encoder-profile";
     89 static const char *kRecorderVideoTimescale = "android.media.mediarecorder.video-timescale";
     90 static const char *kRecorderWidth = "android.media.mediarecorder.width";
     91 
     92 // new fields, not yet frozen in the public Java API definitions
     93 static const char *kRecorderAudioMime = "android.media.mediarecorder.audio.mime";
     94 static const char *kRecorderVideoMime = "android.media.mediarecorder.video.mime";
     95 static const char *kRecorderDurationMs = "android.media.mediarecorder.durationMs";
     96 static const char *kRecorderPaused = "android.media.mediarecorder.pausedMs";
     97 static const char *kRecorderNumPauses = "android.media.mediarecorder.NPauses";
     98 
     99 
    100 // To collect the encoder usage for the battery app
    101 static void addBatteryData(uint32_t params) {
    102     sp<IBinder> binder =
    103         defaultServiceManager()->getService(String16("media.player"));
    104     sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
    105     CHECK(service.get() != NULL);
    106 
    107     service->addBatteryData(params);
    108 }
    109 
    110 
    111 StagefrightRecorder::StagefrightRecorder(const String16 &opPackageName)
    112     : MediaRecorderBase(opPackageName),
    113       mWriter(NULL),
    114       mOutputFd(-1),
    115       mAudioSource((audio_source_t)AUDIO_SOURCE_CNT), // initialize with invalid value
    116       mVideoSource(VIDEO_SOURCE_LIST_END),
    117       mStarted(false),
    118       mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
    119       mDeviceCallbackEnabled(false) {
    120 
    121     ALOGV("Constructor");
    122 
    123     mAnalyticsDirty = false;
    124     reset();
    125 }
    126 
    127 StagefrightRecorder::~StagefrightRecorder() {
    128     ALOGV("Destructor");
    129     stop();
    130 
    131     if (mLooper != NULL) {
    132         mLooper->stop();
    133     }
    134 
    135     // log the current record, provided it has some information worth recording
    136     // NB: this also reclaims & clears mAnalyticsItem.
    137     flushAndResetMetrics(false);
    138 }
    139 
    140 void StagefrightRecorder::updateMetrics() {
    141     ALOGV("updateMetrics");
    142 
    143     // we run as part of the media player service; what we really want to
    144     // know is the app which requested the recording.
    145     mAnalyticsItem->setUid(mClientUid);
    146 
    147     // populate the values from the raw fields.
    148 
    149     // TBD mOutputFormat  = OUTPUT_FORMAT_THREE_GPP;
    150     // TBD mAudioEncoder  = AUDIO_ENCODER_AMR_NB;
    151     // TBD mVideoEncoder  = VIDEO_ENCODER_DEFAULT;
    152     mAnalyticsItem->setInt32(kRecorderHeight, mVideoHeight);
    153     mAnalyticsItem->setInt32(kRecorderWidth, mVideoWidth);
    154     mAnalyticsItem->setInt32(kRecorderFrameRate, mFrameRate);
    155     mAnalyticsItem->setInt32(kRecorderVideoBitrate, mVideoBitRate);
    156     mAnalyticsItem->setInt32(kRecorderAudioSampleRate, mSampleRate);
    157     mAnalyticsItem->setInt32(kRecorderAudioChannels, mAudioChannels);
    158     mAnalyticsItem->setInt32(kRecorderAudioBitrate, mAudioBitRate);
    159     // TBD mInterleaveDurationUs = 0;
    160     mAnalyticsItem->setInt32(kRecorderVideoIframeInterval, mIFramesIntervalSec);
    161     // TBD mAudioSourceNode = 0;
    162     // TBD mUse64BitFileOffset = false;
    163     mAnalyticsItem->setInt32(kRecorderMovieTimescale, mMovieTimeScale);
    164     mAnalyticsItem->setInt32(kRecorderAudioTimescale, mAudioTimeScale);
    165     mAnalyticsItem->setInt32(kRecorderVideoTimescale, mVideoTimeScale);
    166     // TBD mCameraId        = 0;
    167     // TBD mStartTimeOffsetMs = -1;
    168     mAnalyticsItem->setInt32(kRecorderVideoProfile, mVideoEncoderProfile);
    169     mAnalyticsItem->setInt32(kRecorderVideoLevel, mVideoEncoderLevel);
    170     // TBD mMaxFileDurationUs = 0;
    171     // TBD mMaxFileSizeBytes = 0;
    172     // TBD mTrackEveryTimeDurationUs = 0;
    173     mAnalyticsItem->setInt32(kRecorderCaptureFpsEnable, mCaptureFpsEnable);
    174     mAnalyticsItem->setDouble(kRecorderCaptureFps, mCaptureFps);
    175     // TBD mCameraSourceTimeLapse = NULL;
    176     // TBD mMetaDataStoredInVideoBuffers = kMetadataBufferTypeInvalid;
    177     // TBD mEncoderProfiles = MediaProfiles::getInstance();
    178     mAnalyticsItem->setInt32(kRecorderRotation, mRotationDegrees);
    179     // PII mLatitudex10000 = -3600000;
    180     // PII mLongitudex10000 = -3600000;
    181     // TBD mTotalBitRate = 0;
    182 
    183     // duration information (recorded, paused, # of pauses)
    184     mAnalyticsItem->setInt64(kRecorderDurationMs, (mDurationRecordedUs+500)/1000 );
    185     if (mNPauses != 0) {
    186         mAnalyticsItem->setInt64(kRecorderPaused, (mDurationPausedUs+500)/1000 );
    187         mAnalyticsItem->setInt32(kRecorderNumPauses, mNPauses);
    188     }
    189 }
    190 
    191 void StagefrightRecorder::flushAndResetMetrics(bool reinitialize) {
    192     ALOGV("flushAndResetMetrics");
    193     // flush anything we have, maybe setup a new record
    194     if (mAnalyticsDirty && mAnalyticsItem != NULL) {
    195         updateMetrics();
    196         if (mAnalyticsItem->count() > 0) {
    197             mAnalyticsItem->selfrecord();
    198         }
    199         delete mAnalyticsItem;
    200         mAnalyticsItem = NULL;
    201     }
    202     mAnalyticsDirty = false;
    203     if (reinitialize) {
    204         mAnalyticsItem = new MediaAnalyticsItem(kKeyRecorder);
    205     }
    206 }
    207 
    208 status_t StagefrightRecorder::init() {
    209     ALOGV("init");
    210 
    211     mLooper = new ALooper;
    212     mLooper->setName("recorder_looper");
    213     mLooper->start();
    214 
    215     return OK;
    216 }
    217 
    218 // The client side of mediaserver asks it to create a SurfaceMediaSource
    219 // and return a interface reference. The client side will use that
    220 // while encoding GL Frames
    221 sp<IGraphicBufferProducer> StagefrightRecorder::querySurfaceMediaSource() const {
    222     ALOGV("Get SurfaceMediaSource");
    223     return mGraphicBufferProducer;
    224 }
    225 
    226 status_t StagefrightRecorder::setAudioSource(audio_source_t as) {
    227     ALOGV("setAudioSource: %d", as);
    228     if (as < AUDIO_SOURCE_DEFAULT ||
    229         (as >= AUDIO_SOURCE_CNT && as != AUDIO_SOURCE_FM_TUNER)) {
    230         ALOGE("Invalid audio source: %d", as);
    231         return BAD_VALUE;
    232     }
    233 
    234     if (as == AUDIO_SOURCE_DEFAULT) {
    235         mAudioSource = AUDIO_SOURCE_MIC;
    236     } else {
    237         mAudioSource = as;
    238     }
    239 
    240     return OK;
    241 }
    242 
    243 status_t StagefrightRecorder::setVideoSource(video_source vs) {
    244     ALOGV("setVideoSource: %d", vs);
    245     if (vs < VIDEO_SOURCE_DEFAULT ||
    246         vs >= VIDEO_SOURCE_LIST_END) {
    247         ALOGE("Invalid video source: %d", vs);
    248         return BAD_VALUE;
    249     }
    250 
    251     if (vs == VIDEO_SOURCE_DEFAULT) {
    252         mVideoSource = VIDEO_SOURCE_CAMERA;
    253     } else {
    254         mVideoSource = vs;
    255     }
    256 
    257     return OK;
    258 }
    259 
    260 status_t StagefrightRecorder::setOutputFormat(output_format of) {
    261     ALOGV("setOutputFormat: %d", of);
    262     if (of < OUTPUT_FORMAT_DEFAULT ||
    263         of >= OUTPUT_FORMAT_LIST_END) {
    264         ALOGE("Invalid output format: %d", of);
    265         return BAD_VALUE;
    266     }
    267 
    268     if (of == OUTPUT_FORMAT_DEFAULT) {
    269         mOutputFormat = OUTPUT_FORMAT_THREE_GPP;
    270     } else {
    271         mOutputFormat = of;
    272     }
    273 
    274     return OK;
    275 }
    276 
    277 status_t StagefrightRecorder::setAudioEncoder(audio_encoder ae) {
    278     ALOGV("setAudioEncoder: %d", ae);
    279     if (ae < AUDIO_ENCODER_DEFAULT ||
    280         ae >= AUDIO_ENCODER_LIST_END) {
    281         ALOGE("Invalid audio encoder: %d", ae);
    282         return BAD_VALUE;
    283     }
    284 
    285     if (ae == AUDIO_ENCODER_DEFAULT) {
    286         mAudioEncoder = AUDIO_ENCODER_AMR_NB;
    287     } else {
    288         mAudioEncoder = ae;
    289     }
    290 
    291     return OK;
    292 }
    293 
    294 status_t StagefrightRecorder::setVideoEncoder(video_encoder ve) {
    295     ALOGV("setVideoEncoder: %d", ve);
    296     if (ve < VIDEO_ENCODER_DEFAULT ||
    297         ve >= VIDEO_ENCODER_LIST_END) {
    298         ALOGE("Invalid video encoder: %d", ve);
    299         return BAD_VALUE;
    300     }
    301 
    302     mVideoEncoder = ve;
    303 
    304     return OK;
    305 }
    306 
    307 status_t StagefrightRecorder::setVideoSize(int width, int height) {
    308     ALOGV("setVideoSize: %dx%d", width, height);
    309     if (width <= 0 || height <= 0) {
    310         ALOGE("Invalid video size: %dx%d", width, height);
    311         return BAD_VALUE;
    312     }
    313 
    314     // Additional check on the dimension will be performed later
    315     mVideoWidth = width;
    316     mVideoHeight = height;
    317 
    318     return OK;
    319 }
    320 
    321 status_t StagefrightRecorder::setVideoFrameRate(int frames_per_second) {
    322     ALOGV("setVideoFrameRate: %d", frames_per_second);
    323     if ((frames_per_second <= 0 && frames_per_second != -1) ||
    324         frames_per_second > kMaxHighSpeedFps) {
    325         ALOGE("Invalid video frame rate: %d", frames_per_second);
    326         return BAD_VALUE;
    327     }
    328 
    329     // Additional check on the frame rate will be performed later
    330     mFrameRate = frames_per_second;
    331 
    332     return OK;
    333 }
    334 
    335 status_t StagefrightRecorder::setCamera(const sp<hardware::ICamera> &camera,
    336                                         const sp<ICameraRecordingProxy> &proxy) {
    337     ALOGV("setCamera");
    338     if (camera == 0) {
    339         ALOGE("camera is NULL");
    340         return BAD_VALUE;
    341     }
    342     if (proxy == 0) {
    343         ALOGE("camera proxy is NULL");
    344         return BAD_VALUE;
    345     }
    346 
    347     mCamera = camera;
    348     mCameraProxy = proxy;
    349     return OK;
    350 }
    351 
    352 status_t StagefrightRecorder::setPreviewSurface(const sp<IGraphicBufferProducer> &surface) {
    353     ALOGV("setPreviewSurface: %p", surface.get());
    354     mPreviewSurface = surface;
    355 
    356     return OK;
    357 }
    358 
    359 status_t StagefrightRecorder::setInputSurface(
    360         const sp<PersistentSurface>& surface) {
    361     mPersistentSurface = surface;
    362 
    363     return OK;
    364 }
    365 
    366 status_t StagefrightRecorder::setOutputFile(int fd) {
    367     ALOGV("setOutputFile: %d", fd);
    368 
    369     if (fd < 0) {
    370         ALOGE("Invalid file descriptor: %d", fd);
    371         return -EBADF;
    372     }
    373 
    374     // start with a clean, empty file
    375     ftruncate(fd, 0);
    376 
    377     if (mOutputFd >= 0) {
    378         ::close(mOutputFd);
    379     }
    380     mOutputFd = dup(fd);
    381 
    382     return OK;
    383 }
    384 
    385 status_t StagefrightRecorder::setNextOutputFile(int fd) {
    386     Mutex::Autolock autolock(mLock);
    387     // Only support MPEG4
    388     if (mOutputFormat != OUTPUT_FORMAT_MPEG_4) {
    389         ALOGE("Only MP4 file format supports setting next output file");
    390         return INVALID_OPERATION;
    391     }
    392     ALOGV("setNextOutputFile: %d", fd);
    393 
    394     if (fd < 0) {
    395         ALOGE("Invalid file descriptor: %d", fd);
    396         return -EBADF;
    397     }
    398 
    399     // start with a clean, empty file
    400     ftruncate(fd, 0);
    401     int nextFd = dup(fd);
    402     if (mWriter == NULL) {
    403         ALOGE("setNextOutputFile failed. Writer has been freed");
    404         return INVALID_OPERATION;
    405     }
    406     return mWriter->setNextFd(nextFd);
    407 }
    408 
    409 // Attempt to parse an float literal optionally surrounded by whitespace,
    410 // returns true on success, false otherwise.
    411 static bool safe_strtod(const char *s, double *val) {
    412     char *end;
    413 
    414     // It is lame, but according to man page, we have to set errno to 0
    415     // before calling strtod().
    416     errno = 0;
    417     *val = strtod(s, &end);
    418 
    419     if (end == s || errno == ERANGE) {
    420         return false;
    421     }
    422 
    423     // Skip trailing whitespace
    424     while (isspace(*end)) {
    425         ++end;
    426     }
    427 
    428     // For a successful return, the string must contain nothing but a valid
    429     // float literal optionally surrounded by whitespace.
    430 
    431     return *end == '\0';
    432 }
    433 
    434 // Attempt to parse an int64 literal optionally surrounded by whitespace,
    435 // returns true on success, false otherwise.
    436 static bool safe_strtoi64(const char *s, int64_t *val) {
    437     char *end;
    438 
    439     // It is lame, but according to man page, we have to set errno to 0
    440     // before calling strtoll().
    441     errno = 0;
    442     *val = strtoll(s, &end, 10);
    443 
    444     if (end == s || errno == ERANGE) {
    445         return false;
    446     }
    447 
    448     // Skip trailing whitespace
    449     while (isspace(*end)) {
    450         ++end;
    451     }
    452 
    453     // For a successful return, the string must contain nothing but a valid
    454     // int64 literal optionally surrounded by whitespace.
    455 
    456     return *end == '\0';
    457 }
    458 
    459 // Return true if the value is in [0, 0x007FFFFFFF]
    460 static bool safe_strtoi32(const char *s, int32_t *val) {
    461     int64_t temp;
    462     if (safe_strtoi64(s, &temp)) {
    463         if (temp >= 0 && temp <= 0x007FFFFFFF) {
    464             *val = static_cast<int32_t>(temp);
    465             return true;
    466         }
    467     }
    468     return false;
    469 }
    470 
    471 // Trim both leading and trailing whitespace from the given string.
    472 static void TrimString(String8 *s) {
    473     size_t num_bytes = s->bytes();
    474     const char *data = s->string();
    475 
    476     size_t leading_space = 0;
    477     while (leading_space < num_bytes && isspace(data[leading_space])) {
    478         ++leading_space;
    479     }
    480 
    481     size_t i = num_bytes;
    482     while (i > leading_space && isspace(data[i - 1])) {
    483         --i;
    484     }
    485 
    486     s->setTo(String8(&data[leading_space], i - leading_space));
    487 }
    488 
    489 status_t StagefrightRecorder::setParamAudioSamplingRate(int32_t sampleRate) {
    490     ALOGV("setParamAudioSamplingRate: %d", sampleRate);
    491     if (sampleRate <= 0) {
    492         ALOGE("Invalid audio sampling rate: %d", sampleRate);
    493         return BAD_VALUE;
    494     }
    495 
    496     // Additional check on the sample rate will be performed later.
    497     mSampleRate = sampleRate;
    498 
    499     return OK;
    500 }
    501 
    502 status_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) {
    503     ALOGV("setParamAudioNumberOfChannels: %d", channels);
    504     if (channels <= 0 || channels >= 3) {
    505         ALOGE("Invalid number of audio channels: %d", channels);
    506         return BAD_VALUE;
    507     }
    508 
    509     // Additional check on the number of channels will be performed later.
    510     mAudioChannels = channels;
    511 
    512     return OK;
    513 }
    514 
    515 status_t StagefrightRecorder::setParamAudioEncodingBitRate(int32_t bitRate) {
    516     ALOGV("setParamAudioEncodingBitRate: %d", bitRate);
    517     if (bitRate <= 0) {
    518         ALOGE("Invalid audio encoding bit rate: %d", bitRate);
    519         return BAD_VALUE;
    520     }
    521 
    522     // The target bit rate may not be exactly the same as the requested.
    523     // It depends on many factors, such as rate control, and the bit rate
    524     // range that a specific encoder supports. The mismatch between the
    525     // the target and requested bit rate will NOT be treated as an error.
    526     mAudioBitRate = bitRate;
    527     return OK;
    528 }
    529 
    530 status_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) {
    531     ALOGV("setParamVideoEncodingBitRate: %d", bitRate);
    532     if (bitRate <= 0) {
    533         ALOGE("Invalid video encoding bit rate: %d", bitRate);
    534         return BAD_VALUE;
    535     }
    536 
    537     // The target bit rate may not be exactly the same as the requested.
    538     // It depends on many factors, such as rate control, and the bit rate
    539     // range that a specific encoder supports. The mismatch between the
    540     // the target and requested bit rate will NOT be treated as an error.
    541     mVideoBitRate = bitRate;
    542     return OK;
    543 }
    544 
    545 // Always rotate clockwise, and only support 0, 90, 180 and 270 for now.
    546 status_t StagefrightRecorder::setParamVideoRotation(int32_t degrees) {
    547     ALOGV("setParamVideoRotation: %d", degrees);
    548     if (degrees < 0 || degrees % 90 != 0) {
    549         ALOGE("Unsupported video rotation angle: %d", degrees);
    550         return BAD_VALUE;
    551     }
    552     mRotationDegrees = degrees % 360;
    553     return OK;
    554 }
    555 
    556 status_t StagefrightRecorder::setParamMaxFileDurationUs(int64_t timeUs) {
    557     ALOGV("setParamMaxFileDurationUs: %lld us", (long long)timeUs);
    558 
    559     // This is meant for backward compatibility for MediaRecorder.java
    560     if (timeUs <= 0) {
    561         ALOGW("Max file duration is not positive: %lld us. Disabling duration limit.",
    562                 (long long)timeUs);
    563         timeUs = 0; // Disable the duration limit for zero or negative values.
    564     } else if (timeUs <= 100000LL) {  // XXX: 100 milli-seconds
    565         ALOGE("Max file duration is too short: %lld us", (long long)timeUs);
    566         return BAD_VALUE;
    567     }
    568 
    569     if (timeUs <= 15 * 1000000LL) {
    570         ALOGW("Target duration (%lld us) too short to be respected", (long long)timeUs);
    571     }
    572     mMaxFileDurationUs = timeUs;
    573     return OK;
    574 }
    575 
    576 status_t StagefrightRecorder::setParamMaxFileSizeBytes(int64_t bytes) {
    577     ALOGV("setParamMaxFileSizeBytes: %lld bytes", (long long)bytes);
    578 
    579     // This is meant for backward compatibility for MediaRecorder.java
    580     if (bytes <= 0) {
    581         ALOGW("Max file size is not positive: %lld bytes. "
    582              "Disabling file size limit.", (long long)bytes);
    583         bytes = 0; // Disable the file size limit for zero or negative values.
    584     } else if (bytes <= 1024) {  // XXX: 1 kB
    585         ALOGE("Max file size is too small: %lld bytes", (long long)bytes);
    586         return BAD_VALUE;
    587     }
    588 
    589     if (bytes <= 100 * 1024) {
    590         ALOGW("Target file size (%lld bytes) is too small to be respected", (long long)bytes);
    591     }
    592 
    593     mMaxFileSizeBytes = bytes;
    594     return OK;
    595 }
    596 
    597 status_t StagefrightRecorder::setParamInterleaveDuration(int32_t durationUs) {
    598     ALOGV("setParamInterleaveDuration: %d", durationUs);
    599     if (durationUs <= 500000) {           //  500 ms
    600         // If interleave duration is too small, it is very inefficient to do
    601         // interleaving since the metadata overhead will count for a significant
    602         // portion of the saved contents
    603         ALOGE("Audio/video interleave duration is too small: %d us", durationUs);
    604         return BAD_VALUE;
    605     } else if (durationUs >= 10000000) {  // 10 seconds
    606         // If interleaving duration is too large, it can cause the recording
    607         // session to use too much memory since we have to save the output
    608         // data before we write them out
    609         ALOGE("Audio/video interleave duration is too large: %d us", durationUs);
    610         return BAD_VALUE;
    611     }
    612     mInterleaveDurationUs = durationUs;
    613     return OK;
    614 }
    615 
    616 // If seconds <  0, only the first frame is I frame, and rest are all P frames
    617 // If seconds == 0, all frames are encoded as I frames. No P frames
    618 // If seconds >  0, it is the time spacing (seconds) between 2 neighboring I frames
    619 status_t StagefrightRecorder::setParamVideoIFramesInterval(int32_t seconds) {
    620     ALOGV("setParamVideoIFramesInterval: %d seconds", seconds);
    621     mIFramesIntervalSec = seconds;
    622     return OK;
    623 }
    624 
    625 status_t StagefrightRecorder::setParam64BitFileOffset(bool use64Bit) {
    626     ALOGV("setParam64BitFileOffset: %s",
    627         use64Bit? "use 64 bit file offset": "use 32 bit file offset");
    628     mUse64BitFileOffset = use64Bit;
    629     return OK;
    630 }
    631 
    632 status_t StagefrightRecorder::setParamVideoCameraId(int32_t cameraId) {
    633     ALOGV("setParamVideoCameraId: %d", cameraId);
    634     if (cameraId < 0) {
    635         return BAD_VALUE;
    636     }
    637     mCameraId = cameraId;
    638     return OK;
    639 }
    640 
    641 status_t StagefrightRecorder::setParamTrackTimeStatus(int64_t timeDurationUs) {
    642     ALOGV("setParamTrackTimeStatus: %lld", (long long)timeDurationUs);
    643     if (timeDurationUs < 20000) {  // Infeasible if shorter than 20 ms?
    644         ALOGE("Tracking time duration too short: %lld us", (long long)timeDurationUs);
    645         return BAD_VALUE;
    646     }
    647     mTrackEveryTimeDurationUs = timeDurationUs;
    648     return OK;
    649 }
    650 
    651 status_t StagefrightRecorder::setParamVideoEncoderProfile(int32_t profile) {
    652     ALOGV("setParamVideoEncoderProfile: %d", profile);
    653 
    654     // Additional check will be done later when we load the encoder.
    655     // For now, we are accepting values defined in OpenMAX IL.
    656     mVideoEncoderProfile = profile;
    657     return OK;
    658 }
    659 
    660 status_t StagefrightRecorder::setParamVideoEncoderLevel(int32_t level) {
    661     ALOGV("setParamVideoEncoderLevel: %d", level);
    662 
    663     // Additional check will be done later when we load the encoder.
    664     // For now, we are accepting values defined in OpenMAX IL.
    665     mVideoEncoderLevel = level;
    666     return OK;
    667 }
    668 
    669 status_t StagefrightRecorder::setParamMovieTimeScale(int32_t timeScale) {
    670     ALOGV("setParamMovieTimeScale: %d", timeScale);
    671 
    672     // The range is set to be the same as the audio's time scale range
    673     // since audio's time scale has a wider range.
    674     if (timeScale < 600 || timeScale > 96000) {
    675         ALOGE("Time scale (%d) for movie is out of range [600, 96000]", timeScale);
    676         return BAD_VALUE;
    677     }
    678     mMovieTimeScale = timeScale;
    679     return OK;
    680 }
    681 
    682 status_t StagefrightRecorder::setParamVideoTimeScale(int32_t timeScale) {
    683     ALOGV("setParamVideoTimeScale: %d", timeScale);
    684 
    685     // 60000 is chosen to make sure that each video frame from a 60-fps
    686     // video has 1000 ticks.
    687     if (timeScale < 600 || timeScale > 60000) {
    688         ALOGE("Time scale (%d) for video is out of range [600, 60000]", timeScale);
    689         return BAD_VALUE;
    690     }
    691     mVideoTimeScale = timeScale;
    692     return OK;
    693 }
    694 
    695 status_t StagefrightRecorder::setParamAudioTimeScale(int32_t timeScale) {
    696     ALOGV("setParamAudioTimeScale: %d", timeScale);
    697 
    698     // 96000 Hz is the highest sampling rate support in AAC.
    699     if (timeScale < 600 || timeScale > 96000) {
    700         ALOGE("Time scale (%d) for audio is out of range [600, 96000]", timeScale);
    701         return BAD_VALUE;
    702     }
    703     mAudioTimeScale = timeScale;
    704     return OK;
    705 }
    706 
    707 status_t StagefrightRecorder::setParamCaptureFpsEnable(int32_t captureFpsEnable) {
    708     ALOGV("setParamCaptureFpsEnable: %d", captureFpsEnable);
    709 
    710     if(captureFpsEnable == 0) {
    711         mCaptureFpsEnable = false;
    712     } else if (captureFpsEnable == 1) {
    713         mCaptureFpsEnable = true;
    714     } else {
    715         return BAD_VALUE;
    716     }
    717     return OK;
    718 }
    719 
    720 status_t StagefrightRecorder::setParamCaptureFps(double fps) {
    721     ALOGV("setParamCaptureFps: %.2f", fps);
    722 
    723     if (!(fps >= 1.0 / 86400)) {
    724         ALOGE("FPS is too small");
    725         return BAD_VALUE;
    726     }
    727     mCaptureFps = fps;
    728     return OK;
    729 }
    730 
    731 status_t StagefrightRecorder::setParamGeoDataLongitude(
    732     int64_t longitudex10000) {
    733 
    734     if (longitudex10000 > 1800000 || longitudex10000 < -1800000) {
    735         return BAD_VALUE;
    736     }
    737     mLongitudex10000 = longitudex10000;
    738     return OK;
    739 }
    740 
    741 status_t StagefrightRecorder::setParamGeoDataLatitude(
    742     int64_t latitudex10000) {
    743 
    744     if (latitudex10000 > 900000 || latitudex10000 < -900000) {
    745         return BAD_VALUE;
    746     }
    747     mLatitudex10000 = latitudex10000;
    748     return OK;
    749 }
    750 
    751 status_t StagefrightRecorder::setParameter(
    752         const String8 &key, const String8 &value) {
    753     ALOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
    754     if (key == "max-duration") {
    755         int64_t max_duration_ms;
    756         if (safe_strtoi64(value.string(), &max_duration_ms)) {
    757             return setParamMaxFileDurationUs(1000LL * max_duration_ms);
    758         }
    759     } else if (key == "max-filesize") {
    760         int64_t max_filesize_bytes;
    761         if (safe_strtoi64(value.string(), &max_filesize_bytes)) {
    762             return setParamMaxFileSizeBytes(max_filesize_bytes);
    763         }
    764     } else if (key == "interleave-duration-us") {
    765         int32_t durationUs;
    766         if (safe_strtoi32(value.string(), &durationUs)) {
    767             return setParamInterleaveDuration(durationUs);
    768         }
    769     } else if (key == "param-movie-time-scale") {
    770         int32_t timeScale;
    771         if (safe_strtoi32(value.string(), &timeScale)) {
    772             return setParamMovieTimeScale(timeScale);
    773         }
    774     } else if (key == "param-use-64bit-offset") {
    775         int32_t use64BitOffset;
    776         if (safe_strtoi32(value.string(), &use64BitOffset)) {
    777             return setParam64BitFileOffset(use64BitOffset != 0);
    778         }
    779     } else if (key == "param-geotag-longitude") {
    780         int64_t longitudex10000;
    781         if (safe_strtoi64(value.string(), &longitudex10000)) {
    782             return setParamGeoDataLongitude(longitudex10000);
    783         }
    784     } else if (key == "param-geotag-latitude") {
    785         int64_t latitudex10000;
    786         if (safe_strtoi64(value.string(), &latitudex10000)) {
    787             return setParamGeoDataLatitude(latitudex10000);
    788         }
    789     } else if (key == "param-track-time-status") {
    790         int64_t timeDurationUs;
    791         if (safe_strtoi64(value.string(), &timeDurationUs)) {
    792             return setParamTrackTimeStatus(timeDurationUs);
    793         }
    794     } else if (key == "audio-param-sampling-rate") {
    795         int32_t sampling_rate;
    796         if (safe_strtoi32(value.string(), &sampling_rate)) {
    797             return setParamAudioSamplingRate(sampling_rate);
    798         }
    799     } else if (key == "audio-param-number-of-channels") {
    800         int32_t number_of_channels;
    801         if (safe_strtoi32(value.string(), &number_of_channels)) {
    802             return setParamAudioNumberOfChannels(number_of_channels);
    803         }
    804     } else if (key == "audio-param-encoding-bitrate") {
    805         int32_t audio_bitrate;
    806         if (safe_strtoi32(value.string(), &audio_bitrate)) {
    807             return setParamAudioEncodingBitRate(audio_bitrate);
    808         }
    809     } else if (key == "audio-param-time-scale") {
    810         int32_t timeScale;
    811         if (safe_strtoi32(value.string(), &timeScale)) {
    812             return setParamAudioTimeScale(timeScale);
    813         }
    814     } else if (key == "video-param-encoding-bitrate") {
    815         int32_t video_bitrate;
    816         if (safe_strtoi32(value.string(), &video_bitrate)) {
    817             return setParamVideoEncodingBitRate(video_bitrate);
    818         }
    819     } else if (key == "video-param-rotation-angle-degrees") {
    820         int32_t degrees;
    821         if (safe_strtoi32(value.string(), &degrees)) {
    822             return setParamVideoRotation(degrees);
    823         }
    824     } else if (key == "video-param-i-frames-interval") {
    825         int32_t seconds;
    826         if (safe_strtoi32(value.string(), &seconds)) {
    827             return setParamVideoIFramesInterval(seconds);
    828         }
    829     } else if (key == "video-param-encoder-profile") {
    830         int32_t profile;
    831         if (safe_strtoi32(value.string(), &profile)) {
    832             return setParamVideoEncoderProfile(profile);
    833         }
    834     } else if (key == "video-param-encoder-level") {
    835         int32_t level;
    836         if (safe_strtoi32(value.string(), &level)) {
    837             return setParamVideoEncoderLevel(level);
    838         }
    839     } else if (key == "video-param-camera-id") {
    840         int32_t cameraId;
    841         if (safe_strtoi32(value.string(), &cameraId)) {
    842             return setParamVideoCameraId(cameraId);
    843         }
    844     } else if (key == "video-param-time-scale") {
    845         int32_t timeScale;
    846         if (safe_strtoi32(value.string(), &timeScale)) {
    847             return setParamVideoTimeScale(timeScale);
    848         }
    849     } else if (key == "time-lapse-enable") {
    850         int32_t captureFpsEnable;
    851         if (safe_strtoi32(value.string(), &captureFpsEnable)) {
    852             return setParamCaptureFpsEnable(captureFpsEnable);
    853         }
    854     } else if (key == "time-lapse-fps") {
    855         double fps;
    856         if (safe_strtod(value.string(), &fps)) {
    857             return setParamCaptureFps(fps);
    858         }
    859     } else {
    860         ALOGE("setParameter: failed to find key %s", key.string());
    861     }
    862     return BAD_VALUE;
    863 }
    864 
    865 status_t StagefrightRecorder::setParameters(const String8 &params) {
    866     ALOGV("setParameters: %s", params.string());
    867     const char *cparams = params.string();
    868     const char *key_start = cparams;
    869     for (;;) {
    870         const char *equal_pos = strchr(key_start, '=');
    871         if (equal_pos == NULL) {
    872             ALOGE("Parameters %s miss a value", cparams);
    873             return BAD_VALUE;
    874         }
    875         String8 key(key_start, equal_pos - key_start);
    876         TrimString(&key);
    877         if (key.length() == 0) {
    878             ALOGE("Parameters %s contains an empty key", cparams);
    879             return BAD_VALUE;
    880         }
    881         const char *value_start = equal_pos + 1;
    882         const char *semicolon_pos = strchr(value_start, ';');
    883         String8 value;
    884         if (semicolon_pos == NULL) {
    885             value.setTo(value_start);
    886         } else {
    887             value.setTo(value_start, semicolon_pos - value_start);
    888         }
    889         if (setParameter(key, value) != OK) {
    890             return BAD_VALUE;
    891         }
    892         if (semicolon_pos == NULL) {
    893             break;  // Reaches the end
    894         }
    895         key_start = semicolon_pos + 1;
    896     }
    897     return OK;
    898 }
    899 
    900 status_t StagefrightRecorder::setListener(const sp<IMediaRecorderClient> &listener) {
    901     mListener = listener;
    902 
    903     return OK;
    904 }
    905 
    906 status_t StagefrightRecorder::setClientName(const String16& clientName) {
    907     mClientName = clientName;
    908 
    909     return OK;
    910 }
    911 
    912 status_t StagefrightRecorder::prepareInternal() {
    913     ALOGV("prepare");
    914     if (mOutputFd < 0) {
    915         ALOGE("Output file descriptor is invalid");
    916         return INVALID_OPERATION;
    917     }
    918 
    919     // Get UID and PID here for permission checking
    920     mClientUid = IPCThreadState::self()->getCallingUid();
    921     mClientPid = IPCThreadState::self()->getCallingPid();
    922 
    923     status_t status = OK;
    924 
    925     switch (mOutputFormat) {
    926         case OUTPUT_FORMAT_DEFAULT:
    927         case OUTPUT_FORMAT_THREE_GPP:
    928         case OUTPUT_FORMAT_MPEG_4:
    929         case OUTPUT_FORMAT_WEBM:
    930             status = setupMPEG4orWEBMRecording();
    931             break;
    932 
    933         case OUTPUT_FORMAT_AMR_NB:
    934         case OUTPUT_FORMAT_AMR_WB:
    935             status = setupAMRRecording();
    936             break;
    937 
    938         case OUTPUT_FORMAT_AAC_ADIF:
    939         case OUTPUT_FORMAT_AAC_ADTS:
    940             status = setupAACRecording();
    941             break;
    942 
    943         case OUTPUT_FORMAT_RTP_AVP:
    944             status = setupRTPRecording();
    945             break;
    946 
    947         case OUTPUT_FORMAT_MPEG2TS:
    948             status = setupMPEG2TSRecording();
    949             break;
    950 
    951         default:
    952             ALOGE("Unsupported output file format: %d", mOutputFormat);
    953             status = UNKNOWN_ERROR;
    954             break;
    955     }
    956 
    957     ALOGV("Recording frameRate: %d captureFps: %f",
    958             mFrameRate, mCaptureFps);
    959 
    960     return status;
    961 }
    962 
    963 status_t StagefrightRecorder::prepare() {
    964     ALOGV("prepare");
    965     Mutex::Autolock autolock(mLock);
    966     if (mVideoSource == VIDEO_SOURCE_SURFACE) {
    967         return prepareInternal();
    968     }
    969     return OK;
    970 }
    971 
    972 status_t StagefrightRecorder::start() {
    973     ALOGV("start");
    974     Mutex::Autolock autolock(mLock);
    975     if (mOutputFd < 0) {
    976         ALOGE("Output file descriptor is invalid");
    977         return INVALID_OPERATION;
    978     }
    979 
    980     status_t status = OK;
    981 
    982     if (mVideoSource != VIDEO_SOURCE_SURFACE) {
    983         status = prepareInternal();
    984         if (status != OK) {
    985             return status;
    986         }
    987     }
    988 
    989     if (mWriter == NULL) {
    990         ALOGE("File writer is not avaialble");
    991         return UNKNOWN_ERROR;
    992     }
    993 
    994     switch (mOutputFormat) {
    995         case OUTPUT_FORMAT_DEFAULT:
    996         case OUTPUT_FORMAT_THREE_GPP:
    997         case OUTPUT_FORMAT_MPEG_4:
    998         case OUTPUT_FORMAT_WEBM:
    999         {
   1000             bool isMPEG4 = true;
   1001             if (mOutputFormat == OUTPUT_FORMAT_WEBM) {
   1002                 isMPEG4 = false;
   1003             }
   1004             sp<MetaData> meta = new MetaData;
   1005             setupMPEG4orWEBMMetaData(&meta);
   1006             status = mWriter->start(meta.get());
   1007             break;
   1008         }
   1009 
   1010         case OUTPUT_FORMAT_AMR_NB:
   1011         case OUTPUT_FORMAT_AMR_WB:
   1012         case OUTPUT_FORMAT_AAC_ADIF:
   1013         case OUTPUT_FORMAT_AAC_ADTS:
   1014         case OUTPUT_FORMAT_RTP_AVP:
   1015         case OUTPUT_FORMAT_MPEG2TS:
   1016         {
   1017             sp<MetaData> meta = new MetaData;
   1018             int64_t startTimeUs = systemTime() / 1000;
   1019             meta->setInt64(kKeyTime, startTimeUs);
   1020             status = mWriter->start(meta.get());
   1021             break;
   1022         }
   1023 
   1024         default:
   1025         {
   1026             ALOGE("Unsupported output file format: %d", mOutputFormat);
   1027             status = UNKNOWN_ERROR;
   1028             break;
   1029         }
   1030     }
   1031 
   1032     if (status != OK) {
   1033         mWriter.clear();
   1034         mWriter = NULL;
   1035     }
   1036 
   1037     if ((status == OK) && (!mStarted)) {
   1038         mAnalyticsDirty = true;
   1039         mStarted = true;
   1040 
   1041         mStartedRecordingUs = systemTime() / 1000;
   1042 
   1043         uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted;
   1044         if (mAudioSource != AUDIO_SOURCE_CNT) {
   1045             params |= IMediaPlayerService::kBatteryDataTrackAudio;
   1046         }
   1047         if (mVideoSource != VIDEO_SOURCE_LIST_END) {
   1048             params |= IMediaPlayerService::kBatteryDataTrackVideo;
   1049         }
   1050 
   1051         addBatteryData(params);
   1052     }
   1053 
   1054     return status;
   1055 }
   1056 
   1057 sp<MediaCodecSource> StagefrightRecorder::createAudioSource() {
   1058     int32_t sourceSampleRate = mSampleRate;
   1059 
   1060     if (mCaptureFpsEnable && mCaptureFps >= mFrameRate) {
   1061         // Upscale the sample rate for slow motion recording.
   1062         // Fail audio source creation if source sample rate is too high, as it could
   1063         // cause out-of-memory due to large input buffer size. And audio recording
   1064         // probably doesn't make sense in the scenario, since the slow-down factor
   1065         // is probably huge (eg. mSampleRate=48K, mCaptureFps=240, mFrameRate=1).
   1066         const static int32_t SAMPLE_RATE_HZ_MAX = 192000;
   1067         sourceSampleRate =
   1068                 (mSampleRate * mCaptureFps + mFrameRate / 2) / mFrameRate;
   1069         if (sourceSampleRate < mSampleRate || sourceSampleRate > SAMPLE_RATE_HZ_MAX) {
   1070             ALOGE("source sample rate out of range! "
   1071                     "(mSampleRate %d, mCaptureFps %.2f, mFrameRate %d",
   1072                     mSampleRate, mCaptureFps, mFrameRate);
   1073             return NULL;
   1074         }
   1075     }
   1076 
   1077     sp<AudioSource> audioSource =
   1078         new AudioSource(
   1079                 mAudioSource,
   1080                 mOpPackageName,
   1081                 sourceSampleRate,
   1082                 mAudioChannels,
   1083                 mSampleRate,
   1084                 mClientUid,
   1085                 mClientPid,
   1086                 mSelectedDeviceId);
   1087 
   1088     status_t err = audioSource->initCheck();
   1089 
   1090     if (err != OK) {
   1091         ALOGE("audio source is not initialized");
   1092         return NULL;
   1093     }
   1094 
   1095     sp<AMessage> format = new AMessage;
   1096     switch (mAudioEncoder) {
   1097         case AUDIO_ENCODER_AMR_NB:
   1098         case AUDIO_ENCODER_DEFAULT:
   1099             format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
   1100             break;
   1101         case AUDIO_ENCODER_AMR_WB:
   1102             format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
   1103             break;
   1104         case AUDIO_ENCODER_AAC:
   1105             format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
   1106             format->setInt32("aac-profile", OMX_AUDIO_AACObjectLC);
   1107             break;
   1108         case AUDIO_ENCODER_HE_AAC:
   1109             format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
   1110             format->setInt32("aac-profile", OMX_AUDIO_AACObjectHE);
   1111             break;
   1112         case AUDIO_ENCODER_AAC_ELD:
   1113             format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
   1114             format->setInt32("aac-profile", OMX_AUDIO_AACObjectELD);
   1115             break;
   1116 
   1117         default:
   1118             ALOGE("Unknown audio encoder: %d", mAudioEncoder);
   1119             return NULL;
   1120     }
   1121 
   1122     // log audio mime type for media metrics
   1123     if (mAnalyticsItem != NULL) {
   1124         AString audiomime;
   1125         if (format->findString("mime", &audiomime)) {
   1126             mAnalyticsItem->setCString(kRecorderAudioMime, audiomime.c_str());
   1127         }
   1128     }
   1129 
   1130     int32_t maxInputSize;
   1131     CHECK(audioSource->getFormat()->findInt32(
   1132                 kKeyMaxInputSize, &maxInputSize));
   1133 
   1134     format->setInt32("max-input-size", maxInputSize);
   1135     format->setInt32("channel-count", mAudioChannels);
   1136     format->setInt32("sample-rate", mSampleRate);
   1137     format->setInt32("bitrate", mAudioBitRate);
   1138     if (mAudioTimeScale > 0) {
   1139         format->setInt32("time-scale", mAudioTimeScale);
   1140     }
   1141     format->setInt32("priority", 0 /* realtime */);
   1142 
   1143     sp<MediaCodecSource> audioEncoder =
   1144             MediaCodecSource::Create(mLooper, format, audioSource);
   1145     sp<AudioSystem::AudioDeviceCallback> callback = mAudioDeviceCallback.promote();
   1146     if (mDeviceCallbackEnabled && callback != 0) {
   1147         audioSource->addAudioDeviceCallback(callback);
   1148     }
   1149     mAudioSourceNode = audioSource;
   1150 
   1151     if (audioEncoder == NULL) {
   1152         ALOGE("Failed to create audio encoder");
   1153     }
   1154 
   1155     return audioEncoder;
   1156 }
   1157 
   1158 status_t StagefrightRecorder::setupAACRecording() {
   1159     // FIXME:
   1160     // Add support for OUTPUT_FORMAT_AAC_ADIF
   1161     CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_AAC_ADTS);
   1162 
   1163     CHECK(mAudioEncoder == AUDIO_ENCODER_AAC ||
   1164           mAudioEncoder == AUDIO_ENCODER_HE_AAC ||
   1165           mAudioEncoder == AUDIO_ENCODER_AAC_ELD);
   1166     CHECK(mAudioSource != AUDIO_SOURCE_CNT);
   1167 
   1168     mWriter = new AACWriter(mOutputFd);
   1169     return setupRawAudioRecording();
   1170 }
   1171 
   1172 status_t StagefrightRecorder::setupAMRRecording() {
   1173     CHECK(mOutputFormat == OUTPUT_FORMAT_AMR_NB ||
   1174           mOutputFormat == OUTPUT_FORMAT_AMR_WB);
   1175 
   1176     if (mOutputFormat == OUTPUT_FORMAT_AMR_NB) {
   1177         if (mAudioEncoder != AUDIO_ENCODER_DEFAULT &&
   1178             mAudioEncoder != AUDIO_ENCODER_AMR_NB) {
   1179             ALOGE("Invalid encoder %d used for AMRNB recording",
   1180                     mAudioEncoder);
   1181             return BAD_VALUE;
   1182         }
   1183     } else {  // mOutputFormat must be OUTPUT_FORMAT_AMR_WB
   1184         if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
   1185             ALOGE("Invlaid encoder %d used for AMRWB recording",
   1186                     mAudioEncoder);
   1187             return BAD_VALUE;
   1188         }
   1189     }
   1190 
   1191     mWriter = new AMRWriter(mOutputFd);
   1192     return setupRawAudioRecording();
   1193 }
   1194 
   1195 status_t StagefrightRecorder::setupRawAudioRecording() {
   1196     if (mAudioSource >= AUDIO_SOURCE_CNT && mAudioSource != AUDIO_SOURCE_FM_TUNER) {
   1197         ALOGE("Invalid audio source: %d", mAudioSource);
   1198         return BAD_VALUE;
   1199     }
   1200 
   1201     status_t status = BAD_VALUE;
   1202     if (OK != (status = checkAudioEncoderCapabilities())) {
   1203         return status;
   1204     }
   1205 
   1206     sp<MediaCodecSource> audioEncoder = createAudioSource();
   1207     if (audioEncoder == NULL) {
   1208         return UNKNOWN_ERROR;
   1209     }
   1210 
   1211     CHECK(mWriter != 0);
   1212     mWriter->addSource(audioEncoder);
   1213     mAudioEncoderSource = audioEncoder;
   1214 
   1215     if (mMaxFileDurationUs != 0) {
   1216         mWriter->setMaxFileDuration(mMaxFileDurationUs);
   1217     }
   1218     if (mMaxFileSizeBytes != 0) {
   1219         mWriter->setMaxFileSize(mMaxFileSizeBytes);
   1220     }
   1221     mWriter->setListener(mListener);
   1222 
   1223     return OK;
   1224 }
   1225 
   1226 status_t StagefrightRecorder::setupRTPRecording() {
   1227     CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_RTP_AVP);
   1228 
   1229     if ((mAudioSource != AUDIO_SOURCE_CNT
   1230                 && mVideoSource != VIDEO_SOURCE_LIST_END)
   1231             || (mAudioSource == AUDIO_SOURCE_CNT
   1232                 && mVideoSource == VIDEO_SOURCE_LIST_END)) {
   1233         // Must have exactly one source.
   1234         return BAD_VALUE;
   1235     }
   1236 
   1237     if (mOutputFd < 0) {
   1238         return BAD_VALUE;
   1239     }
   1240 
   1241     sp<MediaCodecSource> source;
   1242 
   1243     if (mAudioSource != AUDIO_SOURCE_CNT) {
   1244         source = createAudioSource();
   1245         mAudioEncoderSource = source;
   1246     } else {
   1247         setDefaultVideoEncoderIfNecessary();
   1248 
   1249         sp<MediaSource> mediaSource;
   1250         status_t err = setupMediaSource(&mediaSource);
   1251         if (err != OK) {
   1252             return err;
   1253         }
   1254 
   1255         err = setupVideoEncoder(mediaSource, &source);
   1256         if (err != OK) {
   1257             return err;
   1258         }
   1259         mVideoEncoderSource = source;
   1260     }
   1261 
   1262     mWriter = new ARTPWriter(mOutputFd);
   1263     mWriter->addSource(source);
   1264     mWriter->setListener(mListener);
   1265 
   1266     return OK;
   1267 }
   1268 
   1269 status_t StagefrightRecorder::setupMPEG2TSRecording() {
   1270     CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_MPEG2TS);
   1271 
   1272     sp<MediaWriter> writer = new MPEG2TSWriter(mOutputFd);
   1273 
   1274     if (mAudioSource != AUDIO_SOURCE_CNT) {
   1275         if (mAudioEncoder != AUDIO_ENCODER_AAC &&
   1276             mAudioEncoder != AUDIO_ENCODER_HE_AAC &&
   1277             mAudioEncoder != AUDIO_ENCODER_AAC_ELD) {
   1278             return ERROR_UNSUPPORTED;
   1279         }
   1280 
   1281         status_t err = setupAudioEncoder(writer);
   1282 
   1283         if (err != OK) {
   1284             return err;
   1285         }
   1286     }
   1287 
   1288     if (mVideoSource < VIDEO_SOURCE_LIST_END) {
   1289         if (mVideoEncoder != VIDEO_ENCODER_H264) {
   1290             ALOGE("MPEG2TS recording only supports H.264 encoding!");
   1291             return ERROR_UNSUPPORTED;
   1292         }
   1293 
   1294         sp<MediaSource> mediaSource;
   1295         status_t err = setupMediaSource(&mediaSource);
   1296         if (err != OK) {
   1297             return err;
   1298         }
   1299 
   1300         sp<MediaCodecSource> encoder;
   1301         err = setupVideoEncoder(mediaSource, &encoder);
   1302 
   1303         if (err != OK) {
   1304             return err;
   1305         }
   1306 
   1307         writer->addSource(encoder);
   1308         mVideoEncoderSource = encoder;
   1309     }
   1310 
   1311     if (mMaxFileDurationUs != 0) {
   1312         writer->setMaxFileDuration(mMaxFileDurationUs);
   1313     }
   1314 
   1315     if (mMaxFileSizeBytes != 0) {
   1316         writer->setMaxFileSize(mMaxFileSizeBytes);
   1317     }
   1318 
   1319     mWriter = writer;
   1320 
   1321     return OK;
   1322 }
   1323 
   1324 void StagefrightRecorder::clipVideoFrameRate() {
   1325     ALOGV("clipVideoFrameRate: encoder %d", mVideoEncoder);
   1326     if (mFrameRate == -1) {
   1327         mFrameRate = mEncoderProfiles->getCamcorderProfileParamByName(
   1328                 "vid.fps", mCameraId, CAMCORDER_QUALITY_LOW);
   1329         ALOGW("Using default video fps %d", mFrameRate);
   1330     }
   1331 
   1332     int minFrameRate = mEncoderProfiles->getVideoEncoderParamByName(
   1333                         "enc.vid.fps.min", mVideoEncoder);
   1334     int maxFrameRate = mEncoderProfiles->getVideoEncoderParamByName(
   1335                         "enc.vid.fps.max", mVideoEncoder);
   1336     if (mFrameRate < minFrameRate && minFrameRate != -1) {
   1337         ALOGW("Intended video encoding frame rate (%d fps) is too small"
   1338              " and will be set to (%d fps)", mFrameRate, minFrameRate);
   1339         mFrameRate = minFrameRate;
   1340     } else if (mFrameRate > maxFrameRate && maxFrameRate != -1) {
   1341         ALOGW("Intended video encoding frame rate (%d fps) is too large"
   1342              " and will be set to (%d fps)", mFrameRate, maxFrameRate);
   1343         mFrameRate = maxFrameRate;
   1344     }
   1345 }
   1346 
   1347 void StagefrightRecorder::clipVideoBitRate() {
   1348     ALOGV("clipVideoBitRate: encoder %d", mVideoEncoder);
   1349     int minBitRate = mEncoderProfiles->getVideoEncoderParamByName(
   1350                         "enc.vid.bps.min", mVideoEncoder);
   1351     int maxBitRate = mEncoderProfiles->getVideoEncoderParamByName(
   1352                         "enc.vid.bps.max", mVideoEncoder);
   1353     if (mVideoBitRate < minBitRate && minBitRate != -1) {
   1354         ALOGW("Intended video encoding bit rate (%d bps) is too small"
   1355              " and will be set to (%d bps)", mVideoBitRate, minBitRate);
   1356         mVideoBitRate = minBitRate;
   1357     } else if (mVideoBitRate > maxBitRate && maxBitRate != -1) {
   1358         ALOGW("Intended video encoding bit rate (%d bps) is too large"
   1359              " and will be set to (%d bps)", mVideoBitRate, maxBitRate);
   1360         mVideoBitRate = maxBitRate;
   1361     }
   1362 }
   1363 
   1364 void StagefrightRecorder::clipVideoFrameWidth() {
   1365     ALOGV("clipVideoFrameWidth: encoder %d", mVideoEncoder);
   1366     int minFrameWidth = mEncoderProfiles->getVideoEncoderParamByName(
   1367                         "enc.vid.width.min", mVideoEncoder);
   1368     int maxFrameWidth = mEncoderProfiles->getVideoEncoderParamByName(
   1369                         "enc.vid.width.max", mVideoEncoder);
   1370     if (mVideoWidth < minFrameWidth && minFrameWidth != -1) {
   1371         ALOGW("Intended video encoding frame width (%d) is too small"
   1372              " and will be set to (%d)", mVideoWidth, minFrameWidth);
   1373         mVideoWidth = minFrameWidth;
   1374     } else if (mVideoWidth > maxFrameWidth && maxFrameWidth != -1) {
   1375         ALOGW("Intended video encoding frame width (%d) is too large"
   1376              " and will be set to (%d)", mVideoWidth, maxFrameWidth);
   1377         mVideoWidth = maxFrameWidth;
   1378     }
   1379 }
   1380 
   1381 status_t StagefrightRecorder::checkVideoEncoderCapabilities() {
   1382     if (!mCaptureFpsEnable) {
   1383         // Dont clip for time lapse capture as encoder will have enough
   1384         // time to encode because of slow capture rate of time lapse.
   1385         clipVideoBitRate();
   1386         clipVideoFrameRate();
   1387         clipVideoFrameWidth();
   1388         clipVideoFrameHeight();
   1389         setDefaultProfileIfNecessary();
   1390     }
   1391     return OK;
   1392 }
   1393 
   1394 // Set to use AVC baseline profile if the encoding parameters matches
   1395 // CAMCORDER_QUALITY_LOW profile; this is for the sake of MMS service.
   1396 void StagefrightRecorder::setDefaultProfileIfNecessary() {
   1397     ALOGV("setDefaultProfileIfNecessary");
   1398 
   1399     camcorder_quality quality = CAMCORDER_QUALITY_LOW;
   1400 
   1401     int64_t durationUs   = mEncoderProfiles->getCamcorderProfileParamByName(
   1402                                 "duration", mCameraId, quality) * 1000000LL;
   1403 
   1404     int fileFormat       = mEncoderProfiles->getCamcorderProfileParamByName(
   1405                                 "file.format", mCameraId, quality);
   1406 
   1407     int videoCodec       = mEncoderProfiles->getCamcorderProfileParamByName(
   1408                                 "vid.codec", mCameraId, quality);
   1409 
   1410     int videoBitRate     = mEncoderProfiles->getCamcorderProfileParamByName(
   1411                                 "vid.bps", mCameraId, quality);
   1412 
   1413     int videoFrameRate   = mEncoderProfiles->getCamcorderProfileParamByName(
   1414                                 "vid.fps", mCameraId, quality);
   1415 
   1416     int videoFrameWidth  = mEncoderProfiles->getCamcorderProfileParamByName(
   1417                                 "vid.width", mCameraId, quality);
   1418 
   1419     int videoFrameHeight = mEncoderProfiles->getCamcorderProfileParamByName(
   1420                                 "vid.height", mCameraId, quality);
   1421 
   1422     int audioCodec       = mEncoderProfiles->getCamcorderProfileParamByName(
   1423                                 "aud.codec", mCameraId, quality);
   1424 
   1425     int audioBitRate     = mEncoderProfiles->getCamcorderProfileParamByName(
   1426                                 "aud.bps", mCameraId, quality);
   1427 
   1428     int audioSampleRate  = mEncoderProfiles->getCamcorderProfileParamByName(
   1429                                 "aud.hz", mCameraId, quality);
   1430 
   1431     int audioChannels    = mEncoderProfiles->getCamcorderProfileParamByName(
   1432                                 "aud.ch", mCameraId, quality);
   1433 
   1434     if (durationUs == mMaxFileDurationUs &&
   1435         fileFormat == mOutputFormat &&
   1436         videoCodec == mVideoEncoder &&
   1437         videoBitRate == mVideoBitRate &&
   1438         videoFrameRate == mFrameRate &&
   1439         videoFrameWidth == mVideoWidth &&
   1440         videoFrameHeight == mVideoHeight &&
   1441         audioCodec == mAudioEncoder &&
   1442         audioBitRate == mAudioBitRate &&
   1443         audioSampleRate == mSampleRate &&
   1444         audioChannels == mAudioChannels) {
   1445         if (videoCodec == VIDEO_ENCODER_H264) {
   1446             ALOGI("Force to use AVC baseline profile");
   1447             setParamVideoEncoderProfile(OMX_VIDEO_AVCProfileBaseline);
   1448             // set 0 for invalid levels - this will be rejected by the
   1449             // codec if it cannot handle it during configure
   1450             setParamVideoEncoderLevel(ACodec::getAVCLevelFor(
   1451                     videoFrameWidth, videoFrameHeight, videoFrameRate, videoBitRate));
   1452         }
   1453     }
   1454 }
   1455 
   1456 void StagefrightRecorder::setDefaultVideoEncoderIfNecessary() {
   1457     if (mVideoEncoder == VIDEO_ENCODER_DEFAULT) {
   1458         if (mOutputFormat == OUTPUT_FORMAT_WEBM) {
   1459             // default to VP8 for WEBM recording
   1460             mVideoEncoder = VIDEO_ENCODER_VP8;
   1461         } else {
   1462             // pick the default encoder for CAMCORDER_QUALITY_LOW
   1463             int videoCodec = mEncoderProfiles->getCamcorderProfileParamByName(
   1464                     "vid.codec", mCameraId, CAMCORDER_QUALITY_LOW);
   1465 
   1466             if (videoCodec > VIDEO_ENCODER_DEFAULT &&
   1467                 videoCodec < VIDEO_ENCODER_LIST_END) {
   1468                 mVideoEncoder = (video_encoder)videoCodec;
   1469             } else {
   1470                 // default to H.264 if camcorder profile not available
   1471                 mVideoEncoder = VIDEO_ENCODER_H264;
   1472             }
   1473         }
   1474     }
   1475 }
   1476 
   1477 status_t StagefrightRecorder::checkAudioEncoderCapabilities() {
   1478     clipAudioBitRate();
   1479     clipAudioSampleRate();
   1480     clipNumberOfAudioChannels();
   1481     return OK;
   1482 }
   1483 
   1484 void StagefrightRecorder::clipAudioBitRate() {
   1485     ALOGV("clipAudioBitRate: encoder %d", mAudioEncoder);
   1486 
   1487     int minAudioBitRate =
   1488             mEncoderProfiles->getAudioEncoderParamByName(
   1489                 "enc.aud.bps.min", mAudioEncoder);
   1490     if (minAudioBitRate != -1 && mAudioBitRate < minAudioBitRate) {
   1491         ALOGW("Intended audio encoding bit rate (%d) is too small"
   1492             " and will be set to (%d)", mAudioBitRate, minAudioBitRate);
   1493         mAudioBitRate = minAudioBitRate;
   1494     }
   1495 
   1496     int maxAudioBitRate =
   1497             mEncoderProfiles->getAudioEncoderParamByName(
   1498                 "enc.aud.bps.max", mAudioEncoder);
   1499     if (maxAudioBitRate != -1 && mAudioBitRate > maxAudioBitRate) {
   1500         ALOGW("Intended audio encoding bit rate (%d) is too large"
   1501             " and will be set to (%d)", mAudioBitRate, maxAudioBitRate);
   1502         mAudioBitRate = maxAudioBitRate;
   1503     }
   1504 }
   1505 
   1506 void StagefrightRecorder::clipAudioSampleRate() {
   1507     ALOGV("clipAudioSampleRate: encoder %d", mAudioEncoder);
   1508 
   1509     int minSampleRate =
   1510             mEncoderProfiles->getAudioEncoderParamByName(
   1511                 "enc.aud.hz.min", mAudioEncoder);
   1512     if (minSampleRate != -1 && mSampleRate < minSampleRate) {
   1513         ALOGW("Intended audio sample rate (%d) is too small"
   1514             " and will be set to (%d)", mSampleRate, minSampleRate);
   1515         mSampleRate = minSampleRate;
   1516     }
   1517 
   1518     int maxSampleRate =
   1519             mEncoderProfiles->getAudioEncoderParamByName(
   1520                 "enc.aud.hz.max", mAudioEncoder);
   1521     if (maxSampleRate != -1 && mSampleRate > maxSampleRate) {
   1522         ALOGW("Intended audio sample rate (%d) is too large"
   1523             " and will be set to (%d)", mSampleRate, maxSampleRate);
   1524         mSampleRate = maxSampleRate;
   1525     }
   1526 }
   1527 
   1528 void StagefrightRecorder::clipNumberOfAudioChannels() {
   1529     ALOGV("clipNumberOfAudioChannels: encoder %d", mAudioEncoder);
   1530 
   1531     int minChannels =
   1532             mEncoderProfiles->getAudioEncoderParamByName(
   1533                 "enc.aud.ch.min", mAudioEncoder);
   1534     if (minChannels != -1 && mAudioChannels < minChannels) {
   1535         ALOGW("Intended number of audio channels (%d) is too small"
   1536             " and will be set to (%d)", mAudioChannels, minChannels);
   1537         mAudioChannels = minChannels;
   1538     }
   1539 
   1540     int maxChannels =
   1541             mEncoderProfiles->getAudioEncoderParamByName(
   1542                 "enc.aud.ch.max", mAudioEncoder);
   1543     if (maxChannels != -1 && mAudioChannels > maxChannels) {
   1544         ALOGW("Intended number of audio channels (%d) is too large"
   1545             " and will be set to (%d)", mAudioChannels, maxChannels);
   1546         mAudioChannels = maxChannels;
   1547     }
   1548 }
   1549 
   1550 void StagefrightRecorder::clipVideoFrameHeight() {
   1551     ALOGV("clipVideoFrameHeight: encoder %d", mVideoEncoder);
   1552     int minFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
   1553                         "enc.vid.height.min", mVideoEncoder);
   1554     int maxFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
   1555                         "enc.vid.height.max", mVideoEncoder);
   1556     if (minFrameHeight != -1 && mVideoHeight < minFrameHeight) {
   1557         ALOGW("Intended video encoding frame height (%d) is too small"
   1558              " and will be set to (%d)", mVideoHeight, minFrameHeight);
   1559         mVideoHeight = minFrameHeight;
   1560     } else if (maxFrameHeight != -1 && mVideoHeight > maxFrameHeight) {
   1561         ALOGW("Intended video encoding frame height (%d) is too large"
   1562              " and will be set to (%d)", mVideoHeight, maxFrameHeight);
   1563         mVideoHeight = maxFrameHeight;
   1564     }
   1565 }
   1566 
   1567 // Set up the appropriate MediaSource depending on the chosen option
   1568 status_t StagefrightRecorder::setupMediaSource(
   1569                       sp<MediaSource> *mediaSource) {
   1570     if (mVideoSource == VIDEO_SOURCE_DEFAULT
   1571             || mVideoSource == VIDEO_SOURCE_CAMERA) {
   1572         sp<CameraSource> cameraSource;
   1573         status_t err = setupCameraSource(&cameraSource);
   1574         if (err != OK) {
   1575             return err;
   1576         }
   1577         *mediaSource = cameraSource;
   1578     } else if (mVideoSource == VIDEO_SOURCE_SURFACE) {
   1579         *mediaSource = NULL;
   1580     } else {
   1581         return INVALID_OPERATION;
   1582     }
   1583     return OK;
   1584 }
   1585 
   1586 status_t StagefrightRecorder::setupCameraSource(
   1587         sp<CameraSource> *cameraSource) {
   1588     status_t err = OK;
   1589     if ((err = checkVideoEncoderCapabilities()) != OK) {
   1590         return err;
   1591     }
   1592     Size videoSize;
   1593     videoSize.width = mVideoWidth;
   1594     videoSize.height = mVideoHeight;
   1595     if (mCaptureFpsEnable) {
   1596         if (!(mCaptureFps > 0.)) {
   1597             ALOGE("Invalid mCaptureFps value: %lf", mCaptureFps);
   1598             return BAD_VALUE;
   1599         }
   1600 
   1601         mCameraSourceTimeLapse = CameraSourceTimeLapse::CreateFromCamera(
   1602                 mCamera, mCameraProxy, mCameraId, mClientName, mClientUid, mClientPid,
   1603                 videoSize, mFrameRate, mPreviewSurface,
   1604                 std::llround(1e6 / mCaptureFps));
   1605         *cameraSource = mCameraSourceTimeLapse;
   1606     } else {
   1607         *cameraSource = CameraSource::CreateFromCamera(
   1608                 mCamera, mCameraProxy, mCameraId, mClientName, mClientUid, mClientPid,
   1609                 videoSize, mFrameRate,
   1610                 mPreviewSurface);
   1611     }
   1612     mCamera.clear();
   1613     mCameraProxy.clear();
   1614     if (*cameraSource == NULL) {
   1615         return UNKNOWN_ERROR;
   1616     }
   1617 
   1618     if ((*cameraSource)->initCheck() != OK) {
   1619         (*cameraSource).clear();
   1620         *cameraSource = NULL;
   1621         return NO_INIT;
   1622     }
   1623 
   1624     // When frame rate is not set, the actual frame rate will be set to
   1625     // the current frame rate being used.
   1626     if (mFrameRate == -1) {
   1627         int32_t frameRate = 0;
   1628         CHECK ((*cameraSource)->getFormat()->findInt32(
   1629                     kKeyFrameRate, &frameRate));
   1630         ALOGI("Frame rate is not explicitly set. Use the current frame "
   1631              "rate (%d fps)", frameRate);
   1632         mFrameRate = frameRate;
   1633     }
   1634 
   1635     CHECK(mFrameRate != -1);
   1636 
   1637     mMetaDataStoredInVideoBuffers =
   1638         (*cameraSource)->metaDataStoredInVideoBuffers();
   1639 
   1640     return OK;
   1641 }
   1642 
   1643 status_t StagefrightRecorder::setupVideoEncoder(
   1644         const sp<MediaSource> &cameraSource,
   1645         sp<MediaCodecSource> *source) {
   1646     source->clear();
   1647 
   1648     sp<AMessage> format = new AMessage();
   1649 
   1650     switch (mVideoEncoder) {
   1651         case VIDEO_ENCODER_H263:
   1652             format->setString("mime", MEDIA_MIMETYPE_VIDEO_H263);
   1653             break;
   1654 
   1655         case VIDEO_ENCODER_MPEG_4_SP:
   1656             format->setString("mime", MEDIA_MIMETYPE_VIDEO_MPEG4);
   1657             break;
   1658 
   1659         case VIDEO_ENCODER_H264:
   1660             format->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC);
   1661             break;
   1662 
   1663         case VIDEO_ENCODER_VP8:
   1664             format->setString("mime", MEDIA_MIMETYPE_VIDEO_VP8);
   1665             break;
   1666 
   1667         case VIDEO_ENCODER_HEVC:
   1668             format->setString("mime", MEDIA_MIMETYPE_VIDEO_HEVC);
   1669             break;
   1670 
   1671         default:
   1672             CHECK(!"Should not be here, unsupported video encoding.");
   1673             break;
   1674     }
   1675 
   1676     // log video mime type for media metrics
   1677     if (mAnalyticsItem != NULL) {
   1678         AString videomime;
   1679         if (format->findString("mime", &videomime)) {
   1680             mAnalyticsItem->setCString(kRecorderVideoMime, videomime.c_str());
   1681         }
   1682     }
   1683 
   1684     if (cameraSource != NULL) {
   1685         sp<MetaData> meta = cameraSource->getFormat();
   1686 
   1687         int32_t width, height, stride, sliceHeight, colorFormat;
   1688         CHECK(meta->findInt32(kKeyWidth, &width));
   1689         CHECK(meta->findInt32(kKeyHeight, &height));
   1690         CHECK(meta->findInt32(kKeyStride, &stride));
   1691         CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight));
   1692         CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));
   1693 
   1694         format->setInt32("width", width);
   1695         format->setInt32("height", height);
   1696         format->setInt32("stride", stride);
   1697         format->setInt32("slice-height", sliceHeight);
   1698         format->setInt32("color-format", colorFormat);
   1699     } else {
   1700         format->setInt32("width", mVideoWidth);
   1701         format->setInt32("height", mVideoHeight);
   1702         format->setInt32("stride", mVideoWidth);
   1703         format->setInt32("slice-height", mVideoHeight);
   1704         format->setInt32("color-format", OMX_COLOR_FormatAndroidOpaque);
   1705 
   1706         // set up time lapse/slow motion for surface source
   1707         if (mCaptureFpsEnable) {
   1708             if (!(mCaptureFps > 0.)) {
   1709                 ALOGE("Invalid mCaptureFps value: %lf", mCaptureFps);
   1710                 return BAD_VALUE;
   1711             }
   1712             format->setDouble("time-lapse-fps", mCaptureFps);
   1713         }
   1714     }
   1715 
   1716     format->setInt32("bitrate", mVideoBitRate);
   1717     format->setInt32("frame-rate", mFrameRate);
   1718     format->setInt32("i-frame-interval", mIFramesIntervalSec);
   1719 
   1720     if (mVideoTimeScale > 0) {
   1721         format->setInt32("time-scale", mVideoTimeScale);
   1722     }
   1723     if (mVideoEncoderProfile != -1) {
   1724         format->setInt32("profile", mVideoEncoderProfile);
   1725     }
   1726     if (mVideoEncoderLevel != -1) {
   1727         format->setInt32("level", mVideoEncoderLevel);
   1728     }
   1729 
   1730     uint32_t tsLayers = 1;
   1731     bool preferBFrames = true; // we like B-frames as it produces better quality per bitrate
   1732     format->setInt32("priority", 0 /* realtime */);
   1733     float maxPlaybackFps = mFrameRate; // assume video is only played back at normal speed
   1734 
   1735     if (mCaptureFpsEnable) {
   1736         format->setFloat("operating-rate", mCaptureFps);
   1737 
   1738         // enable layering for all time lapse and high frame rate recordings
   1739         if (mFrameRate / mCaptureFps >= 1.9) { // time lapse
   1740             preferBFrames = false;
   1741             tsLayers = 2; // use at least two layers as resulting video will likely be sped up
   1742         } else if (mCaptureFps > maxPlaybackFps) { // slow-mo
   1743             maxPlaybackFps = mCaptureFps; // assume video will be played back at full capture speed
   1744             preferBFrames = false;
   1745         }
   1746     }
   1747 
   1748     for (uint32_t tryLayers = 1; tryLayers <= kMaxNumVideoTemporalLayers; ++tryLayers) {
   1749         if (tryLayers > tsLayers) {
   1750             tsLayers = tryLayers;
   1751         }
   1752         // keep going until the base layer fps falls below the typical display refresh rate
   1753         float baseLayerFps = maxPlaybackFps / (1 << (tryLayers - 1));
   1754         if (baseLayerFps < kMinTypicalDisplayRefreshingRate / 0.9) {
   1755             break;
   1756         }
   1757     }
   1758 
   1759     if (tsLayers > 1) {
   1760         uint32_t bLayers = std::min(2u, tsLayers - 1); // use up-to 2 B-layers
   1761         uint32_t pLayers = tsLayers - bLayers;
   1762         format->setString(
   1763                 "ts-schema", AStringPrintf("android.generic.%u+%u", pLayers, bLayers));
   1764 
   1765         // TODO: some encoders do not support B-frames with temporal layering, and we have a
   1766         // different preference based on use-case. We could move this into camera profiles.
   1767         format->setInt32("android._prefer-b-frames", preferBFrames);
   1768     }
   1769 
   1770     if (mMetaDataStoredInVideoBuffers != kMetadataBufferTypeInvalid) {
   1771         format->setInt32("android._input-metadata-buffer-type", mMetaDataStoredInVideoBuffers);
   1772     }
   1773 
   1774     uint32_t flags = 0;
   1775     if (cameraSource == NULL) {
   1776         flags |= MediaCodecSource::FLAG_USE_SURFACE_INPUT;
   1777     } else {
   1778         // require dataspace setup even if not using surface input
   1779         format->setInt32("android._using-recorder", 1);
   1780     }
   1781 
   1782     sp<MediaCodecSource> encoder = MediaCodecSource::Create(
   1783             mLooper, format, cameraSource, mPersistentSurface, flags);
   1784     if (encoder == NULL) {
   1785         ALOGE("Failed to create video encoder");
   1786         // When the encoder fails to be created, we need
   1787         // release the camera source due to the camera's lock
   1788         // and unlock mechanism.
   1789         if (cameraSource != NULL) {
   1790             cameraSource->stop();
   1791         }
   1792         return UNKNOWN_ERROR;
   1793     }
   1794 
   1795     if (cameraSource == NULL) {
   1796         mGraphicBufferProducer = encoder->getGraphicBufferProducer();
   1797     }
   1798 
   1799     *source = encoder;
   1800 
   1801     return OK;
   1802 }
   1803 
   1804 status_t StagefrightRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) {
   1805     status_t status = BAD_VALUE;
   1806     if (OK != (status = checkAudioEncoderCapabilities())) {
   1807         return status;
   1808     }
   1809 
   1810     switch(mAudioEncoder) {
   1811         case AUDIO_ENCODER_AMR_NB:
   1812         case AUDIO_ENCODER_AMR_WB:
   1813         case AUDIO_ENCODER_AAC:
   1814         case AUDIO_ENCODER_HE_AAC:
   1815         case AUDIO_ENCODER_AAC_ELD:
   1816             break;
   1817 
   1818         default:
   1819             ALOGE("Unsupported audio encoder: %d", mAudioEncoder);
   1820             return UNKNOWN_ERROR;
   1821     }
   1822 
   1823     sp<MediaCodecSource> audioEncoder = createAudioSource();
   1824     if (audioEncoder == NULL) {
   1825         return UNKNOWN_ERROR;
   1826     }
   1827 
   1828     writer->addSource(audioEncoder);
   1829     mAudioEncoderSource = audioEncoder;
   1830     return OK;
   1831 }
   1832 
   1833 status_t StagefrightRecorder::setupMPEG4orWEBMRecording() {
   1834     mWriter.clear();
   1835     mTotalBitRate = 0;
   1836 
   1837     status_t err = OK;
   1838     sp<MediaWriter> writer;
   1839     sp<MPEG4Writer> mp4writer;
   1840     if (mOutputFormat == OUTPUT_FORMAT_WEBM) {
   1841         writer = new WebmWriter(mOutputFd);
   1842     } else {
   1843         writer = mp4writer = new MPEG4Writer(mOutputFd);
   1844     }
   1845 
   1846     if (mVideoSource < VIDEO_SOURCE_LIST_END) {
   1847         setDefaultVideoEncoderIfNecessary();
   1848 
   1849         sp<MediaSource> mediaSource;
   1850         err = setupMediaSource(&mediaSource);
   1851         if (err != OK) {
   1852             return err;
   1853         }
   1854 
   1855         sp<MediaCodecSource> encoder;
   1856         err = setupVideoEncoder(mediaSource, &encoder);
   1857         if (err != OK) {
   1858             return err;
   1859         }
   1860 
   1861         writer->addSource(encoder);
   1862         mVideoEncoderSource = encoder;
   1863         mTotalBitRate += mVideoBitRate;
   1864     }
   1865 
   1866     if (mOutputFormat != OUTPUT_FORMAT_WEBM) {
   1867         // Audio source is added at the end if it exists.
   1868         // This help make sure that the "recoding" sound is suppressed for
   1869         // camcorder applications in the recorded files.
   1870         // TODO Audio source is currently unsupported for webm output; vorbis encoder needed.
   1871         // disable audio for time lapse recording
   1872         bool disableAudio = mCaptureFpsEnable && mCaptureFps < mFrameRate;
   1873         if (!disableAudio && mAudioSource != AUDIO_SOURCE_CNT) {
   1874             err = setupAudioEncoder(writer);
   1875             if (err != OK) return err;
   1876             mTotalBitRate += mAudioBitRate;
   1877         }
   1878 
   1879         if (mCaptureFpsEnable) {
   1880             mp4writer->setCaptureRate(mCaptureFps);
   1881         }
   1882 
   1883         if (mInterleaveDurationUs > 0) {
   1884             mp4writer->setInterleaveDuration(mInterleaveDurationUs);
   1885         }
   1886         if (mLongitudex10000 > -3600000 && mLatitudex10000 > -3600000) {
   1887             mp4writer->setGeoData(mLatitudex10000, mLongitudex10000);
   1888         }
   1889     }
   1890     if (mMaxFileDurationUs != 0) {
   1891         writer->setMaxFileDuration(mMaxFileDurationUs);
   1892     }
   1893     if (mMaxFileSizeBytes != 0) {
   1894         writer->setMaxFileSize(mMaxFileSizeBytes);
   1895     }
   1896     if (mVideoSource == VIDEO_SOURCE_DEFAULT
   1897             || mVideoSource == VIDEO_SOURCE_CAMERA) {
   1898         mStartTimeOffsetMs = mEncoderProfiles->getStartTimeOffsetMs(mCameraId);
   1899     } else if (mVideoSource == VIDEO_SOURCE_SURFACE) {
   1900         // surface source doesn't need large initial delay
   1901         mStartTimeOffsetMs = 100;
   1902     }
   1903     if (mStartTimeOffsetMs > 0) {
   1904         writer->setStartTimeOffsetMs(mStartTimeOffsetMs);
   1905     }
   1906 
   1907     writer->setListener(mListener);
   1908     mWriter = writer;
   1909     return OK;
   1910 }
   1911 
   1912 void StagefrightRecorder::setupMPEG4orWEBMMetaData(sp<MetaData> *meta) {
   1913     int64_t startTimeUs = systemTime() / 1000;
   1914     (*meta)->setInt64(kKeyTime, startTimeUs);
   1915     (*meta)->setInt32(kKeyFileType, mOutputFormat);
   1916     (*meta)->setInt32(kKeyBitRate, mTotalBitRate);
   1917     if (mMovieTimeScale > 0) {
   1918         (*meta)->setInt32(kKeyTimeScale, mMovieTimeScale);
   1919     }
   1920     if (mOutputFormat != OUTPUT_FORMAT_WEBM) {
   1921         (*meta)->setInt32(kKey64BitFileOffset, mUse64BitFileOffset);
   1922         if (mTrackEveryTimeDurationUs > 0) {
   1923             (*meta)->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs);
   1924         }
   1925         if (mRotationDegrees != 0) {
   1926             (*meta)->setInt32(kKeyRotation, mRotationDegrees);
   1927         }
   1928     }
   1929 }
   1930 
   1931 status_t StagefrightRecorder::pause() {
   1932     ALOGV("pause");
   1933     if (!mStarted) {
   1934         return INVALID_OPERATION;
   1935     }
   1936 
   1937     // Already paused --- no-op.
   1938     if (mPauseStartTimeUs != 0) {
   1939         return OK;
   1940     }
   1941 
   1942     mPauseStartTimeUs = systemTime() / 1000;
   1943     sp<MetaData> meta = new MetaData;
   1944     meta->setInt64(kKeyTime, mPauseStartTimeUs);
   1945 
   1946     if (mStartedRecordingUs != 0) {
   1947         // should always be true
   1948         int64_t recordingUs = mPauseStartTimeUs - mStartedRecordingUs;
   1949         mDurationRecordedUs += recordingUs;
   1950         mStartedRecordingUs = 0;
   1951     }
   1952 
   1953     if (mAudioEncoderSource != NULL) {
   1954         mAudioEncoderSource->pause();
   1955     }
   1956     if (mVideoEncoderSource != NULL) {
   1957         mVideoEncoderSource->pause(meta.get());
   1958     }
   1959 
   1960     return OK;
   1961 }
   1962 
   1963 status_t StagefrightRecorder::resume() {
   1964     ALOGV("resume");
   1965     if (!mStarted) {
   1966         return INVALID_OPERATION;
   1967     }
   1968 
   1969     // Not paused --- no-op.
   1970     if (mPauseStartTimeUs == 0) {
   1971         return OK;
   1972     }
   1973 
   1974     int64_t resumeStartTimeUs = systemTime() / 1000;
   1975 
   1976     int64_t bufferStartTimeUs = 0;
   1977     bool allSourcesStarted = true;
   1978     for (const auto &source : { mAudioEncoderSource, mVideoEncoderSource }) {
   1979         if (source == nullptr) {
   1980             continue;
   1981         }
   1982         int64_t timeUs = source->getFirstSampleSystemTimeUs();
   1983         if (timeUs < 0) {
   1984             allSourcesStarted = false;
   1985         }
   1986         if (bufferStartTimeUs < timeUs) {
   1987             bufferStartTimeUs = timeUs;
   1988         }
   1989     }
   1990 
   1991     if (allSourcesStarted) {
   1992         if (mPauseStartTimeUs < bufferStartTimeUs) {
   1993             mPauseStartTimeUs = bufferStartTimeUs;
   1994         }
   1995         // 30 ms buffer to avoid timestamp overlap
   1996         mTotalPausedDurationUs += resumeStartTimeUs - mPauseStartTimeUs - 30000;
   1997     }
   1998     double timeOffset = -mTotalPausedDurationUs;
   1999     if (mCaptureFpsEnable) {
   2000         timeOffset *= mCaptureFps / mFrameRate;
   2001     }
   2002     sp<MetaData> meta = new MetaData;
   2003     meta->setInt64(kKeyTime, resumeStartTimeUs);
   2004     for (const auto &source : { mAudioEncoderSource, mVideoEncoderSource }) {
   2005         if (source == nullptr) {
   2006             continue;
   2007         }
   2008         source->setInputBufferTimeOffset((int64_t)timeOffset);
   2009         source->start(meta.get());
   2010     }
   2011 
   2012 
   2013     // sum info on pause duration
   2014     // (ignore the 30msec of overlap adjustment factored into mTotalPausedDurationUs)
   2015     int64_t pausedUs = resumeStartTimeUs - mPauseStartTimeUs;
   2016     mDurationPausedUs += pausedUs;
   2017     mNPauses++;
   2018     // and a timestamp marking that we're back to recording....
   2019     mStartedRecordingUs = resumeStartTimeUs;
   2020 
   2021     mPauseStartTimeUs = 0;
   2022 
   2023     return OK;
   2024 }
   2025 
   2026 status_t StagefrightRecorder::stop() {
   2027     ALOGV("stop");
   2028     Mutex::Autolock autolock(mLock);
   2029     status_t err = OK;
   2030 
   2031     if (mCaptureFpsEnable && mCameraSourceTimeLapse != NULL) {
   2032         mCameraSourceTimeLapse->startQuickReadReturns();
   2033         mCameraSourceTimeLapse = NULL;
   2034     }
   2035 
   2036     int64_t stopTimeUs = systemTime() / 1000;
   2037     for (const auto &source : { mAudioEncoderSource, mVideoEncoderSource }) {
   2038         if (source != nullptr && OK != source->setStopTimeUs(stopTimeUs)) {
   2039             ALOGW("Failed to set stopTime %lld us for %s",
   2040                     (long long)stopTimeUs, source->isVideo() ? "Video" : "Audio");
   2041         }
   2042     }
   2043 
   2044     if (mWriter != NULL) {
   2045         err = mWriter->stop();
   2046         mWriter.clear();
   2047     }
   2048 
   2049     // account for the last 'segment' -- whether paused or recording
   2050     if (mPauseStartTimeUs != 0) {
   2051         // we were paused
   2052         int64_t additive = stopTimeUs - mPauseStartTimeUs;
   2053         mDurationPausedUs += additive;
   2054         mNPauses++;
   2055     } else if (mStartedRecordingUs != 0) {
   2056         // we were recording
   2057         int64_t additive = stopTimeUs - mStartedRecordingUs;
   2058         mDurationRecordedUs += additive;
   2059     } else {
   2060         ALOGW("stop while neither recording nor paused");
   2061     }
   2062 
   2063     flushAndResetMetrics(true);
   2064 
   2065     mDurationRecordedUs = 0;
   2066     mDurationPausedUs = 0;
   2067     mNPauses = 0;
   2068     mTotalPausedDurationUs = 0;
   2069     mPauseStartTimeUs = 0;
   2070     mStartedRecordingUs = 0;
   2071 
   2072     mGraphicBufferProducer.clear();
   2073     mPersistentSurface.clear();
   2074     mAudioEncoderSource.clear();
   2075     mVideoEncoderSource.clear();
   2076 
   2077     if (mOutputFd >= 0) {
   2078         ::close(mOutputFd);
   2079         mOutputFd = -1;
   2080     }
   2081 
   2082     if (mStarted) {
   2083         mStarted = false;
   2084 
   2085         uint32_t params = 0;
   2086         if (mAudioSource != AUDIO_SOURCE_CNT) {
   2087             params |= IMediaPlayerService::kBatteryDataTrackAudio;
   2088         }
   2089         if (mVideoSource != VIDEO_SOURCE_LIST_END) {
   2090             params |= IMediaPlayerService::kBatteryDataTrackVideo;
   2091         }
   2092 
   2093         addBatteryData(params);
   2094     }
   2095 
   2096     return err;
   2097 }
   2098 
   2099 status_t StagefrightRecorder::close() {
   2100     ALOGV("close");
   2101     stop();
   2102 
   2103     return OK;
   2104 }
   2105 
   2106 status_t StagefrightRecorder::reset() {
   2107     ALOGV("reset");
   2108     stop();
   2109 
   2110     // No audio or video source by default
   2111     mAudioSource = (audio_source_t)AUDIO_SOURCE_CNT; // reset to invalid value
   2112     mVideoSource = VIDEO_SOURCE_LIST_END;
   2113 
   2114     // Default parameters
   2115     mOutputFormat  = OUTPUT_FORMAT_THREE_GPP;
   2116     mAudioEncoder  = AUDIO_ENCODER_AMR_NB;
   2117     mVideoEncoder  = VIDEO_ENCODER_DEFAULT;
   2118     mVideoWidth    = 176;
   2119     mVideoHeight   = 144;
   2120     mFrameRate     = -1;
   2121     mVideoBitRate  = 192000;
   2122     mSampleRate    = 8000;
   2123     mAudioChannels = 1;
   2124     mAudioBitRate  = 12200;
   2125     mInterleaveDurationUs = 0;
   2126     mIFramesIntervalSec = 1;
   2127     mAudioSourceNode = 0;
   2128     mUse64BitFileOffset = false;
   2129     mMovieTimeScale  = -1;
   2130     mAudioTimeScale  = -1;
   2131     mVideoTimeScale  = -1;
   2132     mCameraId        = 0;
   2133     mStartTimeOffsetMs = -1;
   2134     mVideoEncoderProfile = -1;
   2135     mVideoEncoderLevel   = -1;
   2136     mMaxFileDurationUs = 0;
   2137     mMaxFileSizeBytes = 0;
   2138     mTrackEveryTimeDurationUs = 0;
   2139     mCaptureFpsEnable = false;
   2140     mCaptureFps = -1.0;
   2141     mCameraSourceTimeLapse = NULL;
   2142     mMetaDataStoredInVideoBuffers = kMetadataBufferTypeInvalid;
   2143     mEncoderProfiles = MediaProfiles::getInstance();
   2144     mRotationDegrees = 0;
   2145     mLatitudex10000 = -3600000;
   2146     mLongitudex10000 = -3600000;
   2147     mTotalBitRate = 0;
   2148 
   2149     // tracking how long we recorded.
   2150     mDurationRecordedUs = 0;
   2151     mStartedRecordingUs = 0;
   2152     mDurationPausedUs = 0;
   2153     mNPauses = 0;
   2154 
   2155     mOutputFd = -1;
   2156 
   2157     return OK;
   2158 }
   2159 
   2160 status_t StagefrightRecorder::getMaxAmplitude(int *max) {
   2161     ALOGV("getMaxAmplitude");
   2162 
   2163     if (max == NULL) {
   2164         ALOGE("Null pointer argument");
   2165         return BAD_VALUE;
   2166     }
   2167 
   2168     if (mAudioSourceNode != 0) {
   2169         *max = mAudioSourceNode->getMaxAmplitude();
   2170     } else {
   2171         *max = 0;
   2172     }
   2173 
   2174     return OK;
   2175 }
   2176 
   2177 status_t StagefrightRecorder::getMetrics(Parcel *reply) {
   2178     ALOGD("StagefrightRecorder::getMetrics");
   2179 
   2180     if (reply == NULL) {
   2181         ALOGE("Null pointer argument");
   2182         return BAD_VALUE;
   2183     }
   2184 
   2185     if (mAnalyticsItem == NULL) {
   2186         return UNKNOWN_ERROR;
   2187     }
   2188 
   2189     updateMetrics();
   2190     mAnalyticsItem->writeToParcel(reply);
   2191     return OK;
   2192 }
   2193 
   2194 status_t StagefrightRecorder::setInputDevice(audio_port_handle_t deviceId) {
   2195     ALOGV("setInputDevice");
   2196 
   2197     if (mSelectedDeviceId != deviceId) {
   2198         mSelectedDeviceId = deviceId;
   2199         if (mAudioSourceNode != 0) {
   2200             return mAudioSourceNode->setInputDevice(deviceId);
   2201         }
   2202     }
   2203     return NO_ERROR;
   2204 }
   2205 
   2206 status_t StagefrightRecorder::getRoutedDeviceId(audio_port_handle_t* deviceId) {
   2207     ALOGV("getRoutedDeviceId");
   2208 
   2209     if (mAudioSourceNode != 0) {
   2210         status_t status = mAudioSourceNode->getRoutedDeviceId(deviceId);
   2211         return status;
   2212     }
   2213     return NO_INIT;
   2214 }
   2215 
   2216 void StagefrightRecorder::setAudioDeviceCallback(
   2217         const sp<AudioSystem::AudioDeviceCallback>& callback) {
   2218     mAudioDeviceCallback = callback;
   2219 }
   2220 
   2221 status_t StagefrightRecorder::enableAudioDeviceCallback(bool enabled) {
   2222     mDeviceCallbackEnabled = enabled;
   2223     sp<AudioSystem::AudioDeviceCallback> callback = mAudioDeviceCallback.promote();
   2224     if (mAudioSourceNode != 0 && callback != 0) {
   2225         if (enabled) {
   2226             return mAudioSourceNode->addAudioDeviceCallback(callback);
   2227         } else {
   2228             return mAudioSourceNode->removeAudioDeviceCallback(callback);
   2229         }
   2230     }
   2231     return NO_ERROR;
   2232 }
   2233 
   2234 status_t StagefrightRecorder::getActiveMicrophones(
   2235         std::vector<media::MicrophoneInfo>* activeMicrophones) {
   2236     if (mAudioSourceNode != 0) {
   2237         return mAudioSourceNode->getActiveMicrophones(activeMicrophones);
   2238     }
   2239     return NO_INIT;
   2240 }
   2241 
   2242 
   2243 status_t StagefrightRecorder::dump(
   2244         int fd, const Vector<String16>& args) const {
   2245     ALOGV("dump");
   2246     Mutex::Autolock autolock(mLock);
   2247     const size_t SIZE = 256;
   2248     char buffer[SIZE];
   2249     String8 result;
   2250     if (mWriter != 0) {
   2251         mWriter->dump(fd, args);
   2252     } else {
   2253         snprintf(buffer, SIZE, "   No file writer\n");
   2254         result.append(buffer);
   2255     }
   2256     snprintf(buffer, SIZE, "   Recorder: %p\n", this);
   2257     snprintf(buffer, SIZE, "   Output file (fd %d):\n", mOutputFd);
   2258     result.append(buffer);
   2259     snprintf(buffer, SIZE, "     File format: %d\n", mOutputFormat);
   2260     result.append(buffer);
   2261     snprintf(buffer, SIZE, "     Max file size (bytes): %" PRId64 "\n", mMaxFileSizeBytes);
   2262     result.append(buffer);
   2263     snprintf(buffer, SIZE, "     Max file duration (us): %" PRId64 "\n", mMaxFileDurationUs);
   2264     result.append(buffer);
   2265     snprintf(buffer, SIZE, "     File offset length (bits): %d\n", mUse64BitFileOffset? 64: 32);
   2266     result.append(buffer);
   2267     snprintf(buffer, SIZE, "     Interleave duration (us): %d\n", mInterleaveDurationUs);
   2268     result.append(buffer);
   2269     snprintf(buffer, SIZE, "     Progress notification: %" PRId64 " us\n", mTrackEveryTimeDurationUs);
   2270     result.append(buffer);
   2271     snprintf(buffer, SIZE, "   Audio\n");
   2272     result.append(buffer);
   2273     snprintf(buffer, SIZE, "     Source: %d\n", mAudioSource);
   2274     result.append(buffer);
   2275     snprintf(buffer, SIZE, "     Encoder: %d\n", mAudioEncoder);
   2276     result.append(buffer);
   2277     snprintf(buffer, SIZE, "     Bit rate (bps): %d\n", mAudioBitRate);
   2278     result.append(buffer);
   2279     snprintf(buffer, SIZE, "     Sampling rate (hz): %d\n", mSampleRate);
   2280     result.append(buffer);
   2281     snprintf(buffer, SIZE, "     Number of channels: %d\n", mAudioChannels);
   2282     result.append(buffer);
   2283     snprintf(buffer, SIZE, "     Max amplitude: %d\n", mAudioSourceNode == 0? 0: mAudioSourceNode->getMaxAmplitude());
   2284     result.append(buffer);
   2285     snprintf(buffer, SIZE, "   Video\n");
   2286     result.append(buffer);
   2287     snprintf(buffer, SIZE, "     Source: %d\n", mVideoSource);
   2288     result.append(buffer);
   2289     snprintf(buffer, SIZE, "     Camera Id: %d\n", mCameraId);
   2290     result.append(buffer);
   2291     snprintf(buffer, SIZE, "     Start time offset (ms): %d\n", mStartTimeOffsetMs);
   2292     result.append(buffer);
   2293     snprintf(buffer, SIZE, "     Encoder: %d\n", mVideoEncoder);
   2294     result.append(buffer);
   2295     snprintf(buffer, SIZE, "     Encoder profile: %d\n", mVideoEncoderProfile);
   2296     result.append(buffer);
   2297     snprintf(buffer, SIZE, "     Encoder level: %d\n", mVideoEncoderLevel);
   2298     result.append(buffer);
   2299     snprintf(buffer, SIZE, "     I frames interval (s): %d\n", mIFramesIntervalSec);
   2300     result.append(buffer);
   2301     snprintf(buffer, SIZE, "     Frame size (pixels): %dx%d\n", mVideoWidth, mVideoHeight);
   2302     result.append(buffer);
   2303     snprintf(buffer, SIZE, "     Frame rate (fps): %d\n", mFrameRate);
   2304     result.append(buffer);
   2305     snprintf(buffer, SIZE, "     Bit rate (bps): %d\n", mVideoBitRate);
   2306     result.append(buffer);
   2307     ::write(fd, result.string(), result.size());
   2308     return OK;
   2309 }
   2310 }  // namespace android
   2311