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