130ab66297501757d745b9ae10da61adcd891f497Andreas Huber/*
230ab66297501757d745b9ae10da61adcd891f497Andreas Huber * Copyright (C) 2009 The Android Open Source Project
330ab66297501757d745b9ae10da61adcd891f497Andreas Huber *
430ab66297501757d745b9ae10da61adcd891f497Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
530ab66297501757d745b9ae10da61adcd891f497Andreas Huber * you may not use this file except in compliance with the License.
630ab66297501757d745b9ae10da61adcd891f497Andreas Huber * You may obtain a copy of the License at
730ab66297501757d745b9ae10da61adcd891f497Andreas Huber *
830ab66297501757d745b9ae10da61adcd891f497Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
930ab66297501757d745b9ae10da61adcd891f497Andreas Huber *
1030ab66297501757d745b9ae10da61adcd891f497Andreas Huber * Unless required by applicable law or agreed to in writing, software
1130ab66297501757d745b9ae10da61adcd891f497Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1230ab66297501757d745b9ae10da61adcd891f497Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1330ab66297501757d745b9ae10da61adcd891f497Andreas Huber * See the License for the specific language governing permissions and
1430ab66297501757d745b9ae10da61adcd891f497Andreas Huber * limitations under the License.
1530ab66297501757d745b9ae10da61adcd891f497Andreas Huber */
1630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1730ab66297501757d745b9ae10da61adcd891f497Andreas Huber//#define LOG_NDEBUG 0
1830ab66297501757d745b9ae10da61adcd891f497Andreas Huber#define LOG_TAG "StagefrightRecorder"
19377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT#include <inttypes.h>
2030ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <utils/Log.h>
2130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
22114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih#include "WebmWriter.h"
2330ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include "StagefrightRecorder.h"
2430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
25c96cfbe66d7bf261c57ff93984bc6a4b3a58f6fcLajos Molnar#include <algorithm>
26c96cfbe66d7bf261c57ff93984bc6a4b3a58f6fcLajos Molnar
27d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala#include <android/hardware/ICamera.h>
28d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala
2975b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang#include <binder/IPCThreadState.h>
3075b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang#include <binder/IServiceManager.h>
3175b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
3275b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang#include <media/IMediaPlayerService.h>
33ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick#include <media/MediaAnalyticsItem.h>
3472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ABuffer.h>
35f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h>
3672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/AMessage.h>
3772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ALooper.h>
38a147b4f91143d9f2fb608e22f9fca14bbd029573Lajos Molnar#include <media/stagefright/ACodec.h>
392dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber#include <media/stagefright/AudioSource.h>
402dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber#include <media/stagefright/AMRWriter.h>
41760943b5e7a09b602aba04ec451e97662f48b0a4James Dong#include <media/stagefright/AACWriter.h>
4230ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <media/stagefright/CameraSource.h>
4365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <media/stagefright/CameraSourceTimeLapse.h>
4459b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber#include <media/stagefright/MPEG2TSWriter.h>
4530ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <media/stagefright/MPEG4Writer.h>
4630ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <media/stagefright/MediaDefs.h>
4730ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <media/stagefright/MetaData.h>
4872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaCodecSource.h>
49addf2cbb120346ae42e78fa739245a353db5edadChong Zhang#include <media/stagefright/PersistentSurface.h>
5099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong#include <media/MediaProfiles.h>
51ef9d0cd72e476a4b7556833fb09505a51b626797James Dong#include <camera/CameraParameters.h>
52b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi
5330ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <utils/Errors.h>
54c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong#include <sys/types.h>
55050b28a593350047845a45a14cc5026221ac1620James Dong#include <ctype.h>
56ca2fa61ef03cac008ea86e6fe16b2e5f9f1a2be3Nipun Kwatra#include <unistd.h>
5730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
5864760240f931714858a59c1579f07264d7182ba2Dima Zavin#include <system/audio.h>
59fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin
6039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include "ARTPWriter.h"
6139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
6230ab66297501757d745b9ae10da61adcd891f497Andreas Hubernamespace android {
6330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
642da225766572a3d4746b4e21cb231a0243b114abLajos Molnarstatic const float kTypicalDisplayRefreshingRate = 60.f;
652da225766572a3d4746b4e21cb231a0243b114abLajos Molnar// display refresh rate drops on battery saver
662da225766572a3d4746b4e21cb231a0243b114abLajos Molnarstatic const float kMinTypicalDisplayRefreshingRate = kTypicalDisplayRefreshingRate / 2;
672da225766572a3d4746b4e21cb231a0243b114abLajos Molnarstatic const int kMaxNumVideoTemporalLayers = 8;
682da225766572a3d4746b4e21cb231a0243b114abLajos Molnar
69ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick// key for media statistics
70ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essickstatic const char *kKeyRecorder = "recorder";
71ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick// attrs for media statistics
72afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kRecorderHeight = "android.media.mediarecorder.height";
73afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kRecorderWidth = "android.media.mediarecorder.width";
74afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kRecorderFrameRate = "android.media.mediarecorder.frame-rate";
75afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kRecorderVideoBitrate = "android.media.mediarecorder.video-bitrate";
76afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kRecorderAudioSampleRate = "android.media.mediarecorder.audio-samplerate";
77afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kRecorderAudioChannels = "android.media.mediarecorder.audio-channels";
78afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kRecorderAudioBitrate = "android.media.mediarecorder.audio-bitrate";
79afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kRecorderVideoIframeInterval = "android.media.mediarecorder.video-iframe-interval";
80afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kRecorderMovieTimescale = "android.media.mediarecorder.movie-timescale";
81afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kRecorderAudioTimescale = "android.media.mediarecorder.audio-timescale";
82afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kRecorderVideoTimescale = "android.media.mediarecorder.video-timescale";
83afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kRecorderVideoProfile = "android.media.mediarecorder.video-encoder-profile";
84afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kRecorderVideoLevel = "android.media.mediarecorder.video-encoder-level";
85afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kRecorderCaptureFpsEnable = "android.media.mediarecorder.capture-fpsenable";
86afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kRecorderCaptureFps = "android.media.mediarecorder.capture-fps";
87afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kRecorderRotation = "android.media.mediarecorder.rotation";
88afb43f76821e6a63e17e6484289a40430ada6978Ray Essick
8975b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang// To collect the encoder usage for the battery app
9075b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wangstatic void addBatteryData(uint32_t params) {
9175b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang    sp<IBinder> binder =
9275b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        defaultServiceManager()->getService(String16("media.player"));
9375b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
9475b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang    CHECK(service.get() != NULL);
9575b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
9675b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang    service->addBatteryData(params);
9775b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang}
9875b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
9975b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
100be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet GanovStagefrightRecorder::StagefrightRecorder(const String16 &opPackageName)
101be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov    : MediaRecorderBase(opPackageName),
102be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov      mWriter(NULL),
1033cecf640c4daf2df616b278bd9986018c8182908James Dong      mOutputFd(-1),
104fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin      mAudioSource(AUDIO_SOURCE_CNT),
10575b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang      mVideoSource(VIDEO_SOURCE_LIST_END),
10672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mStarted(false) {
107d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
1083856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("Constructor");
109ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
110ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    mAnalyticsDirty = false;
11130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    reset();
11230ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
11330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
11430ab66297501757d745b9ae10da61adcd891f497Andreas HuberStagefrightRecorder::~StagefrightRecorder() {
1153856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("Destructor");
11630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    stop();
11772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
11872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mLooper != NULL) {
11972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mLooper->stop();
12072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
121ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
122ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // log the current record, provided it has some information worth recording
123ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    if (mAnalyticsDirty && mAnalyticsItem != NULL) {
124ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        updateMetrics();
125ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        if (mAnalyticsItem->count() > 0) {
126ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick            mAnalyticsItem->setFinalized(true);
127ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick            mAnalyticsItem->selfrecord();
128ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        }
129ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        delete mAnalyticsItem;
130ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        mAnalyticsItem = NULL;
131ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    }
132ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick}
133ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
134ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essickvoid StagefrightRecorder::updateMetrics() {
135ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    ALOGV("updateMetrics");
136ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
137ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // we'll populate the values from the raw fields.
138ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // (NOT going to populate as we go through the various set* ops)
139ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
140ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mOutputFormat  = OUTPUT_FORMAT_THREE_GPP;
141ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mAudioEncoder  = AUDIO_ENCODER_AMR_NB;
142ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mVideoEncoder  = VIDEO_ENCODER_DEFAULT;
143afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderHeight, mVideoHeight);
144afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderWidth, mVideoWidth);
145afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderFrameRate, mFrameRate);
146afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderVideoBitrate, mVideoBitRate);
147afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderAudioSampleRate, mSampleRate);
148afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderAudioChannels, mAudioChannels);
149afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderAudioBitrate, mAudioBitRate);
150ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mInterleaveDurationUs = 0;
151afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderVideoIframeInterval, mIFramesIntervalSec);
152ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mAudioSourceNode = 0;
153ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mUse64BitFileOffset = false;
154afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderMovieTimescale, mMovieTimeScale);
155afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderAudioTimescale, mAudioTimeScale);
156afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderVideoTimescale, mVideoTimeScale);
157ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mCameraId        = 0;
158ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mStartTimeOffsetMs = -1;
159afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderVideoProfile, mVideoEncoderProfile);
160afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderVideoLevel, mVideoEncoderLevel);
161ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mMaxFileDurationUs = 0;
162ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mMaxFileSizeBytes = 0;
163ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mTrackEveryTimeDurationUs = 0;
164afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderCaptureFpsEnable, mCaptureFpsEnable);
165afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setDouble(kRecorderCaptureFps, mCaptureFps);
16622dc508717c7767927064ec7c152def99e54adcbPawin Vongmasa    // TBD mCaptureFps = -1.0;
167ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mCameraSourceTimeLapse = NULL;
168ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mMetaDataStoredInVideoBuffers = kMetadataBufferTypeInvalid;
169ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mEncoderProfiles = MediaProfiles::getInstance();
170afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderRotation, mRotationDegrees);
171ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // PII mLatitudex10000 = -3600000;
172ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // PII mLongitudex10000 = -3600000;
173ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mTotalBitRate = 0;
174ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
175ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD: some duration information (capture, paused)
176ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    //
177ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
178ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick}
179ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
180ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essickvoid StagefrightRecorder::resetMetrics() {
181ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    ALOGV("resetMetrics");
182ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // flush anything we have, restart the record
183ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    if (mAnalyticsDirty && mAnalyticsItem != NULL) {
184ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        updateMetrics();
185ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        if (mAnalyticsItem->count() > 0) {
186ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick            mAnalyticsItem->setFinalized(true);
187ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick            mAnalyticsItem->selfrecord();
188ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        }
189ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        delete mAnalyticsItem;
190ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        mAnalyticsItem = NULL;
191ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    }
192ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    mAnalyticsItem = new MediaAnalyticsItem(kKeyRecorder);
193ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    (void) mAnalyticsItem->generateSessionID();
194ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    mAnalyticsDirty = false;
19530ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
19630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
19730ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::init() {
1983856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("init");
19972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
20072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper = new ALooper;
20172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->setName("recorder_looper");
20272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->start();
20372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
20430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
20530ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
20630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
207b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi// The client side of mediaserver asks it to creat a SurfaceMediaSource
208b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi// and return a interface reference. The client side will use that
209b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi// while encoding GL Frames
2108ba01021b573889802e67e029225a96f0dfa471aAndy McFaddensp<IGraphicBufferProducer> StagefrightRecorder::querySurfaceMediaSource() const {
2113856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("Get SurfaceMediaSource");
21272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return mGraphicBufferProducer;
213b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi}
214b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi
215fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavinstatus_t StagefrightRecorder::setAudioSource(audio_source_t as) {
2163856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setAudioSource: %d", as);
217d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (as < AUDIO_SOURCE_DEFAULT ||
2180f8f4e681b867dd611d2d916453337cb0770d4daHochi Huang        (as >= AUDIO_SOURCE_CNT && as != AUDIO_SOURCE_FM_TUNER)) {
21929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid audio source: %d", as);
220d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        return BAD_VALUE;
221d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
222d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
223d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (as == AUDIO_SOURCE_DEFAULT) {
224d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mAudioSource = AUDIO_SOURCE_MIC;
225d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    } else {
226d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mAudioSource = as;
227d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
22830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
22930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
23030ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
23130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
23230ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setVideoSource(video_source vs) {
2333856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setVideoSource: %d", vs);
234d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (vs < VIDEO_SOURCE_DEFAULT ||
235d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        vs >= VIDEO_SOURCE_LIST_END) {
23629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid video source: %d", vs);
237d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        return BAD_VALUE;
238d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
239d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
240d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (vs == VIDEO_SOURCE_DEFAULT) {
241d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mVideoSource = VIDEO_SOURCE_CAMERA;
242d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    } else {
243d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mVideoSource = vs;
244d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
24530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
24630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
24730ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
24830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
24930ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setOutputFormat(output_format of) {
2503856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setOutputFormat: %d", of);
251d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (of < OUTPUT_FORMAT_DEFAULT ||
252d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        of >= OUTPUT_FORMAT_LIST_END) {
25329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid output format: %d", of);
254d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        return BAD_VALUE;
255d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
256d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
257d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (of == OUTPUT_FORMAT_DEFAULT) {
258d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mOutputFormat = OUTPUT_FORMAT_THREE_GPP;
259d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    } else {
260d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mOutputFormat = of;
261d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
26230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
26330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
26430ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
26530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
26630ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setAudioEncoder(audio_encoder ae) {
2673856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setAudioEncoder: %d", ae);
268d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (ae < AUDIO_ENCODER_DEFAULT ||
269d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        ae >= AUDIO_ENCODER_LIST_END) {
27029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid audio encoder: %d", ae);
271d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        return BAD_VALUE;
272d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
273d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
274d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (ae == AUDIO_ENCODER_DEFAULT) {
275d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mAudioEncoder = AUDIO_ENCODER_AMR_NB;
276d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    } else {
277d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mAudioEncoder = ae;
278d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
27930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
28030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
28130ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
28230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
28330ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setVideoEncoder(video_encoder ve) {
2843856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setVideoEncoder: %d", ve);
285d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (ve < VIDEO_ENCODER_DEFAULT ||
286d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        ve >= VIDEO_ENCODER_LIST_END) {
28729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid video encoder: %d", ve);
288d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        return BAD_VALUE;
289d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
290d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
29154ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang    mVideoEncoder = ve;
29230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
29330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
29430ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
29530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
29630ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setVideoSize(int width, int height) {
2973856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setVideoSize: %dx%d", width, height);
298ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (width <= 0 || height <= 0) {
29929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid video size: %dx%d", width, height);
300ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        return BAD_VALUE;
301ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
302ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
303ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // Additional check on the dimension will be performed later
30430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mVideoWidth = width;
30530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mVideoHeight = height;
30630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
30730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
30830ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
30930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
31030ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setVideoFrameRate(int frames_per_second) {
3113856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setVideoFrameRate: %d", frames_per_second);
312635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong    if ((frames_per_second <= 0 && frames_per_second != -1) ||
313c9f122d8f32ba6928ac9087448025fa3bed1553dZhijun He        frames_per_second > kMaxHighSpeedFps) {
31429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid video frame rate: %d", frames_per_second);
315ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        return BAD_VALUE;
316ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
317ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
318ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // Additional check on the frame rate will be performed later
31930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mFrameRate = frames_per_second;
32030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
32130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
32230ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
32330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
324d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvalastatus_t StagefrightRecorder::setCamera(const sp<hardware::ICamera> &camera,
3254ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li                                        const sp<ICameraRecordingProxy> &proxy) {
3263856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setCamera");
327c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    if (camera == 0) {
32829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("camera is NULL");
329934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return BAD_VALUE;
330c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
3314ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    if (proxy == 0) {
33229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("camera proxy is NULL");
3334ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        return BAD_VALUE;
3344ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    }
335c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong
33654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mCamera = camera;
3374ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mCameraProxy = proxy;
33830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
33930ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
34030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
34199617adda9bc46c43f511f0940bc735c73de61deMathias Agopianstatus_t StagefrightRecorder::setPreviewSurface(const sp<IGraphicBufferProducer> &surface) {
3423856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setPreviewSurface: %p", surface.get());
34330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mPreviewSurface = surface;
34430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
34530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
34630ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
34730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
3488f469e18c307cb9dc0d16ed9225972aa8be4516fChong Zhangstatus_t StagefrightRecorder::setInputSurface(
349addf2cbb120346ae42e78fa739245a353db5edadChong Zhang        const sp<PersistentSurface>& surface) {
350e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang    mPersistentSurface = surface;
351e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang
352e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang    return OK;
353e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang}
354e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang
355fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t StagefrightRecorder::setOutputFile(int fd) {
356fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGV("setOutputFile: %d", fd);
35730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
358934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    if (fd < 0) {
35929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid file descriptor: %d", fd);
360934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return -EBADF;
361934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    }
362934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong
36369113e8ccc30fbdb8733ca2070bd3491b21e656dMarco Nelissen    // start with a clean, empty file
36469113e8ccc30fbdb8733ca2070bd3491b21e656dMarco Nelissen    ftruncate(fd, 0);
36569113e8ccc30fbdb8733ca2070bd3491b21e656dMarco Nelissen
36630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    if (mOutputFd >= 0) {
36730ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ::close(mOutputFd);
36830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    }
36930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mOutputFd = dup(fd);
37030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
37130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
37230ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
37330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
374fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t StagefrightRecorder::setNextOutputFile(int fd) {
375fc079f79d8d4f6ef9f138aa615486c10dda99fb7Hangyu Kuang    Mutex::Autolock autolock(mLock);
376fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    // Only support MPEG4
377fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mOutputFormat != OUTPUT_FORMAT_MPEG_4) {
378fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGE("Only MP4 file format supports setting next output file");
379fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return INVALID_OPERATION;
380fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
381fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGV("setNextOutputFile: %d", fd);
382fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
383fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (fd < 0) {
384fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGE("Invalid file descriptor: %d", fd);
385fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return -EBADF;
386fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
387fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
388fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    // start with a clean, empty file
389fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ftruncate(fd, 0);
390fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    int nextFd = dup(fd);
391fc079f79d8d4f6ef9f138aa615486c10dda99fb7Hangyu Kuang    if (mWriter == NULL) {
392fc079f79d8d4f6ef9f138aa615486c10dda99fb7Hangyu Kuang        ALOGE("setNextOutputFile failed. Writer has been freed");
393fc079f79d8d4f6ef9f138aa615486c10dda99fb7Hangyu Kuang        return INVALID_OPERATION;
394fc079f79d8d4f6ef9f138aa615486c10dda99fb7Hangyu Kuang    }
395fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    return mWriter->setNextFd(nextFd);
396fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
397fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
3989ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang// Attempt to parse an float literal optionally surrounded by whitespace,
3999ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang// returns true on success, false otherwise.
40073c3e6363b31fb27882c4666453ad8ef050b3cc1Wonsik Kimstatic bool safe_strtod(const char *s, double *val) {
4019ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    char *end;
4029ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang
4039ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    // It is lame, but according to man page, we have to set errno to 0
40473c3e6363b31fb27882c4666453ad8ef050b3cc1Wonsik Kim    // before calling strtod().
4059ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    errno = 0;
40673c3e6363b31fb27882c4666453ad8ef050b3cc1Wonsik Kim    *val = strtod(s, &end);
4079ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang
4089ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    if (end == s || errno == ERANGE) {
4099ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang        return false;
4109ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    }
4119ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang
4129ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    // Skip trailing whitespace
4139ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    while (isspace(*end)) {
4149ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang        ++end;
4159ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    }
4169ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang
4179ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    // For a successful return, the string must contain nothing but a valid
4189ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    // float literal optionally surrounded by whitespace.
4199ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang
4209ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    return *end == '\0';
4219ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang}
4229ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang
423050b28a593350047845a45a14cc5026221ac1620James Dong// Attempt to parse an int64 literal optionally surrounded by whitespace,
424050b28a593350047845a45a14cc5026221ac1620James Dong// returns true on success, false otherwise.
425ef9d0cd72e476a4b7556833fb09505a51b626797James Dongstatic bool safe_strtoi64(const char *s, int64_t *val) {
426050b28a593350047845a45a14cc5026221ac1620James Dong    char *end;
42727944ef5cd8d0fb476c8c8958986e827c5f8ab83James Dong
42827944ef5cd8d0fb476c8c8958986e827c5f8ab83James Dong    // It is lame, but according to man page, we have to set errno to 0
42927944ef5cd8d0fb476c8c8958986e827c5f8ab83James Dong    // before calling strtoll().
43027944ef5cd8d0fb476c8c8958986e827c5f8ab83James Dong    errno = 0;
431ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    *val = strtoll(s, &end, 10);
432050b28a593350047845a45a14cc5026221ac1620James Dong
433050b28a593350047845a45a14cc5026221ac1620James Dong    if (end == s || errno == ERANGE) {
434050b28a593350047845a45a14cc5026221ac1620James Dong        return false;
435050b28a593350047845a45a14cc5026221ac1620James Dong    }
436050b28a593350047845a45a14cc5026221ac1620James Dong
437050b28a593350047845a45a14cc5026221ac1620James Dong    // Skip trailing whitespace
438050b28a593350047845a45a14cc5026221ac1620James Dong    while (isspace(*end)) {
439050b28a593350047845a45a14cc5026221ac1620James Dong        ++end;
440050b28a593350047845a45a14cc5026221ac1620James Dong    }
441050b28a593350047845a45a14cc5026221ac1620James Dong
442050b28a593350047845a45a14cc5026221ac1620James Dong    // For a successful return, the string must contain nothing but a valid
443050b28a593350047845a45a14cc5026221ac1620James Dong    // int64 literal optionally surrounded by whitespace.
444050b28a593350047845a45a14cc5026221ac1620James Dong
445050b28a593350047845a45a14cc5026221ac1620James Dong    return *end == '\0';
446050b28a593350047845a45a14cc5026221ac1620James Dong}
447050b28a593350047845a45a14cc5026221ac1620James Dong
448ef9d0cd72e476a4b7556833fb09505a51b626797James Dong// Return true if the value is in [0, 0x007FFFFFFF]
449ef9d0cd72e476a4b7556833fb09505a51b626797James Dongstatic bool safe_strtoi32(const char *s, int32_t *val) {
450ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    int64_t temp;
451ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (safe_strtoi64(s, &temp)) {
452ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (temp >= 0 && temp <= 0x007FFFFFFF) {
453ef9d0cd72e476a4b7556833fb09505a51b626797James Dong            *val = static_cast<int32_t>(temp);
454ef9d0cd72e476a4b7556833fb09505a51b626797James Dong            return true;
455ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        }
456ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
457ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    return false;
458ef9d0cd72e476a4b7556833fb09505a51b626797James Dong}
459ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
460050b28a593350047845a45a14cc5026221ac1620James Dong// Trim both leading and trailing whitespace from the given string.
461050b28a593350047845a45a14cc5026221ac1620James Dongstatic void TrimString(String8 *s) {
462050b28a593350047845a45a14cc5026221ac1620James Dong    size_t num_bytes = s->bytes();
463050b28a593350047845a45a14cc5026221ac1620James Dong    const char *data = s->string();
464050b28a593350047845a45a14cc5026221ac1620James Dong
465050b28a593350047845a45a14cc5026221ac1620James Dong    size_t leading_space = 0;
466050b28a593350047845a45a14cc5026221ac1620James Dong    while (leading_space < num_bytes && isspace(data[leading_space])) {
467050b28a593350047845a45a14cc5026221ac1620James Dong        ++leading_space;
468050b28a593350047845a45a14cc5026221ac1620James Dong    }
469050b28a593350047845a45a14cc5026221ac1620James Dong
470050b28a593350047845a45a14cc5026221ac1620James Dong    size_t i = num_bytes;
471050b28a593350047845a45a14cc5026221ac1620James Dong    while (i > leading_space && isspace(data[i - 1])) {
472050b28a593350047845a45a14cc5026221ac1620James Dong        --i;
473050b28a593350047845a45a14cc5026221ac1620James Dong    }
474050b28a593350047845a45a14cc5026221ac1620James Dong
475050b28a593350047845a45a14cc5026221ac1620James Dong    s->setTo(String8(&data[leading_space], i - leading_space));
476050b28a593350047845a45a14cc5026221ac1620James Dong}
477050b28a593350047845a45a14cc5026221ac1620James Dong
478050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParamAudioSamplingRate(int32_t sampleRate) {
4793856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamAudioSamplingRate: %d", sampleRate);
480ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (sampleRate <= 0) {
48129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid audio sampling rate: %d", sampleRate);
482ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        return BAD_VALUE;
483ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
484ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
485ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // Additional check on the sample rate will be performed later.
486050b28a593350047845a45a14cc5026221ac1620James Dong    mSampleRate = sampleRate;
487ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
488050b28a593350047845a45a14cc5026221ac1620James Dong    return OK;
489050b28a593350047845a45a14cc5026221ac1620James Dong}
490050b28a593350047845a45a14cc5026221ac1620James Dong
491050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) {
4923856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamAudioNumberOfChannels: %d", channels);
493ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (channels <= 0 || channels >= 3) {
49429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid number of audio channels: %d", channels);
495934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return BAD_VALUE;
496ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
497ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
498ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // Additional check on the number of channels will be performed later.
499050b28a593350047845a45a14cc5026221ac1620James Dong    mAudioChannels = channels;
500ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
501050b28a593350047845a45a14cc5026221ac1620James Dong    return OK;
502050b28a593350047845a45a14cc5026221ac1620James Dong}
503050b28a593350047845a45a14cc5026221ac1620James Dong
504050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParamAudioEncodingBitRate(int32_t bitRate) {
5053856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamAudioEncodingBitRate: %d", bitRate);
506ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (bitRate <= 0) {
50729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid audio encoding bit rate: %d", bitRate);
508ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        return BAD_VALUE;
509ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
510ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
511ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // The target bit rate may not be exactly the same as the requested.
512ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // It depends on many factors, such as rate control, and the bit rate
513ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // range that a specific encoder supports. The mismatch between the
514ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // the target and requested bit rate will NOT be treated as an error.
515050b28a593350047845a45a14cc5026221ac1620James Dong    mAudioBitRate = bitRate;
516050b28a593350047845a45a14cc5026221ac1620James Dong    return OK;
517050b28a593350047845a45a14cc5026221ac1620James Dong}
518050b28a593350047845a45a14cc5026221ac1620James Dong
519050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) {
5203856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamVideoEncodingBitRate: %d", bitRate);
521ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (bitRate <= 0) {
52229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid video encoding bit rate: %d", bitRate);
523ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        return BAD_VALUE;
524ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
525ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
526ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // The target bit rate may not be exactly the same as the requested.
527ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // It depends on many factors, such as rate control, and the bit rate
528ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // range that a specific encoder supports. The mismatch between the
529ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // the target and requested bit rate will NOT be treated as an error.
530050b28a593350047845a45a14cc5026221ac1620James Dong    mVideoBitRate = bitRate;
531050b28a593350047845a45a14cc5026221ac1620James Dong    return OK;
532050b28a593350047845a45a14cc5026221ac1620James Dong}
533050b28a593350047845a45a14cc5026221ac1620James Dong
53413f6284305e4b27395a23db7882d670bdb1bcae1James Dong// Always rotate clockwise, and only support 0, 90, 180 and 270 for now.
53513f6284305e4b27395a23db7882d670bdb1bcae1James Dongstatus_t StagefrightRecorder::setParamVideoRotation(int32_t degrees) {
5363856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamVideoRotation: %d", degrees);
53713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    if (degrees < 0 || degrees % 90 != 0) {
53829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unsupported video rotation angle: %d", degrees);
53913f6284305e4b27395a23db7882d670bdb1bcae1James Dong        return BAD_VALUE;
54013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
54113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    mRotationDegrees = degrees % 360;
54213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    return OK;
54313f6284305e4b27395a23db7882d670bdb1bcae1James Dong}
54413f6284305e4b27395a23db7882d670bdb1bcae1James Dong
545934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dongstatus_t StagefrightRecorder::setParamMaxFileDurationUs(int64_t timeUs) {
546833b47505c513cb5c8f22aa922a7ea20d153b319Andy Hung    ALOGV("setParamMaxFileDurationUs: %lld us", (long long)timeUs);
5472d1e5d35be5e6d4b55ac8b39fbfcbeb60fcdd084James Dong
5482d1e5d35be5e6d4b55ac8b39fbfcbeb60fcdd084James Dong    // This is meant for backward compatibility for MediaRecorder.java
549be6fd201b9a04fe0f8fd409f10595ddb41832591Nipun Kwatra    if (timeUs <= 0) {
550833b47505c513cb5c8f22aa922a7ea20d153b319Andy Hung        ALOGW("Max file duration is not positive: %lld us. Disabling duration limit.",
551833b47505c513cb5c8f22aa922a7ea20d153b319Andy Hung                (long long)timeUs);
552be6fd201b9a04fe0f8fd409f10595ddb41832591Nipun Kwatra        timeUs = 0; // Disable the duration limit for zero or negative values.
553be6fd201b9a04fe0f8fd409f10595ddb41832591Nipun Kwatra    } else if (timeUs <= 100000LL) {  // XXX: 100 milli-seconds
554833b47505c513cb5c8f22aa922a7ea20d153b319Andy Hung        ALOGE("Max file duration is too short: %lld us", (long long)timeUs);
555934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return BAD_VALUE;
556ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
557be6fd201b9a04fe0f8fd409f10595ddb41832591Nipun Kwatra
558acd234bba9f048971d66890009eeff9a8db94be3James Dong    if (timeUs <= 15 * 1000000LL) {
559833b47505c513cb5c8f22aa922a7ea20d153b319Andy Hung        ALOGW("Target duration (%lld us) too short to be respected", (long long)timeUs);
560acd234bba9f048971d66890009eeff9a8db94be3James Dong    }
561934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    mMaxFileDurationUs = timeUs;
562934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    return OK;
563934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong}
564934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong
565934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dongstatus_t StagefrightRecorder::setParamMaxFileSizeBytes(int64_t bytes) {
566833b47505c513cb5c8f22aa922a7ea20d153b319Andy Hung    ALOGV("setParamMaxFileSizeBytes: %lld bytes", (long long)bytes);
5672d1e5d35be5e6d4b55ac8b39fbfcbeb60fcdd084James Dong
5682d1e5d35be5e6d4b55ac8b39fbfcbeb60fcdd084James Dong    // This is meant for backward compatibility for MediaRecorder.java
5692d1e5d35be5e6d4b55ac8b39fbfcbeb60fcdd084James Dong    if (bytes <= 0) {
5705ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Max file size is not positive: %lld bytes. "
571833b47505c513cb5c8f22aa922a7ea20d153b319Andy Hung             "Disabling file size limit.", (long long)bytes);
5722d1e5d35be5e6d4b55ac8b39fbfcbeb60fcdd084James Dong        bytes = 0; // Disable the file size limit for zero or negative values.
5732d1e5d35be5e6d4b55ac8b39fbfcbeb60fcdd084James Dong    } else if (bytes <= 1024) {  // XXX: 1 kB
574833b47505c513cb5c8f22aa922a7ea20d153b319Andy Hung        ALOGE("Max file size is too small: %lld bytes", (long long)bytes);
575934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return BAD_VALUE;
576934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    }
577acd234bba9f048971d66890009eeff9a8db94be3James Dong
578acd234bba9f048971d66890009eeff9a8db94be3James Dong    if (bytes <= 100 * 1024) {
579833b47505c513cb5c8f22aa922a7ea20d153b319Andy Hung        ALOGW("Target file size (%lld bytes) is too small to be respected", (long long)bytes);
580acd234bba9f048971d66890009eeff9a8db94be3James Dong    }
581acd234bba9f048971d66890009eeff9a8db94be3James Dong
582934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    mMaxFileSizeBytes = bytes;
583050b28a593350047845a45a14cc5026221ac1620James Dong    return OK;
584050b28a593350047845a45a14cc5026221ac1620James Dong}
585050b28a593350047845a45a14cc5026221ac1620James Dong
58613aec890216948b0c364f8f92792129d0335f506James Dongstatus_t StagefrightRecorder::setParamInterleaveDuration(int32_t durationUs) {
5873856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamInterleaveDuration: %d", durationUs);
588ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    if (durationUs <= 500000) {           //  500 ms
589ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        // If interleave duration is too small, it is very inefficient to do
590ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        // interleaving since the metadata overhead will count for a significant
591ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        // portion of the saved contents
59229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Audio/video interleave duration is too small: %d us", durationUs);
593ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        return BAD_VALUE;
594ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    } else if (durationUs >= 10000000) {  // 10 seconds
595ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        // If interleaving duration is too large, it can cause the recording
596ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        // session to use too much memory since we have to save the output
597ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        // data before we write them out
59829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Audio/video interleave duration is too large: %d us", durationUs);
599ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        return BAD_VALUE;
600ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
60113aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
60213aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
60313aec890216948b0c364f8f92792129d0335f506James Dong}
604ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
6058f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong// If seconds <  0, only the first frame is I frame, and rest are all P frames
6068f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong// If seconds == 0, all frames are encoded as I frames. No P frames
6078f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong// If seconds >  0, it is the time spacing (seconds) between 2 neighboring I frames
6088f5f2fcee5c12d08df71d17017410c50951fc2e3James Dongstatus_t StagefrightRecorder::setParamVideoIFramesInterval(int32_t seconds) {
6093856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamVideoIFramesInterval: %d seconds", seconds);
6108f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    mIFramesIntervalSec = seconds;
611ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    return OK;
612ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong}
613ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong
6142dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t StagefrightRecorder::setParam64BitFileOffset(bool use64Bit) {
6153856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParam64BitFileOffset: %s",
6162dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64Bit? "use 64 bit file offset": "use 32 bit file offset");
6172dec2b5be2056c6d9428897dc672185872d30d17James Dong    mUse64BitFileOffset = use64Bit;
6182dec2b5be2056c6d9428897dc672185872d30d17James Dong    return OK;
6192dec2b5be2056c6d9428897dc672185872d30d17James Dong}
6202dec2b5be2056c6d9428897dc672185872d30d17James Dong
62193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t StagefrightRecorder::setParamVideoCameraId(int32_t cameraId) {
6223856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamVideoCameraId: %d", cameraId);
62393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    if (cameraId < 0) {
62493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        return BAD_VALUE;
62593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
62693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mCameraId = cameraId;
62793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    return OK;
62893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
62993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
63093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t StagefrightRecorder::setParamTrackTimeStatus(int64_t timeDurationUs) {
631833b47505c513cb5c8f22aa922a7ea20d153b319Andy Hung    ALOGV("setParamTrackTimeStatus: %lld", (long long)timeDurationUs);
63293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    if (timeDurationUs < 20000) {  // Infeasible if shorter than 20 ms?
633833b47505c513cb5c8f22aa922a7ea20d153b319Andy Hung        ALOGE("Tracking time duration too short: %lld us", (long long)timeDurationUs);
63493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        return BAD_VALUE;
63593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
63693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = timeDurationUs;
63793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    return OK;
63893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
63993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
640145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dongstatus_t StagefrightRecorder::setParamVideoEncoderProfile(int32_t profile) {
6413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamVideoEncoderProfile: %d", profile);
642145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong
643145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    // Additional check will be done later when we load the encoder.
644145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    // For now, we are accepting values defined in OpenMAX IL.
645145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    mVideoEncoderProfile = profile;
646145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    return OK;
647145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong}
648145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong
649145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dongstatus_t StagefrightRecorder::setParamVideoEncoderLevel(int32_t level) {
6503856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamVideoEncoderLevel: %d", level);
651145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong
652145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    // Additional check will be done later when we load the encoder.
653145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    // For now, we are accepting values defined in OpenMAX IL.
654145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    mVideoEncoderLevel = level;
655145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    return OK;
656145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong}
657145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong
6588f5f2fcee5c12d08df71d17017410c50951fc2e3James Dongstatus_t StagefrightRecorder::setParamMovieTimeScale(int32_t timeScale) {
6593856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamMovieTimeScale: %d", timeScale);
6608f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
6618f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    // The range is set to be the same as the audio's time scale range
6628f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    // since audio's time scale has a wider range.
6638f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (timeScale < 600 || timeScale > 96000) {
66429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Time scale (%d) for movie is out of range [600, 96000]", timeScale);
6658f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        return BAD_VALUE;
6668f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
6678f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    mMovieTimeScale = timeScale;
6688f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    return OK;
6698f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong}
6708f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
6718f5f2fcee5c12d08df71d17017410c50951fc2e3James Dongstatus_t StagefrightRecorder::setParamVideoTimeScale(int32_t timeScale) {
6723856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamVideoTimeScale: %d", timeScale);
6738f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
6748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    // 60000 is chosen to make sure that each video frame from a 60-fps
6758f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    // video has 1000 ticks.
6768f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (timeScale < 600 || timeScale > 60000) {
67729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Time scale (%d) for video is out of range [600, 60000]", timeScale);
6788f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        return BAD_VALUE;
6798f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
6808f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    mVideoTimeScale = timeScale;
6818f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    return OK;
6828f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong}
6838f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
6848f5f2fcee5c12d08df71d17017410c50951fc2e3James Dongstatus_t StagefrightRecorder::setParamAudioTimeScale(int32_t timeScale) {
6853856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamAudioTimeScale: %d", timeScale);
6868f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
6878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    // 96000 Hz is the highest sampling rate support in AAC.
6888f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (timeScale < 600 || timeScale > 96000) {
68929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Time scale (%d) for audio is out of range [600, 96000]", timeScale);
6908f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        return BAD_VALUE;
6918f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
6928f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    mAudioTimeScale = timeScale;
6938f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    return OK;
6948f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong}
6958f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
69646d26dd29195450db15704e84d65740628a821fbChong Zhangstatus_t StagefrightRecorder::setParamCaptureFpsEnable(int32_t captureFpsEnable) {
69746d26dd29195450db15704e84d65740628a821fbChong Zhang    ALOGV("setParamCaptureFpsEnable: %d", captureFpsEnable);
698e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra
69946d26dd29195450db15704e84d65740628a821fbChong Zhang    if(captureFpsEnable == 0) {
70046d26dd29195450db15704e84d65740628a821fbChong Zhang        mCaptureFpsEnable = false;
70146d26dd29195450db15704e84d65740628a821fbChong Zhang    } else if (captureFpsEnable == 1) {
70246d26dd29195450db15704e84d65740628a821fbChong Zhang        mCaptureFpsEnable = true;
703e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra    } else {
704e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        return BAD_VALUE;
705e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra    }
706e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra    return OK;
707e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra}
708e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra
70973c3e6363b31fb27882c4666453ad8ef050b3cc1Wonsik Kimstatus_t StagefrightRecorder::setParamCaptureFps(double fps) {
71046d26dd29195450db15704e84d65740628a821fbChong Zhang    ALOGV("setParamCaptureFps: %.2f", fps);
7119ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang
71222dc508717c7767927064ec7c152def99e54adcbPawin Vongmasa    if (!(fps >= 1.0 / 86400)) {
71322dc508717c7767927064ec7c152def99e54adcbPawin Vongmasa        ALOGE("FPS is too small");
714e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        return BAD_VALUE;
715e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra    }
7169ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    mCaptureFps = fps;
717e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra    return OK;
718e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra}
719e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra
72007b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t StagefrightRecorder::setParamGeoDataLongitude(
721b832a03d563dd000faa44f2577e92237525edc32James Dong    int64_t longitudex10000) {
72207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
72307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (longitudex10000 > 1800000 || longitudex10000 < -1800000) {
72407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
72507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
72607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = longitudex10000;
72707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
72807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
72907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
73007b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t StagefrightRecorder::setParamGeoDataLatitude(
731b832a03d563dd000faa44f2577e92237525edc32James Dong    int64_t latitudex10000) {
73207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
73307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (latitudex10000 > 900000 || latitudex10000 < -900000) {
73407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
73507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
73607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = latitudex10000;
73707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
73807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
73907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
740050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParameter(
741050b28a593350047845a45a14cc5026221ac1620James Dong        const String8 &key, const String8 &value) {
7423856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
743050b28a593350047845a45a14cc5026221ac1620James Dong    if (key == "max-duration") {
744ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        int64_t max_duration_ms;
745050b28a593350047845a45a14cc5026221ac1620James Dong        if (safe_strtoi64(value.string(), &max_duration_ms)) {
746934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            return setParamMaxFileDurationUs(1000LL * max_duration_ms);
747050b28a593350047845a45a14cc5026221ac1620James Dong        }
748050b28a593350047845a45a14cc5026221ac1620James Dong    } else if (key == "max-filesize") {
749ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        int64_t max_filesize_bytes;
750050b28a593350047845a45a14cc5026221ac1620James Dong        if (safe_strtoi64(value.string(), &max_filesize_bytes)) {
751934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            return setParamMaxFileSizeBytes(max_filesize_bytes);
752050b28a593350047845a45a14cc5026221ac1620James Dong        }
75393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    } else if (key == "interleave-duration-us") {
75493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int32_t durationUs;
75593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (safe_strtoi32(value.string(), &durationUs)) {
75693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return setParamInterleaveDuration(durationUs);
75793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
7588f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    } else if (key == "param-movie-time-scale") {
7598f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t timeScale;
7608f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (safe_strtoi32(value.string(), &timeScale)) {
7618f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            return setParamMovieTimeScale(timeScale);
7628f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        }
76393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    } else if (key == "param-use-64bit-offset") {
76493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int32_t use64BitOffset;
76593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (safe_strtoi32(value.string(), &use64BitOffset)) {
76693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return setParam64BitFileOffset(use64BitOffset != 0);
76793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
76807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else if (key == "param-geotag-longitude") {
769b832a03d563dd000faa44f2577e92237525edc32James Dong        int64_t longitudex10000;
770b832a03d563dd000faa44f2577e92237525edc32James Dong        if (safe_strtoi64(value.string(), &longitudex10000)) {
77107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong            return setParamGeoDataLongitude(longitudex10000);
77207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        }
77307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else if (key == "param-geotag-latitude") {
774b832a03d563dd000faa44f2577e92237525edc32James Dong        int64_t latitudex10000;
775b832a03d563dd000faa44f2577e92237525edc32James Dong        if (safe_strtoi64(value.string(), &latitudex10000)) {
77607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong            return setParamGeoDataLatitude(latitudex10000);
77707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        }
77893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    } else if (key == "param-track-time-status") {
77993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeDurationUs;
78093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (safe_strtoi64(value.string(), &timeDurationUs)) {
78193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return setParamTrackTimeStatus(timeDurationUs);
78293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
783050b28a593350047845a45a14cc5026221ac1620James Dong    } else if (key == "audio-param-sampling-rate") {
784050b28a593350047845a45a14cc5026221ac1620James Dong        int32_t sampling_rate;
785ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (safe_strtoi32(value.string(), &sampling_rate)) {
786050b28a593350047845a45a14cc5026221ac1620James Dong            return setParamAudioSamplingRate(sampling_rate);
787050b28a593350047845a45a14cc5026221ac1620James Dong        }
788050b28a593350047845a45a14cc5026221ac1620James Dong    } else if (key == "audio-param-number-of-channels") {
789050b28a593350047845a45a14cc5026221ac1620James Dong        int32_t number_of_channels;
790ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (safe_strtoi32(value.string(), &number_of_channels)) {
791050b28a593350047845a45a14cc5026221ac1620James Dong            return setParamAudioNumberOfChannels(number_of_channels);
792050b28a593350047845a45a14cc5026221ac1620James Dong        }
793050b28a593350047845a45a14cc5026221ac1620James Dong    } else if (key == "audio-param-encoding-bitrate") {
794050b28a593350047845a45a14cc5026221ac1620James Dong        int32_t audio_bitrate;
795ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (safe_strtoi32(value.string(), &audio_bitrate)) {
796050b28a593350047845a45a14cc5026221ac1620James Dong            return setParamAudioEncodingBitRate(audio_bitrate);
797050b28a593350047845a45a14cc5026221ac1620James Dong        }
7988f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    } else if (key == "audio-param-time-scale") {
7998f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t timeScale;
8008f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (safe_strtoi32(value.string(), &timeScale)) {
8018f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            return setParamAudioTimeScale(timeScale);
8028f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        }
803050b28a593350047845a45a14cc5026221ac1620James Dong    } else if (key == "video-param-encoding-bitrate") {
804050b28a593350047845a45a14cc5026221ac1620James Dong        int32_t video_bitrate;
805ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (safe_strtoi32(value.string(), &video_bitrate)) {
806050b28a593350047845a45a14cc5026221ac1620James Dong            return setParamVideoEncodingBitRate(video_bitrate);
807050b28a593350047845a45a14cc5026221ac1620James Dong        }
80813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    } else if (key == "video-param-rotation-angle-degrees") {
80913f6284305e4b27395a23db7882d670bdb1bcae1James Dong        int32_t degrees;
81013f6284305e4b27395a23db7882d670bdb1bcae1James Dong        if (safe_strtoi32(value.string(), &degrees)) {
81113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            return setParamVideoRotation(degrees);
81213f6284305e4b27395a23db7882d670bdb1bcae1James Dong        }
81393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    } else if (key == "video-param-i-frames-interval") {
8148f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t seconds;
8158f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (safe_strtoi32(value.string(), &seconds)) {
8168f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            return setParamVideoIFramesInterval(seconds);
817ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        }
818145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    } else if (key == "video-param-encoder-profile") {
819145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong        int32_t profile;
820145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong        if (safe_strtoi32(value.string(), &profile)) {
821145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong            return setParamVideoEncoderProfile(profile);
822145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong        }
823145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    } else if (key == "video-param-encoder-level") {
824145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong        int32_t level;
825145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong        if (safe_strtoi32(value.string(), &level)) {
826145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong            return setParamVideoEncoderLevel(level);
827145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong        }
82893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    } else if (key == "video-param-camera-id") {
82993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int32_t cameraId;
83093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (safe_strtoi32(value.string(), &cameraId)) {
83193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return setParamVideoCameraId(cameraId);
8322dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
8338f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    } else if (key == "video-param-time-scale") {
8348f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t timeScale;
8358f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (safe_strtoi32(value.string(), &timeScale)) {
8368f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            return setParamVideoTimeScale(timeScale);
8378f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        }
838e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra    } else if (key == "time-lapse-enable") {
83946d26dd29195450db15704e84d65740628a821fbChong Zhang        int32_t captureFpsEnable;
84046d26dd29195450db15704e84d65740628a821fbChong Zhang        if (safe_strtoi32(value.string(), &captureFpsEnable)) {
84146d26dd29195450db15704e84d65740628a821fbChong Zhang            return setParamCaptureFpsEnable(captureFpsEnable);
842e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        }
8439ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    } else if (key == "time-lapse-fps") {
84473c3e6363b31fb27882c4666453ad8ef050b3cc1Wonsik Kim        double fps;
84573c3e6363b31fb27882c4666453ad8ef050b3cc1Wonsik Kim        if (safe_strtod(value.string(), &fps)) {
84646d26dd29195450db15704e84d65740628a821fbChong Zhang            return setParamCaptureFps(fps);
847e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        }
848050b28a593350047845a45a14cc5026221ac1620James Dong    } else {
84929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("setParameter: failed to find key %s", key.string());
850050b28a593350047845a45a14cc5026221ac1620James Dong    }
851ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    return BAD_VALUE;
852050b28a593350047845a45a14cc5026221ac1620James Dong}
85330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
854050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParameters(const String8 &params) {
8553856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParameters: %s", params.string());
856050b28a593350047845a45a14cc5026221ac1620James Dong    const char *cparams = params.string();
857050b28a593350047845a45a14cc5026221ac1620James Dong    const char *key_start = cparams;
858050b28a593350047845a45a14cc5026221ac1620James Dong    for (;;) {
859050b28a593350047845a45a14cc5026221ac1620James Dong        const char *equal_pos = strchr(key_start, '=');
860050b28a593350047845a45a14cc5026221ac1620James Dong        if (equal_pos == NULL) {
86129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Parameters %s miss a value", cparams);
862050b28a593350047845a45a14cc5026221ac1620James Dong            return BAD_VALUE;
863050b28a593350047845a45a14cc5026221ac1620James Dong        }
864050b28a593350047845a45a14cc5026221ac1620James Dong        String8 key(key_start, equal_pos - key_start);
865050b28a593350047845a45a14cc5026221ac1620James Dong        TrimString(&key);
866050b28a593350047845a45a14cc5026221ac1620James Dong        if (key.length() == 0) {
86729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Parameters %s contains an empty key", cparams);
868050b28a593350047845a45a14cc5026221ac1620James Dong            return BAD_VALUE;
869050b28a593350047845a45a14cc5026221ac1620James Dong        }
870050b28a593350047845a45a14cc5026221ac1620James Dong        const char *value_start = equal_pos + 1;
871050b28a593350047845a45a14cc5026221ac1620James Dong        const char *semicolon_pos = strchr(value_start, ';');
872050b28a593350047845a45a14cc5026221ac1620James Dong        String8 value;
873050b28a593350047845a45a14cc5026221ac1620James Dong        if (semicolon_pos == NULL) {
874050b28a593350047845a45a14cc5026221ac1620James Dong            value.setTo(value_start);
875050b28a593350047845a45a14cc5026221ac1620James Dong        } else {
876050b28a593350047845a45a14cc5026221ac1620James Dong            value.setTo(value_start, semicolon_pos - value_start);
877050b28a593350047845a45a14cc5026221ac1620James Dong        }
878050b28a593350047845a45a14cc5026221ac1620James Dong        if (setParameter(key, value) != OK) {
879050b28a593350047845a45a14cc5026221ac1620James Dong            return BAD_VALUE;
880050b28a593350047845a45a14cc5026221ac1620James Dong        }
881050b28a593350047845a45a14cc5026221ac1620James Dong        if (semicolon_pos == NULL) {
882050b28a593350047845a45a14cc5026221ac1620James Dong            break;  // Reaches the end
883050b28a593350047845a45a14cc5026221ac1620James Dong        }
884050b28a593350047845a45a14cc5026221ac1620James Dong        key_start = semicolon_pos + 1;
885050b28a593350047845a45a14cc5026221ac1620James Dong    }
88630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
88730ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
88830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
88937047fceba836f341d0108beed0991b0f8dfc543James Dongstatus_t StagefrightRecorder::setListener(const sp<IMediaRecorderClient> &listener) {
89030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mListener = listener;
89130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
89230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
89330ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
89430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
895ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvalastatus_t StagefrightRecorder::setClientName(const String16& clientName) {
896ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    mClientName = clientName;
897ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala
898ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    return OK;
899ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala}
900ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala
9011a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhangstatus_t StagefrightRecorder::prepareInternal() {
90272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGV("prepare");
90372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mOutputFd < 0) {
90472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGE("Output file descriptor is invalid");
90572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return INVALID_OPERATION;
90672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
907934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong
90898a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen    // Get UID and PID here for permission checking
909ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    mClientUid = IPCThreadState::self()->getCallingUid();
91098a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen    mClientPid = IPCThreadState::self()->getCallingPid();
91130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
91275b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang    status_t status = OK;
91375b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
9142dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    switch (mOutputFormat) {
9152dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        case OUTPUT_FORMAT_DEFAULT:
9162dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        case OUTPUT_FORMAT_THREE_GPP:
9172dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        case OUTPUT_FORMAT_MPEG_4:
918114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        case OUTPUT_FORMAT_WEBM:
919114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih            status = setupMPEG4orWEBMRecording();
92075b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang            break;
9212dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
9222dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        case OUTPUT_FORMAT_AMR_NB:
9232dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        case OUTPUT_FORMAT_AMR_WB:
92472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status = setupAMRRecording();
92575b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang            break;
9262dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
927ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        case OUTPUT_FORMAT_AAC_ADIF:
928ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        case OUTPUT_FORMAT_AAC_ADTS:
92972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status = setupAACRecording();
93075b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang            break;
931ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
93239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        case OUTPUT_FORMAT_RTP_AVP:
93372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status = setupRTPRecording();
93475b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang            break;
93539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
93659b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        case OUTPUT_FORMAT_MPEG2TS:
93772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status = setupMPEG2TSRecording();
93875b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang            break;
93959b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
9402dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        default:
94129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unsupported output file format: %d", mOutputFormat);
94275b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang            status = UNKNOWN_ERROR;
94375b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang            break;
94475b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang    }
94575b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
9465a4a0a1e4a44b8e48aff8e74df56d37dc6d7129cHangyu Kuang    ALOGV("Recording frameRate: %d captureFps: %f",
9475a4a0a1e4a44b8e48aff8e74df56d37dc6d7129cHangyu Kuang            mFrameRate, mCaptureFps);
9485a4a0a1e4a44b8e48aff8e74df56d37dc6d7129cHangyu Kuang
94972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return status;
95072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
95172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9521a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhangstatus_t StagefrightRecorder::prepare() {
953fc079f79d8d4f6ef9f138aa615486c10dda99fb7Hangyu Kuang    ALOGV("prepare");
954fc079f79d8d4f6ef9f138aa615486c10dda99fb7Hangyu Kuang    Mutex::Autolock autolock(mLock);
9551a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang    if (mVideoSource == VIDEO_SOURCE_SURFACE) {
9561a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang        return prepareInternal();
9571a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang    }
9581a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang    return OK;
9591a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang}
9601a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang
96172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t StagefrightRecorder::start() {
96272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGV("start");
963fc079f79d8d4f6ef9f138aa615486c10dda99fb7Hangyu Kuang    Mutex::Autolock autolock(mLock);
96472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mOutputFd < 0) {
96572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGE("Output file descriptor is invalid");
96672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return INVALID_OPERATION;
96772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
96872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9691a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang    status_t status = OK;
9701a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang
9711a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang    if (mVideoSource != VIDEO_SOURCE_SURFACE) {
9721a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang        status = prepareInternal();
9731a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang        if (status != OK) {
9741a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang            return status;
9751a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang        }
9761a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang    }
9771a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang
97872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mWriter == NULL) {
97972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGE("File writer is not avaialble");
98072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return UNKNOWN_ERROR;
98172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
98272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
98372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    switch (mOutputFormat) {
98472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case OUTPUT_FORMAT_DEFAULT:
98572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case OUTPUT_FORMAT_THREE_GPP:
98672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case OUTPUT_FORMAT_MPEG_4:
987114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        case OUTPUT_FORMAT_WEBM:
98872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
989114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih            bool isMPEG4 = true;
990114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih            if (mOutputFormat == OUTPUT_FORMAT_WEBM) {
991114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih                isMPEG4 = false;
992114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih            }
99372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            sp<MetaData> meta = new MetaData;
994114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih            setupMPEG4orWEBMMetaData(&meta);
99572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status = mWriter->start(meta.get());
99672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
99772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
99872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
99972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case OUTPUT_FORMAT_AMR_NB:
100072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case OUTPUT_FORMAT_AMR_WB:
100172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case OUTPUT_FORMAT_AAC_ADIF:
100272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case OUTPUT_FORMAT_AAC_ADTS:
100372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case OUTPUT_FORMAT_RTP_AVP:
100472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case OUTPUT_FORMAT_MPEG2TS:
100572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
10068f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang            sp<MetaData> meta = new MetaData;
10078f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang            int64_t startTimeUs = systemTime() / 1000;
10088f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang            meta->setInt64(kKeyTime, startTimeUs);
10098f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang            status = mWriter->start(meta.get());
101072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
101172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
101272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
101372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        default:
101472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
101572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            ALOGE("Unsupported output file format: %d", mOutputFormat);
101672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status = UNKNOWN_ERROR;
101772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
101872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
101972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
102072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
102172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (status != OK) {
102272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mWriter.clear();
102372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mWriter = NULL;
102472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
102572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
102675b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang    if ((status == OK) && (!mStarted)) {
1027ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        mAnalyticsDirty = true;
102875b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        mStarted = true;
102975b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
103075b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted;
1031fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin        if (mAudioSource != AUDIO_SOURCE_CNT) {
103275b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang            params |= IMediaPlayerService::kBatteryDataTrackAudio;
103375b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        }
103475b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        if (mVideoSource != VIDEO_SOURCE_LIST_END) {
103575b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang            params |= IMediaPlayerService::kBatteryDataTrackVideo;
103675b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        }
103775b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
103875b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        addBatteryData(params);
10392dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    }
104075b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
104175b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang    return status;
10422dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber}
10432dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
1044d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kimsp<MediaCodecSource> StagefrightRecorder::createAudioSource() {
104546d26dd29195450db15704e84d65740628a821fbChong Zhang    int32_t sourceSampleRate = mSampleRate;
104646d26dd29195450db15704e84d65740628a821fbChong Zhang
104746d26dd29195450db15704e84d65740628a821fbChong Zhang    if (mCaptureFpsEnable && mCaptureFps >= mFrameRate) {
104846d26dd29195450db15704e84d65740628a821fbChong Zhang        // Upscale the sample rate for slow motion recording.
104946d26dd29195450db15704e84d65740628a821fbChong Zhang        // Fail audio source creation if source sample rate is too high, as it could
105046d26dd29195450db15704e84d65740628a821fbChong Zhang        // cause out-of-memory due to large input buffer size. And audio recording
105146d26dd29195450db15704e84d65740628a821fbChong Zhang        // probably doesn't make sense in the scenario, since the slow-down factor
105246d26dd29195450db15704e84d65740628a821fbChong Zhang        // is probably huge (eg. mSampleRate=48K, mCaptureFps=240, mFrameRate=1).
105346d26dd29195450db15704e84d65740628a821fbChong Zhang        const static int32_t SAMPLE_RATE_HZ_MAX = 192000;
105446d26dd29195450db15704e84d65740628a821fbChong Zhang        sourceSampleRate =
105546d26dd29195450db15704e84d65740628a821fbChong Zhang                (mSampleRate * mCaptureFps + mFrameRate / 2) / mFrameRate;
105646d26dd29195450db15704e84d65740628a821fbChong Zhang        if (sourceSampleRate < mSampleRate || sourceSampleRate > SAMPLE_RATE_HZ_MAX) {
105746d26dd29195450db15704e84d65740628a821fbChong Zhang            ALOGE("source sample rate out of range! "
105846d26dd29195450db15704e84d65740628a821fbChong Zhang                    "(mSampleRate %d, mCaptureFps %.2f, mFrameRate %d",
105946d26dd29195450db15704e84d65740628a821fbChong Zhang                    mSampleRate, mCaptureFps, mFrameRate);
106046d26dd29195450db15704e84d65740628a821fbChong Zhang            return NULL;
106146d26dd29195450db15704e84d65740628a821fbChong Zhang        }
106246d26dd29195450db15704e84d65740628a821fbChong Zhang    }
106346d26dd29195450db15704e84d65740628a821fbChong Zhang
10642dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    sp<AudioSource> audioSource =
10652dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        new AudioSource(
10662dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber                mAudioSource,
1067be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov                mOpPackageName,
106846d26dd29195450db15704e84d65740628a821fbChong Zhang                sourceSampleRate,
106946d26dd29195450db15704e84d65740628a821fbChong Zhang                mAudioChannels,
1070b2379ba0a32638bae2ea0460644f68cf5a0967ceEric Laurent                mSampleRate,
1071b2379ba0a32638bae2ea0460644f68cf5a0967ceEric Laurent                mClientUid,
1072b2379ba0a32638bae2ea0460644f68cf5a0967ceEric Laurent                mClientPid);
10732dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
10742dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    status_t err = audioSource->initCheck();
10752dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
10762dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    if (err != OK) {
107729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("audio source is not initialized");
10782dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        return NULL;
10792dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    }
10802dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
108172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> format = new AMessage;
1082050b28a593350047845a45a14cc5026221ac1620James Dong    switch (mAudioEncoder) {
1083050b28a593350047845a45a14cc5026221ac1620James Dong        case AUDIO_ENCODER_AMR_NB:
1084050b28a593350047845a45a14cc5026221ac1620James Dong        case AUDIO_ENCODER_DEFAULT:
108572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
1086050b28a593350047845a45a14cc5026221ac1620James Dong            break;
1087050b28a593350047845a45a14cc5026221ac1620James Dong        case AUDIO_ENCODER_AMR_WB:
108872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
1089050b28a593350047845a45a14cc5026221ac1620James Dong            break;
1090050b28a593350047845a45a14cc5026221ac1620James Dong        case AUDIO_ENCODER_AAC:
109172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
109272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            format->setInt32("aac-profile", OMX_AUDIO_AACObjectLC);
1093aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            break;
1094f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke        case AUDIO_ENCODER_HE_AAC:
109572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
109672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            format->setInt32("aac-profile", OMX_AUDIO_AACObjectHE);
1097f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke            break;
1098aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        case AUDIO_ENCODER_AAC_ELD:
109972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
110072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            format->setInt32("aac-profile", OMX_AUDIO_AACObjectELD);
1101050b28a593350047845a45a14cc5026221ac1620James Dong            break;
1102f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke
1103050b28a593350047845a45a14cc5026221ac1620James Dong        default:
110429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unknown audio encoder: %d", mAudioEncoder);
1105050b28a593350047845a45a14cc5026221ac1620James Dong            return NULL;
1106050b28a593350047845a45a14cc5026221ac1620James Dong    }
11072dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
1108b45c62c8e9b05c2703bdae18cc298ae55550db8aAndreas Huber    int32_t maxInputSize;
1109b45c62c8e9b05c2703bdae18cc298ae55550db8aAndreas Huber    CHECK(audioSource->getFormat()->findInt32(
1110b45c62c8e9b05c2703bdae18cc298ae55550db8aAndreas Huber                kKeyMaxInputSize, &maxInputSize));
1111b45c62c8e9b05c2703bdae18cc298ae55550db8aAndreas Huber
111272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    format->setInt32("max-input-size", maxInputSize);
111372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    format->setInt32("channel-count", mAudioChannels);
111472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    format->setInt32("sample-rate", mSampleRate);
111572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    format->setInt32("bitrate", mAudioBitRate);
1116c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mAudioTimeScale > 0) {
111772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("time-scale", mAudioTimeScale);
1118c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1119fdbc1b3a885f1e8a59b1788e48e24ea4c66acbc8Ronghua Wu    format->setInt32("priority", 0 /* realtime */);
11202dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
1121d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    sp<MediaCodecSource> audioEncoder =
112272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            MediaCodecSource::Create(mLooper, format, audioSource);
1123d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    mAudioSourceNode = audioSource;
11242dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
1125ef0cf50343f8a6d74894f96f5ecb5eec4c5f1bc6Chong Zhang    if (audioEncoder == NULL) {
1126ef0cf50343f8a6d74894f96f5ecb5eec4c5f1bc6Chong Zhang        ALOGE("Failed to create audio encoder");
1127ef0cf50343f8a6d74894f96f5ecb5eec4c5f1bc6Chong Zhang    }
1128ef0cf50343f8a6d74894f96f5ecb5eec4c5f1bc6Chong Zhang
11292dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return audioEncoder;
11302dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber}
11312dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
113272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t StagefrightRecorder::setupAACRecording() {
1133760943b5e7a09b602aba04ec451e97662f48b0a4James Dong    // FIXME:
1134760943b5e7a09b602aba04ec451e97662f48b0a4James Dong    // Add support for OUTPUT_FORMAT_AAC_ADIF
1135f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong    CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_AAC_ADTS);
1136ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
1137aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    CHECK(mAudioEncoder == AUDIO_ENCODER_AAC ||
1138f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke          mAudioEncoder == AUDIO_ENCODER_HE_AAC ||
1139aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke          mAudioEncoder == AUDIO_ENCODER_AAC_ELD);
1140fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin    CHECK(mAudioSource != AUDIO_SOURCE_CNT);
1141ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
1142760943b5e7a09b602aba04ec451e97662f48b0a4James Dong    mWriter = new AACWriter(mOutputFd);
114372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return setupRawAudioRecording();
1144ef9d0cd72e476a4b7556833fb09505a51b626797James Dong}
1145ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
114672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t StagefrightRecorder::setupAMRRecording() {
1147ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    CHECK(mOutputFormat == OUTPUT_FORMAT_AMR_NB ||
1148ef9d0cd72e476a4b7556833fb09505a51b626797James Dong          mOutputFormat == OUTPUT_FORMAT_AMR_WB);
1149ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
1150ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (mOutputFormat == OUTPUT_FORMAT_AMR_NB) {
1151ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (mAudioEncoder != AUDIO_ENCODER_DEFAULT &&
1152ef9d0cd72e476a4b7556833fb09505a51b626797James Dong            mAudioEncoder != AUDIO_ENCODER_AMR_NB) {
115329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Invalid encoder %d used for AMRNB recording",
1154ef9d0cd72e476a4b7556833fb09505a51b626797James Dong                    mAudioEncoder);
1155934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            return BAD_VALUE;
1156ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        }
1157ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    } else {  // mOutputFormat must be OUTPUT_FORMAT_AMR_WB
1158ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
115929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Invlaid encoder %d used for AMRWB recording",
1160ef9d0cd72e476a4b7556833fb09505a51b626797James Dong                    mAudioEncoder);
1161934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            return BAD_VALUE;
1162ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        }
11632dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    }
11642dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
1165760943b5e7a09b602aba04ec451e97662f48b0a4James Dong    mWriter = new AMRWriter(mOutputFd);
116672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return setupRawAudioRecording();
1167760943b5e7a09b602aba04ec451e97662f48b0a4James Dong}
1168760943b5e7a09b602aba04ec451e97662f48b0a4James Dong
116972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t StagefrightRecorder::setupRawAudioRecording() {
11700f8f4e681b867dd611d2d916453337cb0770d4daHochi Huang    if (mAudioSource >= AUDIO_SOURCE_CNT && mAudioSource != AUDIO_SOURCE_FM_TUNER) {
117129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid audio source: %d", mAudioSource);
1172934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return BAD_VALUE;
11732dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    }
11742dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
117542dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    status_t status = BAD_VALUE;
117642dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    if (OK != (status = checkAudioEncoderCapabilities())) {
117742dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong        return status;
117842dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    }
11792dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
1180d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    sp<MediaCodecSource> audioEncoder = createAudioSource();
11812dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    if (audioEncoder == NULL) {
11822dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        return UNKNOWN_ERROR;
11832dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    }
11842dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
1185760943b5e7a09b602aba04ec451e97662f48b0a4James Dong    CHECK(mWriter != 0);
11862dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    mWriter->addSource(audioEncoder);
1187d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    mAudioEncoderSource = audioEncoder;
1188d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1189d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationUs != 0) {
1190d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        mWriter->setMaxFileDuration(mMaxFileDurationUs);
1191d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1192d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeBytes != 0) {
1193d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        mWriter->setMaxFileSize(mMaxFileSizeBytes);
1194d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1195d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    mWriter->setListener(mListener);
11962dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
11972dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
11982dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber}
11992dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
120072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t StagefrightRecorder::setupRTPRecording() {
120139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_RTP_AVP);
120239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
1203fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin    if ((mAudioSource != AUDIO_SOURCE_CNT
120439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                && mVideoSource != VIDEO_SOURCE_LIST_END)
1205fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin            || (mAudioSource == AUDIO_SOURCE_CNT
120639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                && mVideoSource == VIDEO_SOURCE_LIST_END)) {
120739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        // Must have exactly one source.
120839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        return BAD_VALUE;
120939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
121039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
121139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    if (mOutputFd < 0) {
121239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        return BAD_VALUE;
121339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
121439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
1215d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    sp<MediaCodecSource> source;
121639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
1217fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin    if (mAudioSource != AUDIO_SOURCE_CNT) {
121839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        source = createAudioSource();
1219d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        mAudioEncoderSource = source;
122039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    } else {
122154ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang        setDefaultVideoEncoderIfNecessary();
12229c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra
1223b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi        sp<MediaSource> mediaSource;
1224b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi        status_t err = setupMediaSource(&mediaSource);
12259c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra        if (err != OK) {
12269c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra            return err;
12279c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra        }
12289c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra
12294db37cedd4db8230f3ec6191d8d7ba2b0036886eRobert Shih        err = setupVideoEncoder(mediaSource, &source);
123039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        if (err != OK) {
123139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            return err;
123239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        }
1233d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        mVideoEncoderSource = source;
123439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
123539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
1236674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    mWriter = new ARTPWriter(mOutputFd);
123739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mWriter->addSource(source);
123839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mWriter->setListener(mListener);
123939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
124072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
124139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
124239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
124372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t StagefrightRecorder::setupMPEG2TSRecording() {
124459b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_MPEG2TS);
124559b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
1246674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    sp<MediaWriter> writer = new MPEG2TSWriter(mOutputFd);
124759b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
1248fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin    if (mAudioSource != AUDIO_SOURCE_CNT) {
1249f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke        if (mAudioEncoder != AUDIO_ENCODER_AAC &&
1250f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke            mAudioEncoder != AUDIO_ENCODER_HE_AAC &&
1251f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke            mAudioEncoder != AUDIO_ENCODER_AAC_ELD) {
125259b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber            return ERROR_UNSUPPORTED;
125359b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        }
125459b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
125559b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        status_t err = setupAudioEncoder(writer);
125659b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
125759b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        if (err != OK) {
125859b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber            return err;
125959b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        }
126059b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    }
126159b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
1262b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi    if (mVideoSource < VIDEO_SOURCE_LIST_END) {
126359b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        if (mVideoEncoder != VIDEO_ENCODER_H264) {
126454ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang            ALOGE("MPEG2TS recording only supports H.264 encoding!");
126559b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber            return ERROR_UNSUPPORTED;
126659b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        }
126759b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
1268b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi        sp<MediaSource> mediaSource;
1269b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi        status_t err = setupMediaSource(&mediaSource);
1270f9f083e2853740c97588f4db82c24645ae5880e4Kenny Root        if (err != OK) {
1271f9f083e2853740c97588f4db82c24645ae5880e4Kenny Root            return err;
1272f9f083e2853740c97588f4db82c24645ae5880e4Kenny Root        }
1273f9f083e2853740c97588f4db82c24645ae5880e4Kenny Root
1274d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        sp<MediaCodecSource> encoder;
12754db37cedd4db8230f3ec6191d8d7ba2b0036886eRobert Shih        err = setupVideoEncoder(mediaSource, &encoder);
127659b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
127759b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        if (err != OK) {
127859b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber            return err;
127959b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        }
128059b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
128159b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        writer->addSource(encoder);
1282d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        mVideoEncoderSource = encoder;
128359b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    }
128459b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
128559b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    if (mMaxFileDurationUs != 0) {
128659b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        writer->setMaxFileDuration(mMaxFileDurationUs);
128759b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    }
128859b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
128959b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    if (mMaxFileSizeBytes != 0) {
129059b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        writer->setMaxFileSize(mMaxFileSizeBytes);
129159b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    }
129259b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
129359b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    mWriter = writer;
129459b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
129572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
129659b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber}
129759b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
129899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dongvoid StagefrightRecorder::clipVideoFrameRate() {
12993856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("clipVideoFrameRate: encoder %d", mVideoEncoder);
130054ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang    if (mFrameRate == -1) {
130154ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang        mFrameRate = mEncoderProfiles->getCamcorderProfileParamByName(
130254ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang                "vid.fps", mCameraId, CAMCORDER_QUALITY_LOW);
130354ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang        ALOGW("Using default video fps %d", mFrameRate);
130454ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang    }
130554ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang
130699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int minFrameRate = mEncoderProfiles->getVideoEncoderParamByName(
130799c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.fps.min", mVideoEncoder);
130899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int maxFrameRate = mEncoderProfiles->getVideoEncoderParamByName(
130999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.fps.max", mVideoEncoder);
1310b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    if (mFrameRate < minFrameRate && minFrameRate != -1) {
13115ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended video encoding frame rate (%d fps) is too small"
131299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d fps)", mFrameRate, minFrameRate);
131399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mFrameRate = minFrameRate;
1314b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    } else if (mFrameRate > maxFrameRate && maxFrameRate != -1) {
13155ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended video encoding frame rate (%d fps) is too large"
131699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d fps)", mFrameRate, maxFrameRate);
131799c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mFrameRate = maxFrameRate;
131899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    }
131999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong}
132099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong
132199c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dongvoid StagefrightRecorder::clipVideoBitRate() {
13223856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("clipVideoBitRate: encoder %d", mVideoEncoder);
132399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int minBitRate = mEncoderProfiles->getVideoEncoderParamByName(
132499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.bps.min", mVideoEncoder);
132599c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int maxBitRate = mEncoderProfiles->getVideoEncoderParamByName(
132699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.bps.max", mVideoEncoder);
1327b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    if (mVideoBitRate < minBitRate && minBitRate != -1) {
13285ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended video encoding bit rate (%d bps) is too small"
132999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d bps)", mVideoBitRate, minBitRate);
133099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mVideoBitRate = minBitRate;
1331b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    } else if (mVideoBitRate > maxBitRate && maxBitRate != -1) {
13325ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended video encoding bit rate (%d bps) is too large"
133399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d bps)", mVideoBitRate, maxBitRate);
133499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mVideoBitRate = maxBitRate;
133599c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    }
133699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong}
133799c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong
133899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dongvoid StagefrightRecorder::clipVideoFrameWidth() {
13393856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("clipVideoFrameWidth: encoder %d", mVideoEncoder);
134099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int minFrameWidth = mEncoderProfiles->getVideoEncoderParamByName(
134199c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.width.min", mVideoEncoder);
134299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int maxFrameWidth = mEncoderProfiles->getVideoEncoderParamByName(
134399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.width.max", mVideoEncoder);
1344b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    if (mVideoWidth < minFrameWidth && minFrameWidth != -1) {
13455ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended video encoding frame width (%d) is too small"
134699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d)", mVideoWidth, minFrameWidth);
134799c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mVideoWidth = minFrameWidth;
1348b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    } else if (mVideoWidth > maxFrameWidth && maxFrameWidth != -1) {
13495ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended video encoding frame width (%d) is too large"
135099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d)", mVideoWidth, maxFrameWidth);
135199c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mVideoWidth = maxFrameWidth;
135299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    }
135399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong}
135499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong
1355d46a6b9fd8b2a4f9098757384711e2cd03a91651Eino-Ville Talvalastatus_t StagefrightRecorder::checkVideoEncoderCapabilities() {
135646d26dd29195450db15704e84d65740628a821fbChong Zhang    if (!mCaptureFpsEnable) {
1357e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        // Dont clip for time lapse capture as encoder will have enough
1358e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        // time to encode because of slow capture rate of time lapse.
1359e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        clipVideoBitRate();
1360e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        clipVideoFrameRate();
1361e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        clipVideoFrameWidth();
1362e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        clipVideoFrameHeight();
1363d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        setDefaultProfileIfNecessary();
1364e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra    }
1365934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    return OK;
1366934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong}
1367934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong
1368d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong// Set to use AVC baseline profile if the encoding parameters matches
1369d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong// CAMCORDER_QUALITY_LOW profile; this is for the sake of MMS service.
1370d552b88515c6ccd18695e5db5e6032a6425d8c63James Dongvoid StagefrightRecorder::setDefaultProfileIfNecessary() {
13713856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setDefaultProfileIfNecessary");
1372d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1373d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    camcorder_quality quality = CAMCORDER_QUALITY_LOW;
1374d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1375d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    int64_t durationUs   = mEncoderProfiles->getCamcorderProfileParamByName(
1376d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong                                "duration", mCameraId, quality) * 1000000LL;
1377d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1378d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    int fileFormat       = mEncoderProfiles->getCamcorderProfileParamByName(
1379d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong                                "file.format", mCameraId, quality);
1380d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1381d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    int videoCodec       = mEncoderProfiles->getCamcorderProfileParamByName(
1382d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong                                "vid.codec", mCameraId, quality);
1383d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1384d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    int videoBitRate     = mEncoderProfiles->getCamcorderProfileParamByName(
1385d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong                                "vid.bps", mCameraId, quality);
1386d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1387d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    int videoFrameRate   = mEncoderProfiles->getCamcorderProfileParamByName(
1388d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong                                "vid.fps", mCameraId, quality);
1389d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1390d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    int videoFrameWidth  = mEncoderProfiles->getCamcorderProfileParamByName(
1391d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong                                "vid.width", mCameraId, quality);
1392d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1393d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    int videoFrameHeight = mEncoderProfiles->getCamcorderProfileParamByName(
1394d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong                                "vid.height", mCameraId, quality);
1395d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1396d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    int audioCodec       = mEncoderProfiles->getCamcorderProfileParamByName(
1397d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong                                "aud.codec", mCameraId, quality);
1398d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1399d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    int audioBitRate     = mEncoderProfiles->getCamcorderProfileParamByName(
1400d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong                                "aud.bps", mCameraId, quality);
1401d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1402d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    int audioSampleRate  = mEncoderProfiles->getCamcorderProfileParamByName(
1403d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong                                "aud.hz", mCameraId, quality);
1404d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1405d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    int audioChannels    = mEncoderProfiles->getCamcorderProfileParamByName(
1406d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong                                "aud.ch", mCameraId, quality);
1407d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1408d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    if (durationUs == mMaxFileDurationUs &&
1409d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        fileFormat == mOutputFormat &&
1410d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        videoCodec == mVideoEncoder &&
1411d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        videoBitRate == mVideoBitRate &&
1412d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        videoFrameRate == mFrameRate &&
1413d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        videoFrameWidth == mVideoWidth &&
1414d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        videoFrameHeight == mVideoHeight &&
1415d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        audioCodec == mAudioEncoder &&
1416d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        audioBitRate == mAudioBitRate &&
1417d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        audioSampleRate == mSampleRate &&
1418d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        audioChannels == mAudioChannels) {
1419d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        if (videoCodec == VIDEO_ENCODER_H264) {
1420df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block            ALOGI("Force to use AVC baseline profile");
1421d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong            setParamVideoEncoderProfile(OMX_VIDEO_AVCProfileBaseline);
1422a147b4f91143d9f2fb608e22f9fca14bbd029573Lajos Molnar            // set 0 for invalid levels - this will be rejected by the
1423a147b4f91143d9f2fb608e22f9fca14bbd029573Lajos Molnar            // codec if it cannot handle it during configure
1424a147b4f91143d9f2fb608e22f9fca14bbd029573Lajos Molnar            setParamVideoEncoderLevel(ACodec::getAVCLevelFor(
1425a147b4f91143d9f2fb608e22f9fca14bbd029573Lajos Molnar                    videoFrameWidth, videoFrameHeight, videoFrameRate, videoBitRate));
1426d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        }
1427d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    }
1428d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong}
1429d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
143054ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhangvoid StagefrightRecorder::setDefaultVideoEncoderIfNecessary() {
143154ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang    if (mVideoEncoder == VIDEO_ENCODER_DEFAULT) {
143254ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang        if (mOutputFormat == OUTPUT_FORMAT_WEBM) {
143354ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang            // default to VP8 for WEBM recording
143454ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang            mVideoEncoder = VIDEO_ENCODER_VP8;
143554ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang        } else {
143654ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang            // pick the default encoder for CAMCORDER_QUALITY_LOW
143754ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang            int videoCodec = mEncoderProfiles->getCamcorderProfileParamByName(
143854ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang                    "vid.codec", mCameraId, CAMCORDER_QUALITY_LOW);
143954ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang
144054ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang            if (videoCodec > VIDEO_ENCODER_DEFAULT &&
144154ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang                videoCodec < VIDEO_ENCODER_LIST_END) {
144254ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang                mVideoEncoder = (video_encoder)videoCodec;
144354ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang            } else {
144454ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang                // default to H.264 if camcorder profile not available
144554ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang                mVideoEncoder = VIDEO_ENCODER_H264;
144654ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang            }
144754ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang        }
144854ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang    }
144954ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang}
145054ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang
145142dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dongstatus_t StagefrightRecorder::checkAudioEncoderCapabilities() {
145242dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    clipAudioBitRate();
145342dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    clipAudioSampleRate();
145442dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    clipNumberOfAudioChannels();
145542dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    return OK;
145642dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong}
145742dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
145842dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dongvoid StagefrightRecorder::clipAudioBitRate() {
14593856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("clipAudioBitRate: encoder %d", mAudioEncoder);
146042dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
146142dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    int minAudioBitRate =
146242dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            mEncoderProfiles->getAudioEncoderParamByName(
146342dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong                "enc.aud.bps.min", mAudioEncoder);
1464b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    if (minAudioBitRate != -1 && mAudioBitRate < minAudioBitRate) {
14655ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended audio encoding bit rate (%d) is too small"
146642dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            " and will be set to (%d)", mAudioBitRate, minAudioBitRate);
146742dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong        mAudioBitRate = minAudioBitRate;
146842dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    }
146942dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
147042dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    int maxAudioBitRate =
147142dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            mEncoderProfiles->getAudioEncoderParamByName(
147242dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong                "enc.aud.bps.max", mAudioEncoder);
1473b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    if (maxAudioBitRate != -1 && mAudioBitRate > maxAudioBitRate) {
14745ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended audio encoding bit rate (%d) is too large"
147542dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            " and will be set to (%d)", mAudioBitRate, maxAudioBitRate);
147642dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong        mAudioBitRate = maxAudioBitRate;
147742dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    }
147842dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong}
147942dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
148042dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dongvoid StagefrightRecorder::clipAudioSampleRate() {
14813856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("clipAudioSampleRate: encoder %d", mAudioEncoder);
148242dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
148342dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    int minSampleRate =
148442dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            mEncoderProfiles->getAudioEncoderParamByName(
148542dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong                "enc.aud.hz.min", mAudioEncoder);
1486b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    if (minSampleRate != -1 && mSampleRate < minSampleRate) {
14875ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended audio sample rate (%d) is too small"
148842dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            " and will be set to (%d)", mSampleRate, minSampleRate);
148942dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong        mSampleRate = minSampleRate;
149042dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    }
149142dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
149242dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    int maxSampleRate =
149342dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            mEncoderProfiles->getAudioEncoderParamByName(
149442dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong                "enc.aud.hz.max", mAudioEncoder);
1495b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    if (maxSampleRate != -1 && mSampleRate > maxSampleRate) {
14965ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended audio sample rate (%d) is too large"
149742dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            " and will be set to (%d)", mSampleRate, maxSampleRate);
149842dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong        mSampleRate = maxSampleRate;
149942dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    }
150042dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong}
150142dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
150242dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dongvoid StagefrightRecorder::clipNumberOfAudioChannels() {
15033856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("clipNumberOfAudioChannels: encoder %d", mAudioEncoder);
150442dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
150542dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    int minChannels =
150642dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            mEncoderProfiles->getAudioEncoderParamByName(
150742dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong                "enc.aud.ch.min", mAudioEncoder);
1508b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    if (minChannels != -1 && mAudioChannels < minChannels) {
15095ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended number of audio channels (%d) is too small"
151042dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            " and will be set to (%d)", mAudioChannels, minChannels);
151142dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong        mAudioChannels = minChannels;
151242dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    }
151342dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
151442dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    int maxChannels =
151542dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            mEncoderProfiles->getAudioEncoderParamByName(
151642dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong                "enc.aud.ch.max", mAudioEncoder);
1517b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    if (maxChannels != -1 && mAudioChannels > maxChannels) {
15185ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended number of audio channels (%d) is too large"
151942dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            " and will be set to (%d)", mAudioChannels, maxChannels);
152042dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong        mAudioChannels = maxChannels;
152142dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    }
152242dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong}
152342dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
152499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dongvoid StagefrightRecorder::clipVideoFrameHeight() {
15253856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("clipVideoFrameHeight: encoder %d", mVideoEncoder);
152699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int minFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
152799c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.height.min", mVideoEncoder);
152899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int maxFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
152999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.height.max", mVideoEncoder);
1530b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    if (minFrameHeight != -1 && mVideoHeight < minFrameHeight) {
15315ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended video encoding frame height (%d) is too small"
153299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d)", mVideoHeight, minFrameHeight);
153399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mVideoHeight = minFrameHeight;
1534b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    } else if (maxFrameHeight != -1 && mVideoHeight > maxFrameHeight) {
15355ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended video encoding frame height (%d) is too large"
153699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d)", mVideoHeight, maxFrameHeight);
153799c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mVideoHeight = maxFrameHeight;
153899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    }
153999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong}
154099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong
1541b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi// Set up the appropriate MediaSource depending on the chosen option
1542b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketistatus_t StagefrightRecorder::setupMediaSource(
1543b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi                      sp<MediaSource> *mediaSource) {
1544b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi    if (mVideoSource == VIDEO_SOURCE_DEFAULT
1545b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi            || mVideoSource == VIDEO_SOURCE_CAMERA) {
1546b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi        sp<CameraSource> cameraSource;
1547b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi        status_t err = setupCameraSource(&cameraSource);
1548b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi        if (err != OK) {
1549b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi            return err;
1550b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi        }
1551b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi        *mediaSource = cameraSource;
155272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    } else if (mVideoSource == VIDEO_SOURCE_SURFACE) {
155372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        *mediaSource = NULL;
1554b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi    } else {
1555b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi        return INVALID_OPERATION;
1556b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi    }
1557b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi    return OK;
1558b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi}
1559b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi
15608480835b4bc1350646376aa7f3ae33742a7adeb1James Dongstatus_t StagefrightRecorder::setupCameraSource(
15618480835b4bc1350646376aa7f3ae33742a7adeb1James Dong        sp<CameraSource> *cameraSource) {
1562635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong    status_t err = OK;
1563d46a6b9fd8b2a4f9098757384711e2cd03a91651Eino-Ville Talvala    if ((err = checkVideoEncoderCapabilities()) != OK) {
1564635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        return err;
1565635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong    }
156654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size videoSize;
156754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    videoSize.width = mVideoWidth;
156854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    videoSize.height = mVideoHeight;
156946d26dd29195450db15704e84d65740628a821fbChong Zhang    if (mCaptureFpsEnable) {
157022dc508717c7767927064ec7c152def99e54adcbPawin Vongmasa        if (!(mCaptureFps > 0.)) {
157122dc508717c7767927064ec7c152def99e54adcbPawin Vongmasa            ALOGE("Invalid mCaptureFps value: %lf", mCaptureFps);
15722e77ad2a9f7afb57b6f9127dd7c229e774baa9c8James Dong            return BAD_VALUE;
15732e77ad2a9f7afb57b6f9127dd7c229e774baa9c8James Dong        }
15742e77ad2a9f7afb57b6f9127dd7c229e774baa9c8James Dong
157554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCameraSourceTimeLapse = CameraSourceTimeLapse::CreateFromCamera(
157698a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen                mCamera, mCameraProxy, mCameraId, mClientName, mClientUid, mClientPid,
157754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                videoSize, mFrameRate, mPreviewSurface,
157822dc508717c7767927064ec7c152def99e54adcbPawin Vongmasa                std::llround(1e6 / mCaptureFps));
157978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        *cameraSource = mCameraSourceTimeLapse;
158078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    } else {
158154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        *cameraSource = CameraSource::CreateFromCamera(
158298a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen                mCamera, mCameraProxy, mCameraId, mClientName, mClientUid, mClientPid,
1583ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala                videoSize, mFrameRate,
1584d46a6b9fd8b2a4f9098757384711e2cd03a91651Eino-Ville Talvala                mPreviewSurface);
158578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    }
15864ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mCamera.clear();
15874ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mCameraProxy.clear();
1588ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    if (*cameraSource == NULL) {
1589ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong        return UNKNOWN_ERROR;
1590ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    }
1591ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong
1592ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    if ((*cameraSource)->initCheck() != OK) {
1593ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong        (*cameraSource).clear();
1594ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong        *cameraSource = NULL;
1595ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong        return NO_INIT;
1596ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    }
15979c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra
1598635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong    // When frame rate is not set, the actual frame rate will be set to
1599635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong    // the current frame rate being used.
1600635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong    if (mFrameRate == -1) {
1601635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        int32_t frameRate = 0;
1602635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        CHECK ((*cameraSource)->getFormat()->findInt32(
1603393410a441b6d06daf286ed496470e9d6b2b6ca8James Dong                    kKeyFrameRate, &frameRate));
1604df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("Frame rate is not explicitly set. Use the current frame "
1605635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong             "rate (%d fps)", frameRate);
1606635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        mFrameRate = frameRate;
1607635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong    }
1608635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong
1609635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong    CHECK(mFrameRate != -1);
16108480835b4bc1350646376aa7f3ae33742a7adeb1James Dong
16113e328782f1e1061d08ea0c45b855cc418a2d9ea6Lajos Molnar    mMetaDataStoredInVideoBuffers =
16123e328782f1e1061d08ea0c45b855cc418a2d9ea6Lajos Molnar        (*cameraSource)->metaDataStoredInVideoBuffers();
16138480835b4bc1350646376aa7f3ae33742a7adeb1James Dong
16149c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra    return OK;
16159c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra}
16169c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra
16179c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatrastatus_t StagefrightRecorder::setupVideoEncoder(
16180d1ed381fde5dac12dd84fcf3da66dac46699378Chih-Hung Hsieh        const sp<MediaSource> &cameraSource,
1619d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        sp<MediaCodecSource> *source) {
16209c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra    source->clear();
1621050b28a593350047845a45a14cc5026221ac1620James Dong
162272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> format = new AMessage();
1623ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
1624934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    switch (mVideoEncoder) {
1625934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        case VIDEO_ENCODER_H263:
162672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            format->setString("mime", MEDIA_MIMETYPE_VIDEO_H263);
1627934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            break;
162865ae665befd929efd1a7d1c9addac41c699f04b2James Dong
1629934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        case VIDEO_ENCODER_MPEG_4_SP:
163072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            format->setString("mime", MEDIA_MIMETYPE_VIDEO_MPEG4);
1631934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            break;
163230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1633934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        case VIDEO_ENCODER_H264:
163472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            format->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC);
1635934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            break;
163630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
163776dc9c5052741bf0910a23a20c9df6018c4979d8Robert Shih        case VIDEO_ENCODER_VP8:
163876dc9c5052741bf0910a23a20c9df6018c4979d8Robert Shih            format->setString("mime", MEDIA_MIMETYPE_VIDEO_VP8);
163976dc9c5052741bf0910a23a20c9df6018c4979d8Robert Shih            break;
164076dc9c5052741bf0910a23a20c9df6018c4979d8Robert Shih
16419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        case VIDEO_ENCODER_HEVC:
16429aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            format->setString("mime", MEDIA_MIMETYPE_VIDEO_HEVC);
16439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            break;
16449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
1645934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        default:
1646934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            CHECK(!"Should not be here, unsupported video encoding.");
1647934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            break;
1648934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    }
1649ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
165072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (cameraSource != NULL) {
165172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<MetaData> meta = cameraSource->getFormat();
165230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
165372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        int32_t width, height, stride, sliceHeight, colorFormat;
165472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(meta->findInt32(kKeyWidth, &width));
165572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(meta->findInt32(kKeyHeight, &height));
165672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(meta->findInt32(kKeyStride, &stride));
165772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight));
165872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));
165972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
166072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("width", width);
166172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("height", height);
166272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("stride", stride);
166372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("slice-height", sliceHeight);
166472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("color-format", colorFormat);
166572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    } else {
166672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("width", mVideoWidth);
166772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("height", mVideoHeight);
166872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("stride", mVideoWidth);
1669e62ba9cce4631737e38db1b0d8a7a64ee81cc397xrwu        format->setInt32("slice-height", mVideoHeight);
167072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("color-format", OMX_COLOR_FormatAndroidOpaque);
16712c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang
16722c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang        // set up time lapse/slow motion for surface source
167346d26dd29195450db15704e84d65740628a821fbChong Zhang        if (mCaptureFpsEnable) {
167422dc508717c7767927064ec7c152def99e54adcbPawin Vongmasa            if (!(mCaptureFps > 0.)) {
167522dc508717c7767927064ec7c152def99e54adcbPawin Vongmasa                ALOGE("Invalid mCaptureFps value: %lf", mCaptureFps);
16762c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang                return BAD_VALUE;
16772c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang            }
167822dc508717c7767927064ec7c152def99e54adcbPawin Vongmasa            format->setDouble("time-lapse-fps", mCaptureFps);
16792c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang        }
168072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
168172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
168272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    format->setInt32("bitrate", mVideoBitRate);
168372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    format->setInt32("frame-rate", mFrameRate);
168472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    format->setInt32("i-frame-interval", mIFramesIntervalSec);
168530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1686c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mVideoTimeScale > 0) {
168772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("time-scale", mVideoTimeScale);
1688c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1689145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    if (mVideoEncoderProfile != -1) {
169072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("profile", mVideoEncoderProfile);
1691145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    }
1692145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    if (mVideoEncoderLevel != -1) {
169372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("level", mVideoEncoderLevel);
1694145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    }
169530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
16962da225766572a3d4746b4e21cb231a0243b114abLajos Molnar    uint32_t tsLayers = 1;
1697e19f2956de379b9c9a852d50d83d0608ca42bfe9Lajos Molnar    bool preferBFrames = true; // we like B-frames as it produces better quality per bitrate
1698fdbc1b3a885f1e8a59b1788e48e24ea4c66acbc8Ronghua Wu    format->setInt32("priority", 0 /* realtime */);
16992da225766572a3d4746b4e21cb231a0243b114abLajos Molnar    float maxPlaybackFps = mFrameRate; // assume video is only played back at normal speed
17002da225766572a3d4746b4e21cb231a0243b114abLajos Molnar
170146d26dd29195450db15704e84d65740628a821fbChong Zhang    if (mCaptureFpsEnable) {
1702fdbc1b3a885f1e8a59b1788e48e24ea4c66acbc8Ronghua Wu        format->setFloat("operating-rate", mCaptureFps);
1703c96cfbe66d7bf261c57ff93984bc6a4b3a58f6fcLajos Molnar
1704c96cfbe66d7bf261c57ff93984bc6a4b3a58f6fcLajos Molnar        // enable layering for all time lapse and high frame rate recordings
17052da225766572a3d4746b4e21cb231a0243b114abLajos Molnar        if (mFrameRate / mCaptureFps >= 1.9) { // time lapse
1706e19f2956de379b9c9a852d50d83d0608ca42bfe9Lajos Molnar            preferBFrames = false;
17072da225766572a3d4746b4e21cb231a0243b114abLajos Molnar            tsLayers = 2; // use at least two layers as resulting video will likely be sped up
17082da225766572a3d4746b4e21cb231a0243b114abLajos Molnar        } else if (mCaptureFps > maxPlaybackFps) { // slow-mo
17092da225766572a3d4746b4e21cb231a0243b114abLajos Molnar            maxPlaybackFps = mCaptureFps; // assume video will be played back at full capture speed
1710e19f2956de379b9c9a852d50d83d0608ca42bfe9Lajos Molnar            preferBFrames = false;
17112da225766572a3d4746b4e21cb231a0243b114abLajos Molnar        }
17122da225766572a3d4746b4e21cb231a0243b114abLajos Molnar    }
1713c96cfbe66d7bf261c57ff93984bc6a4b3a58f6fcLajos Molnar
17142da225766572a3d4746b4e21cb231a0243b114abLajos Molnar    for (uint32_t tryLayers = 1; tryLayers <= kMaxNumVideoTemporalLayers; ++tryLayers) {
17152da225766572a3d4746b4e21cb231a0243b114abLajos Molnar        if (tryLayers > tsLayers) {
17162da225766572a3d4746b4e21cb231a0243b114abLajos Molnar            tsLayers = tryLayers;
1717c96cfbe66d7bf261c57ff93984bc6a4b3a58f6fcLajos Molnar        }
17182da225766572a3d4746b4e21cb231a0243b114abLajos Molnar        // keep going until the base layer fps falls below the typical display refresh rate
17192da225766572a3d4746b4e21cb231a0243b114abLajos Molnar        float baseLayerFps = maxPlaybackFps / (1 << (tryLayers - 1));
17202da225766572a3d4746b4e21cb231a0243b114abLajos Molnar        if (baseLayerFps < kMinTypicalDisplayRefreshingRate / 0.9) {
17212da225766572a3d4746b4e21cb231a0243b114abLajos Molnar            break;
17222da225766572a3d4746b4e21cb231a0243b114abLajos Molnar        }
17232da225766572a3d4746b4e21cb231a0243b114abLajos Molnar    }
17242da225766572a3d4746b4e21cb231a0243b114abLajos Molnar
17252da225766572a3d4746b4e21cb231a0243b114abLajos Molnar    if (tsLayers > 1) {
17262da225766572a3d4746b4e21cb231a0243b114abLajos Molnar        uint32_t bLayers = std::min(2u, tsLayers - 1); // use up-to 2 B-layers
17272da225766572a3d4746b4e21cb231a0243b114abLajos Molnar        uint32_t pLayers = tsLayers - bLayers;
17282da225766572a3d4746b4e21cb231a0243b114abLajos Molnar        format->setString(
17292da225766572a3d4746b4e21cb231a0243b114abLajos Molnar                "ts-schema", AStringPrintf("android.generic.%u+%u", pLayers, bLayers));
1730e19f2956de379b9c9a852d50d83d0608ca42bfe9Lajos Molnar
1731e19f2956de379b9c9a852d50d83d0608ca42bfe9Lajos Molnar        // TODO: some encoders do not support B-frames with temporal layering, and we have a
1732e19f2956de379b9c9a852d50d83d0608ca42bfe9Lajos Molnar        // different preference based on use-case. We could move this into camera profiles.
1733e19f2956de379b9c9a852d50d83d0608ca42bfe9Lajos Molnar        format->setInt32("android._prefer-b-frames", preferBFrames);
1734fdbc1b3a885f1e8a59b1788e48e24ea4c66acbc8Ronghua Wu    }
1735fdbc1b3a885f1e8a59b1788e48e24ea4c66acbc8Ronghua Wu
17363e328782f1e1061d08ea0c45b855cc418a2d9ea6Lajos Molnar    if (mMetaDataStoredInVideoBuffers != kMetadataBufferTypeInvalid) {
17373e328782f1e1061d08ea0c45b855cc418a2d9ea6Lajos Molnar        format->setInt32("android._input-metadata-buffer-type", mMetaDataStoredInVideoBuffers);
17388480835b4bc1350646376aa7f3ae33742a7adeb1James Dong    }
17397757f5010a771fb8824b6fdf9788f588a1577e3fJames Dong
17403e328782f1e1061d08ea0c45b855cc418a2d9ea6Lajos Molnar    uint32_t flags = 0;
174172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (cameraSource == NULL) {
174272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        flags |= MediaCodecSource::FLAG_USE_SURFACE_INPUT;
1743b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar    } else {
1744b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar        // require dataspace setup even if not using surface input
1745b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar        format->setInt32("android._using-recorder", 1);
17467757f5010a771fb8824b6fdf9788f588a1577e3fJames Dong    }
17477757f5010a771fb8824b6fdf9788f588a1577e3fJames Dong
1748e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang    sp<MediaCodecSource> encoder = MediaCodecSource::Create(
1749e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            mLooper, format, cameraSource, mPersistentSurface, flags);
1750934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    if (encoder == NULL) {
1751ef0cf50343f8a6d74894f96f5ecb5eec4c5f1bc6Chong Zhang        ALOGE("Failed to create video encoder");
17521cc73922339a110d7ffc47e8842f958492dd85bfJames Dong        // When the encoder fails to be created, we need
17531cc73922339a110d7ffc47e8842f958492dd85bfJames Dong        // release the camera source due to the camera's lock
17541cc73922339a110d7ffc47e8842f958492dd85bfJames Dong        // and unlock mechanism.
175572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (cameraSource != NULL) {
175672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            cameraSource->stop();
175772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
1758934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return UNKNOWN_ERROR;
1759934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    }
176030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
176172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (cameraSource == NULL) {
176272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mGraphicBufferProducer = encoder->getGraphicBufferProducer();
176372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
176472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
176539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    *source = encoder;
176639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
1767934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    return OK;
1768934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong}
176930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1770934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dongstatus_t StagefrightRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) {
177142dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    status_t status = BAD_VALUE;
177242dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    if (OK != (status = checkAudioEncoderCapabilities())) {
177342dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong        return status;
177442dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    }
177542dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
1776934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    switch(mAudioEncoder) {
1777934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        case AUDIO_ENCODER_AMR_NB:
1778934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        case AUDIO_ENCODER_AMR_WB:
1779934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        case AUDIO_ENCODER_AAC:
1780f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke        case AUDIO_ENCODER_HE_AAC:
1781aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        case AUDIO_ENCODER_AAC_ELD:
1782934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            break;
178342dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
1784934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        default:
178529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unsupported audio encoder: %d", mAudioEncoder);
1786934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            return UNKNOWN_ERROR;
1787934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    }
178830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1789d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    sp<MediaCodecSource> audioEncoder = createAudioSource();
1790934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    if (audioEncoder == NULL) {
1791934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return UNKNOWN_ERROR;
1792934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    }
17938f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
1794934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    writer->addSource(audioEncoder);
1795d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    mAudioEncoderSource = audioEncoder;
1796934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    return OK;
1797934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong}
179830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1799114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shihstatus_t StagefrightRecorder::setupMPEG4orWEBMRecording() {
18004db37cedd4db8230f3ec6191d8d7ba2b0036886eRobert Shih    mWriter.clear();
180172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mTotalBitRate = 0;
180272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
1803934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    status_t err = OK;
1804114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih    sp<MediaWriter> writer;
1805e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    sp<MPEG4Writer> mp4writer;
180668e97e7388bc9efa03e56c999645002cc3f38df5Robert Shih    if (mOutputFormat == OUTPUT_FORMAT_WEBM) {
1807114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        writer = new WebmWriter(mOutputFd);
180868e97e7388bc9efa03e56c999645002cc3f38df5Robert Shih    } else {
1809e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writer = mp4writer = new MPEG4Writer(mOutputFd);
1810114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih    }
181130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1812b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi    if (mVideoSource < VIDEO_SOURCE_LIST_END) {
181354ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang        setDefaultVideoEncoderIfNecessary();
18149c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra
1815b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi        sp<MediaSource> mediaSource;
18163cecf640c4daf2df616b278bd9986018c8182908James Dong        err = setupMediaSource(&mediaSource);
18179c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra        if (err != OK) {
18189c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra            return err;
18199c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra        }
18209c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra
1821d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        sp<MediaCodecSource> encoder;
18224db37cedd4db8230f3ec6191d8d7ba2b0036886eRobert Shih        err = setupVideoEncoder(mediaSource, &encoder);
18239c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra        if (err != OK) {
18249c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra            return err;
18259c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra        }
18269c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra
182739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        writer->addSource(encoder);
1828d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        mVideoEncoderSource = encoder;
182972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mTotalBitRate += mVideoBitRate;
183030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    }
183130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
183268e97e7388bc9efa03e56c999645002cc3f38df5Robert Shih    if (mOutputFormat != OUTPUT_FORMAT_WEBM) {
1833114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        // Audio source is added at the end if it exists.
1834114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        // This help make sure that the "recoding" sound is suppressed for
1835114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        // camcorder applications in the recorded files.
1836114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        // TODO Audio source is currently unsupported for webm output; vorbis encoder needed.
183746d26dd29195450db15704e84d65740628a821fbChong Zhang        // disable audio for time lapse recording
183846d26dd29195450db15704e84d65740628a821fbChong Zhang        bool disableAudio = mCaptureFpsEnable && mCaptureFps < mFrameRate;
183946d26dd29195450db15704e84d65740628a821fbChong Zhang        if (!disableAudio && mAudioSource != AUDIO_SOURCE_CNT) {
1840114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih            err = setupAudioEncoder(writer);
1841114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih            if (err != OK) return err;
1842114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih            mTotalBitRate += mAudioBitRate;
1843114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        }
18447bd460110b27a979384dda351788eac95d8467f5James Dong
184546d26dd29195450db15704e84d65740628a821fbChong Zhang        if (mCaptureFpsEnable) {
18469ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang            mp4writer->setCaptureRate(mCaptureFps);
1847e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        }
1848e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
1849114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        if (mInterleaveDurationUs > 0) {
1850e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            mp4writer->setInterleaveDuration(mInterleaveDurationUs);
1851114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        }
1852114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        if (mLongitudex10000 > -3600000 && mLatitudex10000 > -3600000) {
1853e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            mp4writer->setGeoData(mLatitudex10000, mLongitudex10000);
1854114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        }
185507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
1856d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationUs != 0) {
1857934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        writer->setMaxFileDuration(mMaxFileDurationUs);
1858d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1859d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeBytes != 0) {
1860934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        writer->setMaxFileSize(mMaxFileSizeBytes);
1861d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
186272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mVideoSource == VIDEO_SOURCE_DEFAULT
186372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            || mVideoSource == VIDEO_SOURCE_CAMERA) {
186472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStartTimeOffsetMs = mEncoderProfiles->getStartTimeOffsetMs(mCameraId);
186572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    } else if (mVideoSource == VIDEO_SOURCE_SURFACE) {
186672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // surface source doesn't need large initial delay
186772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStartTimeOffsetMs = 200;
186872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
186986b7f47aa7482424cf8fd248f1315311919be3b0James Dong    if (mStartTimeOffsetMs > 0) {
1870114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        writer->setStartTimeOffsetMs(mStartTimeOffsetMs);
187186b7f47aa7482424cf8fd248f1315311919be3b0James Dong    }
187286b7f47aa7482424cf8fd248f1315311919be3b0James Dong
18739c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra    writer->setListener(mListener);
18744db37cedd4db8230f3ec6191d8d7ba2b0036886eRobert Shih    mWriter = writer;
18759c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra    return OK;
18769c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra}
18779c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra
1878114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shihvoid StagefrightRecorder::setupMPEG4orWEBMMetaData(sp<MetaData> *meta) {
187972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    int64_t startTimeUs = systemTime() / 1000;
18809c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra    (*meta)->setInt64(kKeyTime, startTimeUs);
18819c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra    (*meta)->setInt32(kKeyFileType, mOutputFormat);
188272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    (*meta)->setInt32(kKeyBitRate, mTotalBitRate);
1883c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMovieTimeScale > 0) {
18849c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra        (*meta)->setInt32(kKeyTimeScale, mMovieTimeScale);
1885c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
188668e97e7388bc9efa03e56c999645002cc3f38df5Robert Shih    if (mOutputFormat != OUTPUT_FORMAT_WEBM) {
1887114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        (*meta)->setInt32(kKey64BitFileOffset, mUse64BitFileOffset);
1888114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        if (mTrackEveryTimeDurationUs > 0) {
1889114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih            (*meta)->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs);
1890114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        }
1891114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        if (mRotationDegrees != 0) {
1892114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih            (*meta)->setInt32(kKeyRotation, mRotationDegrees);
1893114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        }
189413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
18959c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra}
18969c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra
1897a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongstatus_t StagefrightRecorder::pause() {
18983856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("pause");
1899d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    if (!mStarted) {
1900d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        return INVALID_OPERATION;
1901a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
19029c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra
1903d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    // Already paused --- no-op.
1904d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    if (mPauseStartTimeUs != 0) {
1905d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        return OK;
1906d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    }
190775b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
1908764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    mPauseStartTimeUs = systemTime() / 1000;
1909764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    sp<MetaData> meta = new MetaData;
1910764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    meta->setInt64(kKeyTime, mPauseStartTimeUs);
1911764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang
1912d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    if (mAudioEncoderSource != NULL) {
1913d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        mAudioEncoderSource->pause();
1914d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    }
1915d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    if (mVideoEncoderSource != NULL) {
1916764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        mVideoEncoderSource->pause(meta.get());
1917d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    }
191875b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
1919d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    return OK;
1920d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim}
1921d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim
1922d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kimstatus_t StagefrightRecorder::resume() {
1923d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    ALOGV("resume");
1924d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    if (!mStarted) {
1925d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        return INVALID_OPERATION;
1926d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    }
1927d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim
1928d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    // Not paused --- no-op.
1929d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    if (mPauseStartTimeUs == 0) {
1930d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        return OK;
193175b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang    }
193275b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
1933764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    int64_t resumeStartTimeUs = systemTime() / 1000;
1934764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang
1935a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    int64_t bufferStartTimeUs = 0;
1936a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    bool allSourcesStarted = true;
1937a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    for (const auto &source : { mAudioEncoderSource, mVideoEncoderSource }) {
1938a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        if (source == nullptr) {
1939a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            continue;
1940a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        }
1941a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        int64_t timeUs = source->getFirstSampleSystemTimeUs();
1942a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        if (timeUs < 0) {
1943a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            allSourcesStarted = false;
1944a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        }
1945a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        if (bufferStartTimeUs < timeUs) {
1946a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            bufferStartTimeUs = timeUs;
1947a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        }
1948a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    }
1949a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim
1950a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    if (allSourcesStarted) {
1951a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        if (mPauseStartTimeUs < bufferStartTimeUs) {
1952a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            mPauseStartTimeUs = bufferStartTimeUs;
1953a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        }
1954a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        // 30 ms buffer to avoid timestamp overlap
1955764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        mTotalPausedDurationUs += resumeStartTimeUs - mPauseStartTimeUs - 30000;
1956a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    }
19579f5c692300e02f9f1b4e08b238a76f1428c854d3Wonsik Kim    double timeOffset = -mTotalPausedDurationUs;
19589f5c692300e02f9f1b4e08b238a76f1428c854d3Wonsik Kim    if (mCaptureFpsEnable) {
19599f5c692300e02f9f1b4e08b238a76f1428c854d3Wonsik Kim        timeOffset *= mCaptureFps / mFrameRate;
19609f5c692300e02f9f1b4e08b238a76f1428c854d3Wonsik Kim    }
1961764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    sp<MetaData> meta = new MetaData;
1962764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    meta->setInt64(kKeyTime, resumeStartTimeUs);
1963a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    for (const auto &source : { mAudioEncoderSource, mVideoEncoderSource }) {
1964a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        if (source == nullptr) {
1965a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            continue;
1966a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        }
1967a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        source->setInputBufferTimeOffset((int64_t)timeOffset);
1968764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        source->start(meta.get());
1969d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    }
1970d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    mPauseStartTimeUs = 0;
197175b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
1972a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
1973a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
1974a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
197530ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::stop() {
19763856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("stop");
1977fc079f79d8d4f6ef9f138aa615486c10dda99fb7Hangyu Kuang    Mutex::Autolock autolock(mLock);
197837187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
19799c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra
198046d26dd29195450db15704e84d65740628a821fbChong Zhang    if (mCaptureFpsEnable && mCameraSourceTimeLapse != NULL) {
198178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        mCameraSourceTimeLapse->startQuickReadReturns();
198278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        mCameraSourceTimeLapse = NULL;
198378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    }
198478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
1985764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    if (mVideoEncoderSource != NULL) {
1986764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        int64_t stopTimeUs = systemTime() / 1000;
1987764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        sp<MetaData> meta = new MetaData;
1988764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        err = mVideoEncoderSource->setStopStimeUs(stopTimeUs);
1989764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    }
1990764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang
1991d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (mWriter != NULL) {
199237187916a486504acaf83bea30147eb5fbf46ae5James Dong        err = mWriter->stop();
1993934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        mWriter.clear();
199430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    }
1995ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
1996ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    resetMetrics();
1997ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
1998148c3d67710ca9353f14e5c37a0a38c88d4f0e53Wonsik Kim    mTotalPausedDurationUs = 0;
1999e6cab24fa5857eaf48c957988f153b47a52d1b45Wonsik Kim    mPauseStartTimeUs = 0;
200030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
200172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mGraphicBufferProducer.clear();
20028f469e18c307cb9dc0d16ed9225972aa8be4516fChong Zhang    mPersistentSurface.clear();
2003d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    mAudioEncoderSource.clear();
2004d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    mVideoEncoderSource.clear();
200572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
200625d83125cee222993673d3ba261ae1186bcad8c2James Dong    if (mOutputFd >= 0) {
200725d83125cee222993673d3ba261ae1186bcad8c2James Dong        ::close(mOutputFd);
200825d83125cee222993673d3ba261ae1186bcad8c2James Dong        mOutputFd = -1;
200925d83125cee222993673d3ba261ae1186bcad8c2James Dong    }
201025d83125cee222993673d3ba261ae1186bcad8c2James Dong
201175b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang    if (mStarted) {
201275b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        mStarted = false;
201375b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
201475b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        uint32_t params = 0;
2015fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin        if (mAudioSource != AUDIO_SOURCE_CNT) {
201675b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang            params |= IMediaPlayerService::kBatteryDataTrackAudio;
201775b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        }
201875b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        if (mVideoSource != VIDEO_SOURCE_LIST_END) {
201975b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang            params |= IMediaPlayerService::kBatteryDataTrackVideo;
202075b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        }
202175b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
202275b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        addBatteryData(params);
202375b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang    }
202475b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
202537187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
2026d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong}
2027d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
2028d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dongstatus_t StagefrightRecorder::close() {
20293856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("close");
2030d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    stop();
2031d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
203230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
203330ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
203430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
203530ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::reset() {
20363856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("reset");
203730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    stop();
203830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
2039050b28a593350047845a45a14cc5026221ac1620James Dong    // No audio or video source by default
2040fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin    mAudioSource = AUDIO_SOURCE_CNT;
204130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mVideoSource = VIDEO_SOURCE_LIST_END;
2042050b28a593350047845a45a14cc5026221ac1620James Dong
2043050b28a593350047845a45a14cc5026221ac1620James Dong    // Default parameters
2044050b28a593350047845a45a14cc5026221ac1620James Dong    mOutputFormat  = OUTPUT_FORMAT_THREE_GPP;
2045050b28a593350047845a45a14cc5026221ac1620James Dong    mAudioEncoder  = AUDIO_ENCODER_AMR_NB;
204654ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang    mVideoEncoder  = VIDEO_ENCODER_DEFAULT;
2047050b28a593350047845a45a14cc5026221ac1620James Dong    mVideoWidth    = 176;
2048050b28a593350047845a45a14cc5026221ac1620James Dong    mVideoHeight   = 144;
2049635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong    mFrameRate     = -1;
2050050b28a593350047845a45a14cc5026221ac1620James Dong    mVideoBitRate  = 192000;
2051050b28a593350047845a45a14cc5026221ac1620James Dong    mSampleRate    = 8000;
2052050b28a593350047845a45a14cc5026221ac1620James Dong    mAudioChannels = 1;
2053050b28a593350047845a45a14cc5026221ac1620James Dong    mAudioBitRate  = 12200;
2054e136c3bb38e88315bf8797a464ebf2c788296b22James Dong    mInterleaveDurationUs = 0;
20558f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    mIFramesIntervalSec = 1;
2056d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    mAudioSourceNode = 0;
20572dec2b5be2056c6d9428897dc672185872d30d17James Dong    mUse64BitFileOffset = false;
2058c059860c73678a202bfa33062723e8f82fb779d9James Dong    mMovieTimeScale  = -1;
2059c059860c73678a202bfa33062723e8f82fb779d9James Dong    mAudioTimeScale  = -1;
2060c059860c73678a202bfa33062723e8f82fb779d9James Dong    mVideoTimeScale  = -1;
206193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mCameraId        = 0;
206286b7f47aa7482424cf8fd248f1315311919be3b0James Dong    mStartTimeOffsetMs = -1;
2063145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    mVideoEncoderProfile = -1;
2064145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    mVideoEncoderLevel   = -1;
2065145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    mMaxFileDurationUs = 0;
2066145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    mMaxFileSizeBytes = 0;
206793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
206846d26dd29195450db15704e84d65740628a821fbChong Zhang    mCaptureFpsEnable = false;
206922dc508717c7767927064ec7c152def99e54adcbPawin Vongmasa    mCaptureFps = -1.0;
207078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    mCameraSourceTimeLapse = NULL;
20713e328782f1e1061d08ea0c45b855cc418a2d9ea6Lajos Molnar    mMetaDataStoredInVideoBuffers = kMetadataBufferTypeInvalid;
207299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    mEncoderProfiles = MediaProfiles::getInstance();
207362db7db731c47a00ee1493e94f3e1d953c6e297aJames Dong    mRotationDegrees = 0;
207407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = -3600000;
207507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = -3600000;
207672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mTotalBitRate = 0;
2077050b28a593350047845a45a14cc5026221ac1620James Dong
207830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mOutputFd = -1;
207930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
208030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
208130ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
208230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
208330ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::getMaxAmplitude(int *max) {
20843856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getMaxAmplitude");
2085d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
2086d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (max == NULL) {
208729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Null pointer argument");
2088d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        return BAD_VALUE;
2089d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
2090d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
2091d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    if (mAudioSourceNode != 0) {
2092d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        *max = mAudioSourceNode->getMaxAmplitude();
2093d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    } else {
2094d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        *max = 0;
2095d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    }
20962dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
20972dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
209830ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
209930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
2100ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essickstatus_t StagefrightRecorder::getMetrics(Parcel *reply) {
2101ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    ALOGD("StagefrightRecorder::getMetrics");
2102ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
2103ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    if (reply == NULL) {
2104ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        ALOGE("Null pointer argument");
2105ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        return BAD_VALUE;
2106ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    }
2107ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
2108ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    if (mAnalyticsItem == NULL) {
2109ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        return UNKNOWN_ERROR;
2110ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    }
2111ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
2112ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    updateMetrics();
2113ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    mAnalyticsItem->writeToParcel(reply);
2114ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    return OK;
2115ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick}
2116ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
2117dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t StagefrightRecorder::dump(
2118dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) const {
21193856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("dump");
2120fc079f79d8d4f6ef9f138aa615486c10dda99fb7Hangyu Kuang    Mutex::Autolock autolock(mLock);
2121b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    const size_t SIZE = 256;
2122b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    char buffer[SIZE];
2123b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    String8 result;
2124dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    if (mWriter != 0) {
2125dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        mWriter->dump(fd, args);
2126dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    } else {
2127dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        snprintf(buffer, SIZE, "   No file writer\n");
2128dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        result.append(buffer);
2129dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
2130dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   Recorder: %p\n", this);
2131b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "   Output file (fd %d):\n", mOutputFd);
2132b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2133b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     File format: %d\n", mOutputFormat);
2134b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2135377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    snprintf(buffer, SIZE, "     Max file size (bytes): %" PRId64 "\n", mMaxFileSizeBytes);
2136b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2137377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    snprintf(buffer, SIZE, "     Max file duration (us): %" PRId64 "\n", mMaxFileDurationUs);
2138b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2139b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     File offset length (bits): %d\n", mUse64BitFileOffset? 64: 32);
2140b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2141b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Interleave duration (us): %d\n", mInterleaveDurationUs);
2142b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2143377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    snprintf(buffer, SIZE, "     Progress notification: %" PRId64 " us\n", mTrackEveryTimeDurationUs);
2144b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2145b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "   Audio\n");
2146b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2147b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Source: %d\n", mAudioSource);
2148b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2149b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Encoder: %d\n", mAudioEncoder);
2150b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2151b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Bit rate (bps): %d\n", mAudioBitRate);
2152b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2153b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Sampling rate (hz): %d\n", mSampleRate);
2154b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2155b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Number of channels: %d\n", mAudioChannels);
2156b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2157b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Max amplitude: %d\n", mAudioSourceNode == 0? 0: mAudioSourceNode->getMaxAmplitude());
2158b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2159b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "   Video\n");
2160b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2161b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Source: %d\n", mVideoSource);
2162b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2163b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Camera Id: %d\n", mCameraId);
2164b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
216586b7f47aa7482424cf8fd248f1315311919be3b0James Dong    snprintf(buffer, SIZE, "     Start time offset (ms): %d\n", mStartTimeOffsetMs);
216686b7f47aa7482424cf8fd248f1315311919be3b0James Dong    result.append(buffer);
2167b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Encoder: %d\n", mVideoEncoder);
2168b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2169b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Encoder profile: %d\n", mVideoEncoderProfile);
2170b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2171b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Encoder level: %d\n", mVideoEncoderLevel);
2172b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
21738f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    snprintf(buffer, SIZE, "     I frames interval (s): %d\n", mIFramesIntervalSec);
2174b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2175b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Frame size (pixels): %dx%d\n", mVideoWidth, mVideoHeight);
2176b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2177b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Frame rate (fps): %d\n", mFrameRate);
2178b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2179b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Bit rate (bps): %d\n", mVideoBitRate);
2180b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2181b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    ::write(fd, result.string(), result.size());
2182b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    return OK;
2183b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong}
218430ab66297501757d745b9ae10da61adcd891f497Andreas Huber}  // namespace android
2185