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 <utils/Log.h>
     20 
     21 #include "StagefrightRecorder.h"
     22 
     23 #include <binder/IPCThreadState.h>
     24 #include <binder/IServiceManager.h>
     25 
     26 #include <media/IMediaPlayerService.h>
     27 #include <media/openmax/OMX_Audio.h>
     28 #include <media/stagefright/foundation/ADebug.h>
     29 #include <media/stagefright/AudioSource.h>
     30 #include <media/stagefright/AMRWriter.h>
     31 #include <media/stagefright/AACWriter.h>
     32 #include <media/stagefright/CameraSource.h>
     33 #include <media/stagefright/CameraSourceTimeLapse.h>
     34 #include <media/stagefright/MPEG2TSWriter.h>
     35 #include <media/stagefright/MPEG4Writer.h>
     36 #include <media/stagefright/MediaDefs.h>
     37 #include <media/stagefright/MetaData.h>
     38 #include <media/stagefright/OMXClient.h>
     39 #include <media/stagefright/OMXCodec.h>
     40 #include <media/stagefright/SurfaceMediaSource.h>
     41 #include <media/MediaProfiles.h>
     42 #include <camera/ICamera.h>
     43 #include <camera/CameraParameters.h>
     44 #include <gui/Surface.h>
     45 
     46 #include <utils/Errors.h>
     47 #include <sys/types.h>
     48 #include <ctype.h>
     49 #include <unistd.h>
     50 
     51 #include <system/audio.h>
     52 
     53 #include "ARTPWriter.h"
     54 
     55 namespace android {
     56 
     57 // To collect the encoder usage for the battery app
     58 static void addBatteryData(uint32_t params) {
     59     sp<IBinder> binder =
     60         defaultServiceManager()->getService(String16("media.player"));
     61     sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
     62     CHECK(service.get() != NULL);
     63 
     64     service->addBatteryData(params);
     65 }
     66 
     67 
     68 StagefrightRecorder::StagefrightRecorder()
     69     : mWriter(NULL),
     70       mOutputFd(-1),
     71       mAudioSource(AUDIO_SOURCE_CNT),
     72       mVideoSource(VIDEO_SOURCE_LIST_END),
     73       mStarted(false), mSurfaceMediaSource(NULL),
     74       mCaptureTimeLapse(false) {
     75 
     76     ALOGV("Constructor");
     77     reset();
     78 }
     79 
     80 StagefrightRecorder::~StagefrightRecorder() {
     81     ALOGV("Destructor");
     82     stop();
     83 }
     84 
     85 status_t StagefrightRecorder::init() {
     86     ALOGV("init");
     87     return OK;
     88 }
     89 
     90 // The client side of mediaserver asks it to creat a SurfaceMediaSource
     91 // and return a interface reference. The client side will use that
     92 // while encoding GL Frames
     93 sp<IGraphicBufferProducer> StagefrightRecorder::querySurfaceMediaSource() const {
     94     ALOGV("Get SurfaceMediaSource");
     95     return mSurfaceMediaSource->getBufferQueue();
     96 }
     97 
     98 status_t StagefrightRecorder::setAudioSource(audio_source_t as) {
     99     ALOGV("setAudioSource: %d", as);
    100     if (as < AUDIO_SOURCE_DEFAULT ||
    101         as >= AUDIO_SOURCE_CNT) {
    102         ALOGE("Invalid audio source: %d", as);
    103         return BAD_VALUE;
    104     }
    105 
    106     if (as == AUDIO_SOURCE_DEFAULT) {
    107         mAudioSource = AUDIO_SOURCE_MIC;
    108     } else {
    109         mAudioSource = as;
    110     }
    111 
    112     return OK;
    113 }
    114 
    115 status_t StagefrightRecorder::setVideoSource(video_source vs) {
    116     ALOGV("setVideoSource: %d", vs);
    117     if (vs < VIDEO_SOURCE_DEFAULT ||
    118         vs >= VIDEO_SOURCE_LIST_END) {
    119         ALOGE("Invalid video source: %d", vs);
    120         return BAD_VALUE;
    121     }
    122 
    123     if (vs == VIDEO_SOURCE_DEFAULT) {
    124         mVideoSource = VIDEO_SOURCE_CAMERA;
    125     } else {
    126         mVideoSource = vs;
    127     }
    128 
    129     return OK;
    130 }
    131 
    132 status_t StagefrightRecorder::setOutputFormat(output_format of) {
    133     ALOGV("setOutputFormat: %d", of);
    134     if (of < OUTPUT_FORMAT_DEFAULT ||
    135         of >= OUTPUT_FORMAT_LIST_END) {
    136         ALOGE("Invalid output format: %d", of);
    137         return BAD_VALUE;
    138     }
    139 
    140     if (of == OUTPUT_FORMAT_DEFAULT) {
    141         mOutputFormat = OUTPUT_FORMAT_THREE_GPP;
    142     } else {
    143         mOutputFormat = of;
    144     }
    145 
    146     return OK;
    147 }
    148 
    149 status_t StagefrightRecorder::setAudioEncoder(audio_encoder ae) {
    150     ALOGV("setAudioEncoder: %d", ae);
    151     if (ae < AUDIO_ENCODER_DEFAULT ||
    152         ae >= AUDIO_ENCODER_LIST_END) {
    153         ALOGE("Invalid audio encoder: %d", ae);
    154         return BAD_VALUE;
    155     }
    156 
    157     if (ae == AUDIO_ENCODER_DEFAULT) {
    158         mAudioEncoder = AUDIO_ENCODER_AMR_NB;
    159     } else {
    160         mAudioEncoder = ae;
    161     }
    162 
    163     return OK;
    164 }
    165 
    166 status_t StagefrightRecorder::setVideoEncoder(video_encoder ve) {
    167     ALOGV("setVideoEncoder: %d", ve);
    168     if (ve < VIDEO_ENCODER_DEFAULT ||
    169         ve >= VIDEO_ENCODER_LIST_END) {
    170         ALOGE("Invalid video encoder: %d", ve);
    171         return BAD_VALUE;
    172     }
    173 
    174     if (ve == VIDEO_ENCODER_DEFAULT) {
    175         mVideoEncoder = VIDEO_ENCODER_H263;
    176     } else {
    177         mVideoEncoder = ve;
    178     }
    179 
    180     return OK;
    181 }
    182 
    183 status_t StagefrightRecorder::setVideoSize(int width, int height) {
    184     ALOGV("setVideoSize: %dx%d", width, height);
    185     if (width <= 0 || height <= 0) {
    186         ALOGE("Invalid video size: %dx%d", width, height);
    187         return BAD_VALUE;
    188     }
    189 
    190     // Additional check on the dimension will be performed later
    191     mVideoWidth = width;
    192     mVideoHeight = height;
    193 
    194     return OK;
    195 }
    196 
    197 status_t StagefrightRecorder::setVideoFrameRate(int frames_per_second) {
    198     ALOGV("setVideoFrameRate: %d", frames_per_second);
    199     if ((frames_per_second <= 0 && frames_per_second != -1) ||
    200         frames_per_second > 120) {
    201         ALOGE("Invalid video frame rate: %d", frames_per_second);
    202         return BAD_VALUE;
    203     }
    204 
    205     // Additional check on the frame rate will be performed later
    206     mFrameRate = frames_per_second;
    207 
    208     return OK;
    209 }
    210 
    211 status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera,
    212                                         const sp<ICameraRecordingProxy> &proxy) {
    213     ALOGV("setCamera");
    214     if (camera == 0) {
    215         ALOGE("camera is NULL");
    216         return BAD_VALUE;
    217     }
    218     if (proxy == 0) {
    219         ALOGE("camera proxy is NULL");
    220         return BAD_VALUE;
    221     }
    222 
    223     mCamera = camera;
    224     mCameraProxy = proxy;
    225     return OK;
    226 }
    227 
    228 status_t StagefrightRecorder::setPreviewSurface(const sp<IGraphicBufferProducer> &surface) {
    229     ALOGV("setPreviewSurface: %p", surface.get());
    230     mPreviewSurface = surface;
    231 
    232     return OK;
    233 }
    234 
    235 status_t StagefrightRecorder::setOutputFile(const char *path) {
    236     ALOGE("setOutputFile(const char*) must not be called");
    237     // We don't actually support this at all, as the media_server process
    238     // no longer has permissions to create files.
    239 
    240     return -EPERM;
    241 }
    242 
    243 status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t length) {
    244     ALOGV("setOutputFile: %d, %lld, %lld", fd, offset, length);
    245     // These don't make any sense, do they?
    246     CHECK_EQ(offset, 0ll);
    247     CHECK_EQ(length, 0ll);
    248 
    249     if (fd < 0) {
    250         ALOGE("Invalid file descriptor: %d", fd);
    251         return -EBADF;
    252     }
    253 
    254     if (mOutputFd >= 0) {
    255         ::close(mOutputFd);
    256     }
    257     mOutputFd = dup(fd);
    258 
    259     return OK;
    260 }
    261 
    262 // Attempt to parse an int64 literal optionally surrounded by whitespace,
    263 // returns true on success, false otherwise.
    264 static bool safe_strtoi64(const char *s, int64_t *val) {
    265     char *end;
    266 
    267     // It is lame, but according to man page, we have to set errno to 0
    268     // before calling strtoll().
    269     errno = 0;
    270     *val = strtoll(s, &end, 10);
    271 
    272     if (end == s || errno == ERANGE) {
    273         return false;
    274     }
    275 
    276     // Skip trailing whitespace
    277     while (isspace(*end)) {
    278         ++end;
    279     }
    280 
    281     // For a successful return, the string must contain nothing but a valid
    282     // int64 literal optionally surrounded by whitespace.
    283 
    284     return *end == '\0';
    285 }
    286 
    287 // Return true if the value is in [0, 0x007FFFFFFF]
    288 static bool safe_strtoi32(const char *s, int32_t *val) {
    289     int64_t temp;
    290     if (safe_strtoi64(s, &temp)) {
    291         if (temp >= 0 && temp <= 0x007FFFFFFF) {
    292             *val = static_cast<int32_t>(temp);
    293             return true;
    294         }
    295     }
    296     return false;
    297 }
    298 
    299 // Trim both leading and trailing whitespace from the given string.
    300 static void TrimString(String8 *s) {
    301     size_t num_bytes = s->bytes();
    302     const char *data = s->string();
    303 
    304     size_t leading_space = 0;
    305     while (leading_space < num_bytes && isspace(data[leading_space])) {
    306         ++leading_space;
    307     }
    308 
    309     size_t i = num_bytes;
    310     while (i > leading_space && isspace(data[i - 1])) {
    311         --i;
    312     }
    313 
    314     s->setTo(String8(&data[leading_space], i - leading_space));
    315 }
    316 
    317 status_t StagefrightRecorder::setParamAudioSamplingRate(int32_t sampleRate) {
    318     ALOGV("setParamAudioSamplingRate: %d", sampleRate);
    319     if (sampleRate <= 0) {
    320         ALOGE("Invalid audio sampling rate: %d", sampleRate);
    321         return BAD_VALUE;
    322     }
    323 
    324     // Additional check on the sample rate will be performed later.
    325     mSampleRate = sampleRate;
    326     return OK;
    327 }
    328 
    329 status_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) {
    330     ALOGV("setParamAudioNumberOfChannels: %d", channels);
    331     if (channels <= 0 || channels >= 3) {
    332         ALOGE("Invalid number of audio channels: %d", channels);
    333         return BAD_VALUE;
    334     }
    335 
    336     // Additional check on the number of channels will be performed later.
    337     mAudioChannels = channels;
    338     return OK;
    339 }
    340 
    341 status_t StagefrightRecorder::setParamAudioEncodingBitRate(int32_t bitRate) {
    342     ALOGV("setParamAudioEncodingBitRate: %d", bitRate);
    343     if (bitRate <= 0) {
    344         ALOGE("Invalid audio encoding bit rate: %d", bitRate);
    345         return BAD_VALUE;
    346     }
    347 
    348     // The target bit rate may not be exactly the same as the requested.
    349     // It depends on many factors, such as rate control, and the bit rate
    350     // range that a specific encoder supports. The mismatch between the
    351     // the target and requested bit rate will NOT be treated as an error.
    352     mAudioBitRate = bitRate;
    353     return OK;
    354 }
    355 
    356 status_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) {
    357     ALOGV("setParamVideoEncodingBitRate: %d", bitRate);
    358     if (bitRate <= 0) {
    359         ALOGE("Invalid video encoding bit rate: %d", bitRate);
    360         return BAD_VALUE;
    361     }
    362 
    363     // The target bit rate may not be exactly the same as the requested.
    364     // It depends on many factors, such as rate control, and the bit rate
    365     // range that a specific encoder supports. The mismatch between the
    366     // the target and requested bit rate will NOT be treated as an error.
    367     mVideoBitRate = bitRate;
    368     return OK;
    369 }
    370 
    371 // Always rotate clockwise, and only support 0, 90, 180 and 270 for now.
    372 status_t StagefrightRecorder::setParamVideoRotation(int32_t degrees) {
    373     ALOGV("setParamVideoRotation: %d", degrees);
    374     if (degrees < 0 || degrees % 90 != 0) {
    375         ALOGE("Unsupported video rotation angle: %d", degrees);
    376         return BAD_VALUE;
    377     }
    378     mRotationDegrees = degrees % 360;
    379     return OK;
    380 }
    381 
    382 status_t StagefrightRecorder::setParamMaxFileDurationUs(int64_t timeUs) {
    383     ALOGV("setParamMaxFileDurationUs: %lld us", timeUs);
    384 
    385     // This is meant for backward compatibility for MediaRecorder.java
    386     if (timeUs <= 0) {
    387         ALOGW("Max file duration is not positive: %lld us. Disabling duration limit.", timeUs);
    388         timeUs = 0; // Disable the duration limit for zero or negative values.
    389     } else if (timeUs <= 100000LL) {  // XXX: 100 milli-seconds
    390         ALOGE("Max file duration is too short: %lld us", timeUs);
    391         return BAD_VALUE;
    392     }
    393 
    394     if (timeUs <= 15 * 1000000LL) {
    395         ALOGW("Target duration (%lld us) too short to be respected", timeUs);
    396     }
    397     mMaxFileDurationUs = timeUs;
    398     return OK;
    399 }
    400 
    401 status_t StagefrightRecorder::setParamMaxFileSizeBytes(int64_t bytes) {
    402     ALOGV("setParamMaxFileSizeBytes: %lld bytes", bytes);
    403 
    404     // This is meant for backward compatibility for MediaRecorder.java
    405     if (bytes <= 0) {
    406         ALOGW("Max file size is not positive: %lld bytes. "
    407              "Disabling file size limit.", bytes);
    408         bytes = 0; // Disable the file size limit for zero or negative values.
    409     } else if (bytes <= 1024) {  // XXX: 1 kB
    410         ALOGE("Max file size is too small: %lld bytes", bytes);
    411         return BAD_VALUE;
    412     }
    413 
    414     if (bytes <= 100 * 1024) {
    415         ALOGW("Target file size (%lld bytes) is too small to be respected", bytes);
    416     }
    417 
    418     mMaxFileSizeBytes = bytes;
    419     return OK;
    420 }
    421 
    422 status_t StagefrightRecorder::setParamInterleaveDuration(int32_t durationUs) {
    423     ALOGV("setParamInterleaveDuration: %d", durationUs);
    424     if (durationUs <= 500000) {           //  500 ms
    425         // If interleave duration is too small, it is very inefficient to do
    426         // interleaving since the metadata overhead will count for a significant
    427         // portion of the saved contents
    428         ALOGE("Audio/video interleave duration is too small: %d us", durationUs);
    429         return BAD_VALUE;
    430     } else if (durationUs >= 10000000) {  // 10 seconds
    431         // If interleaving duration is too large, it can cause the recording
    432         // session to use too much memory since we have to save the output
    433         // data before we write them out
    434         ALOGE("Audio/video interleave duration is too large: %d us", durationUs);
    435         return BAD_VALUE;
    436     }
    437     mInterleaveDurationUs = durationUs;
    438     return OK;
    439 }
    440 
    441 // If seconds <  0, only the first frame is I frame, and rest are all P frames
    442 // If seconds == 0, all frames are encoded as I frames. No P frames
    443 // If seconds >  0, it is the time spacing (seconds) between 2 neighboring I frames
    444 status_t StagefrightRecorder::setParamVideoIFramesInterval(int32_t seconds) {
    445     ALOGV("setParamVideoIFramesInterval: %d seconds", seconds);
    446     mIFramesIntervalSec = seconds;
    447     return OK;
    448 }
    449 
    450 status_t StagefrightRecorder::setParam64BitFileOffset(bool use64Bit) {
    451     ALOGV("setParam64BitFileOffset: %s",
    452         use64Bit? "use 64 bit file offset": "use 32 bit file offset");
    453     mUse64BitFileOffset = use64Bit;
    454     return OK;
    455 }
    456 
    457 status_t StagefrightRecorder::setParamVideoCameraId(int32_t cameraId) {
    458     ALOGV("setParamVideoCameraId: %d", cameraId);
    459     if (cameraId < 0) {
    460         return BAD_VALUE;
    461     }
    462     mCameraId = cameraId;
    463     return OK;
    464 }
    465 
    466 status_t StagefrightRecorder::setParamTrackTimeStatus(int64_t timeDurationUs) {
    467     ALOGV("setParamTrackTimeStatus: %lld", timeDurationUs);
    468     if (timeDurationUs < 20000) {  // Infeasible if shorter than 20 ms?
    469         ALOGE("Tracking time duration too short: %lld us", timeDurationUs);
    470         return BAD_VALUE;
    471     }
    472     mTrackEveryTimeDurationUs = timeDurationUs;
    473     return OK;
    474 }
    475 
    476 status_t StagefrightRecorder::setParamVideoEncoderProfile(int32_t profile) {
    477     ALOGV("setParamVideoEncoderProfile: %d", profile);
    478 
    479     // Additional check will be done later when we load the encoder.
    480     // For now, we are accepting values defined in OpenMAX IL.
    481     mVideoEncoderProfile = profile;
    482     return OK;
    483 }
    484 
    485 status_t StagefrightRecorder::setParamVideoEncoderLevel(int32_t level) {
    486     ALOGV("setParamVideoEncoderLevel: %d", level);
    487 
    488     // Additional check will be done later when we load the encoder.
    489     // For now, we are accepting values defined in OpenMAX IL.
    490     mVideoEncoderLevel = level;
    491     return OK;
    492 }
    493 
    494 status_t StagefrightRecorder::setParamMovieTimeScale(int32_t timeScale) {
    495     ALOGV("setParamMovieTimeScale: %d", timeScale);
    496 
    497     // The range is set to be the same as the audio's time scale range
    498     // since audio's time scale has a wider range.
    499     if (timeScale < 600 || timeScale > 96000) {
    500         ALOGE("Time scale (%d) for movie is out of range [600, 96000]", timeScale);
    501         return BAD_VALUE;
    502     }
    503     mMovieTimeScale = timeScale;
    504     return OK;
    505 }
    506 
    507 status_t StagefrightRecorder::setParamVideoTimeScale(int32_t timeScale) {
    508     ALOGV("setParamVideoTimeScale: %d", timeScale);
    509 
    510     // 60000 is chosen to make sure that each video frame from a 60-fps
    511     // video has 1000 ticks.
    512     if (timeScale < 600 || timeScale > 60000) {
    513         ALOGE("Time scale (%d) for video is out of range [600, 60000]", timeScale);
    514         return BAD_VALUE;
    515     }
    516     mVideoTimeScale = timeScale;
    517     return OK;
    518 }
    519 
    520 status_t StagefrightRecorder::setParamAudioTimeScale(int32_t timeScale) {
    521     ALOGV("setParamAudioTimeScale: %d", timeScale);
    522 
    523     // 96000 Hz is the highest sampling rate support in AAC.
    524     if (timeScale < 600 || timeScale > 96000) {
    525         ALOGE("Time scale (%d) for audio is out of range [600, 96000]", timeScale);
    526         return BAD_VALUE;
    527     }
    528     mAudioTimeScale = timeScale;
    529     return OK;
    530 }
    531 
    532 status_t StagefrightRecorder::setParamTimeLapseEnable(int32_t timeLapseEnable) {
    533     ALOGV("setParamTimeLapseEnable: %d", timeLapseEnable);
    534 
    535     if(timeLapseEnable == 0) {
    536         mCaptureTimeLapse = false;
    537     } else if (timeLapseEnable == 1) {
    538         mCaptureTimeLapse = true;
    539     } else {
    540         return BAD_VALUE;
    541     }
    542     return OK;
    543 }
    544 
    545 status_t StagefrightRecorder::setParamTimeBetweenTimeLapseFrameCapture(int64_t timeUs) {
    546     ALOGV("setParamTimeBetweenTimeLapseFrameCapture: %lld us", timeUs);
    547 
    548     // Not allowing time more than a day
    549     if (timeUs <= 0 || timeUs > 86400*1E6) {
    550         ALOGE("Time between time lapse frame capture (%lld) is out of range [0, 1 Day]", timeUs);
    551         return BAD_VALUE;
    552     }
    553 
    554     mTimeBetweenTimeLapseFrameCaptureUs = timeUs;
    555     return OK;
    556 }
    557 
    558 status_t StagefrightRecorder::setParamGeoDataLongitude(
    559     int64_t longitudex10000) {
    560 
    561     if (longitudex10000 > 1800000 || longitudex10000 < -1800000) {
    562         return BAD_VALUE;
    563     }
    564     mLongitudex10000 = longitudex10000;
    565     return OK;
    566 }
    567 
    568 status_t StagefrightRecorder::setParamGeoDataLatitude(
    569     int64_t latitudex10000) {
    570 
    571     if (latitudex10000 > 900000 || latitudex10000 < -900000) {
    572         return BAD_VALUE;
    573     }
    574     mLatitudex10000 = latitudex10000;
    575     return OK;
    576 }
    577 
    578 status_t StagefrightRecorder::setParameter(
    579         const String8 &key, const String8 &value) {
    580     ALOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
    581     if (key == "max-duration") {
    582         int64_t max_duration_ms;
    583         if (safe_strtoi64(value.string(), &max_duration_ms)) {
    584             return setParamMaxFileDurationUs(1000LL * max_duration_ms);
    585         }
    586     } else if (key == "max-filesize") {
    587         int64_t max_filesize_bytes;
    588         if (safe_strtoi64(value.string(), &max_filesize_bytes)) {
    589             return setParamMaxFileSizeBytes(max_filesize_bytes);
    590         }
    591     } else if (key == "interleave-duration-us") {
    592         int32_t durationUs;
    593         if (safe_strtoi32(value.string(), &durationUs)) {
    594             return setParamInterleaveDuration(durationUs);
    595         }
    596     } else if (key == "param-movie-time-scale") {
    597         int32_t timeScale;
    598         if (safe_strtoi32(value.string(), &timeScale)) {
    599             return setParamMovieTimeScale(timeScale);
    600         }
    601     } else if (key == "param-use-64bit-offset") {
    602         int32_t use64BitOffset;
    603         if (safe_strtoi32(value.string(), &use64BitOffset)) {
    604             return setParam64BitFileOffset(use64BitOffset != 0);
    605         }
    606     } else if (key == "param-geotag-longitude") {
    607         int64_t longitudex10000;
    608         if (safe_strtoi64(value.string(), &longitudex10000)) {
    609             return setParamGeoDataLongitude(longitudex10000);
    610         }
    611     } else if (key == "param-geotag-latitude") {
    612         int64_t latitudex10000;
    613         if (safe_strtoi64(value.string(), &latitudex10000)) {
    614             return setParamGeoDataLatitude(latitudex10000);
    615         }
    616     } else if (key == "param-track-time-status") {
    617         int64_t timeDurationUs;
    618         if (safe_strtoi64(value.string(), &timeDurationUs)) {
    619             return setParamTrackTimeStatus(timeDurationUs);
    620         }
    621     } else if (key == "audio-param-sampling-rate") {
    622         int32_t sampling_rate;
    623         if (safe_strtoi32(value.string(), &sampling_rate)) {
    624             return setParamAudioSamplingRate(sampling_rate);
    625         }
    626     } else if (key == "audio-param-number-of-channels") {
    627         int32_t number_of_channels;
    628         if (safe_strtoi32(value.string(), &number_of_channels)) {
    629             return setParamAudioNumberOfChannels(number_of_channels);
    630         }
    631     } else if (key == "audio-param-encoding-bitrate") {
    632         int32_t audio_bitrate;
    633         if (safe_strtoi32(value.string(), &audio_bitrate)) {
    634             return setParamAudioEncodingBitRate(audio_bitrate);
    635         }
    636     } else if (key == "audio-param-time-scale") {
    637         int32_t timeScale;
    638         if (safe_strtoi32(value.string(), &timeScale)) {
    639             return setParamAudioTimeScale(timeScale);
    640         }
    641     } else if (key == "video-param-encoding-bitrate") {
    642         int32_t video_bitrate;
    643         if (safe_strtoi32(value.string(), &video_bitrate)) {
    644             return setParamVideoEncodingBitRate(video_bitrate);
    645         }
    646     } else if (key == "video-param-rotation-angle-degrees") {
    647         int32_t degrees;
    648         if (safe_strtoi32(value.string(), &degrees)) {
    649             return setParamVideoRotation(degrees);
    650         }
    651     } else if (key == "video-param-i-frames-interval") {
    652         int32_t seconds;
    653         if (safe_strtoi32(value.string(), &seconds)) {
    654             return setParamVideoIFramesInterval(seconds);
    655         }
    656     } else if (key == "video-param-encoder-profile") {
    657         int32_t profile;
    658         if (safe_strtoi32(value.string(), &profile)) {
    659             return setParamVideoEncoderProfile(profile);
    660         }
    661     } else if (key == "video-param-encoder-level") {
    662         int32_t level;
    663         if (safe_strtoi32(value.string(), &level)) {
    664             return setParamVideoEncoderLevel(level);
    665         }
    666     } else if (key == "video-param-camera-id") {
    667         int32_t cameraId;
    668         if (safe_strtoi32(value.string(), &cameraId)) {
    669             return setParamVideoCameraId(cameraId);
    670         }
    671     } else if (key == "video-param-time-scale") {
    672         int32_t timeScale;
    673         if (safe_strtoi32(value.string(), &timeScale)) {
    674             return setParamVideoTimeScale(timeScale);
    675         }
    676     } else if (key == "time-lapse-enable") {
    677         int32_t timeLapseEnable;
    678         if (safe_strtoi32(value.string(), &timeLapseEnable)) {
    679             return setParamTimeLapseEnable(timeLapseEnable);
    680         }
    681     } else if (key == "time-between-time-lapse-frame-capture") {
    682         int64_t timeBetweenTimeLapseFrameCaptureMs;
    683         if (safe_strtoi64(value.string(), &timeBetweenTimeLapseFrameCaptureMs)) {
    684             return setParamTimeBetweenTimeLapseFrameCapture(
    685                     1000LL * timeBetweenTimeLapseFrameCaptureMs);
    686         }
    687     } else {
    688         ALOGE("setParameter: failed to find key %s", key.string());
    689     }
    690     return BAD_VALUE;
    691 }
    692 
    693 status_t StagefrightRecorder::setParameters(const String8 &params) {
    694     ALOGV("setParameters: %s", params.string());
    695     const char *cparams = params.string();
    696     const char *key_start = cparams;
    697     for (;;) {
    698         const char *equal_pos = strchr(key_start, '=');
    699         if (equal_pos == NULL) {
    700             ALOGE("Parameters %s miss a value", cparams);
    701             return BAD_VALUE;
    702         }
    703         String8 key(key_start, equal_pos - key_start);
    704         TrimString(&key);
    705         if (key.length() == 0) {
    706             ALOGE("Parameters %s contains an empty key", cparams);
    707             return BAD_VALUE;
    708         }
    709         const char *value_start = equal_pos + 1;
    710         const char *semicolon_pos = strchr(value_start, ';');
    711         String8 value;
    712         if (semicolon_pos == NULL) {
    713             value.setTo(value_start);
    714         } else {
    715             value.setTo(value_start, semicolon_pos - value_start);
    716         }
    717         if (setParameter(key, value) != OK) {
    718             return BAD_VALUE;
    719         }
    720         if (semicolon_pos == NULL) {
    721             break;  // Reaches the end
    722         }
    723         key_start = semicolon_pos + 1;
    724     }
    725     return OK;
    726 }
    727 
    728 status_t StagefrightRecorder::setListener(const sp<IMediaRecorderClient> &listener) {
    729     mListener = listener;
    730 
    731     return OK;
    732 }
    733 
    734 status_t StagefrightRecorder::setClientName(const String16& clientName) {
    735     mClientName = clientName;
    736 
    737     return OK;
    738 }
    739 
    740 status_t StagefrightRecorder::prepare() {
    741     return OK;
    742 }
    743 
    744 status_t StagefrightRecorder::start() {
    745     CHECK_GE(mOutputFd, 0);
    746 
    747     // Get UID here for permission checking
    748     mClientUid = IPCThreadState::self()->getCallingUid();
    749     if (mWriter != NULL) {
    750         ALOGE("File writer is not avaialble");
    751         return UNKNOWN_ERROR;
    752     }
    753 
    754     status_t status = OK;
    755 
    756     switch (mOutputFormat) {
    757         case OUTPUT_FORMAT_DEFAULT:
    758         case OUTPUT_FORMAT_THREE_GPP:
    759         case OUTPUT_FORMAT_MPEG_4:
    760             status = startMPEG4Recording();
    761             break;
    762 
    763         case OUTPUT_FORMAT_AMR_NB:
    764         case OUTPUT_FORMAT_AMR_WB:
    765             status = startAMRRecording();
    766             break;
    767 
    768         case OUTPUT_FORMAT_AAC_ADIF:
    769         case OUTPUT_FORMAT_AAC_ADTS:
    770             status = startAACRecording();
    771             break;
    772 
    773         case OUTPUT_FORMAT_RTP_AVP:
    774             status = startRTPRecording();
    775             break;
    776 
    777         case OUTPUT_FORMAT_MPEG2TS:
    778             status = startMPEG2TSRecording();
    779             break;
    780 
    781         default:
    782             ALOGE("Unsupported output file format: %d", mOutputFormat);
    783             status = UNKNOWN_ERROR;
    784             break;
    785     }
    786 
    787     if ((status == OK) && (!mStarted)) {
    788         mStarted = true;
    789 
    790         uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted;
    791         if (mAudioSource != AUDIO_SOURCE_CNT) {
    792             params |= IMediaPlayerService::kBatteryDataTrackAudio;
    793         }
    794         if (mVideoSource != VIDEO_SOURCE_LIST_END) {
    795             params |= IMediaPlayerService::kBatteryDataTrackVideo;
    796         }
    797 
    798         addBatteryData(params);
    799     }
    800 
    801     return status;
    802 }
    803 
    804 sp<MediaSource> StagefrightRecorder::createAudioSource() {
    805     sp<AudioSource> audioSource =
    806         new AudioSource(
    807                 mAudioSource,
    808                 mSampleRate,
    809                 mAudioChannels);
    810 
    811     status_t err = audioSource->initCheck();
    812 
    813     if (err != OK) {
    814         ALOGE("audio source is not initialized");
    815         return NULL;
    816     }
    817 
    818     sp<MetaData> encMeta = new MetaData;
    819     const char *mime;
    820     switch (mAudioEncoder) {
    821         case AUDIO_ENCODER_AMR_NB:
    822         case AUDIO_ENCODER_DEFAULT:
    823             mime = MEDIA_MIMETYPE_AUDIO_AMR_NB;
    824             break;
    825         case AUDIO_ENCODER_AMR_WB:
    826             mime = MEDIA_MIMETYPE_AUDIO_AMR_WB;
    827             break;
    828         case AUDIO_ENCODER_AAC:
    829             mime = MEDIA_MIMETYPE_AUDIO_AAC;
    830             encMeta->setInt32(kKeyAACProfile, OMX_AUDIO_AACObjectLC);
    831             break;
    832         case AUDIO_ENCODER_HE_AAC:
    833             mime = MEDIA_MIMETYPE_AUDIO_AAC;
    834             encMeta->setInt32(kKeyAACProfile, OMX_AUDIO_AACObjectHE);
    835             break;
    836         case AUDIO_ENCODER_AAC_ELD:
    837             mime = MEDIA_MIMETYPE_AUDIO_AAC;
    838             encMeta->setInt32(kKeyAACProfile, OMX_AUDIO_AACObjectELD);
    839             break;
    840 
    841         default:
    842             ALOGE("Unknown audio encoder: %d", mAudioEncoder);
    843             return NULL;
    844     }
    845     encMeta->setCString(kKeyMIMEType, mime);
    846 
    847     int32_t maxInputSize;
    848     CHECK(audioSource->getFormat()->findInt32(
    849                 kKeyMaxInputSize, &maxInputSize));
    850 
    851     encMeta->setInt32(kKeyMaxInputSize, maxInputSize);
    852     encMeta->setInt32(kKeyChannelCount, mAudioChannels);
    853     encMeta->setInt32(kKeySampleRate, mSampleRate);
    854     encMeta->setInt32(kKeyBitRate, mAudioBitRate);
    855     if (mAudioTimeScale > 0) {
    856         encMeta->setInt32(kKeyTimeScale, mAudioTimeScale);
    857     }
    858 
    859     OMXClient client;
    860     CHECK_EQ(client.connect(), (status_t)OK);
    861     sp<MediaSource> audioEncoder =
    862         OMXCodec::Create(client.interface(), encMeta,
    863                          true /* createEncoder */, audioSource);
    864     mAudioSourceNode = audioSource;
    865 
    866     return audioEncoder;
    867 }
    868 
    869 status_t StagefrightRecorder::startAACRecording() {
    870     // FIXME:
    871     // Add support for OUTPUT_FORMAT_AAC_ADIF
    872     CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_AAC_ADTS);
    873 
    874     CHECK(mAudioEncoder == AUDIO_ENCODER_AAC ||
    875           mAudioEncoder == AUDIO_ENCODER_HE_AAC ||
    876           mAudioEncoder == AUDIO_ENCODER_AAC_ELD);
    877     CHECK(mAudioSource != AUDIO_SOURCE_CNT);
    878 
    879     mWriter = new AACWriter(mOutputFd);
    880     status_t status = startRawAudioRecording();
    881     if (status != OK) {
    882         mWriter.clear();
    883         mWriter = NULL;
    884     }
    885 
    886     return status;
    887 }
    888 
    889 status_t StagefrightRecorder::startAMRRecording() {
    890     CHECK(mOutputFormat == OUTPUT_FORMAT_AMR_NB ||
    891           mOutputFormat == OUTPUT_FORMAT_AMR_WB);
    892 
    893     if (mOutputFormat == OUTPUT_FORMAT_AMR_NB) {
    894         if (mAudioEncoder != AUDIO_ENCODER_DEFAULT &&
    895             mAudioEncoder != AUDIO_ENCODER_AMR_NB) {
    896             ALOGE("Invalid encoder %d used for AMRNB recording",
    897                     mAudioEncoder);
    898             return BAD_VALUE;
    899         }
    900     } else {  // mOutputFormat must be OUTPUT_FORMAT_AMR_WB
    901         if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
    902             ALOGE("Invlaid encoder %d used for AMRWB recording",
    903                     mAudioEncoder);
    904             return BAD_VALUE;
    905         }
    906     }
    907 
    908     mWriter = new AMRWriter(mOutputFd);
    909     status_t status = startRawAudioRecording();
    910     if (status != OK) {
    911         mWriter.clear();
    912         mWriter = NULL;
    913     }
    914     return status;
    915 }
    916 
    917 status_t StagefrightRecorder::startRawAudioRecording() {
    918     if (mAudioSource >= AUDIO_SOURCE_CNT) {
    919         ALOGE("Invalid audio source: %d", mAudioSource);
    920         return BAD_VALUE;
    921     }
    922 
    923     status_t status = BAD_VALUE;
    924     if (OK != (status = checkAudioEncoderCapabilities())) {
    925         return status;
    926     }
    927 
    928     sp<MediaSource> audioEncoder = createAudioSource();
    929     if (audioEncoder == NULL) {
    930         return UNKNOWN_ERROR;
    931     }
    932 
    933     CHECK(mWriter != 0);
    934     mWriter->addSource(audioEncoder);
    935 
    936     if (mMaxFileDurationUs != 0) {
    937         mWriter->setMaxFileDuration(mMaxFileDurationUs);
    938     }
    939     if (mMaxFileSizeBytes != 0) {
    940         mWriter->setMaxFileSize(mMaxFileSizeBytes);
    941     }
    942     mWriter->setListener(mListener);
    943     mWriter->start();
    944 
    945     return OK;
    946 }
    947 
    948 status_t StagefrightRecorder::startRTPRecording() {
    949     CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_RTP_AVP);
    950 
    951     if ((mAudioSource != AUDIO_SOURCE_CNT
    952                 && mVideoSource != VIDEO_SOURCE_LIST_END)
    953             || (mAudioSource == AUDIO_SOURCE_CNT
    954                 && mVideoSource == VIDEO_SOURCE_LIST_END)) {
    955         // Must have exactly one source.
    956         return BAD_VALUE;
    957     }
    958 
    959     if (mOutputFd < 0) {
    960         return BAD_VALUE;
    961     }
    962 
    963     sp<MediaSource> source;
    964 
    965     if (mAudioSource != AUDIO_SOURCE_CNT) {
    966         source = createAudioSource();
    967     } else {
    968 
    969         sp<MediaSource> mediaSource;
    970         status_t err = setupMediaSource(&mediaSource);
    971         if (err != OK) {
    972             return err;
    973         }
    974 
    975         err = setupVideoEncoder(mediaSource, mVideoBitRate, &source);
    976         if (err != OK) {
    977             return err;
    978         }
    979     }
    980 
    981     mWriter = new ARTPWriter(mOutputFd);
    982     mWriter->addSource(source);
    983     mWriter->setListener(mListener);
    984 
    985     return mWriter->start();
    986 }
    987 
    988 status_t StagefrightRecorder::startMPEG2TSRecording() {
    989     CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_MPEG2TS);
    990 
    991     sp<MediaWriter> writer = new MPEG2TSWriter(mOutputFd);
    992 
    993     if (mAudioSource != AUDIO_SOURCE_CNT) {
    994         if (mAudioEncoder != AUDIO_ENCODER_AAC &&
    995             mAudioEncoder != AUDIO_ENCODER_HE_AAC &&
    996             mAudioEncoder != AUDIO_ENCODER_AAC_ELD) {
    997             return ERROR_UNSUPPORTED;
    998         }
    999 
   1000         status_t err = setupAudioEncoder(writer);
   1001 
   1002         if (err != OK) {
   1003             return err;
   1004         }
   1005     }
   1006 
   1007     if (mVideoSource < VIDEO_SOURCE_LIST_END) {
   1008         if (mVideoEncoder != VIDEO_ENCODER_H264) {
   1009             return ERROR_UNSUPPORTED;
   1010         }
   1011 
   1012         sp<MediaSource> mediaSource;
   1013         status_t err = setupMediaSource(&mediaSource);
   1014         if (err != OK) {
   1015             return err;
   1016         }
   1017 
   1018         sp<MediaSource> encoder;
   1019         err = setupVideoEncoder(mediaSource, mVideoBitRate, &encoder);
   1020 
   1021         if (err != OK) {
   1022             return err;
   1023         }
   1024 
   1025         writer->addSource(encoder);
   1026     }
   1027 
   1028     if (mMaxFileDurationUs != 0) {
   1029         writer->setMaxFileDuration(mMaxFileDurationUs);
   1030     }
   1031 
   1032     if (mMaxFileSizeBytes != 0) {
   1033         writer->setMaxFileSize(mMaxFileSizeBytes);
   1034     }
   1035 
   1036     mWriter = writer;
   1037 
   1038     return mWriter->start();
   1039 }
   1040 
   1041 void StagefrightRecorder::clipVideoFrameRate() {
   1042     ALOGV("clipVideoFrameRate: encoder %d", mVideoEncoder);
   1043     int minFrameRate = mEncoderProfiles->getVideoEncoderParamByName(
   1044                         "enc.vid.fps.min", mVideoEncoder);
   1045     int maxFrameRate = mEncoderProfiles->getVideoEncoderParamByName(
   1046                         "enc.vid.fps.max", mVideoEncoder);
   1047     if (mFrameRate < minFrameRate && minFrameRate != -1) {
   1048         ALOGW("Intended video encoding frame rate (%d fps) is too small"
   1049              " and will be set to (%d fps)", mFrameRate, minFrameRate);
   1050         mFrameRate = minFrameRate;
   1051     } else if (mFrameRate > maxFrameRate && maxFrameRate != -1) {
   1052         ALOGW("Intended video encoding frame rate (%d fps) is too large"
   1053              " and will be set to (%d fps)", mFrameRate, maxFrameRate);
   1054         mFrameRate = maxFrameRate;
   1055     }
   1056 }
   1057 
   1058 void StagefrightRecorder::clipVideoBitRate() {
   1059     ALOGV("clipVideoBitRate: encoder %d", mVideoEncoder);
   1060     int minBitRate = mEncoderProfiles->getVideoEncoderParamByName(
   1061                         "enc.vid.bps.min", mVideoEncoder);
   1062     int maxBitRate = mEncoderProfiles->getVideoEncoderParamByName(
   1063                         "enc.vid.bps.max", mVideoEncoder);
   1064     if (mVideoBitRate < minBitRate && minBitRate != -1) {
   1065         ALOGW("Intended video encoding bit rate (%d bps) is too small"
   1066              " and will be set to (%d bps)", mVideoBitRate, minBitRate);
   1067         mVideoBitRate = minBitRate;
   1068     } else if (mVideoBitRate > maxBitRate && maxBitRate != -1) {
   1069         ALOGW("Intended video encoding bit rate (%d bps) is too large"
   1070              " and will be set to (%d bps)", mVideoBitRate, maxBitRate);
   1071         mVideoBitRate = maxBitRate;
   1072     }
   1073 }
   1074 
   1075 void StagefrightRecorder::clipVideoFrameWidth() {
   1076     ALOGV("clipVideoFrameWidth: encoder %d", mVideoEncoder);
   1077     int minFrameWidth = mEncoderProfiles->getVideoEncoderParamByName(
   1078                         "enc.vid.width.min", mVideoEncoder);
   1079     int maxFrameWidth = mEncoderProfiles->getVideoEncoderParamByName(
   1080                         "enc.vid.width.max", mVideoEncoder);
   1081     if (mVideoWidth < minFrameWidth && minFrameWidth != -1) {
   1082         ALOGW("Intended video encoding frame width (%d) is too small"
   1083              " and will be set to (%d)", mVideoWidth, minFrameWidth);
   1084         mVideoWidth = minFrameWidth;
   1085     } else if (mVideoWidth > maxFrameWidth && maxFrameWidth != -1) {
   1086         ALOGW("Intended video encoding frame width (%d) is too large"
   1087              " and will be set to (%d)", mVideoWidth, maxFrameWidth);
   1088         mVideoWidth = maxFrameWidth;
   1089     }
   1090 }
   1091 
   1092 status_t StagefrightRecorder::checkVideoEncoderCapabilities() {
   1093     if (!mCaptureTimeLapse) {
   1094         // Dont clip for time lapse capture as encoder will have enough
   1095         // time to encode because of slow capture rate of time lapse.
   1096         clipVideoBitRate();
   1097         clipVideoFrameRate();
   1098         clipVideoFrameWidth();
   1099         clipVideoFrameHeight();
   1100         setDefaultProfileIfNecessary();
   1101     }
   1102     return OK;
   1103 }
   1104 
   1105 // Set to use AVC baseline profile if the encoding parameters matches
   1106 // CAMCORDER_QUALITY_LOW profile; this is for the sake of MMS service.
   1107 void StagefrightRecorder::setDefaultProfileIfNecessary() {
   1108     ALOGV("setDefaultProfileIfNecessary");
   1109 
   1110     camcorder_quality quality = CAMCORDER_QUALITY_LOW;
   1111 
   1112     int64_t durationUs   = mEncoderProfiles->getCamcorderProfileParamByName(
   1113                                 "duration", mCameraId, quality) * 1000000LL;
   1114 
   1115     int fileFormat       = mEncoderProfiles->getCamcorderProfileParamByName(
   1116                                 "file.format", mCameraId, quality);
   1117 
   1118     int videoCodec       = mEncoderProfiles->getCamcorderProfileParamByName(
   1119                                 "vid.codec", mCameraId, quality);
   1120 
   1121     int videoBitRate     = mEncoderProfiles->getCamcorderProfileParamByName(
   1122                                 "vid.bps", mCameraId, quality);
   1123 
   1124     int videoFrameRate   = mEncoderProfiles->getCamcorderProfileParamByName(
   1125                                 "vid.fps", mCameraId, quality);
   1126 
   1127     int videoFrameWidth  = mEncoderProfiles->getCamcorderProfileParamByName(
   1128                                 "vid.width", mCameraId, quality);
   1129 
   1130     int videoFrameHeight = mEncoderProfiles->getCamcorderProfileParamByName(
   1131                                 "vid.height", mCameraId, quality);
   1132 
   1133     int audioCodec       = mEncoderProfiles->getCamcorderProfileParamByName(
   1134                                 "aud.codec", mCameraId, quality);
   1135 
   1136     int audioBitRate     = mEncoderProfiles->getCamcorderProfileParamByName(
   1137                                 "aud.bps", mCameraId, quality);
   1138 
   1139     int audioSampleRate  = mEncoderProfiles->getCamcorderProfileParamByName(
   1140                                 "aud.hz", mCameraId, quality);
   1141 
   1142     int audioChannels    = mEncoderProfiles->getCamcorderProfileParamByName(
   1143                                 "aud.ch", mCameraId, quality);
   1144 
   1145     if (durationUs == mMaxFileDurationUs &&
   1146         fileFormat == mOutputFormat &&
   1147         videoCodec == mVideoEncoder &&
   1148         videoBitRate == mVideoBitRate &&
   1149         videoFrameRate == mFrameRate &&
   1150         videoFrameWidth == mVideoWidth &&
   1151         videoFrameHeight == mVideoHeight &&
   1152         audioCodec == mAudioEncoder &&
   1153         audioBitRate == mAudioBitRate &&
   1154         audioSampleRate == mSampleRate &&
   1155         audioChannels == mAudioChannels) {
   1156         if (videoCodec == VIDEO_ENCODER_H264) {
   1157             ALOGI("Force to use AVC baseline profile");
   1158             setParamVideoEncoderProfile(OMX_VIDEO_AVCProfileBaseline);
   1159         }
   1160     }
   1161 }
   1162 
   1163 status_t StagefrightRecorder::checkAudioEncoderCapabilities() {
   1164     clipAudioBitRate();
   1165     clipAudioSampleRate();
   1166     clipNumberOfAudioChannels();
   1167     return OK;
   1168 }
   1169 
   1170 void StagefrightRecorder::clipAudioBitRate() {
   1171     ALOGV("clipAudioBitRate: encoder %d", mAudioEncoder);
   1172 
   1173     int minAudioBitRate =
   1174             mEncoderProfiles->getAudioEncoderParamByName(
   1175                 "enc.aud.bps.min", mAudioEncoder);
   1176     if (minAudioBitRate != -1 && mAudioBitRate < minAudioBitRate) {
   1177         ALOGW("Intended audio encoding bit rate (%d) is too small"
   1178             " and will be set to (%d)", mAudioBitRate, minAudioBitRate);
   1179         mAudioBitRate = minAudioBitRate;
   1180     }
   1181 
   1182     int maxAudioBitRate =
   1183             mEncoderProfiles->getAudioEncoderParamByName(
   1184                 "enc.aud.bps.max", mAudioEncoder);
   1185     if (maxAudioBitRate != -1 && mAudioBitRate > maxAudioBitRate) {
   1186         ALOGW("Intended audio encoding bit rate (%d) is too large"
   1187             " and will be set to (%d)", mAudioBitRate, maxAudioBitRate);
   1188         mAudioBitRate = maxAudioBitRate;
   1189     }
   1190 }
   1191 
   1192 void StagefrightRecorder::clipAudioSampleRate() {
   1193     ALOGV("clipAudioSampleRate: encoder %d", mAudioEncoder);
   1194 
   1195     int minSampleRate =
   1196             mEncoderProfiles->getAudioEncoderParamByName(
   1197                 "enc.aud.hz.min", mAudioEncoder);
   1198     if (minSampleRate != -1 && mSampleRate < minSampleRate) {
   1199         ALOGW("Intended audio sample rate (%d) is too small"
   1200             " and will be set to (%d)", mSampleRate, minSampleRate);
   1201         mSampleRate = minSampleRate;
   1202     }
   1203 
   1204     int maxSampleRate =
   1205             mEncoderProfiles->getAudioEncoderParamByName(
   1206                 "enc.aud.hz.max", mAudioEncoder);
   1207     if (maxSampleRate != -1 && mSampleRate > maxSampleRate) {
   1208         ALOGW("Intended audio sample rate (%d) is too large"
   1209             " and will be set to (%d)", mSampleRate, maxSampleRate);
   1210         mSampleRate = maxSampleRate;
   1211     }
   1212 }
   1213 
   1214 void StagefrightRecorder::clipNumberOfAudioChannels() {
   1215     ALOGV("clipNumberOfAudioChannels: encoder %d", mAudioEncoder);
   1216 
   1217     int minChannels =
   1218             mEncoderProfiles->getAudioEncoderParamByName(
   1219                 "enc.aud.ch.min", mAudioEncoder);
   1220     if (minChannels != -1 && mAudioChannels < minChannels) {
   1221         ALOGW("Intended number of audio channels (%d) is too small"
   1222             " and will be set to (%d)", mAudioChannels, minChannels);
   1223         mAudioChannels = minChannels;
   1224     }
   1225 
   1226     int maxChannels =
   1227             mEncoderProfiles->getAudioEncoderParamByName(
   1228                 "enc.aud.ch.max", mAudioEncoder);
   1229     if (maxChannels != -1 && mAudioChannels > maxChannels) {
   1230         ALOGW("Intended number of audio channels (%d) is too large"
   1231             " and will be set to (%d)", mAudioChannels, maxChannels);
   1232         mAudioChannels = maxChannels;
   1233     }
   1234 }
   1235 
   1236 void StagefrightRecorder::clipVideoFrameHeight() {
   1237     ALOGV("clipVideoFrameHeight: encoder %d", mVideoEncoder);
   1238     int minFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
   1239                         "enc.vid.height.min", mVideoEncoder);
   1240     int maxFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
   1241                         "enc.vid.height.max", mVideoEncoder);
   1242     if (minFrameHeight != -1 && mVideoHeight < minFrameHeight) {
   1243         ALOGW("Intended video encoding frame height (%d) is too small"
   1244              " and will be set to (%d)", mVideoHeight, minFrameHeight);
   1245         mVideoHeight = minFrameHeight;
   1246     } else if (maxFrameHeight != -1 && mVideoHeight > maxFrameHeight) {
   1247         ALOGW("Intended video encoding frame height (%d) is too large"
   1248              " and will be set to (%d)", mVideoHeight, maxFrameHeight);
   1249         mVideoHeight = maxFrameHeight;
   1250     }
   1251 }
   1252 
   1253 // Set up the appropriate MediaSource depending on the chosen option
   1254 status_t StagefrightRecorder::setupMediaSource(
   1255                       sp<MediaSource> *mediaSource) {
   1256     if (mVideoSource == VIDEO_SOURCE_DEFAULT
   1257             || mVideoSource == VIDEO_SOURCE_CAMERA) {
   1258         sp<CameraSource> cameraSource;
   1259         status_t err = setupCameraSource(&cameraSource);
   1260         if (err != OK) {
   1261             return err;
   1262         }
   1263         *mediaSource = cameraSource;
   1264     } else if (mVideoSource == VIDEO_SOURCE_GRALLOC_BUFFER) {
   1265         // If using GRAlloc buffers, setup surfacemediasource.
   1266         // Later a handle to that will be passed
   1267         // to the client side when queried
   1268         status_t err = setupSurfaceMediaSource();
   1269         if (err != OK) {
   1270             return err;
   1271         }
   1272         *mediaSource = mSurfaceMediaSource;
   1273     } else {
   1274         return INVALID_OPERATION;
   1275     }
   1276     return OK;
   1277 }
   1278 
   1279 // setupSurfaceMediaSource creates a source with the given
   1280 // width and height and framerate.
   1281 // TODO: This could go in a static function inside SurfaceMediaSource
   1282 // similar to that in CameraSource
   1283 status_t StagefrightRecorder::setupSurfaceMediaSource() {
   1284     status_t err = OK;
   1285     mSurfaceMediaSource = new SurfaceMediaSource(mVideoWidth, mVideoHeight);
   1286     if (mSurfaceMediaSource == NULL) {
   1287         return NO_INIT;
   1288     }
   1289 
   1290     if (mFrameRate == -1) {
   1291         int32_t frameRate = 0;
   1292         CHECK (mSurfaceMediaSource->getFormat()->findInt32(
   1293                                         kKeyFrameRate, &frameRate));
   1294         ALOGI("Frame rate is not explicitly set. Use the current frame "
   1295              "rate (%d fps)", frameRate);
   1296         mFrameRate = frameRate;
   1297     } else {
   1298         err = mSurfaceMediaSource->setFrameRate(mFrameRate);
   1299     }
   1300     CHECK(mFrameRate != -1);
   1301 
   1302     mIsMetaDataStoredInVideoBuffers =
   1303         mSurfaceMediaSource->isMetaDataStoredInVideoBuffers();
   1304     return err;
   1305 }
   1306 
   1307 status_t StagefrightRecorder::setupCameraSource(
   1308         sp<CameraSource> *cameraSource) {
   1309     status_t err = OK;
   1310     if ((err = checkVideoEncoderCapabilities()) != OK) {
   1311         return err;
   1312     }
   1313     Size videoSize;
   1314     videoSize.width = mVideoWidth;
   1315     videoSize.height = mVideoHeight;
   1316     if (mCaptureTimeLapse) {
   1317         if (mTimeBetweenTimeLapseFrameCaptureUs < 0) {
   1318             ALOGE("Invalid mTimeBetweenTimeLapseFrameCaptureUs value: %lld",
   1319                 mTimeBetweenTimeLapseFrameCaptureUs);
   1320             return BAD_VALUE;
   1321         }
   1322 
   1323         mCameraSourceTimeLapse = CameraSourceTimeLapse::CreateFromCamera(
   1324                 mCamera, mCameraProxy, mCameraId, mClientName, mClientUid,
   1325                 videoSize, mFrameRate, mPreviewSurface,
   1326                 mTimeBetweenTimeLapseFrameCaptureUs);
   1327         *cameraSource = mCameraSourceTimeLapse;
   1328     } else {
   1329         *cameraSource = CameraSource::CreateFromCamera(
   1330                 mCamera, mCameraProxy, mCameraId, mClientName, mClientUid,
   1331                 videoSize, mFrameRate,
   1332                 mPreviewSurface, true /*storeMetaDataInVideoBuffers*/);
   1333     }
   1334     mCamera.clear();
   1335     mCameraProxy.clear();
   1336     if (*cameraSource == NULL) {
   1337         return UNKNOWN_ERROR;
   1338     }
   1339 
   1340     if ((*cameraSource)->initCheck() != OK) {
   1341         (*cameraSource).clear();
   1342         *cameraSource = NULL;
   1343         return NO_INIT;
   1344     }
   1345 
   1346     // When frame rate is not set, the actual frame rate will be set to
   1347     // the current frame rate being used.
   1348     if (mFrameRate == -1) {
   1349         int32_t frameRate = 0;
   1350         CHECK ((*cameraSource)->getFormat()->findInt32(
   1351                     kKeyFrameRate, &frameRate));
   1352         ALOGI("Frame rate is not explicitly set. Use the current frame "
   1353              "rate (%d fps)", frameRate);
   1354         mFrameRate = frameRate;
   1355     }
   1356 
   1357     CHECK(mFrameRate != -1);
   1358 
   1359     mIsMetaDataStoredInVideoBuffers =
   1360         (*cameraSource)->isMetaDataStoredInVideoBuffers();
   1361 
   1362     return OK;
   1363 }
   1364 
   1365 status_t StagefrightRecorder::setupVideoEncoder(
   1366         sp<MediaSource> cameraSource,
   1367         int32_t videoBitRate,
   1368         sp<MediaSource> *source) {
   1369     source->clear();
   1370 
   1371     sp<MetaData> enc_meta = new MetaData;
   1372     enc_meta->setInt32(kKeyBitRate, videoBitRate);
   1373     enc_meta->setInt32(kKeyFrameRate, mFrameRate);
   1374 
   1375     switch (mVideoEncoder) {
   1376         case VIDEO_ENCODER_H263:
   1377             enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
   1378             break;
   1379 
   1380         case VIDEO_ENCODER_MPEG_4_SP:
   1381             enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
   1382             break;
   1383 
   1384         case VIDEO_ENCODER_H264:
   1385             enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
   1386             break;
   1387 
   1388         default:
   1389             CHECK(!"Should not be here, unsupported video encoding.");
   1390             break;
   1391     }
   1392 
   1393     sp<MetaData> meta = cameraSource->getFormat();
   1394 
   1395     int32_t width, height, stride, sliceHeight, colorFormat;
   1396     CHECK(meta->findInt32(kKeyWidth, &width));
   1397     CHECK(meta->findInt32(kKeyHeight, &height));
   1398     CHECK(meta->findInt32(kKeyStride, &stride));
   1399     CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight));
   1400     CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));
   1401 
   1402     enc_meta->setInt32(kKeyWidth, width);
   1403     enc_meta->setInt32(kKeyHeight, height);
   1404     enc_meta->setInt32(kKeyIFramesInterval, mIFramesIntervalSec);
   1405     enc_meta->setInt32(kKeyStride, stride);
   1406     enc_meta->setInt32(kKeySliceHeight, sliceHeight);
   1407     enc_meta->setInt32(kKeyColorFormat, colorFormat);
   1408     if (mVideoTimeScale > 0) {
   1409         enc_meta->setInt32(kKeyTimeScale, mVideoTimeScale);
   1410     }
   1411     if (mVideoEncoderProfile != -1) {
   1412         enc_meta->setInt32(kKeyVideoProfile, mVideoEncoderProfile);
   1413     }
   1414     if (mVideoEncoderLevel != -1) {
   1415         enc_meta->setInt32(kKeyVideoLevel, mVideoEncoderLevel);
   1416     }
   1417 
   1418     OMXClient client;
   1419     CHECK_EQ(client.connect(), (status_t)OK);
   1420 
   1421     uint32_t encoder_flags = 0;
   1422     if (mIsMetaDataStoredInVideoBuffers) {
   1423         encoder_flags |= OMXCodec::kStoreMetaDataInVideoBuffers;
   1424     }
   1425 
   1426     // Do not wait for all the input buffers to become available.
   1427     // This give timelapse video recording faster response in
   1428     // receiving output from video encoder component.
   1429     if (mCaptureTimeLapse) {
   1430         encoder_flags |= OMXCodec::kOnlySubmitOneInputBufferAtOneTime;
   1431     }
   1432 
   1433     sp<MediaSource> encoder = OMXCodec::Create(
   1434             client.interface(), enc_meta,
   1435             true /* createEncoder */, cameraSource,
   1436             NULL, encoder_flags);
   1437     if (encoder == NULL) {
   1438         ALOGW("Failed to create the encoder");
   1439         // When the encoder fails to be created, we need
   1440         // release the camera source due to the camera's lock
   1441         // and unlock mechanism.
   1442         cameraSource->stop();
   1443         return UNKNOWN_ERROR;
   1444     }
   1445 
   1446     *source = encoder;
   1447 
   1448     return OK;
   1449 }
   1450 
   1451 status_t StagefrightRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) {
   1452     status_t status = BAD_VALUE;
   1453     if (OK != (status = checkAudioEncoderCapabilities())) {
   1454         return status;
   1455     }
   1456 
   1457     switch(mAudioEncoder) {
   1458         case AUDIO_ENCODER_AMR_NB:
   1459         case AUDIO_ENCODER_AMR_WB:
   1460         case AUDIO_ENCODER_AAC:
   1461         case AUDIO_ENCODER_HE_AAC:
   1462         case AUDIO_ENCODER_AAC_ELD:
   1463             break;
   1464 
   1465         default:
   1466             ALOGE("Unsupported audio encoder: %d", mAudioEncoder);
   1467             return UNKNOWN_ERROR;
   1468     }
   1469 
   1470     sp<MediaSource> audioEncoder = createAudioSource();
   1471     if (audioEncoder == NULL) {
   1472         return UNKNOWN_ERROR;
   1473     }
   1474 
   1475     writer->addSource(audioEncoder);
   1476     return OK;
   1477 }
   1478 
   1479 status_t StagefrightRecorder::setupMPEG4Recording(
   1480         int outputFd,
   1481         int32_t videoWidth, int32_t videoHeight,
   1482         int32_t videoBitRate,
   1483         int32_t *totalBitRate,
   1484         sp<MediaWriter> *mediaWriter) {
   1485     mediaWriter->clear();
   1486     *totalBitRate = 0;
   1487     status_t err = OK;
   1488     sp<MediaWriter> writer = new MPEG4Writer(outputFd);
   1489 
   1490     if (mVideoSource < VIDEO_SOURCE_LIST_END) {
   1491 
   1492         sp<MediaSource> mediaSource;
   1493         err = setupMediaSource(&mediaSource);
   1494         if (err != OK) {
   1495             return err;
   1496         }
   1497 
   1498         sp<MediaSource> encoder;
   1499         err = setupVideoEncoder(mediaSource, videoBitRate, &encoder);
   1500         if (err != OK) {
   1501             return err;
   1502         }
   1503 
   1504         writer->addSource(encoder);
   1505         *totalBitRate += videoBitRate;
   1506     }
   1507 
   1508     // Audio source is added at the end if it exists.
   1509     // This help make sure that the "recoding" sound is suppressed for
   1510     // camcorder applications in the recorded files.
   1511     if (!mCaptureTimeLapse && (mAudioSource != AUDIO_SOURCE_CNT)) {
   1512         err = setupAudioEncoder(writer);
   1513         if (err != OK) return err;
   1514         *totalBitRate += mAudioBitRate;
   1515     }
   1516 
   1517     if (mInterleaveDurationUs > 0) {
   1518         reinterpret_cast<MPEG4Writer *>(writer.get())->
   1519             setInterleaveDuration(mInterleaveDurationUs);
   1520     }
   1521     if (mLongitudex10000 > -3600000 && mLatitudex10000 > -3600000) {
   1522         reinterpret_cast<MPEG4Writer *>(writer.get())->
   1523             setGeoData(mLatitudex10000, mLongitudex10000);
   1524     }
   1525     if (mMaxFileDurationUs != 0) {
   1526         writer->setMaxFileDuration(mMaxFileDurationUs);
   1527     }
   1528     if (mMaxFileSizeBytes != 0) {
   1529         writer->setMaxFileSize(mMaxFileSizeBytes);
   1530     }
   1531 
   1532     mStartTimeOffsetMs = mEncoderProfiles->getStartTimeOffsetMs(mCameraId);
   1533     if (mStartTimeOffsetMs > 0) {
   1534         reinterpret_cast<MPEG4Writer *>(writer.get())->
   1535             setStartTimeOffsetMs(mStartTimeOffsetMs);
   1536     }
   1537 
   1538     writer->setListener(mListener);
   1539     *mediaWriter = writer;
   1540     return OK;
   1541 }
   1542 
   1543 void StagefrightRecorder::setupMPEG4MetaData(int64_t startTimeUs, int32_t totalBitRate,
   1544         sp<MetaData> *meta) {
   1545     (*meta)->setInt64(kKeyTime, startTimeUs);
   1546     (*meta)->setInt32(kKeyFileType, mOutputFormat);
   1547     (*meta)->setInt32(kKeyBitRate, totalBitRate);
   1548     (*meta)->setInt32(kKey64BitFileOffset, mUse64BitFileOffset);
   1549     if (mMovieTimeScale > 0) {
   1550         (*meta)->setInt32(kKeyTimeScale, mMovieTimeScale);
   1551     }
   1552     if (mTrackEveryTimeDurationUs > 0) {
   1553         (*meta)->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs);
   1554     }
   1555     if (mRotationDegrees != 0) {
   1556         (*meta)->setInt32(kKeyRotation, mRotationDegrees);
   1557     }
   1558 }
   1559 
   1560 status_t StagefrightRecorder::startMPEG4Recording() {
   1561     int32_t totalBitRate;
   1562     status_t err = setupMPEG4Recording(
   1563             mOutputFd, mVideoWidth, mVideoHeight,
   1564             mVideoBitRate, &totalBitRate, &mWriter);
   1565     if (err != OK) {
   1566         return err;
   1567     }
   1568 
   1569     int64_t startTimeUs = systemTime() / 1000;
   1570     sp<MetaData> meta = new MetaData;
   1571     setupMPEG4MetaData(startTimeUs, totalBitRate, &meta);
   1572 
   1573     err = mWriter->start(meta.get());
   1574     if (err != OK) {
   1575         return err;
   1576     }
   1577 
   1578     return OK;
   1579 }
   1580 
   1581 status_t StagefrightRecorder::pause() {
   1582     ALOGV("pause");
   1583     if (mWriter == NULL) {
   1584         return UNKNOWN_ERROR;
   1585     }
   1586     mWriter->pause();
   1587 
   1588     if (mStarted) {
   1589         mStarted = false;
   1590 
   1591         uint32_t params = 0;
   1592         if (mAudioSource != AUDIO_SOURCE_CNT) {
   1593             params |= IMediaPlayerService::kBatteryDataTrackAudio;
   1594         }
   1595         if (mVideoSource != VIDEO_SOURCE_LIST_END) {
   1596             params |= IMediaPlayerService::kBatteryDataTrackVideo;
   1597         }
   1598 
   1599         addBatteryData(params);
   1600     }
   1601 
   1602 
   1603     return OK;
   1604 }
   1605 
   1606 status_t StagefrightRecorder::stop() {
   1607     ALOGV("stop");
   1608     status_t err = OK;
   1609 
   1610     if (mCaptureTimeLapse && mCameraSourceTimeLapse != NULL) {
   1611         mCameraSourceTimeLapse->startQuickReadReturns();
   1612         mCameraSourceTimeLapse = NULL;
   1613     }
   1614 
   1615     if (mWriter != NULL) {
   1616         err = mWriter->stop();
   1617         mWriter.clear();
   1618     }
   1619 
   1620     if (mOutputFd >= 0) {
   1621         ::close(mOutputFd);
   1622         mOutputFd = -1;
   1623     }
   1624 
   1625     if (mStarted) {
   1626         mStarted = false;
   1627 
   1628         uint32_t params = 0;
   1629         if (mAudioSource != AUDIO_SOURCE_CNT) {
   1630             params |= IMediaPlayerService::kBatteryDataTrackAudio;
   1631         }
   1632         if (mVideoSource != VIDEO_SOURCE_LIST_END) {
   1633             params |= IMediaPlayerService::kBatteryDataTrackVideo;
   1634         }
   1635 
   1636         addBatteryData(params);
   1637     }
   1638 
   1639 
   1640     return err;
   1641 }
   1642 
   1643 status_t StagefrightRecorder::close() {
   1644     ALOGV("close");
   1645     stop();
   1646 
   1647     return OK;
   1648 }
   1649 
   1650 status_t StagefrightRecorder::reset() {
   1651     ALOGV("reset");
   1652     stop();
   1653 
   1654     // No audio or video source by default
   1655     mAudioSource = AUDIO_SOURCE_CNT;
   1656     mVideoSource = VIDEO_SOURCE_LIST_END;
   1657 
   1658     // Default parameters
   1659     mOutputFormat  = OUTPUT_FORMAT_THREE_GPP;
   1660     mAudioEncoder  = AUDIO_ENCODER_AMR_NB;
   1661     mVideoEncoder  = VIDEO_ENCODER_H263;
   1662     mVideoWidth    = 176;
   1663     mVideoHeight   = 144;
   1664     mFrameRate     = -1;
   1665     mVideoBitRate  = 192000;
   1666     mSampleRate    = 8000;
   1667     mAudioChannels = 1;
   1668     mAudioBitRate  = 12200;
   1669     mInterleaveDurationUs = 0;
   1670     mIFramesIntervalSec = 1;
   1671     mAudioSourceNode = 0;
   1672     mUse64BitFileOffset = false;
   1673     mMovieTimeScale  = -1;
   1674     mAudioTimeScale  = -1;
   1675     mVideoTimeScale  = -1;
   1676     mCameraId        = 0;
   1677     mStartTimeOffsetMs = -1;
   1678     mVideoEncoderProfile = -1;
   1679     mVideoEncoderLevel   = -1;
   1680     mMaxFileDurationUs = 0;
   1681     mMaxFileSizeBytes = 0;
   1682     mTrackEveryTimeDurationUs = 0;
   1683     mCaptureTimeLapse = false;
   1684     mTimeBetweenTimeLapseFrameCaptureUs = -1;
   1685     mCameraSourceTimeLapse = NULL;
   1686     mIsMetaDataStoredInVideoBuffers = false;
   1687     mEncoderProfiles = MediaProfiles::getInstance();
   1688     mRotationDegrees = 0;
   1689     mLatitudex10000 = -3600000;
   1690     mLongitudex10000 = -3600000;
   1691 
   1692     mOutputFd = -1;
   1693 
   1694     return OK;
   1695 }
   1696 
   1697 status_t StagefrightRecorder::getMaxAmplitude(int *max) {
   1698     ALOGV("getMaxAmplitude");
   1699 
   1700     if (max == NULL) {
   1701         ALOGE("Null pointer argument");
   1702         return BAD_VALUE;
   1703     }
   1704 
   1705     if (mAudioSourceNode != 0) {
   1706         *max = mAudioSourceNode->getMaxAmplitude();
   1707     } else {
   1708         *max = 0;
   1709     }
   1710 
   1711     return OK;
   1712 }
   1713 
   1714 status_t StagefrightRecorder::dump(
   1715         int fd, const Vector<String16>& args) const {
   1716     ALOGV("dump");
   1717     const size_t SIZE = 256;
   1718     char buffer[SIZE];
   1719     String8 result;
   1720     if (mWriter != 0) {
   1721         mWriter->dump(fd, args);
   1722     } else {
   1723         snprintf(buffer, SIZE, "   No file writer\n");
   1724         result.append(buffer);
   1725     }
   1726     snprintf(buffer, SIZE, "   Recorder: %p\n", this);
   1727     snprintf(buffer, SIZE, "   Output file (fd %d):\n", mOutputFd);
   1728     result.append(buffer);
   1729     snprintf(buffer, SIZE, "     File format: %d\n", mOutputFormat);
   1730     result.append(buffer);
   1731     snprintf(buffer, SIZE, "     Max file size (bytes): %lld\n", mMaxFileSizeBytes);
   1732     result.append(buffer);
   1733     snprintf(buffer, SIZE, "     Max file duration (us): %lld\n", mMaxFileDurationUs);
   1734     result.append(buffer);
   1735     snprintf(buffer, SIZE, "     File offset length (bits): %d\n", mUse64BitFileOffset? 64: 32);
   1736     result.append(buffer);
   1737     snprintf(buffer, SIZE, "     Interleave duration (us): %d\n", mInterleaveDurationUs);
   1738     result.append(buffer);
   1739     snprintf(buffer, SIZE, "     Progress notification: %lld us\n", mTrackEveryTimeDurationUs);
   1740     result.append(buffer);
   1741     snprintf(buffer, SIZE, "   Audio\n");
   1742     result.append(buffer);
   1743     snprintf(buffer, SIZE, "     Source: %d\n", mAudioSource);
   1744     result.append(buffer);
   1745     snprintf(buffer, SIZE, "     Encoder: %d\n", mAudioEncoder);
   1746     result.append(buffer);
   1747     snprintf(buffer, SIZE, "     Bit rate (bps): %d\n", mAudioBitRate);
   1748     result.append(buffer);
   1749     snprintf(buffer, SIZE, "     Sampling rate (hz): %d\n", mSampleRate);
   1750     result.append(buffer);
   1751     snprintf(buffer, SIZE, "     Number of channels: %d\n", mAudioChannels);
   1752     result.append(buffer);
   1753     snprintf(buffer, SIZE, "     Max amplitude: %d\n", mAudioSourceNode == 0? 0: mAudioSourceNode->getMaxAmplitude());
   1754     result.append(buffer);
   1755     snprintf(buffer, SIZE, "   Video\n");
   1756     result.append(buffer);
   1757     snprintf(buffer, SIZE, "     Source: %d\n", mVideoSource);
   1758     result.append(buffer);
   1759     snprintf(buffer, SIZE, "     Camera Id: %d\n", mCameraId);
   1760     result.append(buffer);
   1761     snprintf(buffer, SIZE, "     Start time offset (ms): %d\n", mStartTimeOffsetMs);
   1762     result.append(buffer);
   1763     snprintf(buffer, SIZE, "     Encoder: %d\n", mVideoEncoder);
   1764     result.append(buffer);
   1765     snprintf(buffer, SIZE, "     Encoder profile: %d\n", mVideoEncoderProfile);
   1766     result.append(buffer);
   1767     snprintf(buffer, SIZE, "     Encoder level: %d\n", mVideoEncoderLevel);
   1768     result.append(buffer);
   1769     snprintf(buffer, SIZE, "     I frames interval (s): %d\n", mIFramesIntervalSec);
   1770     result.append(buffer);
   1771     snprintf(buffer, SIZE, "     Frame size (pixels): %dx%d\n", mVideoWidth, mVideoHeight);
   1772     result.append(buffer);
   1773     snprintf(buffer, SIZE, "     Frame rate (fps): %d\n", mFrameRate);
   1774     result.append(buffer);
   1775     snprintf(buffer, SIZE, "     Bit rate (bps): %d\n", mVideoBitRate);
   1776     result.append(buffer);
   1777     ::write(fd, result.string(), result.size());
   1778     return OK;
   1779 }
   1780 }  // namespace android
   1781