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
72de15b8c160c720c48b93796016801e7ae0b6bd2dRay Essick// NB: these are matched with public Java API constants defined
73de15b8c160c720c48b93796016801e7ae0b6bd2dRay Essick// in frameworks/base/media/java/android/media/MediaRecorder.java
74de15b8c160c720c48b93796016801e7ae0b6bd2dRay Essick// These must be kept synchronized with the constants there.
75afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kRecorderAudioBitrate = "android.media.mediarecorder.audio-bitrate";
76de15b8c160c720c48b93796016801e7ae0b6bd2dRay Essickstatic const char *kRecorderAudioChannels = "android.media.mediarecorder.audio-channels";
77de15b8c160c720c48b93796016801e7ae0b6bd2dRay Essickstatic const char *kRecorderAudioSampleRate = "android.media.mediarecorder.audio-samplerate";
78afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kRecorderAudioTimescale = "android.media.mediarecorder.audio-timescale";
79afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kRecorderCaptureFps = "android.media.mediarecorder.capture-fps";
80de15b8c160c720c48b93796016801e7ae0b6bd2dRay Essickstatic const char *kRecorderCaptureFpsEnable = "android.media.mediarecorder.capture-fpsenable";
81de15b8c160c720c48b93796016801e7ae0b6bd2dRay Essickstatic const char *kRecorderFrameRate = "android.media.mediarecorder.frame-rate";
82de15b8c160c720c48b93796016801e7ae0b6bd2dRay Essickstatic const char *kRecorderHeight = "android.media.mediarecorder.height";
83de15b8c160c720c48b93796016801e7ae0b6bd2dRay Essickstatic const char *kRecorderMovieTimescale = "android.media.mediarecorder.movie-timescale";
84afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kRecorderRotation = "android.media.mediarecorder.rotation";
85de15b8c160c720c48b93796016801e7ae0b6bd2dRay Essickstatic const char *kRecorderVideoBitrate = "android.media.mediarecorder.video-bitrate";
86de15b8c160c720c48b93796016801e7ae0b6bd2dRay Essickstatic const char *kRecorderVideoIframeInterval = "android.media.mediarecorder.video-iframe-interval";
87de15b8c160c720c48b93796016801e7ae0b6bd2dRay Essickstatic const char *kRecorderVideoLevel = "android.media.mediarecorder.video-encoder-level";
88de15b8c160c720c48b93796016801e7ae0b6bd2dRay Essickstatic const char *kRecorderVideoProfile = "android.media.mediarecorder.video-encoder-profile";
89de15b8c160c720c48b93796016801e7ae0b6bd2dRay Essickstatic const char *kRecorderVideoTimescale = "android.media.mediarecorder.video-timescale";
90de15b8c160c720c48b93796016801e7ae0b6bd2dRay Essickstatic const char *kRecorderWidth = "android.media.mediarecorder.width";
91de15b8c160c720c48b93796016801e7ae0b6bd2dRay Essick
9235cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick// new fields, not yet frozen in the public Java API definitions
9335cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essickstatic const char *kRecorderAudioMime = "android.media.mediarecorder.audio.mime";
9435cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essickstatic const char *kRecorderVideoMime = "android.media.mediarecorder.video.mime";
9535cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essickstatic const char *kRecorderDurationMs = "android.media.mediarecorder.durationMs";
9635cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essickstatic const char *kRecorderPaused = "android.media.mediarecorder.pausedMs";
9735cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essickstatic const char *kRecorderNumPauses = "android.media.mediarecorder.NPauses";
9835cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick
99afb43f76821e6a63e17e6484289a40430ada6978Ray Essick
10075b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang// To collect the encoder usage for the battery app
10175b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wangstatic void addBatteryData(uint32_t params) {
10275b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang    sp<IBinder> binder =
10375b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        defaultServiceManager()->getService(String16("media.player"));
10475b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
10575b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang    CHECK(service.get() != NULL);
10675b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
10775b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang    service->addBatteryData(params);
10875b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang}
10975b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
11075b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
111be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet GanovStagefrightRecorder::StagefrightRecorder(const String16 &opPackageName)
112be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov    : MediaRecorderBase(opPackageName),
113be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov      mWriter(NULL),
1143cecf640c4daf2df616b278bd9986018c8182908James Dong      mOutputFd(-1),
115174e1094a41828111c86793232d9492ab8e29395Kevin Rocard      mAudioSource((audio_source_t)AUDIO_SOURCE_CNT), // initialize with invalid value
11675b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang      mVideoSource(VIDEO_SOURCE_LIST_END),
117fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin      mStarted(false),
118fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin      mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
119fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin      mDeviceCallbackEnabled(false) {
120d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
1213856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("Constructor");
122ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
123ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    mAnalyticsDirty = false;
12430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    reset();
12530ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
12630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
12730ab66297501757d745b9ae10da61adcd891f497Andreas HuberStagefrightRecorder::~StagefrightRecorder() {
1283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("Destructor");
12930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    stop();
13072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
13172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mLooper != NULL) {
13272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mLooper->stop();
13372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
134ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
135ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // log the current record, provided it has some information worth recording
13635cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    // NB: this also reclaims & clears mAnalyticsItem.
13735cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    flushAndResetMetrics(false);
138ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick}
139ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
140ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essickvoid StagefrightRecorder::updateMetrics() {
141ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    ALOGV("updateMetrics");
142ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
14335cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    // we run as part of the media player service; what we really want to
14435cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    // know is the app which requested the recording.
14535cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    mAnalyticsItem->setUid(mClientUid);
14635cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick
14735cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    // populate the values from the raw fields.
148ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
149ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mOutputFormat  = OUTPUT_FORMAT_THREE_GPP;
150ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mAudioEncoder  = AUDIO_ENCODER_AMR_NB;
151ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mVideoEncoder  = VIDEO_ENCODER_DEFAULT;
152afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderHeight, mVideoHeight);
153afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderWidth, mVideoWidth);
154afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderFrameRate, mFrameRate);
155afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderVideoBitrate, mVideoBitRate);
156afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderAudioSampleRate, mSampleRate);
157afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderAudioChannels, mAudioChannels);
158afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderAudioBitrate, mAudioBitRate);
159ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mInterleaveDurationUs = 0;
160afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderVideoIframeInterval, mIFramesIntervalSec);
161ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mAudioSourceNode = 0;
162ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mUse64BitFileOffset = false;
163afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderMovieTimescale, mMovieTimeScale);
164afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderAudioTimescale, mAudioTimeScale);
165afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderVideoTimescale, mVideoTimeScale);
166ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mCameraId        = 0;
167ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mStartTimeOffsetMs = -1;
168afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderVideoProfile, mVideoEncoderProfile);
169afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderVideoLevel, mVideoEncoderLevel);
170ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mMaxFileDurationUs = 0;
171ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mMaxFileSizeBytes = 0;
172ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mTrackEveryTimeDurationUs = 0;
173afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderCaptureFpsEnable, mCaptureFpsEnable);
174afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setDouble(kRecorderCaptureFps, mCaptureFps);
175ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mCameraSourceTimeLapse = NULL;
176ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mMetaDataStoredInVideoBuffers = kMetadataBufferTypeInvalid;
177ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mEncoderProfiles = MediaProfiles::getInstance();
178afb43f76821e6a63e17e6484289a40430ada6978Ray Essick    mAnalyticsItem->setInt32(kRecorderRotation, mRotationDegrees);
179ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // PII mLatitudex10000 = -3600000;
180ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // PII mLongitudex10000 = -3600000;
181ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    // TBD mTotalBitRate = 0;
182ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
18335cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    // duration information (recorded, paused, # of pauses)
18435cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    mAnalyticsItem->setInt64(kRecorderDurationMs, (mDurationRecordedUs+500)/1000 );
18535cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    if (mNPauses != 0) {
18635cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick        mAnalyticsItem->setInt64(kRecorderPaused, (mDurationPausedUs+500)/1000 );
18735cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick        mAnalyticsItem->setInt32(kRecorderNumPauses, mNPauses);
18835cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    }
189ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick}
190ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
19135cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essickvoid StagefrightRecorder::flushAndResetMetrics(bool reinitialize) {
19235cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    ALOGV("flushAndResetMetrics");
19335cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    // flush anything we have, maybe setup a new record
194ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    if (mAnalyticsDirty && mAnalyticsItem != NULL) {
195ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        updateMetrics();
196ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        if (mAnalyticsItem->count() > 0) {
197ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick            mAnalyticsItem->selfrecord();
198ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        }
199ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        delete mAnalyticsItem;
200ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        mAnalyticsItem = NULL;
201ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    }
202ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    mAnalyticsDirty = false;
20335cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    if (reinitialize) {
20435cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick        mAnalyticsItem = new MediaAnalyticsItem(kKeyRecorder);
20535cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    }
20630ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
20730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
20830ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::init() {
2093856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("init");
21072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
21172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper = new ALooper;
21272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->setName("recorder_looper");
21372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->start();
21472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
21530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
21630ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
21730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
218fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin// The client side of mediaserver asks it to create a SurfaceMediaSource
219b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi// and return a interface reference. The client side will use that
220b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi// while encoding GL Frames
2218ba01021b573889802e67e029225a96f0dfa471aAndy McFaddensp<IGraphicBufferProducer> StagefrightRecorder::querySurfaceMediaSource() const {
2223856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("Get SurfaceMediaSource");
22372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return mGraphicBufferProducer;
224b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi}
225b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi
226fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavinstatus_t StagefrightRecorder::setAudioSource(audio_source_t as) {
2273856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setAudioSource: %d", as);
228d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (as < AUDIO_SOURCE_DEFAULT ||
2290f8f4e681b867dd611d2d916453337cb0770d4daHochi Huang        (as >= AUDIO_SOURCE_CNT && as != AUDIO_SOURCE_FM_TUNER)) {
23029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid audio source: %d", as);
231d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        return BAD_VALUE;
232d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
233d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
234d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (as == AUDIO_SOURCE_DEFAULT) {
235d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mAudioSource = AUDIO_SOURCE_MIC;
236d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    } else {
237d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mAudioSource = as;
238d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
23930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
24030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
24130ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
24230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
24330ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setVideoSource(video_source vs) {
2443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setVideoSource: %d", vs);
245d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (vs < VIDEO_SOURCE_DEFAULT ||
246d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        vs >= VIDEO_SOURCE_LIST_END) {
24729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid video source: %d", vs);
248d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        return BAD_VALUE;
249d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
250d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
251d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (vs == VIDEO_SOURCE_DEFAULT) {
252d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mVideoSource = VIDEO_SOURCE_CAMERA;
253d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    } else {
254d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mVideoSource = vs;
255d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
25630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
25730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
25830ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
25930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
26030ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setOutputFormat(output_format of) {
2613856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setOutputFormat: %d", of);
262d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (of < OUTPUT_FORMAT_DEFAULT ||
263d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        of >= OUTPUT_FORMAT_LIST_END) {
26429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid output format: %d", of);
265d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        return BAD_VALUE;
266d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
267d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
268d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (of == OUTPUT_FORMAT_DEFAULT) {
269d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mOutputFormat = OUTPUT_FORMAT_THREE_GPP;
270d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    } else {
271d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mOutputFormat = of;
272d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
27330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
27430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
27530ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
27630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
27730ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setAudioEncoder(audio_encoder ae) {
2783856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setAudioEncoder: %d", ae);
279d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (ae < AUDIO_ENCODER_DEFAULT ||
280d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        ae >= AUDIO_ENCODER_LIST_END) {
28129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid audio encoder: %d", ae);
282d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        return BAD_VALUE;
283d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
284d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
285d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (ae == AUDIO_ENCODER_DEFAULT) {
286d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mAudioEncoder = AUDIO_ENCODER_AMR_NB;
287d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    } else {
288d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mAudioEncoder = ae;
289d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
29030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
29130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
29230ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
29330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
29430ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setVideoEncoder(video_encoder ve) {
2953856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setVideoEncoder: %d", ve);
296d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (ve < VIDEO_ENCODER_DEFAULT ||
297d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        ve >= VIDEO_ENCODER_LIST_END) {
29829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid video encoder: %d", ve);
299d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        return BAD_VALUE;
300d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
301d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
30254ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang    mVideoEncoder = ve;
30330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
30430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
30530ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
30630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
30730ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setVideoSize(int width, int height) {
3083856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setVideoSize: %dx%d", width, height);
309ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (width <= 0 || height <= 0) {
31029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid video size: %dx%d", width, height);
311ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        return BAD_VALUE;
312ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
313ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
314ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // Additional check on the dimension will be performed later
31530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mVideoWidth = width;
31630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mVideoHeight = height;
31730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
31830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
31930ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
32030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
32130ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setVideoFrameRate(int frames_per_second) {
3223856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setVideoFrameRate: %d", frames_per_second);
323635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong    if ((frames_per_second <= 0 && frames_per_second != -1) ||
324c9f122d8f32ba6928ac9087448025fa3bed1553dZhijun He        frames_per_second > kMaxHighSpeedFps) {
32529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid video frame rate: %d", frames_per_second);
326ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        return BAD_VALUE;
327ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
328ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
329ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // Additional check on the frame rate will be performed later
33030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mFrameRate = frames_per_second;
33130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
33230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
33330ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
33430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
335d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvalastatus_t StagefrightRecorder::setCamera(const sp<hardware::ICamera> &camera,
3364ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li                                        const sp<ICameraRecordingProxy> &proxy) {
3373856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setCamera");
338c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    if (camera == 0) {
33929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("camera is NULL");
340934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return BAD_VALUE;
341c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
3424ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    if (proxy == 0) {
34329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("camera proxy is NULL");
3444ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        return BAD_VALUE;
3454ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    }
346c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong
34754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mCamera = camera;
3484ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mCameraProxy = proxy;
34930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
35030ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
35130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
35299617adda9bc46c43f511f0940bc735c73de61deMathias Agopianstatus_t StagefrightRecorder::setPreviewSurface(const sp<IGraphicBufferProducer> &surface) {
3533856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setPreviewSurface: %p", surface.get());
35430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mPreviewSurface = surface;
35530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
35630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
35730ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
35830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
3598f469e18c307cb9dc0d16ed9225972aa8be4516fChong Zhangstatus_t StagefrightRecorder::setInputSurface(
360addf2cbb120346ae42e78fa739245a353db5edadChong Zhang        const sp<PersistentSurface>& surface) {
361e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang    mPersistentSurface = surface;
362e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang
363e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang    return OK;
364e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang}
365e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang
366fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t StagefrightRecorder::setOutputFile(int fd) {
367fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGV("setOutputFile: %d", fd);
36830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
369934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    if (fd < 0) {
37029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid file descriptor: %d", fd);
371934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return -EBADF;
372934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    }
373934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong
37469113e8ccc30fbdb8733ca2070bd3491b21e656dMarco Nelissen    // start with a clean, empty file
37569113e8ccc30fbdb8733ca2070bd3491b21e656dMarco Nelissen    ftruncate(fd, 0);
37669113e8ccc30fbdb8733ca2070bd3491b21e656dMarco Nelissen
37730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    if (mOutputFd >= 0) {
37830ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ::close(mOutputFd);
37930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    }
38030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mOutputFd = dup(fd);
38130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
38230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
38330ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
38430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
385fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t StagefrightRecorder::setNextOutputFile(int fd) {
386fc079f79d8d4f6ef9f138aa615486c10dda99fb7Hangyu Kuang    Mutex::Autolock autolock(mLock);
387fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    // Only support MPEG4
388fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mOutputFormat != OUTPUT_FORMAT_MPEG_4) {
389fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGE("Only MP4 file format supports setting next output file");
390fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return INVALID_OPERATION;
391fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
392fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGV("setNextOutputFile: %d", fd);
393fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
394fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (fd < 0) {
395fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGE("Invalid file descriptor: %d", fd);
396fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return -EBADF;
397fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
398fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
399fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    // start with a clean, empty file
400fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ftruncate(fd, 0);
401fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    int nextFd = dup(fd);
402fc079f79d8d4f6ef9f138aa615486c10dda99fb7Hangyu Kuang    if (mWriter == NULL) {
403fc079f79d8d4f6ef9f138aa615486c10dda99fb7Hangyu Kuang        ALOGE("setNextOutputFile failed. Writer has been freed");
404fc079f79d8d4f6ef9f138aa615486c10dda99fb7Hangyu Kuang        return INVALID_OPERATION;
405fc079f79d8d4f6ef9f138aa615486c10dda99fb7Hangyu Kuang    }
406fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    return mWriter->setNextFd(nextFd);
407fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
408fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
4099ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang// Attempt to parse an float literal optionally surrounded by whitespace,
4109ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang// returns true on success, false otherwise.
41173c3e6363b31fb27882c4666453ad8ef050b3cc1Wonsik Kimstatic bool safe_strtod(const char *s, double *val) {
4129ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    char *end;
4139ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang
4149ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    // It is lame, but according to man page, we have to set errno to 0
41573c3e6363b31fb27882c4666453ad8ef050b3cc1Wonsik Kim    // before calling strtod().
4169ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    errno = 0;
41773c3e6363b31fb27882c4666453ad8ef050b3cc1Wonsik Kim    *val = strtod(s, &end);
4189ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang
4199ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    if (end == s || errno == ERANGE) {
4209ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang        return false;
4219ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    }
4229ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang
4239ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    // Skip trailing whitespace
4249ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    while (isspace(*end)) {
4259ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang        ++end;
4269ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    }
4279ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang
4289ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    // For a successful return, the string must contain nothing but a valid
4299ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    // float literal optionally surrounded by whitespace.
4309ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang
4319ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    return *end == '\0';
4329ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang}
4339ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang
434050b28a593350047845a45a14cc5026221ac1620James Dong// Attempt to parse an int64 literal optionally surrounded by whitespace,
435050b28a593350047845a45a14cc5026221ac1620James Dong// returns true on success, false otherwise.
436ef9d0cd72e476a4b7556833fb09505a51b626797James Dongstatic bool safe_strtoi64(const char *s, int64_t *val) {
437050b28a593350047845a45a14cc5026221ac1620James Dong    char *end;
43827944ef5cd8d0fb476c8c8958986e827c5f8ab83James Dong
43927944ef5cd8d0fb476c8c8958986e827c5f8ab83James Dong    // It is lame, but according to man page, we have to set errno to 0
44027944ef5cd8d0fb476c8c8958986e827c5f8ab83James Dong    // before calling strtoll().
44127944ef5cd8d0fb476c8c8958986e827c5f8ab83James Dong    errno = 0;
442ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    *val = strtoll(s, &end, 10);
443050b28a593350047845a45a14cc5026221ac1620James Dong
444050b28a593350047845a45a14cc5026221ac1620James Dong    if (end == s || errno == ERANGE) {
445050b28a593350047845a45a14cc5026221ac1620James Dong        return false;
446050b28a593350047845a45a14cc5026221ac1620James Dong    }
447050b28a593350047845a45a14cc5026221ac1620James Dong
448050b28a593350047845a45a14cc5026221ac1620James Dong    // Skip trailing whitespace
449050b28a593350047845a45a14cc5026221ac1620James Dong    while (isspace(*end)) {
450050b28a593350047845a45a14cc5026221ac1620James Dong        ++end;
451050b28a593350047845a45a14cc5026221ac1620James Dong    }
452050b28a593350047845a45a14cc5026221ac1620James Dong
453050b28a593350047845a45a14cc5026221ac1620James Dong    // For a successful return, the string must contain nothing but a valid
454050b28a593350047845a45a14cc5026221ac1620James Dong    // int64 literal optionally surrounded by whitespace.
455050b28a593350047845a45a14cc5026221ac1620James Dong
456050b28a593350047845a45a14cc5026221ac1620James Dong    return *end == '\0';
457050b28a593350047845a45a14cc5026221ac1620James Dong}
458050b28a593350047845a45a14cc5026221ac1620James Dong
459ef9d0cd72e476a4b7556833fb09505a51b626797James Dong// Return true if the value is in [0, 0x007FFFFFFF]
460ef9d0cd72e476a4b7556833fb09505a51b626797James Dongstatic bool safe_strtoi32(const char *s, int32_t *val) {
461ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    int64_t temp;
462ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (safe_strtoi64(s, &temp)) {
463ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (temp >= 0 && temp <= 0x007FFFFFFF) {
464ef9d0cd72e476a4b7556833fb09505a51b626797James Dong            *val = static_cast<int32_t>(temp);
465ef9d0cd72e476a4b7556833fb09505a51b626797James Dong            return true;
466ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        }
467ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
468ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    return false;
469ef9d0cd72e476a4b7556833fb09505a51b626797James Dong}
470ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
471050b28a593350047845a45a14cc5026221ac1620James Dong// Trim both leading and trailing whitespace from the given string.
472050b28a593350047845a45a14cc5026221ac1620James Dongstatic void TrimString(String8 *s) {
473050b28a593350047845a45a14cc5026221ac1620James Dong    size_t num_bytes = s->bytes();
474050b28a593350047845a45a14cc5026221ac1620James Dong    const char *data = s->string();
475050b28a593350047845a45a14cc5026221ac1620James Dong
476050b28a593350047845a45a14cc5026221ac1620James Dong    size_t leading_space = 0;
477050b28a593350047845a45a14cc5026221ac1620James Dong    while (leading_space < num_bytes && isspace(data[leading_space])) {
478050b28a593350047845a45a14cc5026221ac1620James Dong        ++leading_space;
479050b28a593350047845a45a14cc5026221ac1620James Dong    }
480050b28a593350047845a45a14cc5026221ac1620James Dong
481050b28a593350047845a45a14cc5026221ac1620James Dong    size_t i = num_bytes;
482050b28a593350047845a45a14cc5026221ac1620James Dong    while (i > leading_space && isspace(data[i - 1])) {
483050b28a593350047845a45a14cc5026221ac1620James Dong        --i;
484050b28a593350047845a45a14cc5026221ac1620James Dong    }
485050b28a593350047845a45a14cc5026221ac1620James Dong
486050b28a593350047845a45a14cc5026221ac1620James Dong    s->setTo(String8(&data[leading_space], i - leading_space));
487050b28a593350047845a45a14cc5026221ac1620James Dong}
488050b28a593350047845a45a14cc5026221ac1620James Dong
489050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParamAudioSamplingRate(int32_t sampleRate) {
4903856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamAudioSamplingRate: %d", sampleRate);
491ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (sampleRate <= 0) {
49229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid audio sampling rate: %d", sampleRate);
493ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        return BAD_VALUE;
494ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
495ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
496ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // Additional check on the sample rate will be performed later.
497050b28a593350047845a45a14cc5026221ac1620James Dong    mSampleRate = sampleRate;
498ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
499050b28a593350047845a45a14cc5026221ac1620James Dong    return OK;
500050b28a593350047845a45a14cc5026221ac1620James Dong}
501050b28a593350047845a45a14cc5026221ac1620James Dong
502050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) {
5033856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamAudioNumberOfChannels: %d", channels);
504ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (channels <= 0 || channels >= 3) {
50529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid number of audio channels: %d", channels);
506934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return BAD_VALUE;
507ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
508ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
509ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // Additional check on the number of channels will be performed later.
510050b28a593350047845a45a14cc5026221ac1620James Dong    mAudioChannels = channels;
511ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
512050b28a593350047845a45a14cc5026221ac1620James Dong    return OK;
513050b28a593350047845a45a14cc5026221ac1620James Dong}
514050b28a593350047845a45a14cc5026221ac1620James Dong
515050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParamAudioEncodingBitRate(int32_t bitRate) {
5163856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamAudioEncodingBitRate: %d", bitRate);
517ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (bitRate <= 0) {
51829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid audio encoding bit rate: %d", bitRate);
519ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        return BAD_VALUE;
520ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
521ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
522ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // The target bit rate may not be exactly the same as the requested.
523ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // It depends on many factors, such as rate control, and the bit rate
524ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // range that a specific encoder supports. The mismatch between the
525ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // the target and requested bit rate will NOT be treated as an error.
526050b28a593350047845a45a14cc5026221ac1620James Dong    mAudioBitRate = bitRate;
527050b28a593350047845a45a14cc5026221ac1620James Dong    return OK;
528050b28a593350047845a45a14cc5026221ac1620James Dong}
529050b28a593350047845a45a14cc5026221ac1620James Dong
530050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) {
5313856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamVideoEncodingBitRate: %d", bitRate);
532ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (bitRate <= 0) {
53329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid video encoding bit rate: %d", bitRate);
534ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        return BAD_VALUE;
535ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
536ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
537ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // The target bit rate may not be exactly the same as the requested.
538ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // It depends on many factors, such as rate control, and the bit rate
539ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // range that a specific encoder supports. The mismatch between the
540ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // the target and requested bit rate will NOT be treated as an error.
541050b28a593350047845a45a14cc5026221ac1620James Dong    mVideoBitRate = bitRate;
542050b28a593350047845a45a14cc5026221ac1620James Dong    return OK;
543050b28a593350047845a45a14cc5026221ac1620James Dong}
544050b28a593350047845a45a14cc5026221ac1620James Dong
54513f6284305e4b27395a23db7882d670bdb1bcae1James Dong// Always rotate clockwise, and only support 0, 90, 180 and 270 for now.
54613f6284305e4b27395a23db7882d670bdb1bcae1James Dongstatus_t StagefrightRecorder::setParamVideoRotation(int32_t degrees) {
5473856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamVideoRotation: %d", degrees);
54813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    if (degrees < 0 || degrees % 90 != 0) {
54929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unsupported video rotation angle: %d", degrees);
55013f6284305e4b27395a23db7882d670bdb1bcae1James Dong        return BAD_VALUE;
55113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
55213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    mRotationDegrees = degrees % 360;
55313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    return OK;
55413f6284305e4b27395a23db7882d670bdb1bcae1James Dong}
55513f6284305e4b27395a23db7882d670bdb1bcae1James Dong
556934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dongstatus_t StagefrightRecorder::setParamMaxFileDurationUs(int64_t timeUs) {
557833b47505c513cb5c8f22aa922a7ea20d153b319Andy Hung    ALOGV("setParamMaxFileDurationUs: %lld us", (long long)timeUs);
5582d1e5d35be5e6d4b55ac8b39fbfcbeb60fcdd084James Dong
5592d1e5d35be5e6d4b55ac8b39fbfcbeb60fcdd084James Dong    // This is meant for backward compatibility for MediaRecorder.java
560be6fd201b9a04fe0f8fd409f10595ddb41832591Nipun Kwatra    if (timeUs <= 0) {
561833b47505c513cb5c8f22aa922a7ea20d153b319Andy Hung        ALOGW("Max file duration is not positive: %lld us. Disabling duration limit.",
562833b47505c513cb5c8f22aa922a7ea20d153b319Andy Hung                (long long)timeUs);
563be6fd201b9a04fe0f8fd409f10595ddb41832591Nipun Kwatra        timeUs = 0; // Disable the duration limit for zero or negative values.
564be6fd201b9a04fe0f8fd409f10595ddb41832591Nipun Kwatra    } else if (timeUs <= 100000LL) {  // XXX: 100 milli-seconds
565833b47505c513cb5c8f22aa922a7ea20d153b319Andy Hung        ALOGE("Max file duration is too short: %lld us", (long long)timeUs);
566934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return BAD_VALUE;
567ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
568be6fd201b9a04fe0f8fd409f10595ddb41832591Nipun Kwatra
569acd234bba9f048971d66890009eeff9a8db94be3James Dong    if (timeUs <= 15 * 1000000LL) {
570833b47505c513cb5c8f22aa922a7ea20d153b319Andy Hung        ALOGW("Target duration (%lld us) too short to be respected", (long long)timeUs);
571acd234bba9f048971d66890009eeff9a8db94be3James Dong    }
572934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    mMaxFileDurationUs = timeUs;
573934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    return OK;
574934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong}
575934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong
576934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dongstatus_t StagefrightRecorder::setParamMaxFileSizeBytes(int64_t bytes) {
577833b47505c513cb5c8f22aa922a7ea20d153b319Andy Hung    ALOGV("setParamMaxFileSizeBytes: %lld bytes", (long long)bytes);
5782d1e5d35be5e6d4b55ac8b39fbfcbeb60fcdd084James Dong
5792d1e5d35be5e6d4b55ac8b39fbfcbeb60fcdd084James Dong    // This is meant for backward compatibility for MediaRecorder.java
5802d1e5d35be5e6d4b55ac8b39fbfcbeb60fcdd084James Dong    if (bytes <= 0) {
5815ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Max file size is not positive: %lld bytes. "
582833b47505c513cb5c8f22aa922a7ea20d153b319Andy Hung             "Disabling file size limit.", (long long)bytes);
5832d1e5d35be5e6d4b55ac8b39fbfcbeb60fcdd084James Dong        bytes = 0; // Disable the file size limit for zero or negative values.
5842d1e5d35be5e6d4b55ac8b39fbfcbeb60fcdd084James Dong    } else if (bytes <= 1024) {  // XXX: 1 kB
585833b47505c513cb5c8f22aa922a7ea20d153b319Andy Hung        ALOGE("Max file size is too small: %lld bytes", (long long)bytes);
586934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return BAD_VALUE;
587934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    }
588acd234bba9f048971d66890009eeff9a8db94be3James Dong
589acd234bba9f048971d66890009eeff9a8db94be3James Dong    if (bytes <= 100 * 1024) {
590833b47505c513cb5c8f22aa922a7ea20d153b319Andy Hung        ALOGW("Target file size (%lld bytes) is too small to be respected", (long long)bytes);
591acd234bba9f048971d66890009eeff9a8db94be3James Dong    }
592acd234bba9f048971d66890009eeff9a8db94be3James Dong
593934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    mMaxFileSizeBytes = bytes;
594050b28a593350047845a45a14cc5026221ac1620James Dong    return OK;
595050b28a593350047845a45a14cc5026221ac1620James Dong}
596050b28a593350047845a45a14cc5026221ac1620James Dong
59713aec890216948b0c364f8f92792129d0335f506James Dongstatus_t StagefrightRecorder::setParamInterleaveDuration(int32_t durationUs) {
5983856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamInterleaveDuration: %d", durationUs);
599ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    if (durationUs <= 500000) {           //  500 ms
600ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        // If interleave duration is too small, it is very inefficient to do
601ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        // interleaving since the metadata overhead will count for a significant
602ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        // portion of the saved contents
60329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Audio/video interleave duration is too small: %d us", durationUs);
604ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        return BAD_VALUE;
605ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    } else if (durationUs >= 10000000) {  // 10 seconds
606ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        // If interleaving duration is too large, it can cause the recording
607ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        // session to use too much memory since we have to save the output
608ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        // data before we write them out
60929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Audio/video interleave duration is too large: %d us", durationUs);
610ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        return BAD_VALUE;
611ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
61213aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
61313aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
61413aec890216948b0c364f8f92792129d0335f506James Dong}
615ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
6168f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong// If seconds <  0, only the first frame is I frame, and rest are all P frames
6178f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong// If seconds == 0, all frames are encoded as I frames. No P frames
6188f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong// If seconds >  0, it is the time spacing (seconds) between 2 neighboring I frames
6198f5f2fcee5c12d08df71d17017410c50951fc2e3James Dongstatus_t StagefrightRecorder::setParamVideoIFramesInterval(int32_t seconds) {
6203856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamVideoIFramesInterval: %d seconds", seconds);
6218f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    mIFramesIntervalSec = seconds;
622ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    return OK;
623ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong}
624ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong
6252dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t StagefrightRecorder::setParam64BitFileOffset(bool use64Bit) {
6263856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParam64BitFileOffset: %s",
6272dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64Bit? "use 64 bit file offset": "use 32 bit file offset");
6282dec2b5be2056c6d9428897dc672185872d30d17James Dong    mUse64BitFileOffset = use64Bit;
6292dec2b5be2056c6d9428897dc672185872d30d17James Dong    return OK;
6302dec2b5be2056c6d9428897dc672185872d30d17James Dong}
6312dec2b5be2056c6d9428897dc672185872d30d17James Dong
63293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t StagefrightRecorder::setParamVideoCameraId(int32_t cameraId) {
6333856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamVideoCameraId: %d", cameraId);
63493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    if (cameraId < 0) {
63593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        return BAD_VALUE;
63693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
63793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mCameraId = cameraId;
63893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    return OK;
63993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
64093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
64193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t StagefrightRecorder::setParamTrackTimeStatus(int64_t timeDurationUs) {
642833b47505c513cb5c8f22aa922a7ea20d153b319Andy Hung    ALOGV("setParamTrackTimeStatus: %lld", (long long)timeDurationUs);
64393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    if (timeDurationUs < 20000) {  // Infeasible if shorter than 20 ms?
644833b47505c513cb5c8f22aa922a7ea20d153b319Andy Hung        ALOGE("Tracking time duration too short: %lld us", (long long)timeDurationUs);
64593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        return BAD_VALUE;
64693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
64793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = timeDurationUs;
64893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    return OK;
64993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
65093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
651145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dongstatus_t StagefrightRecorder::setParamVideoEncoderProfile(int32_t profile) {
6523856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamVideoEncoderProfile: %d", profile);
653145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong
654145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    // Additional check will be done later when we load the encoder.
655145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    // For now, we are accepting values defined in OpenMAX IL.
656145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    mVideoEncoderProfile = profile;
657145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    return OK;
658145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong}
659145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong
660145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dongstatus_t StagefrightRecorder::setParamVideoEncoderLevel(int32_t level) {
6613856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamVideoEncoderLevel: %d", level);
662145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong
663145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    // Additional check will be done later when we load the encoder.
664145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    // For now, we are accepting values defined in OpenMAX IL.
665145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    mVideoEncoderLevel = level;
666145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    return OK;
667145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong}
668145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong
6698f5f2fcee5c12d08df71d17017410c50951fc2e3James Dongstatus_t StagefrightRecorder::setParamMovieTimeScale(int32_t timeScale) {
6703856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamMovieTimeScale: %d", timeScale);
6718f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
6728f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    // The range is set to be the same as the audio's time scale range
6738f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    // since audio's time scale has a wider range.
6748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (timeScale < 600 || timeScale > 96000) {
67529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Time scale (%d) for movie is out of range [600, 96000]", timeScale);
6768f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        return BAD_VALUE;
6778f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
6788f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    mMovieTimeScale = timeScale;
6798f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    return OK;
6808f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong}
6818f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
6828f5f2fcee5c12d08df71d17017410c50951fc2e3James Dongstatus_t StagefrightRecorder::setParamVideoTimeScale(int32_t timeScale) {
6833856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamVideoTimeScale: %d", timeScale);
6848f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
6858f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    // 60000 is chosen to make sure that each video frame from a 60-fps
6868f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    // video has 1000 ticks.
6878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (timeScale < 600 || timeScale > 60000) {
68829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Time scale (%d) for video is out of range [600, 60000]", timeScale);
6898f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        return BAD_VALUE;
6908f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
6918f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    mVideoTimeScale = timeScale;
6928f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    return OK;
6938f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong}
6948f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
6958f5f2fcee5c12d08df71d17017410c50951fc2e3James Dongstatus_t StagefrightRecorder::setParamAudioTimeScale(int32_t timeScale) {
6963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParamAudioTimeScale: %d", timeScale);
6978f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
6988f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    // 96000 Hz is the highest sampling rate support in AAC.
6998f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (timeScale < 600 || timeScale > 96000) {
70029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Time scale (%d) for audio is out of range [600, 96000]", timeScale);
7018f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        return BAD_VALUE;
7028f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
7038f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    mAudioTimeScale = timeScale;
7048f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    return OK;
7058f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong}
7068f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
70746d26dd29195450db15704e84d65740628a821fbChong Zhangstatus_t StagefrightRecorder::setParamCaptureFpsEnable(int32_t captureFpsEnable) {
70846d26dd29195450db15704e84d65740628a821fbChong Zhang    ALOGV("setParamCaptureFpsEnable: %d", captureFpsEnable);
709e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra
71046d26dd29195450db15704e84d65740628a821fbChong Zhang    if(captureFpsEnable == 0) {
71146d26dd29195450db15704e84d65740628a821fbChong Zhang        mCaptureFpsEnable = false;
71246d26dd29195450db15704e84d65740628a821fbChong Zhang    } else if (captureFpsEnable == 1) {
71346d26dd29195450db15704e84d65740628a821fbChong Zhang        mCaptureFpsEnable = true;
714e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra    } else {
715e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        return BAD_VALUE;
716e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra    }
717e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra    return OK;
718e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra}
719e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra
72073c3e6363b31fb27882c4666453ad8ef050b3cc1Wonsik Kimstatus_t StagefrightRecorder::setParamCaptureFps(double fps) {
72146d26dd29195450db15704e84d65740628a821fbChong Zhang    ALOGV("setParamCaptureFps: %.2f", fps);
7229ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang
72322dc508717c7767927064ec7c152def99e54adcbPawin Vongmasa    if (!(fps >= 1.0 / 86400)) {
72422dc508717c7767927064ec7c152def99e54adcbPawin Vongmasa        ALOGE("FPS is too small");
725e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        return BAD_VALUE;
726e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra    }
7279ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    mCaptureFps = fps;
728e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra    return OK;
729e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra}
730e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra
73107b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t StagefrightRecorder::setParamGeoDataLongitude(
732b832a03d563dd000faa44f2577e92237525edc32James Dong    int64_t longitudex10000) {
73307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
73407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (longitudex10000 > 1800000 || longitudex10000 < -1800000) {
73507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
73607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
73707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = longitudex10000;
73807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
73907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
74007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
74107b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t StagefrightRecorder::setParamGeoDataLatitude(
742b832a03d563dd000faa44f2577e92237525edc32James Dong    int64_t latitudex10000) {
74307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
74407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (latitudex10000 > 900000 || latitudex10000 < -900000) {
74507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
74607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
74707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = latitudex10000;
74807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
74907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
75007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
751050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParameter(
752050b28a593350047845a45a14cc5026221ac1620James Dong        const String8 &key, const String8 &value) {
7533856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
754050b28a593350047845a45a14cc5026221ac1620James Dong    if (key == "max-duration") {
755ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        int64_t max_duration_ms;
756050b28a593350047845a45a14cc5026221ac1620James Dong        if (safe_strtoi64(value.string(), &max_duration_ms)) {
757934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            return setParamMaxFileDurationUs(1000LL * max_duration_ms);
758050b28a593350047845a45a14cc5026221ac1620James Dong        }
759050b28a593350047845a45a14cc5026221ac1620James Dong    } else if (key == "max-filesize") {
760ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        int64_t max_filesize_bytes;
761050b28a593350047845a45a14cc5026221ac1620James Dong        if (safe_strtoi64(value.string(), &max_filesize_bytes)) {
762934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            return setParamMaxFileSizeBytes(max_filesize_bytes);
763050b28a593350047845a45a14cc5026221ac1620James Dong        }
76493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    } else if (key == "interleave-duration-us") {
76593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int32_t durationUs;
76693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (safe_strtoi32(value.string(), &durationUs)) {
76793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return setParamInterleaveDuration(durationUs);
76893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
7698f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    } else if (key == "param-movie-time-scale") {
7708f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t timeScale;
7718f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (safe_strtoi32(value.string(), &timeScale)) {
7728f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            return setParamMovieTimeScale(timeScale);
7738f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        }
77493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    } else if (key == "param-use-64bit-offset") {
77593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int32_t use64BitOffset;
77693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (safe_strtoi32(value.string(), &use64BitOffset)) {
77793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return setParam64BitFileOffset(use64BitOffset != 0);
77893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
77907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else if (key == "param-geotag-longitude") {
780b832a03d563dd000faa44f2577e92237525edc32James Dong        int64_t longitudex10000;
781b832a03d563dd000faa44f2577e92237525edc32James Dong        if (safe_strtoi64(value.string(), &longitudex10000)) {
78207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong            return setParamGeoDataLongitude(longitudex10000);
78307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        }
78407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else if (key == "param-geotag-latitude") {
785b832a03d563dd000faa44f2577e92237525edc32James Dong        int64_t latitudex10000;
786b832a03d563dd000faa44f2577e92237525edc32James Dong        if (safe_strtoi64(value.string(), &latitudex10000)) {
78707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong            return setParamGeoDataLatitude(latitudex10000);
78807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        }
78993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    } else if (key == "param-track-time-status") {
79093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeDurationUs;
79193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (safe_strtoi64(value.string(), &timeDurationUs)) {
79293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return setParamTrackTimeStatus(timeDurationUs);
79393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
794050b28a593350047845a45a14cc5026221ac1620James Dong    } else if (key == "audio-param-sampling-rate") {
795050b28a593350047845a45a14cc5026221ac1620James Dong        int32_t sampling_rate;
796ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (safe_strtoi32(value.string(), &sampling_rate)) {
797050b28a593350047845a45a14cc5026221ac1620James Dong            return setParamAudioSamplingRate(sampling_rate);
798050b28a593350047845a45a14cc5026221ac1620James Dong        }
799050b28a593350047845a45a14cc5026221ac1620James Dong    } else if (key == "audio-param-number-of-channels") {
800050b28a593350047845a45a14cc5026221ac1620James Dong        int32_t number_of_channels;
801ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (safe_strtoi32(value.string(), &number_of_channels)) {
802050b28a593350047845a45a14cc5026221ac1620James Dong            return setParamAudioNumberOfChannels(number_of_channels);
803050b28a593350047845a45a14cc5026221ac1620James Dong        }
804050b28a593350047845a45a14cc5026221ac1620James Dong    } else if (key == "audio-param-encoding-bitrate") {
805050b28a593350047845a45a14cc5026221ac1620James Dong        int32_t audio_bitrate;
806ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (safe_strtoi32(value.string(), &audio_bitrate)) {
807050b28a593350047845a45a14cc5026221ac1620James Dong            return setParamAudioEncodingBitRate(audio_bitrate);
808050b28a593350047845a45a14cc5026221ac1620James Dong        }
8098f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    } else if (key == "audio-param-time-scale") {
8108f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t timeScale;
8118f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (safe_strtoi32(value.string(), &timeScale)) {
8128f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            return setParamAudioTimeScale(timeScale);
8138f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        }
814050b28a593350047845a45a14cc5026221ac1620James Dong    } else if (key == "video-param-encoding-bitrate") {
815050b28a593350047845a45a14cc5026221ac1620James Dong        int32_t video_bitrate;
816ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (safe_strtoi32(value.string(), &video_bitrate)) {
817050b28a593350047845a45a14cc5026221ac1620James Dong            return setParamVideoEncodingBitRate(video_bitrate);
818050b28a593350047845a45a14cc5026221ac1620James Dong        }
81913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    } else if (key == "video-param-rotation-angle-degrees") {
82013f6284305e4b27395a23db7882d670bdb1bcae1James Dong        int32_t degrees;
82113f6284305e4b27395a23db7882d670bdb1bcae1James Dong        if (safe_strtoi32(value.string(), &degrees)) {
82213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            return setParamVideoRotation(degrees);
82313f6284305e4b27395a23db7882d670bdb1bcae1James Dong        }
82493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    } else if (key == "video-param-i-frames-interval") {
8258f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t seconds;
8268f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (safe_strtoi32(value.string(), &seconds)) {
8278f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            return setParamVideoIFramesInterval(seconds);
828ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        }
829145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    } else if (key == "video-param-encoder-profile") {
830145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong        int32_t profile;
831145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong        if (safe_strtoi32(value.string(), &profile)) {
832145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong            return setParamVideoEncoderProfile(profile);
833145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong        }
834145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    } else if (key == "video-param-encoder-level") {
835145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong        int32_t level;
836145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong        if (safe_strtoi32(value.string(), &level)) {
837145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong            return setParamVideoEncoderLevel(level);
838145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong        }
83993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    } else if (key == "video-param-camera-id") {
84093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int32_t cameraId;
84193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (safe_strtoi32(value.string(), &cameraId)) {
84293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return setParamVideoCameraId(cameraId);
8432dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
8448f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    } else if (key == "video-param-time-scale") {
8458f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t timeScale;
8468f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (safe_strtoi32(value.string(), &timeScale)) {
8478f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            return setParamVideoTimeScale(timeScale);
8488f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        }
849e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra    } else if (key == "time-lapse-enable") {
85046d26dd29195450db15704e84d65740628a821fbChong Zhang        int32_t captureFpsEnable;
85146d26dd29195450db15704e84d65740628a821fbChong Zhang        if (safe_strtoi32(value.string(), &captureFpsEnable)) {
85246d26dd29195450db15704e84d65740628a821fbChong Zhang            return setParamCaptureFpsEnable(captureFpsEnable);
853e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        }
8549ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang    } else if (key == "time-lapse-fps") {
85573c3e6363b31fb27882c4666453ad8ef050b3cc1Wonsik Kim        double fps;
85673c3e6363b31fb27882c4666453ad8ef050b3cc1Wonsik Kim        if (safe_strtod(value.string(), &fps)) {
85746d26dd29195450db15704e84d65740628a821fbChong Zhang            return setParamCaptureFps(fps);
858e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        }
859050b28a593350047845a45a14cc5026221ac1620James Dong    } else {
86029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("setParameter: failed to find key %s", key.string());
861050b28a593350047845a45a14cc5026221ac1620James Dong    }
862ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    return BAD_VALUE;
863050b28a593350047845a45a14cc5026221ac1620James Dong}
86430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
865050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParameters(const String8 &params) {
8663856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setParameters: %s", params.string());
867050b28a593350047845a45a14cc5026221ac1620James Dong    const char *cparams = params.string();
868050b28a593350047845a45a14cc5026221ac1620James Dong    const char *key_start = cparams;
869050b28a593350047845a45a14cc5026221ac1620James Dong    for (;;) {
870050b28a593350047845a45a14cc5026221ac1620James Dong        const char *equal_pos = strchr(key_start, '=');
871050b28a593350047845a45a14cc5026221ac1620James Dong        if (equal_pos == NULL) {
87229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Parameters %s miss a value", cparams);
873050b28a593350047845a45a14cc5026221ac1620James Dong            return BAD_VALUE;
874050b28a593350047845a45a14cc5026221ac1620James Dong        }
875050b28a593350047845a45a14cc5026221ac1620James Dong        String8 key(key_start, equal_pos - key_start);
876050b28a593350047845a45a14cc5026221ac1620James Dong        TrimString(&key);
877050b28a593350047845a45a14cc5026221ac1620James Dong        if (key.length() == 0) {
87829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Parameters %s contains an empty key", cparams);
879050b28a593350047845a45a14cc5026221ac1620James Dong            return BAD_VALUE;
880050b28a593350047845a45a14cc5026221ac1620James Dong        }
881050b28a593350047845a45a14cc5026221ac1620James Dong        const char *value_start = equal_pos + 1;
882050b28a593350047845a45a14cc5026221ac1620James Dong        const char *semicolon_pos = strchr(value_start, ';');
883050b28a593350047845a45a14cc5026221ac1620James Dong        String8 value;
884050b28a593350047845a45a14cc5026221ac1620James Dong        if (semicolon_pos == NULL) {
885050b28a593350047845a45a14cc5026221ac1620James Dong            value.setTo(value_start);
886050b28a593350047845a45a14cc5026221ac1620James Dong        } else {
887050b28a593350047845a45a14cc5026221ac1620James Dong            value.setTo(value_start, semicolon_pos - value_start);
888050b28a593350047845a45a14cc5026221ac1620James Dong        }
889050b28a593350047845a45a14cc5026221ac1620James Dong        if (setParameter(key, value) != OK) {
890050b28a593350047845a45a14cc5026221ac1620James Dong            return BAD_VALUE;
891050b28a593350047845a45a14cc5026221ac1620James Dong        }
892050b28a593350047845a45a14cc5026221ac1620James Dong        if (semicolon_pos == NULL) {
893050b28a593350047845a45a14cc5026221ac1620James Dong            break;  // Reaches the end
894050b28a593350047845a45a14cc5026221ac1620James Dong        }
895050b28a593350047845a45a14cc5026221ac1620James Dong        key_start = semicolon_pos + 1;
896050b28a593350047845a45a14cc5026221ac1620James Dong    }
89730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
89830ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
89930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
90037047fceba836f341d0108beed0991b0f8dfc543James Dongstatus_t StagefrightRecorder::setListener(const sp<IMediaRecorderClient> &listener) {
90130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mListener = listener;
90230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
90330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
90430ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
90530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
906ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvalastatus_t StagefrightRecorder::setClientName(const String16& clientName) {
907ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    mClientName = clientName;
908ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala
909ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    return OK;
910ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala}
911ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala
9121a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhangstatus_t StagefrightRecorder::prepareInternal() {
91372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGV("prepare");
91472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mOutputFd < 0) {
91572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGE("Output file descriptor is invalid");
91672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return INVALID_OPERATION;
91772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
918934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong
91998a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen    // Get UID and PID here for permission checking
920ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    mClientUid = IPCThreadState::self()->getCallingUid();
92198a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen    mClientPid = IPCThreadState::self()->getCallingPid();
92230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
92375b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang    status_t status = OK;
92475b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
9252dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    switch (mOutputFormat) {
9262dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        case OUTPUT_FORMAT_DEFAULT:
9272dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        case OUTPUT_FORMAT_THREE_GPP:
9282dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        case OUTPUT_FORMAT_MPEG_4:
929114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        case OUTPUT_FORMAT_WEBM:
930114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih            status = setupMPEG4orWEBMRecording();
93175b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang            break;
9322dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
9332dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        case OUTPUT_FORMAT_AMR_NB:
9342dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        case OUTPUT_FORMAT_AMR_WB:
93572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status = setupAMRRecording();
93675b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang            break;
9372dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
938ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        case OUTPUT_FORMAT_AAC_ADIF:
939ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        case OUTPUT_FORMAT_AAC_ADTS:
94072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status = setupAACRecording();
94175b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang            break;
942ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
94339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        case OUTPUT_FORMAT_RTP_AVP:
94472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status = setupRTPRecording();
94575b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang            break;
94639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
94759b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        case OUTPUT_FORMAT_MPEG2TS:
94872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status = setupMPEG2TSRecording();
94975b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang            break;
95059b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
9512dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        default:
95229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unsupported output file format: %d", mOutputFormat);
95375b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang            status = UNKNOWN_ERROR;
95475b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang            break;
95575b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang    }
95675b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
9575a4a0a1e4a44b8e48aff8e74df56d37dc6d7129cHangyu Kuang    ALOGV("Recording frameRate: %d captureFps: %f",
9585a4a0a1e4a44b8e48aff8e74df56d37dc6d7129cHangyu Kuang            mFrameRate, mCaptureFps);
9595a4a0a1e4a44b8e48aff8e74df56d37dc6d7129cHangyu Kuang
96072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return status;
96172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
96272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9631a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhangstatus_t StagefrightRecorder::prepare() {
964fc079f79d8d4f6ef9f138aa615486c10dda99fb7Hangyu Kuang    ALOGV("prepare");
965fc079f79d8d4f6ef9f138aa615486c10dda99fb7Hangyu Kuang    Mutex::Autolock autolock(mLock);
9661a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang    if (mVideoSource == VIDEO_SOURCE_SURFACE) {
9671a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang        return prepareInternal();
9681a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang    }
9691a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang    return OK;
9701a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang}
9711a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang
97272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t StagefrightRecorder::start() {
97372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGV("start");
974fc079f79d8d4f6ef9f138aa615486c10dda99fb7Hangyu Kuang    Mutex::Autolock autolock(mLock);
97572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mOutputFd < 0) {
97672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGE("Output file descriptor is invalid");
97772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return INVALID_OPERATION;
97872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
97972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9801a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang    status_t status = OK;
9811a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang
9821a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang    if (mVideoSource != VIDEO_SOURCE_SURFACE) {
9831a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang        status = prepareInternal();
9841a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang        if (status != OK) {
9851a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang            return status;
9861a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang        }
9871a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang    }
9881a5690652f3f6ee40f15c2f9f6c4b6badf4dbcf5Chong Zhang
98972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mWriter == NULL) {
99072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGE("File writer is not avaialble");
99172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return UNKNOWN_ERROR;
99272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
99372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
99472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    switch (mOutputFormat) {
99572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case OUTPUT_FORMAT_DEFAULT:
99672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case OUTPUT_FORMAT_THREE_GPP:
99772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case OUTPUT_FORMAT_MPEG_4:
998114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        case OUTPUT_FORMAT_WEBM:
99972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
1000114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih            bool isMPEG4 = true;
1001114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih            if (mOutputFormat == OUTPUT_FORMAT_WEBM) {
1002114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih                isMPEG4 = false;
1003114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih            }
100472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            sp<MetaData> meta = new MetaData;
1005114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih            setupMPEG4orWEBMMetaData(&meta);
100672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status = mWriter->start(meta.get());
100772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
100872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
100972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
101072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case OUTPUT_FORMAT_AMR_NB:
101172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case OUTPUT_FORMAT_AMR_WB:
101272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case OUTPUT_FORMAT_AAC_ADIF:
101372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case OUTPUT_FORMAT_AAC_ADTS:
101472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case OUTPUT_FORMAT_RTP_AVP:
101572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case OUTPUT_FORMAT_MPEG2TS:
101672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
10178f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang            sp<MetaData> meta = new MetaData;
10188f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang            int64_t startTimeUs = systemTime() / 1000;
10198f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang            meta->setInt64(kKeyTime, startTimeUs);
10208f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang            status = mWriter->start(meta.get());
102172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
102272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
102372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
102472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        default:
102572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
102672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            ALOGE("Unsupported output file format: %d", mOutputFormat);
102772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status = UNKNOWN_ERROR;
102872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
102972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
103072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
103172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
103272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (status != OK) {
103372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mWriter.clear();
103472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mWriter = NULL;
103572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
103672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
103775b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang    if ((status == OK) && (!mStarted)) {
1038ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        mAnalyticsDirty = true;
103975b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        mStarted = true;
104075b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
104135cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick        mStartedRecordingUs = systemTime() / 1000;
104235cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick
104375b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted;
1044fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin        if (mAudioSource != AUDIO_SOURCE_CNT) {
104575b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang            params |= IMediaPlayerService::kBatteryDataTrackAudio;
104675b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        }
104775b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        if (mVideoSource != VIDEO_SOURCE_LIST_END) {
104875b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang            params |= IMediaPlayerService::kBatteryDataTrackVideo;
104975b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        }
105075b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
105175b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        addBatteryData(params);
10522dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    }
105375b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
105475b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang    return status;
10552dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber}
10562dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
1057d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kimsp<MediaCodecSource> StagefrightRecorder::createAudioSource() {
105846d26dd29195450db15704e84d65740628a821fbChong Zhang    int32_t sourceSampleRate = mSampleRate;
105946d26dd29195450db15704e84d65740628a821fbChong Zhang
106046d26dd29195450db15704e84d65740628a821fbChong Zhang    if (mCaptureFpsEnable && mCaptureFps >= mFrameRate) {
106146d26dd29195450db15704e84d65740628a821fbChong Zhang        // Upscale the sample rate for slow motion recording.
106246d26dd29195450db15704e84d65740628a821fbChong Zhang        // Fail audio source creation if source sample rate is too high, as it could
106346d26dd29195450db15704e84d65740628a821fbChong Zhang        // cause out-of-memory due to large input buffer size. And audio recording
106446d26dd29195450db15704e84d65740628a821fbChong Zhang        // probably doesn't make sense in the scenario, since the slow-down factor
106546d26dd29195450db15704e84d65740628a821fbChong Zhang        // is probably huge (eg. mSampleRate=48K, mCaptureFps=240, mFrameRate=1).
106646d26dd29195450db15704e84d65740628a821fbChong Zhang        const static int32_t SAMPLE_RATE_HZ_MAX = 192000;
106746d26dd29195450db15704e84d65740628a821fbChong Zhang        sourceSampleRate =
106846d26dd29195450db15704e84d65740628a821fbChong Zhang                (mSampleRate * mCaptureFps + mFrameRate / 2) / mFrameRate;
106946d26dd29195450db15704e84d65740628a821fbChong Zhang        if (sourceSampleRate < mSampleRate || sourceSampleRate > SAMPLE_RATE_HZ_MAX) {
107046d26dd29195450db15704e84d65740628a821fbChong Zhang            ALOGE("source sample rate out of range! "
107146d26dd29195450db15704e84d65740628a821fbChong Zhang                    "(mSampleRate %d, mCaptureFps %.2f, mFrameRate %d",
107246d26dd29195450db15704e84d65740628a821fbChong Zhang                    mSampleRate, mCaptureFps, mFrameRate);
107346d26dd29195450db15704e84d65740628a821fbChong Zhang            return NULL;
107446d26dd29195450db15704e84d65740628a821fbChong Zhang        }
107546d26dd29195450db15704e84d65740628a821fbChong Zhang    }
107646d26dd29195450db15704e84d65740628a821fbChong Zhang
10772dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    sp<AudioSource> audioSource =
10782dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        new AudioSource(
10792dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber                mAudioSource,
1080be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov                mOpPackageName,
108146d26dd29195450db15704e84d65740628a821fbChong Zhang                sourceSampleRate,
108246d26dd29195450db15704e84d65740628a821fbChong Zhang                mAudioChannels,
1083b2379ba0a32638bae2ea0460644f68cf5a0967ceEric Laurent                mSampleRate,
1084b2379ba0a32638bae2ea0460644f68cf5a0967ceEric Laurent                mClientUid,
1085fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin                mClientPid,
1086fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin                mSelectedDeviceId);
10872dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
10882dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    status_t err = audioSource->initCheck();
10892dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
10902dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    if (err != OK) {
109129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("audio source is not initialized");
10922dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        return NULL;
10932dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    }
10942dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
109572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> format = new AMessage;
1096050b28a593350047845a45a14cc5026221ac1620James Dong    switch (mAudioEncoder) {
1097050b28a593350047845a45a14cc5026221ac1620James Dong        case AUDIO_ENCODER_AMR_NB:
1098050b28a593350047845a45a14cc5026221ac1620James Dong        case AUDIO_ENCODER_DEFAULT:
109972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
1100050b28a593350047845a45a14cc5026221ac1620James Dong            break;
1101050b28a593350047845a45a14cc5026221ac1620James Dong        case AUDIO_ENCODER_AMR_WB:
110272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
1103050b28a593350047845a45a14cc5026221ac1620James Dong            break;
1104050b28a593350047845a45a14cc5026221ac1620James Dong        case AUDIO_ENCODER_AAC:
110572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
110672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            format->setInt32("aac-profile", OMX_AUDIO_AACObjectLC);
1107aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke            break;
1108f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke        case AUDIO_ENCODER_HE_AAC:
110972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
111072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            format->setInt32("aac-profile", OMX_AUDIO_AACObjectHE);
1111f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke            break;
1112aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        case AUDIO_ENCODER_AAC_ELD:
111372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
111472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            format->setInt32("aac-profile", OMX_AUDIO_AACObjectELD);
1115050b28a593350047845a45a14cc5026221ac1620James Dong            break;
1116f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke
1117050b28a593350047845a45a14cc5026221ac1620James Dong        default:
111829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unknown audio encoder: %d", mAudioEncoder);
1119050b28a593350047845a45a14cc5026221ac1620James Dong            return NULL;
1120050b28a593350047845a45a14cc5026221ac1620James Dong    }
11212dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
112235cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    // log audio mime type for media metrics
112335cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    if (mAnalyticsItem != NULL) {
112435cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick        AString audiomime;
112535cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick        if (format->findString("mime", &audiomime)) {
112635cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick            mAnalyticsItem->setCString(kRecorderAudioMime, audiomime.c_str());
112735cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick        }
112835cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    }
112935cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick
1130b45c62c8e9b05c2703bdae18cc298ae55550db8aAndreas Huber    int32_t maxInputSize;
1131b45c62c8e9b05c2703bdae18cc298ae55550db8aAndreas Huber    CHECK(audioSource->getFormat()->findInt32(
1132b45c62c8e9b05c2703bdae18cc298ae55550db8aAndreas Huber                kKeyMaxInputSize, &maxInputSize));
1133b45c62c8e9b05c2703bdae18cc298ae55550db8aAndreas Huber
113472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    format->setInt32("max-input-size", maxInputSize);
113572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    format->setInt32("channel-count", mAudioChannels);
113672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    format->setInt32("sample-rate", mSampleRate);
113772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    format->setInt32("bitrate", mAudioBitRate);
1138c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mAudioTimeScale > 0) {
113972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("time-scale", mAudioTimeScale);
1140c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1141fdbc1b3a885f1e8a59b1788e48e24ea4c66acbc8Ronghua Wu    format->setInt32("priority", 0 /* realtime */);
11422dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
1143d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    sp<MediaCodecSource> audioEncoder =
114472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            MediaCodecSource::Create(mLooper, format, audioSource);
1145fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin    sp<AudioSystem::AudioDeviceCallback> callback = mAudioDeviceCallback.promote();
1146fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin    if (mDeviceCallbackEnabled && callback != 0) {
1147fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin        audioSource->addAudioDeviceCallback(callback);
1148fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin    }
1149d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    mAudioSourceNode = audioSource;
11502dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
1151ef0cf50343f8a6d74894f96f5ecb5eec4c5f1bc6Chong Zhang    if (audioEncoder == NULL) {
1152ef0cf50343f8a6d74894f96f5ecb5eec4c5f1bc6Chong Zhang        ALOGE("Failed to create audio encoder");
1153ef0cf50343f8a6d74894f96f5ecb5eec4c5f1bc6Chong Zhang    }
1154ef0cf50343f8a6d74894f96f5ecb5eec4c5f1bc6Chong Zhang
11552dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return audioEncoder;
11562dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber}
11572dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
115872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t StagefrightRecorder::setupAACRecording() {
1159760943b5e7a09b602aba04ec451e97662f48b0a4James Dong    // FIXME:
1160760943b5e7a09b602aba04ec451e97662f48b0a4James Dong    // Add support for OUTPUT_FORMAT_AAC_ADIF
1161f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong    CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_AAC_ADTS);
1162ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
1163aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    CHECK(mAudioEncoder == AUDIO_ENCODER_AAC ||
1164f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke          mAudioEncoder == AUDIO_ENCODER_HE_AAC ||
1165aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke          mAudioEncoder == AUDIO_ENCODER_AAC_ELD);
1166fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin    CHECK(mAudioSource != AUDIO_SOURCE_CNT);
1167ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
1168760943b5e7a09b602aba04ec451e97662f48b0a4James Dong    mWriter = new AACWriter(mOutputFd);
116972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return setupRawAudioRecording();
1170ef9d0cd72e476a4b7556833fb09505a51b626797James Dong}
1171ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
117272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t StagefrightRecorder::setupAMRRecording() {
1173ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    CHECK(mOutputFormat == OUTPUT_FORMAT_AMR_NB ||
1174ef9d0cd72e476a4b7556833fb09505a51b626797James Dong          mOutputFormat == OUTPUT_FORMAT_AMR_WB);
1175ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
1176ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (mOutputFormat == OUTPUT_FORMAT_AMR_NB) {
1177ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (mAudioEncoder != AUDIO_ENCODER_DEFAULT &&
1178ef9d0cd72e476a4b7556833fb09505a51b626797James Dong            mAudioEncoder != AUDIO_ENCODER_AMR_NB) {
117929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Invalid encoder %d used for AMRNB recording",
1180ef9d0cd72e476a4b7556833fb09505a51b626797James Dong                    mAudioEncoder);
1181934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            return BAD_VALUE;
1182ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        }
1183ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    } else {  // mOutputFormat must be OUTPUT_FORMAT_AMR_WB
1184ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
118529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Invlaid encoder %d used for AMRWB recording",
1186ef9d0cd72e476a4b7556833fb09505a51b626797James Dong                    mAudioEncoder);
1187934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            return BAD_VALUE;
1188ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        }
11892dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    }
11902dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
1191760943b5e7a09b602aba04ec451e97662f48b0a4James Dong    mWriter = new AMRWriter(mOutputFd);
119272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return setupRawAudioRecording();
1193760943b5e7a09b602aba04ec451e97662f48b0a4James Dong}
1194760943b5e7a09b602aba04ec451e97662f48b0a4James Dong
119572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t StagefrightRecorder::setupRawAudioRecording() {
11960f8f4e681b867dd611d2d916453337cb0770d4daHochi Huang    if (mAudioSource >= AUDIO_SOURCE_CNT && mAudioSource != AUDIO_SOURCE_FM_TUNER) {
119729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid audio source: %d", mAudioSource);
1198934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return BAD_VALUE;
11992dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    }
12002dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
120142dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    status_t status = BAD_VALUE;
120242dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    if (OK != (status = checkAudioEncoderCapabilities())) {
120342dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong        return status;
120442dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    }
12052dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
1206d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    sp<MediaCodecSource> audioEncoder = createAudioSource();
12072dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    if (audioEncoder == NULL) {
12082dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        return UNKNOWN_ERROR;
12092dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    }
12102dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
1211760943b5e7a09b602aba04ec451e97662f48b0a4James Dong    CHECK(mWriter != 0);
12122dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    mWriter->addSource(audioEncoder);
1213d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    mAudioEncoderSource = audioEncoder;
1214d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1215d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationUs != 0) {
1216d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        mWriter->setMaxFileDuration(mMaxFileDurationUs);
1217d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1218d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeBytes != 0) {
1219d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        mWriter->setMaxFileSize(mMaxFileSizeBytes);
1220d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1221d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    mWriter->setListener(mListener);
12222dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
12232dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
12242dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber}
12252dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
122672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t StagefrightRecorder::setupRTPRecording() {
122739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_RTP_AVP);
122839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
1229fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin    if ((mAudioSource != AUDIO_SOURCE_CNT
123039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                && mVideoSource != VIDEO_SOURCE_LIST_END)
1231fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin            || (mAudioSource == AUDIO_SOURCE_CNT
123239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                && mVideoSource == VIDEO_SOURCE_LIST_END)) {
123339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        // Must have exactly one source.
123439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        return BAD_VALUE;
123539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
123639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
123739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    if (mOutputFd < 0) {
123839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        return BAD_VALUE;
123939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
124039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
1241d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    sp<MediaCodecSource> source;
124239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
1243fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin    if (mAudioSource != AUDIO_SOURCE_CNT) {
124439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        source = createAudioSource();
1245d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        mAudioEncoderSource = source;
124639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    } else {
124754ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang        setDefaultVideoEncoderIfNecessary();
12489c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra
1249b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi        sp<MediaSource> mediaSource;
1250b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi        status_t err = setupMediaSource(&mediaSource);
12519c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra        if (err != OK) {
12529c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra            return err;
12539c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra        }
12549c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra
12554db37cedd4db8230f3ec6191d8d7ba2b0036886eRobert Shih        err = setupVideoEncoder(mediaSource, &source);
125639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        if (err != OK) {
125739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            return err;
125839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        }
1259d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        mVideoEncoderSource = source;
126039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
126139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
1262674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    mWriter = new ARTPWriter(mOutputFd);
126339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mWriter->addSource(source);
126439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mWriter->setListener(mListener);
126539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
126672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
126739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
126839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
126972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t StagefrightRecorder::setupMPEG2TSRecording() {
127059b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_MPEG2TS);
127159b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
1272674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    sp<MediaWriter> writer = new MPEG2TSWriter(mOutputFd);
127359b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
1274fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin    if (mAudioSource != AUDIO_SOURCE_CNT) {
1275f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke        if (mAudioEncoder != AUDIO_ENCODER_AAC &&
1276f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke            mAudioEncoder != AUDIO_ENCODER_HE_AAC &&
1277f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke            mAudioEncoder != AUDIO_ENCODER_AAC_ELD) {
127859b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber            return ERROR_UNSUPPORTED;
127959b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        }
128059b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
128159b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        status_t err = setupAudioEncoder(writer);
128259b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
128359b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        if (err != OK) {
128459b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber            return err;
128559b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        }
128659b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    }
128759b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
1288b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi    if (mVideoSource < VIDEO_SOURCE_LIST_END) {
128959b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        if (mVideoEncoder != VIDEO_ENCODER_H264) {
129054ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang            ALOGE("MPEG2TS recording only supports H.264 encoding!");
129159b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber            return ERROR_UNSUPPORTED;
129259b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        }
129359b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
1294b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi        sp<MediaSource> mediaSource;
1295b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi        status_t err = setupMediaSource(&mediaSource);
1296f9f083e2853740c97588f4db82c24645ae5880e4Kenny Root        if (err != OK) {
1297f9f083e2853740c97588f4db82c24645ae5880e4Kenny Root            return err;
1298f9f083e2853740c97588f4db82c24645ae5880e4Kenny Root        }
1299f9f083e2853740c97588f4db82c24645ae5880e4Kenny Root
1300d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        sp<MediaCodecSource> encoder;
13014db37cedd4db8230f3ec6191d8d7ba2b0036886eRobert Shih        err = setupVideoEncoder(mediaSource, &encoder);
130259b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
130359b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        if (err != OK) {
130459b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber            return err;
130559b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        }
130659b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
130759b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        writer->addSource(encoder);
1308d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        mVideoEncoderSource = encoder;
130959b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    }
131059b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
131159b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    if (mMaxFileDurationUs != 0) {
131259b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        writer->setMaxFileDuration(mMaxFileDurationUs);
131359b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    }
131459b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
131559b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    if (mMaxFileSizeBytes != 0) {
131659b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        writer->setMaxFileSize(mMaxFileSizeBytes);
131759b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    }
131859b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
131959b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    mWriter = writer;
132059b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
132172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
132259b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber}
132359b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
132499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dongvoid StagefrightRecorder::clipVideoFrameRate() {
13253856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("clipVideoFrameRate: encoder %d", mVideoEncoder);
132654ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang    if (mFrameRate == -1) {
132754ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang        mFrameRate = mEncoderProfiles->getCamcorderProfileParamByName(
132854ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang                "vid.fps", mCameraId, CAMCORDER_QUALITY_LOW);
132954ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang        ALOGW("Using default video fps %d", mFrameRate);
133054ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang    }
133154ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang
133299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int minFrameRate = mEncoderProfiles->getVideoEncoderParamByName(
133399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.fps.min", mVideoEncoder);
133499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int maxFrameRate = mEncoderProfiles->getVideoEncoderParamByName(
133599c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.fps.max", mVideoEncoder);
1336b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    if (mFrameRate < minFrameRate && minFrameRate != -1) {
13375ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended video encoding frame rate (%d fps) is too small"
133899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d fps)", mFrameRate, minFrameRate);
133999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mFrameRate = minFrameRate;
1340b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    } else if (mFrameRate > maxFrameRate && maxFrameRate != -1) {
13415ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended video encoding frame rate (%d fps) is too large"
134299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d fps)", mFrameRate, maxFrameRate);
134399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mFrameRate = maxFrameRate;
134499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    }
134599c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong}
134699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong
134799c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dongvoid StagefrightRecorder::clipVideoBitRate() {
13483856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("clipVideoBitRate: encoder %d", mVideoEncoder);
134999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int minBitRate = mEncoderProfiles->getVideoEncoderParamByName(
135099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.bps.min", mVideoEncoder);
135199c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int maxBitRate = mEncoderProfiles->getVideoEncoderParamByName(
135299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.bps.max", mVideoEncoder);
1353b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    if (mVideoBitRate < minBitRate && minBitRate != -1) {
13545ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended video encoding bit rate (%d bps) is too small"
135599c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d bps)", mVideoBitRate, minBitRate);
135699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mVideoBitRate = minBitRate;
1357b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    } else if (mVideoBitRate > maxBitRate && maxBitRate != -1) {
13585ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended video encoding bit rate (%d bps) is too large"
135999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d bps)", mVideoBitRate, maxBitRate);
136099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mVideoBitRate = maxBitRate;
136199c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    }
136299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong}
136399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong
136499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dongvoid StagefrightRecorder::clipVideoFrameWidth() {
13653856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("clipVideoFrameWidth: encoder %d", mVideoEncoder);
136699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int minFrameWidth = mEncoderProfiles->getVideoEncoderParamByName(
136799c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.width.min", mVideoEncoder);
136899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int maxFrameWidth = mEncoderProfiles->getVideoEncoderParamByName(
136999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.width.max", mVideoEncoder);
1370b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    if (mVideoWidth < minFrameWidth && minFrameWidth != -1) {
13715ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended video encoding frame width (%d) is too small"
137299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d)", mVideoWidth, minFrameWidth);
137399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mVideoWidth = minFrameWidth;
1374b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    } else if (mVideoWidth > maxFrameWidth && maxFrameWidth != -1) {
13755ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended video encoding frame width (%d) is too large"
137699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d)", mVideoWidth, maxFrameWidth);
137799c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mVideoWidth = maxFrameWidth;
137899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    }
137999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong}
138099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong
1381d46a6b9fd8b2a4f9098757384711e2cd03a91651Eino-Ville Talvalastatus_t StagefrightRecorder::checkVideoEncoderCapabilities() {
138246d26dd29195450db15704e84d65740628a821fbChong Zhang    if (!mCaptureFpsEnable) {
1383e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        // Dont clip for time lapse capture as encoder will have enough
1384e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        // time to encode because of slow capture rate of time lapse.
1385e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        clipVideoBitRate();
1386e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        clipVideoFrameRate();
1387e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        clipVideoFrameWidth();
1388e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        clipVideoFrameHeight();
1389d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        setDefaultProfileIfNecessary();
1390e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra    }
1391934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    return OK;
1392934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong}
1393934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong
1394d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong// Set to use AVC baseline profile if the encoding parameters matches
1395d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong// CAMCORDER_QUALITY_LOW profile; this is for the sake of MMS service.
1396d552b88515c6ccd18695e5db5e6032a6425d8c63James Dongvoid StagefrightRecorder::setDefaultProfileIfNecessary() {
13973856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setDefaultProfileIfNecessary");
1398d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1399d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    camcorder_quality quality = CAMCORDER_QUALITY_LOW;
1400d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1401d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    int64_t durationUs   = mEncoderProfiles->getCamcorderProfileParamByName(
1402d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong                                "duration", mCameraId, quality) * 1000000LL;
1403d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1404d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    int fileFormat       = mEncoderProfiles->getCamcorderProfileParamByName(
1405d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong                                "file.format", mCameraId, quality);
1406d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1407d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    int videoCodec       = mEncoderProfiles->getCamcorderProfileParamByName(
1408d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong                                "vid.codec", mCameraId, quality);
1409d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1410d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    int videoBitRate     = mEncoderProfiles->getCamcorderProfileParamByName(
1411d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong                                "vid.bps", mCameraId, quality);
1412d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1413d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    int videoFrameRate   = mEncoderProfiles->getCamcorderProfileParamByName(
1414d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong                                "vid.fps", mCameraId, quality);
1415d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1416d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    int videoFrameWidth  = mEncoderProfiles->getCamcorderProfileParamByName(
1417d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong                                "vid.width", mCameraId, quality);
1418d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1419d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    int videoFrameHeight = mEncoderProfiles->getCamcorderProfileParamByName(
1420d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong                                "vid.height", mCameraId, quality);
1421d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1422d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    int audioCodec       = mEncoderProfiles->getCamcorderProfileParamByName(
1423d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong                                "aud.codec", mCameraId, quality);
1424d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1425d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    int audioBitRate     = mEncoderProfiles->getCamcorderProfileParamByName(
1426d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong                                "aud.bps", mCameraId, quality);
1427d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1428d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    int audioSampleRate  = mEncoderProfiles->getCamcorderProfileParamByName(
1429d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong                                "aud.hz", mCameraId, quality);
1430d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1431d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    int audioChannels    = mEncoderProfiles->getCamcorderProfileParamByName(
1432d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong                                "aud.ch", mCameraId, quality);
1433d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
1434d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    if (durationUs == mMaxFileDurationUs &&
1435d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        fileFormat == mOutputFormat &&
1436d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        videoCodec == mVideoEncoder &&
1437d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        videoBitRate == mVideoBitRate &&
1438d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        videoFrameRate == mFrameRate &&
1439d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        videoFrameWidth == mVideoWidth &&
1440d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        videoFrameHeight == mVideoHeight &&
1441d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        audioCodec == mAudioEncoder &&
1442d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        audioBitRate == mAudioBitRate &&
1443d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        audioSampleRate == mSampleRate &&
1444d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        audioChannels == mAudioChannels) {
1445d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        if (videoCodec == VIDEO_ENCODER_H264) {
1446df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block            ALOGI("Force to use AVC baseline profile");
1447d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong            setParamVideoEncoderProfile(OMX_VIDEO_AVCProfileBaseline);
1448a147b4f91143d9f2fb608e22f9fca14bbd029573Lajos Molnar            // set 0 for invalid levels - this will be rejected by the
1449a147b4f91143d9f2fb608e22f9fca14bbd029573Lajos Molnar            // codec if it cannot handle it during configure
1450a147b4f91143d9f2fb608e22f9fca14bbd029573Lajos Molnar            setParamVideoEncoderLevel(ACodec::getAVCLevelFor(
1451a147b4f91143d9f2fb608e22f9fca14bbd029573Lajos Molnar                    videoFrameWidth, videoFrameHeight, videoFrameRate, videoBitRate));
1452d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong        }
1453d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong    }
1454d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong}
1455d552b88515c6ccd18695e5db5e6032a6425d8c63James Dong
145654ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhangvoid StagefrightRecorder::setDefaultVideoEncoderIfNecessary() {
145754ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang    if (mVideoEncoder == VIDEO_ENCODER_DEFAULT) {
145854ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang        if (mOutputFormat == OUTPUT_FORMAT_WEBM) {
145954ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang            // default to VP8 for WEBM recording
146054ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang            mVideoEncoder = VIDEO_ENCODER_VP8;
146154ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang        } else {
146254ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang            // pick the default encoder for CAMCORDER_QUALITY_LOW
146354ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang            int videoCodec = mEncoderProfiles->getCamcorderProfileParamByName(
146454ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang                    "vid.codec", mCameraId, CAMCORDER_QUALITY_LOW);
146554ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang
146654ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang            if (videoCodec > VIDEO_ENCODER_DEFAULT &&
146754ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang                videoCodec < VIDEO_ENCODER_LIST_END) {
146854ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang                mVideoEncoder = (video_encoder)videoCodec;
146954ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang            } else {
147054ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang                // default to H.264 if camcorder profile not available
147154ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang                mVideoEncoder = VIDEO_ENCODER_H264;
147254ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang            }
147354ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang        }
147454ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang    }
147554ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang}
147654ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang
147742dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dongstatus_t StagefrightRecorder::checkAudioEncoderCapabilities() {
147842dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    clipAudioBitRate();
147942dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    clipAudioSampleRate();
148042dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    clipNumberOfAudioChannels();
148142dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    return OK;
148242dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong}
148342dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
148442dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dongvoid StagefrightRecorder::clipAudioBitRate() {
14853856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("clipAudioBitRate: encoder %d", mAudioEncoder);
148642dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
148742dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    int minAudioBitRate =
148842dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            mEncoderProfiles->getAudioEncoderParamByName(
148942dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong                "enc.aud.bps.min", mAudioEncoder);
1490b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    if (minAudioBitRate != -1 && mAudioBitRate < minAudioBitRate) {
14915ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended audio encoding bit rate (%d) is too small"
149242dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            " and will be set to (%d)", mAudioBitRate, minAudioBitRate);
149342dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong        mAudioBitRate = minAudioBitRate;
149442dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    }
149542dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
149642dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    int maxAudioBitRate =
149742dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            mEncoderProfiles->getAudioEncoderParamByName(
149842dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong                "enc.aud.bps.max", mAudioEncoder);
1499b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    if (maxAudioBitRate != -1 && mAudioBitRate > maxAudioBitRate) {
15005ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended audio encoding bit rate (%d) is too large"
150142dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            " and will be set to (%d)", mAudioBitRate, maxAudioBitRate);
150242dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong        mAudioBitRate = maxAudioBitRate;
150342dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    }
150442dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong}
150542dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
150642dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dongvoid StagefrightRecorder::clipAudioSampleRate() {
15073856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("clipAudioSampleRate: encoder %d", mAudioEncoder);
150842dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
150942dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    int minSampleRate =
151042dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            mEncoderProfiles->getAudioEncoderParamByName(
151142dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong                "enc.aud.hz.min", mAudioEncoder);
1512b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    if (minSampleRate != -1 && mSampleRate < minSampleRate) {
15135ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended audio sample rate (%d) is too small"
151442dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            " and will be set to (%d)", mSampleRate, minSampleRate);
151542dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong        mSampleRate = minSampleRate;
151642dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    }
151742dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
151842dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    int maxSampleRate =
151942dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            mEncoderProfiles->getAudioEncoderParamByName(
152042dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong                "enc.aud.hz.max", mAudioEncoder);
1521b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    if (maxSampleRate != -1 && mSampleRate > maxSampleRate) {
15225ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended audio sample rate (%d) is too large"
152342dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            " and will be set to (%d)", mSampleRate, maxSampleRate);
152442dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong        mSampleRate = maxSampleRate;
152542dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    }
152642dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong}
152742dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
152842dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dongvoid StagefrightRecorder::clipNumberOfAudioChannels() {
15293856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("clipNumberOfAudioChannels: encoder %d", mAudioEncoder);
153042dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
153142dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    int minChannels =
153242dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            mEncoderProfiles->getAudioEncoderParamByName(
153342dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong                "enc.aud.ch.min", mAudioEncoder);
1534b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    if (minChannels != -1 && mAudioChannels < minChannels) {
15355ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended number of audio channels (%d) is too small"
153642dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            " and will be set to (%d)", mAudioChannels, minChannels);
153742dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong        mAudioChannels = minChannels;
153842dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    }
153942dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
154042dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    int maxChannels =
154142dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            mEncoderProfiles->getAudioEncoderParamByName(
154242dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong                "enc.aud.ch.max", mAudioEncoder);
1543b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    if (maxChannels != -1 && mAudioChannels > maxChannels) {
15445ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended number of audio channels (%d) is too large"
154542dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong            " and will be set to (%d)", mAudioChannels, maxChannels);
154642dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong        mAudioChannels = maxChannels;
154742dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    }
154842dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong}
154942dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
155099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dongvoid StagefrightRecorder::clipVideoFrameHeight() {
15513856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("clipVideoFrameHeight: encoder %d", mVideoEncoder);
155299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int minFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
155399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.height.min", mVideoEncoder);
155499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int maxFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
155599c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.height.max", mVideoEncoder);
1556b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    if (minFrameHeight != -1 && mVideoHeight < minFrameHeight) {
15575ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended video encoding frame height (%d) is too small"
155899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d)", mVideoHeight, minFrameHeight);
155999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mVideoHeight = minFrameHeight;
1560b4a55269a5b39c73de2cc1d4013d0631ef18c77dJames Dong    } else if (maxFrameHeight != -1 && mVideoHeight > maxFrameHeight) {
15615ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Intended video encoding frame height (%d) is too large"
156299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d)", mVideoHeight, maxFrameHeight);
156399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mVideoHeight = maxFrameHeight;
156499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    }
156599c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong}
156699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong
1567b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi// Set up the appropriate MediaSource depending on the chosen option
1568b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketistatus_t StagefrightRecorder::setupMediaSource(
1569b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi                      sp<MediaSource> *mediaSource) {
1570b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi    if (mVideoSource == VIDEO_SOURCE_DEFAULT
1571b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi            || mVideoSource == VIDEO_SOURCE_CAMERA) {
1572b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi        sp<CameraSource> cameraSource;
1573b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi        status_t err = setupCameraSource(&cameraSource);
1574b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi        if (err != OK) {
1575b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi            return err;
1576b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi        }
1577b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi        *mediaSource = cameraSource;
157872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    } else if (mVideoSource == VIDEO_SOURCE_SURFACE) {
157972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        *mediaSource = NULL;
1580b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi    } else {
1581b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi        return INVALID_OPERATION;
1582b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi    }
1583b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi    return OK;
1584b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi}
1585b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi
15868480835b4bc1350646376aa7f3ae33742a7adeb1James Dongstatus_t StagefrightRecorder::setupCameraSource(
15878480835b4bc1350646376aa7f3ae33742a7adeb1James Dong        sp<CameraSource> *cameraSource) {
1588635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong    status_t err = OK;
1589d46a6b9fd8b2a4f9098757384711e2cd03a91651Eino-Ville Talvala    if ((err = checkVideoEncoderCapabilities()) != OK) {
1590635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        return err;
1591635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong    }
159254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size videoSize;
159354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    videoSize.width = mVideoWidth;
159454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    videoSize.height = mVideoHeight;
159546d26dd29195450db15704e84d65740628a821fbChong Zhang    if (mCaptureFpsEnable) {
159622dc508717c7767927064ec7c152def99e54adcbPawin Vongmasa        if (!(mCaptureFps > 0.)) {
159722dc508717c7767927064ec7c152def99e54adcbPawin Vongmasa            ALOGE("Invalid mCaptureFps value: %lf", mCaptureFps);
15982e77ad2a9f7afb57b6f9127dd7c229e774baa9c8James Dong            return BAD_VALUE;
15992e77ad2a9f7afb57b6f9127dd7c229e774baa9c8James Dong        }
16002e77ad2a9f7afb57b6f9127dd7c229e774baa9c8James Dong
160154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCameraSourceTimeLapse = CameraSourceTimeLapse::CreateFromCamera(
160298a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen                mCamera, mCameraProxy, mCameraId, mClientName, mClientUid, mClientPid,
160354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                videoSize, mFrameRate, mPreviewSurface,
160422dc508717c7767927064ec7c152def99e54adcbPawin Vongmasa                std::llround(1e6 / mCaptureFps));
160578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        *cameraSource = mCameraSourceTimeLapse;
160678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    } else {
160754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        *cameraSource = CameraSource::CreateFromCamera(
160898a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen                mCamera, mCameraProxy, mCameraId, mClientName, mClientUid, mClientPid,
1609ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala                videoSize, mFrameRate,
1610d46a6b9fd8b2a4f9098757384711e2cd03a91651Eino-Ville Talvala                mPreviewSurface);
161178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    }
16124ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mCamera.clear();
16134ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mCameraProxy.clear();
1614ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    if (*cameraSource == NULL) {
1615ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong        return UNKNOWN_ERROR;
1616ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    }
1617ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong
1618ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    if ((*cameraSource)->initCheck() != OK) {
1619ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong        (*cameraSource).clear();
1620ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong        *cameraSource = NULL;
1621ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong        return NO_INIT;
1622ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    }
16239c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra
1624635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong    // When frame rate is not set, the actual frame rate will be set to
1625635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong    // the current frame rate being used.
1626635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong    if (mFrameRate == -1) {
1627635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        int32_t frameRate = 0;
1628635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        CHECK ((*cameraSource)->getFormat()->findInt32(
1629393410a441b6d06daf286ed496470e9d6b2b6ca8James Dong                    kKeyFrameRate, &frameRate));
1630df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("Frame rate is not explicitly set. Use the current frame "
1631635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong             "rate (%d fps)", frameRate);
1632635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        mFrameRate = frameRate;
1633635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong    }
1634635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong
1635635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong    CHECK(mFrameRate != -1);
16368480835b4bc1350646376aa7f3ae33742a7adeb1James Dong
16373e328782f1e1061d08ea0c45b855cc418a2d9ea6Lajos Molnar    mMetaDataStoredInVideoBuffers =
16383e328782f1e1061d08ea0c45b855cc418a2d9ea6Lajos Molnar        (*cameraSource)->metaDataStoredInVideoBuffers();
16398480835b4bc1350646376aa7f3ae33742a7adeb1James Dong
16409c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra    return OK;
16419c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra}
16429c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra
16439c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatrastatus_t StagefrightRecorder::setupVideoEncoder(
16440d1ed381fde5dac12dd84fcf3da66dac46699378Chih-Hung Hsieh        const sp<MediaSource> &cameraSource,
1645d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        sp<MediaCodecSource> *source) {
16469c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra    source->clear();
1647050b28a593350047845a45a14cc5026221ac1620James Dong
164872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> format = new AMessage();
1649ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
1650934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    switch (mVideoEncoder) {
1651934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        case VIDEO_ENCODER_H263:
165272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            format->setString("mime", MEDIA_MIMETYPE_VIDEO_H263);
1653934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            break;
165465ae665befd929efd1a7d1c9addac41c699f04b2James Dong
1655934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        case VIDEO_ENCODER_MPEG_4_SP:
165672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            format->setString("mime", MEDIA_MIMETYPE_VIDEO_MPEG4);
1657934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            break;
165830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1659934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        case VIDEO_ENCODER_H264:
166072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            format->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC);
1661934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            break;
166230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
166376dc9c5052741bf0910a23a20c9df6018c4979d8Robert Shih        case VIDEO_ENCODER_VP8:
166476dc9c5052741bf0910a23a20c9df6018c4979d8Robert Shih            format->setString("mime", MEDIA_MIMETYPE_VIDEO_VP8);
166576dc9c5052741bf0910a23a20c9df6018c4979d8Robert Shih            break;
166676dc9c5052741bf0910a23a20c9df6018c4979d8Robert Shih
16679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        case VIDEO_ENCODER_HEVC:
16689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            format->setString("mime", MEDIA_MIMETYPE_VIDEO_HEVC);
16699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            break;
16709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
1671934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        default:
1672934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            CHECK(!"Should not be here, unsupported video encoding.");
1673934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            break;
1674934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    }
1675ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
167635cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    // log video mime type for media metrics
167735cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    if (mAnalyticsItem != NULL) {
167835cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick        AString videomime;
167935cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick        if (format->findString("mime", &videomime)) {
168035cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick            mAnalyticsItem->setCString(kRecorderVideoMime, videomime.c_str());
168135cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick        }
168235cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    }
168335cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick
168472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (cameraSource != NULL) {
168572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<MetaData> meta = cameraSource->getFormat();
168630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
168772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        int32_t width, height, stride, sliceHeight, colorFormat;
168872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(meta->findInt32(kKeyWidth, &width));
168972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(meta->findInt32(kKeyHeight, &height));
169072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(meta->findInt32(kKeyStride, &stride));
169172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight));
169272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));
169372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
169472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("width", width);
169572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("height", height);
169672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("stride", stride);
169772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("slice-height", sliceHeight);
169872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("color-format", colorFormat);
169972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    } else {
170072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("width", mVideoWidth);
170172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("height", mVideoHeight);
170272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("stride", mVideoWidth);
1703e62ba9cce4631737e38db1b0d8a7a64ee81cc397xrwu        format->setInt32("slice-height", mVideoHeight);
170472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("color-format", OMX_COLOR_FormatAndroidOpaque);
17052c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang
17062c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang        // set up time lapse/slow motion for surface source
170746d26dd29195450db15704e84d65740628a821fbChong Zhang        if (mCaptureFpsEnable) {
170822dc508717c7767927064ec7c152def99e54adcbPawin Vongmasa            if (!(mCaptureFps > 0.)) {
170922dc508717c7767927064ec7c152def99e54adcbPawin Vongmasa                ALOGE("Invalid mCaptureFps value: %lf", mCaptureFps);
17102c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang                return BAD_VALUE;
17112c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang            }
171222dc508717c7767927064ec7c152def99e54adcbPawin Vongmasa            format->setDouble("time-lapse-fps", mCaptureFps);
17132c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang        }
171472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
171572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
171672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    format->setInt32("bitrate", mVideoBitRate);
171772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    format->setInt32("frame-rate", mFrameRate);
171872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    format->setInt32("i-frame-interval", mIFramesIntervalSec);
171930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1720c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mVideoTimeScale > 0) {
172172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("time-scale", mVideoTimeScale);
1722c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1723145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    if (mVideoEncoderProfile != -1) {
172472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("profile", mVideoEncoderProfile);
1725145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    }
1726145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    if (mVideoEncoderLevel != -1) {
172772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        format->setInt32("level", mVideoEncoderLevel);
1728145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    }
172930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
17302da225766572a3d4746b4e21cb231a0243b114abLajos Molnar    uint32_t tsLayers = 1;
1731e19f2956de379b9c9a852d50d83d0608ca42bfe9Lajos Molnar    bool preferBFrames = true; // we like B-frames as it produces better quality per bitrate
1732fdbc1b3a885f1e8a59b1788e48e24ea4c66acbc8Ronghua Wu    format->setInt32("priority", 0 /* realtime */);
17332da225766572a3d4746b4e21cb231a0243b114abLajos Molnar    float maxPlaybackFps = mFrameRate; // assume video is only played back at normal speed
17342da225766572a3d4746b4e21cb231a0243b114abLajos Molnar
173546d26dd29195450db15704e84d65740628a821fbChong Zhang    if (mCaptureFpsEnable) {
1736fdbc1b3a885f1e8a59b1788e48e24ea4c66acbc8Ronghua Wu        format->setFloat("operating-rate", mCaptureFps);
1737c96cfbe66d7bf261c57ff93984bc6a4b3a58f6fcLajos Molnar
1738c96cfbe66d7bf261c57ff93984bc6a4b3a58f6fcLajos Molnar        // enable layering for all time lapse and high frame rate recordings
17392da225766572a3d4746b4e21cb231a0243b114abLajos Molnar        if (mFrameRate / mCaptureFps >= 1.9) { // time lapse
1740e19f2956de379b9c9a852d50d83d0608ca42bfe9Lajos Molnar            preferBFrames = false;
17412da225766572a3d4746b4e21cb231a0243b114abLajos Molnar            tsLayers = 2; // use at least two layers as resulting video will likely be sped up
17422da225766572a3d4746b4e21cb231a0243b114abLajos Molnar        } else if (mCaptureFps > maxPlaybackFps) { // slow-mo
17432da225766572a3d4746b4e21cb231a0243b114abLajos Molnar            maxPlaybackFps = mCaptureFps; // assume video will be played back at full capture speed
1744e19f2956de379b9c9a852d50d83d0608ca42bfe9Lajos Molnar            preferBFrames = false;
17452da225766572a3d4746b4e21cb231a0243b114abLajos Molnar        }
17462da225766572a3d4746b4e21cb231a0243b114abLajos Molnar    }
1747c96cfbe66d7bf261c57ff93984bc6a4b3a58f6fcLajos Molnar
17482da225766572a3d4746b4e21cb231a0243b114abLajos Molnar    for (uint32_t tryLayers = 1; tryLayers <= kMaxNumVideoTemporalLayers; ++tryLayers) {
17492da225766572a3d4746b4e21cb231a0243b114abLajos Molnar        if (tryLayers > tsLayers) {
17502da225766572a3d4746b4e21cb231a0243b114abLajos Molnar            tsLayers = tryLayers;
1751c96cfbe66d7bf261c57ff93984bc6a4b3a58f6fcLajos Molnar        }
17522da225766572a3d4746b4e21cb231a0243b114abLajos Molnar        // keep going until the base layer fps falls below the typical display refresh rate
17532da225766572a3d4746b4e21cb231a0243b114abLajos Molnar        float baseLayerFps = maxPlaybackFps / (1 << (tryLayers - 1));
17542da225766572a3d4746b4e21cb231a0243b114abLajos Molnar        if (baseLayerFps < kMinTypicalDisplayRefreshingRate / 0.9) {
17552da225766572a3d4746b4e21cb231a0243b114abLajos Molnar            break;
17562da225766572a3d4746b4e21cb231a0243b114abLajos Molnar        }
17572da225766572a3d4746b4e21cb231a0243b114abLajos Molnar    }
17582da225766572a3d4746b4e21cb231a0243b114abLajos Molnar
17592da225766572a3d4746b4e21cb231a0243b114abLajos Molnar    if (tsLayers > 1) {
17602da225766572a3d4746b4e21cb231a0243b114abLajos Molnar        uint32_t bLayers = std::min(2u, tsLayers - 1); // use up-to 2 B-layers
17612da225766572a3d4746b4e21cb231a0243b114abLajos Molnar        uint32_t pLayers = tsLayers - bLayers;
17622da225766572a3d4746b4e21cb231a0243b114abLajos Molnar        format->setString(
17632da225766572a3d4746b4e21cb231a0243b114abLajos Molnar                "ts-schema", AStringPrintf("android.generic.%u+%u", pLayers, bLayers));
1764e19f2956de379b9c9a852d50d83d0608ca42bfe9Lajos Molnar
1765e19f2956de379b9c9a852d50d83d0608ca42bfe9Lajos Molnar        // TODO: some encoders do not support B-frames with temporal layering, and we have a
1766e19f2956de379b9c9a852d50d83d0608ca42bfe9Lajos Molnar        // different preference based on use-case. We could move this into camera profiles.
1767e19f2956de379b9c9a852d50d83d0608ca42bfe9Lajos Molnar        format->setInt32("android._prefer-b-frames", preferBFrames);
1768fdbc1b3a885f1e8a59b1788e48e24ea4c66acbc8Ronghua Wu    }
1769fdbc1b3a885f1e8a59b1788e48e24ea4c66acbc8Ronghua Wu
17703e328782f1e1061d08ea0c45b855cc418a2d9ea6Lajos Molnar    if (mMetaDataStoredInVideoBuffers != kMetadataBufferTypeInvalid) {
17713e328782f1e1061d08ea0c45b855cc418a2d9ea6Lajos Molnar        format->setInt32("android._input-metadata-buffer-type", mMetaDataStoredInVideoBuffers);
17728480835b4bc1350646376aa7f3ae33742a7adeb1James Dong    }
17737757f5010a771fb8824b6fdf9788f588a1577e3fJames Dong
17743e328782f1e1061d08ea0c45b855cc418a2d9ea6Lajos Molnar    uint32_t flags = 0;
177572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (cameraSource == NULL) {
177672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        flags |= MediaCodecSource::FLAG_USE_SURFACE_INPUT;
1777b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar    } else {
1778b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar        // require dataspace setup even if not using surface input
1779b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar        format->setInt32("android._using-recorder", 1);
17807757f5010a771fb8824b6fdf9788f588a1577e3fJames Dong    }
17817757f5010a771fb8824b6fdf9788f588a1577e3fJames Dong
1782e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang    sp<MediaCodecSource> encoder = MediaCodecSource::Create(
1783e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            mLooper, format, cameraSource, mPersistentSurface, flags);
1784934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    if (encoder == NULL) {
1785ef0cf50343f8a6d74894f96f5ecb5eec4c5f1bc6Chong Zhang        ALOGE("Failed to create video encoder");
17861cc73922339a110d7ffc47e8842f958492dd85bfJames Dong        // When the encoder fails to be created, we need
17871cc73922339a110d7ffc47e8842f958492dd85bfJames Dong        // release the camera source due to the camera's lock
17881cc73922339a110d7ffc47e8842f958492dd85bfJames Dong        // and unlock mechanism.
178972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (cameraSource != NULL) {
179072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            cameraSource->stop();
179172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
1792934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return UNKNOWN_ERROR;
1793934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    }
179430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
179572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (cameraSource == NULL) {
179672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mGraphicBufferProducer = encoder->getGraphicBufferProducer();
179772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
179872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
179939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    *source = encoder;
180039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
1801934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    return OK;
1802934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong}
180330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1804934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dongstatus_t StagefrightRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) {
180542dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    status_t status = BAD_VALUE;
180642dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    if (OK != (status = checkAudioEncoderCapabilities())) {
180742dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong        return status;
180842dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong    }
180942dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
1810934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    switch(mAudioEncoder) {
1811934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        case AUDIO_ENCODER_AMR_NB:
1812934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        case AUDIO_ENCODER_AMR_WB:
1813934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        case AUDIO_ENCODER_AAC:
1814f60c660f048d5f5e2458cff243c20400d73757a7Dave Burke        case AUDIO_ENCODER_HE_AAC:
1815aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        case AUDIO_ENCODER_AAC_ELD:
1816934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            break;
181742dd1d5f186252a7f09f8fb1a46ea82e3877b2d3James Dong
1818934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        default:
181929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unsupported audio encoder: %d", mAudioEncoder);
1820934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            return UNKNOWN_ERROR;
1821934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    }
182230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1823d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    sp<MediaCodecSource> audioEncoder = createAudioSource();
1824934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    if (audioEncoder == NULL) {
1825934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return UNKNOWN_ERROR;
1826934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    }
18278f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
1828934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    writer->addSource(audioEncoder);
1829d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    mAudioEncoderSource = audioEncoder;
1830934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    return OK;
1831934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong}
183230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1833114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shihstatus_t StagefrightRecorder::setupMPEG4orWEBMRecording() {
18344db37cedd4db8230f3ec6191d8d7ba2b0036886eRobert Shih    mWriter.clear();
183572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mTotalBitRate = 0;
183672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
1837934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    status_t err = OK;
1838114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih    sp<MediaWriter> writer;
1839e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    sp<MPEG4Writer> mp4writer;
184068e97e7388bc9efa03e56c999645002cc3f38df5Robert Shih    if (mOutputFormat == OUTPUT_FORMAT_WEBM) {
1841114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        writer = new WebmWriter(mOutputFd);
184268e97e7388bc9efa03e56c999645002cc3f38df5Robert Shih    } else {
1843e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writer = mp4writer = new MPEG4Writer(mOutputFd);
1844114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih    }
184530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1846b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi    if (mVideoSource < VIDEO_SOURCE_LIST_END) {
184754ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang        setDefaultVideoEncoderIfNecessary();
18489c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra
1849b33f3407bab0970a7f9241680723a1140b177c50Pannag Sanketi        sp<MediaSource> mediaSource;
18503cecf640c4daf2df616b278bd9986018c8182908James Dong        err = setupMediaSource(&mediaSource);
18519c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra        if (err != OK) {
18529c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra            return err;
18539c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra        }
18549c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra
1855d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        sp<MediaCodecSource> encoder;
18564db37cedd4db8230f3ec6191d8d7ba2b0036886eRobert Shih        err = setupVideoEncoder(mediaSource, &encoder);
18579c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra        if (err != OK) {
18589c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra            return err;
18599c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra        }
18609c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra
186139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        writer->addSource(encoder);
1862d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        mVideoEncoderSource = encoder;
186372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mTotalBitRate += mVideoBitRate;
186430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    }
186530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
186668e97e7388bc9efa03e56c999645002cc3f38df5Robert Shih    if (mOutputFormat != OUTPUT_FORMAT_WEBM) {
1867114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        // Audio source is added at the end if it exists.
1868114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        // This help make sure that the "recoding" sound is suppressed for
1869114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        // camcorder applications in the recorded files.
1870114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        // TODO Audio source is currently unsupported for webm output; vorbis encoder needed.
187146d26dd29195450db15704e84d65740628a821fbChong Zhang        // disable audio for time lapse recording
187246d26dd29195450db15704e84d65740628a821fbChong Zhang        bool disableAudio = mCaptureFpsEnable && mCaptureFps < mFrameRate;
187346d26dd29195450db15704e84d65740628a821fbChong Zhang        if (!disableAudio && mAudioSource != AUDIO_SOURCE_CNT) {
1874114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih            err = setupAudioEncoder(writer);
1875114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih            if (err != OK) return err;
1876114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih            mTotalBitRate += mAudioBitRate;
1877114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        }
18787bd460110b27a979384dda351788eac95d8467f5James Dong
187946d26dd29195450db15704e84d65740628a821fbChong Zhang        if (mCaptureFpsEnable) {
18809ee53a49860e91c2b012883eef09d669a7829e06Chong Zhang            mp4writer->setCaptureRate(mCaptureFps);
1881e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        }
1882e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
1883114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        if (mInterleaveDurationUs > 0) {
1884e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            mp4writer->setInterleaveDuration(mInterleaveDurationUs);
1885114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        }
1886114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        if (mLongitudex10000 > -3600000 && mLatitudex10000 > -3600000) {
1887e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            mp4writer->setGeoData(mLatitudex10000, mLongitudex10000);
1888114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        }
188907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
1890d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationUs != 0) {
1891934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        writer->setMaxFileDuration(mMaxFileDurationUs);
1892d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1893d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeBytes != 0) {
1894934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        writer->setMaxFileSize(mMaxFileSizeBytes);
1895d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
189672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mVideoSource == VIDEO_SOURCE_DEFAULT
189772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            || mVideoSource == VIDEO_SOURCE_CAMERA) {
189872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStartTimeOffsetMs = mEncoderProfiles->getStartTimeOffsetMs(mCameraId);
189972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    } else if (mVideoSource == VIDEO_SOURCE_SURFACE) {
190072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // surface source doesn't need large initial delay
19013a5d1e8f18f1ec62962fb0e35eab473a6176d004Hangyu Kuang        mStartTimeOffsetMs = 100;
190272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
190386b7f47aa7482424cf8fd248f1315311919be3b0James Dong    if (mStartTimeOffsetMs > 0) {
1904114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        writer->setStartTimeOffsetMs(mStartTimeOffsetMs);
190586b7f47aa7482424cf8fd248f1315311919be3b0James Dong    }
190686b7f47aa7482424cf8fd248f1315311919be3b0James Dong
19079c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra    writer->setListener(mListener);
19084db37cedd4db8230f3ec6191d8d7ba2b0036886eRobert Shih    mWriter = writer;
19099c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra    return OK;
19109c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra}
19119c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra
1912114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shihvoid StagefrightRecorder::setupMPEG4orWEBMMetaData(sp<MetaData> *meta) {
191372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    int64_t startTimeUs = systemTime() / 1000;
19149c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra    (*meta)->setInt64(kKeyTime, startTimeUs);
19159c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra    (*meta)->setInt32(kKeyFileType, mOutputFormat);
191672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    (*meta)->setInt32(kKeyBitRate, mTotalBitRate);
1917c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMovieTimeScale > 0) {
19189c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra        (*meta)->setInt32(kKeyTimeScale, mMovieTimeScale);
1919c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
192068e97e7388bc9efa03e56c999645002cc3f38df5Robert Shih    if (mOutputFormat != OUTPUT_FORMAT_WEBM) {
1921114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        (*meta)->setInt32(kKey64BitFileOffset, mUse64BitFileOffset);
1922114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        if (mTrackEveryTimeDurationUs > 0) {
1923114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih            (*meta)->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs);
1924114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        }
1925114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        if (mRotationDegrees != 0) {
1926114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih            (*meta)->setInt32(kKeyRotation, mRotationDegrees);
1927114819633470ebd5b346c13c2a82a0025d2d39c0Robert Shih        }
192813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
19299c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra}
19309c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra
1931a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongstatus_t StagefrightRecorder::pause() {
19323856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("pause");
1933d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    if (!mStarted) {
1934d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        return INVALID_OPERATION;
1935a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
19369c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra
1937d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    // Already paused --- no-op.
1938d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    if (mPauseStartTimeUs != 0) {
1939d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        return OK;
1940d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    }
194175b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
1942764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    mPauseStartTimeUs = systemTime() / 1000;
1943764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    sp<MetaData> meta = new MetaData;
1944764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    meta->setInt64(kKeyTime, mPauseStartTimeUs);
1945764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang
194635cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    if (mStartedRecordingUs != 0) {
194735cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick        // should always be true
194835cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick        int64_t recordingUs = mPauseStartTimeUs - mStartedRecordingUs;
194935cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick        mDurationRecordedUs += recordingUs;
195035cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick        mStartedRecordingUs = 0;
195135cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    }
195235cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick
1953d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    if (mAudioEncoderSource != NULL) {
1954d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        mAudioEncoderSource->pause();
1955d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    }
1956d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    if (mVideoEncoderSource != NULL) {
1957764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        mVideoEncoderSource->pause(meta.get());
1958d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    }
195975b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
1960d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    return OK;
1961d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim}
1962d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim
1963d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kimstatus_t StagefrightRecorder::resume() {
1964d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    ALOGV("resume");
1965d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    if (!mStarted) {
1966d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        return INVALID_OPERATION;
1967d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    }
1968d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim
1969d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    // Not paused --- no-op.
1970d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    if (mPauseStartTimeUs == 0) {
1971d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        return OK;
197275b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang    }
197375b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
1974764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    int64_t resumeStartTimeUs = systemTime() / 1000;
1975764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang
1976a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    int64_t bufferStartTimeUs = 0;
1977a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    bool allSourcesStarted = true;
1978a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    for (const auto &source : { mAudioEncoderSource, mVideoEncoderSource }) {
1979a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        if (source == nullptr) {
1980a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            continue;
1981a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        }
1982a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        int64_t timeUs = source->getFirstSampleSystemTimeUs();
1983a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        if (timeUs < 0) {
1984a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            allSourcesStarted = false;
1985a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        }
1986a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        if (bufferStartTimeUs < timeUs) {
1987a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            bufferStartTimeUs = timeUs;
1988a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        }
1989a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    }
1990a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim
1991a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    if (allSourcesStarted) {
1992a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        if (mPauseStartTimeUs < bufferStartTimeUs) {
1993a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            mPauseStartTimeUs = bufferStartTimeUs;
1994a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        }
1995a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        // 30 ms buffer to avoid timestamp overlap
1996764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        mTotalPausedDurationUs += resumeStartTimeUs - mPauseStartTimeUs - 30000;
1997a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    }
19989f5c692300e02f9f1b4e08b238a76f1428c854d3Wonsik Kim    double timeOffset = -mTotalPausedDurationUs;
19999f5c692300e02f9f1b4e08b238a76f1428c854d3Wonsik Kim    if (mCaptureFpsEnable) {
20009f5c692300e02f9f1b4e08b238a76f1428c854d3Wonsik Kim        timeOffset *= mCaptureFps / mFrameRate;
20019f5c692300e02f9f1b4e08b238a76f1428c854d3Wonsik Kim    }
2002764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    sp<MetaData> meta = new MetaData;
2003764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    meta->setInt64(kKeyTime, resumeStartTimeUs);
2004a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    for (const auto &source : { mAudioEncoderSource, mVideoEncoderSource }) {
2005a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        if (source == nullptr) {
2006a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            continue;
2007a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        }
2008a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        source->setInputBufferTimeOffset((int64_t)timeOffset);
2009764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        source->start(meta.get());
2010d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    }
201135cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick
201235cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick
201335cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    // sum info on pause duration
201435cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    // (ignore the 30msec of overlap adjustment factored into mTotalPausedDurationUs)
201535cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    int64_t pausedUs = resumeStartTimeUs - mPauseStartTimeUs;
201635cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    mDurationPausedUs += pausedUs;
201735cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    mNPauses++;
201835cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    // and a timestamp marking that we're back to recording....
201935cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    mStartedRecordingUs = resumeStartTimeUs;
202035cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick
2021d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    mPauseStartTimeUs = 0;
202275b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
2023a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
2024a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
2025a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
202630ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::stop() {
20273856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("stop");
2028fc079f79d8d4f6ef9f138aa615486c10dda99fb7Hangyu Kuang    Mutex::Autolock autolock(mLock);
202937187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
20309c075bca0b75093ca0514a3c8f74d73c8e9e83fdNipun Kwatra
203146d26dd29195450db15704e84d65740628a821fbChong Zhang    if (mCaptureFpsEnable && mCameraSourceTimeLapse != NULL) {
203278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        mCameraSourceTimeLapse->startQuickReadReturns();
203378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        mCameraSourceTimeLapse = NULL;
203478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    }
203578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
2036f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    int64_t stopTimeUs = systemTime() / 1000;
2037f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    for (const auto &source : { mAudioEncoderSource, mVideoEncoderSource }) {
2038f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang        if (source != nullptr && OK != source->setStopTimeUs(stopTimeUs)) {
2039f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang            ALOGW("Failed to set stopTime %lld us for %s",
2040f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang                    (long long)stopTimeUs, source->isVideo() ? "Video" : "Audio");
2041f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang        }
2042764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    }
2043764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang
2044d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (mWriter != NULL) {
204537187916a486504acaf83bea30147eb5fbf46ae5James Dong        err = mWriter->stop();
2046934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        mWriter.clear();
204730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    }
2048ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
204935cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    // account for the last 'segment' -- whether paused or recording
205035cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    if (mPauseStartTimeUs != 0) {
205135cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick        // we were paused
205235cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick        int64_t additive = stopTimeUs - mPauseStartTimeUs;
205335cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick        mDurationPausedUs += additive;
205435cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick        mNPauses++;
205535cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    } else if (mStartedRecordingUs != 0) {
205635cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick        // we were recording
205735cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick        int64_t additive = stopTimeUs - mStartedRecordingUs;
205835cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick        mDurationRecordedUs += additive;
205935cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    } else {
206035cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick        ALOGW("stop while neither recording nor paused");
206135cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    }
206235cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick
206335cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    flushAndResetMetrics(true);
2064ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
206535cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    mDurationRecordedUs = 0;
206635cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    mDurationPausedUs = 0;
206735cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    mNPauses = 0;
2068148c3d67710ca9353f14e5c37a0a38c88d4f0e53Wonsik Kim    mTotalPausedDurationUs = 0;
2069e6cab24fa5857eaf48c957988f153b47a52d1b45Wonsik Kim    mPauseStartTimeUs = 0;
207035cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    mStartedRecordingUs = 0;
207130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
207272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mGraphicBufferProducer.clear();
20738f469e18c307cb9dc0d16ed9225972aa8be4516fChong Zhang    mPersistentSurface.clear();
2074d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    mAudioEncoderSource.clear();
2075d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    mVideoEncoderSource.clear();
207672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
207725d83125cee222993673d3ba261ae1186bcad8c2James Dong    if (mOutputFd >= 0) {
207825d83125cee222993673d3ba261ae1186bcad8c2James Dong        ::close(mOutputFd);
207925d83125cee222993673d3ba261ae1186bcad8c2James Dong        mOutputFd = -1;
208025d83125cee222993673d3ba261ae1186bcad8c2James Dong    }
208125d83125cee222993673d3ba261ae1186bcad8c2James Dong
208275b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang    if (mStarted) {
208375b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        mStarted = false;
208475b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
208575b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        uint32_t params = 0;
2086fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin        if (mAudioSource != AUDIO_SOURCE_CNT) {
208775b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang            params |= IMediaPlayerService::kBatteryDataTrackAudio;
208875b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        }
208975b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        if (mVideoSource != VIDEO_SOURCE_LIST_END) {
209075b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang            params |= IMediaPlayerService::kBatteryDataTrackVideo;
209175b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        }
209275b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
209375b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang        addBatteryData(params);
209475b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang    }
209575b0b5473c7b43f8c5972db7e6e8930988ead751Gloria Wang
209637187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
2097d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong}
2098d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
2099d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dongstatus_t StagefrightRecorder::close() {
21003856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("close");
2101d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    stop();
2102d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
210330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
210430ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
210530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
210630ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::reset() {
21073856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("reset");
210830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    stop();
210930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
2110050b28a593350047845a45a14cc5026221ac1620James Dong    // No audio or video source by default
2111174e1094a41828111c86793232d9492ab8e29395Kevin Rocard    mAudioSource = (audio_source_t)AUDIO_SOURCE_CNT; // reset to invalid value
211230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mVideoSource = VIDEO_SOURCE_LIST_END;
2113050b28a593350047845a45a14cc5026221ac1620James Dong
2114050b28a593350047845a45a14cc5026221ac1620James Dong    // Default parameters
2115050b28a593350047845a45a14cc5026221ac1620James Dong    mOutputFormat  = OUTPUT_FORMAT_THREE_GPP;
2116050b28a593350047845a45a14cc5026221ac1620James Dong    mAudioEncoder  = AUDIO_ENCODER_AMR_NB;
211754ef1bae010f12dfe6a40ff4452695b1b11ff449Chong Zhang    mVideoEncoder  = VIDEO_ENCODER_DEFAULT;
2118050b28a593350047845a45a14cc5026221ac1620James Dong    mVideoWidth    = 176;
2119050b28a593350047845a45a14cc5026221ac1620James Dong    mVideoHeight   = 144;
2120635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong    mFrameRate     = -1;
2121050b28a593350047845a45a14cc5026221ac1620James Dong    mVideoBitRate  = 192000;
2122050b28a593350047845a45a14cc5026221ac1620James Dong    mSampleRate    = 8000;
2123050b28a593350047845a45a14cc5026221ac1620James Dong    mAudioChannels = 1;
2124050b28a593350047845a45a14cc5026221ac1620James Dong    mAudioBitRate  = 12200;
2125e136c3bb38e88315bf8797a464ebf2c788296b22James Dong    mInterleaveDurationUs = 0;
21268f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    mIFramesIntervalSec = 1;
2127d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    mAudioSourceNode = 0;
21282dec2b5be2056c6d9428897dc672185872d30d17James Dong    mUse64BitFileOffset = false;
2129c059860c73678a202bfa33062723e8f82fb779d9James Dong    mMovieTimeScale  = -1;
2130c059860c73678a202bfa33062723e8f82fb779d9James Dong    mAudioTimeScale  = -1;
2131c059860c73678a202bfa33062723e8f82fb779d9James Dong    mVideoTimeScale  = -1;
213293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mCameraId        = 0;
213386b7f47aa7482424cf8fd248f1315311919be3b0James Dong    mStartTimeOffsetMs = -1;
2134145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    mVideoEncoderProfile = -1;
2135145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    mVideoEncoderLevel   = -1;
2136145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    mMaxFileDurationUs = 0;
2137145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    mMaxFileSizeBytes = 0;
213893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
213946d26dd29195450db15704e84d65740628a821fbChong Zhang    mCaptureFpsEnable = false;
214022dc508717c7767927064ec7c152def99e54adcbPawin Vongmasa    mCaptureFps = -1.0;
214178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    mCameraSourceTimeLapse = NULL;
21423e328782f1e1061d08ea0c45b855cc418a2d9ea6Lajos Molnar    mMetaDataStoredInVideoBuffers = kMetadataBufferTypeInvalid;
214399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    mEncoderProfiles = MediaProfiles::getInstance();
214462db7db731c47a00ee1493e94f3e1d953c6e297aJames Dong    mRotationDegrees = 0;
214507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = -3600000;
214607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = -3600000;
214772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mTotalBitRate = 0;
2148050b28a593350047845a45a14cc5026221ac1620James Dong
214935cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    // tracking how long we recorded.
215035cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    mDurationRecordedUs = 0;
215135cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    mStartedRecordingUs = 0;
215235cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    mDurationPausedUs = 0;
215335cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick    mNPauses = 0;
215435cc20b52fdc551b5b0ed1fc32803a56d82e8881Ray Essick
215530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mOutputFd = -1;
215630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
215730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
215830ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
215930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
216030ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::getMaxAmplitude(int *max) {
21613856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getMaxAmplitude");
2162d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
2163d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (max == NULL) {
216429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Null pointer argument");
2165d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        return BAD_VALUE;
2166d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
2167d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
2168d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    if (mAudioSourceNode != 0) {
2169d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        *max = mAudioSourceNode->getMaxAmplitude();
2170d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    } else {
2171d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        *max = 0;
2172d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    }
21732dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
21742dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
217530ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
217630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
2177ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essickstatus_t StagefrightRecorder::getMetrics(Parcel *reply) {
2178ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    ALOGD("StagefrightRecorder::getMetrics");
2179ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
2180ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    if (reply == NULL) {
2181ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        ALOGE("Null pointer argument");
2182ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        return BAD_VALUE;
2183ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    }
2184ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
2185ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    if (mAnalyticsItem == NULL) {
2186ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick        return UNKNOWN_ERROR;
2187ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    }
2188ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
2189ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    updateMetrics();
2190ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    mAnalyticsItem->writeToParcel(reply);
2191ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick    return OK;
2192ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick}
2193ac4e4189db77dc0af7671b162d11be5ccec69339Ray Essick
2194fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabinstatus_t StagefrightRecorder::setInputDevice(audio_port_handle_t deviceId) {
2195fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin    ALOGV("setInputDevice");
2196fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin
2197fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin    if (mSelectedDeviceId != deviceId) {
2198fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin        mSelectedDeviceId = deviceId;
2199fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin        if (mAudioSourceNode != 0) {
2200fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin            return mAudioSourceNode->setInputDevice(deviceId);
2201fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin        }
2202fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin    }
2203fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin    return NO_ERROR;
2204fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin}
2205fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin
2206fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabinstatus_t StagefrightRecorder::getRoutedDeviceId(audio_port_handle_t* deviceId) {
2207fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin    ALOGV("getRoutedDeviceId");
2208fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin
2209fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin    if (mAudioSourceNode != 0) {
2210fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin        status_t status = mAudioSourceNode->getRoutedDeviceId(deviceId);
2211fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin        return status;
2212fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin    }
2213fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin    return NO_INIT;
2214fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin}
2215fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin
2216fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabinvoid StagefrightRecorder::setAudioDeviceCallback(
2217fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin        const sp<AudioSystem::AudioDeviceCallback>& callback) {
2218fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin    mAudioDeviceCallback = callback;
2219fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin}
2220fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin
2221fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabinstatus_t StagefrightRecorder::enableAudioDeviceCallback(bool enabled) {
2222fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin    mDeviceCallbackEnabled = enabled;
2223fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin    sp<AudioSystem::AudioDeviceCallback> callback = mAudioDeviceCallback.promote();
2224fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin    if (mAudioSourceNode != 0 && callback != 0) {
2225fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin        if (enabled) {
2226fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin            return mAudioSourceNode->addAudioDeviceCallback(callback);
2227fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin        } else {
2228fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin            return mAudioSourceNode->removeAudioDeviceCallback(callback);
2229fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin        }
2230fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin    }
2231fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin    return NO_ERROR;
2232fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin}
2233fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin
2234609850df59219845a8c4ebe18a2687447ea570ccjiabinstatus_t StagefrightRecorder::getActiveMicrophones(
2235609850df59219845a8c4ebe18a2687447ea570ccjiabin        std::vector<media::MicrophoneInfo>* activeMicrophones) {
2236609850df59219845a8c4ebe18a2687447ea570ccjiabin    if (mAudioSourceNode != 0) {
2237609850df59219845a8c4ebe18a2687447ea570ccjiabin        return mAudioSourceNode->getActiveMicrophones(activeMicrophones);
2238609850df59219845a8c4ebe18a2687447ea570ccjiabin    }
2239609850df59219845a8c4ebe18a2687447ea570ccjiabin    return NO_INIT;
2240609850df59219845a8c4ebe18a2687447ea570ccjiabin}
2241609850df59219845a8c4ebe18a2687447ea570ccjiabin
2242609850df59219845a8c4ebe18a2687447ea570ccjiabin
2243dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t StagefrightRecorder::dump(
2244dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) const {
22453856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("dump");
2246fc079f79d8d4f6ef9f138aa615486c10dda99fb7Hangyu Kuang    Mutex::Autolock autolock(mLock);
2247b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    const size_t SIZE = 256;
2248b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    char buffer[SIZE];
2249b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    String8 result;
2250dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    if (mWriter != 0) {
2251dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        mWriter->dump(fd, args);
2252dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    } else {
2253dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        snprintf(buffer, SIZE, "   No file writer\n");
2254dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        result.append(buffer);
2255dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
2256dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   Recorder: %p\n", this);
2257b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "   Output file (fd %d):\n", mOutputFd);
2258b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2259b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     File format: %d\n", mOutputFormat);
2260b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2261377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    snprintf(buffer, SIZE, "     Max file size (bytes): %" PRId64 "\n", mMaxFileSizeBytes);
2262b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2263377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    snprintf(buffer, SIZE, "     Max file duration (us): %" PRId64 "\n", mMaxFileDurationUs);
2264b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2265b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     File offset length (bits): %d\n", mUse64BitFileOffset? 64: 32);
2266b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2267b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Interleave duration (us): %d\n", mInterleaveDurationUs);
2268b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2269377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    snprintf(buffer, SIZE, "     Progress notification: %" PRId64 " us\n", mTrackEveryTimeDurationUs);
2270b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2271b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "   Audio\n");
2272b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2273b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Source: %d\n", mAudioSource);
2274b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2275b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Encoder: %d\n", mAudioEncoder);
2276b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2277b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Bit rate (bps): %d\n", mAudioBitRate);
2278b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2279b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Sampling rate (hz): %d\n", mSampleRate);
2280b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2281b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Number of channels: %d\n", mAudioChannels);
2282b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2283b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Max amplitude: %d\n", mAudioSourceNode == 0? 0: mAudioSourceNode->getMaxAmplitude());
2284b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2285b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "   Video\n");
2286b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2287b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Source: %d\n", mVideoSource);
2288b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2289b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Camera Id: %d\n", mCameraId);
2290b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
229186b7f47aa7482424cf8fd248f1315311919be3b0James Dong    snprintf(buffer, SIZE, "     Start time offset (ms): %d\n", mStartTimeOffsetMs);
229286b7f47aa7482424cf8fd248f1315311919be3b0James Dong    result.append(buffer);
2293b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Encoder: %d\n", mVideoEncoder);
2294b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2295b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Encoder profile: %d\n", mVideoEncoderProfile);
2296b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2297b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Encoder level: %d\n", mVideoEncoderLevel);
2298b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
22998f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    snprintf(buffer, SIZE, "     I frames interval (s): %d\n", mIFramesIntervalSec);
2300b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2301b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Frame size (pixels): %dx%d\n", mVideoWidth, mVideoHeight);
2302b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2303b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Frame rate (fps): %d\n", mFrameRate);
2304b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2305b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Bit rate (bps): %d\n", mVideoBitRate);
2306b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
2307b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    ::write(fd, result.string(), result.size());
2308b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    return OK;
2309b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong}
231030ab66297501757d745b9ae10da61adcd891f497Andreas Huber}  // namespace android
2311