StagefrightRecorder.cpp revision 48f6ce0e17297c575dcbb25671a7bee80ba13061
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"
1930ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <utils/Log.h>
2030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
2130ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include "StagefrightRecorder.h"
2230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
23c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong#include <binder/IPCThreadState.h>
242dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber#include <media/stagefright/AudioSource.h>
252dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber#include <media/stagefright/AMRWriter.h>
2630ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <media/stagefright/CameraSource.h>
2730ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <media/stagefright/MPEG4Writer.h>
2830ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <media/stagefright/MediaDebug.h>
2930ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <media/stagefright/MediaDefs.h>
3030ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <media/stagefright/MetaData.h>
3130ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <media/stagefright/OMXClient.h>
3230ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <media/stagefright/OMXCodec.h>
3399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong#include <media/MediaProfiles.h>
343cf613507f1e2f7bd932d921a6e222e426fd3be4Mathias Agopian#include <camera/ICamera.h>
35c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong#include <camera/Camera.h>
36ef9d0cd72e476a4b7556833fb09505a51b626797James Dong#include <camera/CameraParameters.h>
373cf613507f1e2f7bd932d921a6e222e426fd3be4Mathias Agopian#include <surfaceflinger/ISurface.h>
3830ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <utils/Errors.h>
39c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong#include <sys/types.h>
40c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong#include <unistd.h>
41050b28a593350047845a45a14cc5026221ac1620James Dong#include <ctype.h>
4230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
4330ab66297501757d745b9ae10da61adcd891f497Andreas Hubernamespace android {
4430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
45d329e21495eda9dbc531fdd0c26c77f1593ac3f4James DongStagefrightRecorder::StagefrightRecorder()
46d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    : mWriter(NULL),
47d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong      mOutputFd(-1) {
48d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
49d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    LOGV("Constructor");
5030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    reset();
5130ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
5230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
5330ab66297501757d745b9ae10da61adcd891f497Andreas HuberStagefrightRecorder::~StagefrightRecorder() {
54d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    LOGV("Destructor");
5530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    stop();
5630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
5730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    if (mOutputFd >= 0) {
5830ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ::close(mOutputFd);
5930ab66297501757d745b9ae10da61adcd891f497Andreas Huber        mOutputFd = -1;
6030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    }
6130ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
6230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
6330ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::init() {
64d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    LOGV("init");
6530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
6630ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
6730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
6830ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setAudioSource(audio_source as) {
69d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    LOGV("setAudioSource: %d", as);
70d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (as < AUDIO_SOURCE_DEFAULT ||
71d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        as >= AUDIO_SOURCE_LIST_END) {
72934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        LOGE("Invalid audio source: %d", as);
73d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        return BAD_VALUE;
74d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
75d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
76d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (as == AUDIO_SOURCE_DEFAULT) {
77d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mAudioSource = AUDIO_SOURCE_MIC;
78d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    } else {
79d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mAudioSource = as;
80d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
8130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
8230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
8330ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
8430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
8530ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setVideoSource(video_source vs) {
86d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    LOGV("setVideoSource: %d", vs);
87d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (vs < VIDEO_SOURCE_DEFAULT ||
88d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        vs >= VIDEO_SOURCE_LIST_END) {
89934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        LOGE("Invalid video source: %d", vs);
90d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        return BAD_VALUE;
91d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
92d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
93d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (vs == VIDEO_SOURCE_DEFAULT) {
94d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mVideoSource = VIDEO_SOURCE_CAMERA;
95d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    } else {
96d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mVideoSource = vs;
97d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
9830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
9930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
10030ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
10130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
10230ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setOutputFormat(output_format of) {
103d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    LOGV("setOutputFormat: %d", of);
104d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (of < OUTPUT_FORMAT_DEFAULT ||
105d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        of >= OUTPUT_FORMAT_LIST_END) {
106934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        LOGE("Invalid output format: %d", of);
107d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        return BAD_VALUE;
108d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
109d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
110d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (of == OUTPUT_FORMAT_DEFAULT) {
111d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mOutputFormat = OUTPUT_FORMAT_THREE_GPP;
112d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    } else {
113d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mOutputFormat = of;
114d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
11530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
11630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
11730ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
11830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
11930ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setAudioEncoder(audio_encoder ae) {
120d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    LOGV("setAudioEncoder: %d", ae);
121d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (ae < AUDIO_ENCODER_DEFAULT ||
122d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        ae >= AUDIO_ENCODER_LIST_END) {
123934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        LOGE("Invalid audio encoder: %d", ae);
124d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        return BAD_VALUE;
125d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
126d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
127d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (ae == AUDIO_ENCODER_DEFAULT) {
128d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mAudioEncoder = AUDIO_ENCODER_AMR_NB;
129d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    } else {
130d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mAudioEncoder = ae;
131d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
13230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
13330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
13430ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
13530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
13630ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setVideoEncoder(video_encoder ve) {
137d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    LOGV("setVideoEncoder: %d", ve);
138d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (ve < VIDEO_ENCODER_DEFAULT ||
139d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        ve >= VIDEO_ENCODER_LIST_END) {
140934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        LOGE("Invalid video encoder: %d", ve);
141d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        return BAD_VALUE;
142d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
143d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
144d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (ve == VIDEO_ENCODER_DEFAULT) {
145d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mVideoEncoder = VIDEO_ENCODER_H263;
146d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    } else {
147d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mVideoEncoder = ve;
148d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
14930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
15030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
15130ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
15230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
15330ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setVideoSize(int width, int height) {
154d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    LOGV("setVideoSize: %dx%d", width, height);
155ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (width <= 0 || height <= 0) {
156ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        LOGE("Invalid video size: %dx%d", width, height);
157ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        return BAD_VALUE;
158ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
159ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
160ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // Additional check on the dimension will be performed later
16130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mVideoWidth = width;
16230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mVideoHeight = height;
16330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
16430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
16530ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
16630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
16730ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setVideoFrameRate(int frames_per_second) {
168d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    LOGV("setVideoFrameRate: %d", frames_per_second);
169ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (frames_per_second <= 0 || frames_per_second > 30) {
170ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        LOGE("Invalid video frame rate: %d", frames_per_second);
171ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        return BAD_VALUE;
172ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
173ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
174ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // Additional check on the frame rate will be performed later
17530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mFrameRate = frames_per_second;
17630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
17730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
17830ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
17930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
18030ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) {
1819d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong    LOGV("setCamera");
182c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    if (camera == 0) {
183c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        LOGE("camera is NULL");
184934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return BAD_VALUE;
185c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
186c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong
1879d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong    int64_t token = IPCThreadState::self()->clearCallingIdentity();
1889d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong    mFlags &= ~FLAGS_HOT_CAMERA;
189c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    mCamera = Camera::create(camera);
190c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    if (mCamera == 0) {
191c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        LOGE("Unable to connect to camera");
1929d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong        IPCThreadState::self()->restoreCallingIdentity(token);
193934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return -EBUSY;
194c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
195c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong
196c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    LOGV("Connected to camera");
197c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    if (mCamera->previewEnabled()) {
198c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        LOGV("camera is hot");
199c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        mFlags |= FLAGS_HOT_CAMERA;
200c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
2019d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong    IPCThreadState::self()->restoreCallingIdentity(token);
20230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
20330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
20430ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
20530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
20630ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setPreviewSurface(const sp<ISurface> &surface) {
207d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    LOGV("setPreviewSurface: %p", surface.get());
20830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mPreviewSurface = surface;
20930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
21030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
21130ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
21230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
21330ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setOutputFile(const char *path) {
214934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    LOGE("setOutputFile(const char*) must not be called");
21530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    // We don't actually support this at all, as the media_server process
21630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    // no longer has permissions to create files.
21730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
218934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    return -EPERM;
21930ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
22030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
22130ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t length) {
222d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    LOGV("setOutputFile: %d, %lld, %lld", fd, offset, length);
22330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    // These don't make any sense, do they?
22430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    CHECK_EQ(offset, 0);
22530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    CHECK_EQ(length, 0);
22630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
227934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    if (fd < 0) {
228934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        LOGE("Invalid file descriptor: %d", fd);
229934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return -EBADF;
230934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    }
231934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong
23230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    if (mOutputFd >= 0) {
23330ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ::close(mOutputFd);
23430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    }
23530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mOutputFd = dup(fd);
23630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
23730ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
23830ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
23930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
240050b28a593350047845a45a14cc5026221ac1620James Dong// Attempt to parse an int64 literal optionally surrounded by whitespace,
241050b28a593350047845a45a14cc5026221ac1620James Dong// returns true on success, false otherwise.
242ef9d0cd72e476a4b7556833fb09505a51b626797James Dongstatic bool safe_strtoi64(const char *s, int64_t *val) {
243050b28a593350047845a45a14cc5026221ac1620James Dong    char *end;
244ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    *val = strtoll(s, &end, 10);
245050b28a593350047845a45a14cc5026221ac1620James Dong
246050b28a593350047845a45a14cc5026221ac1620James Dong    if (end == s || errno == ERANGE) {
247050b28a593350047845a45a14cc5026221ac1620James Dong        return false;
248050b28a593350047845a45a14cc5026221ac1620James Dong    }
249050b28a593350047845a45a14cc5026221ac1620James Dong
250050b28a593350047845a45a14cc5026221ac1620James Dong    // Skip trailing whitespace
251050b28a593350047845a45a14cc5026221ac1620James Dong    while (isspace(*end)) {
252050b28a593350047845a45a14cc5026221ac1620James Dong        ++end;
253050b28a593350047845a45a14cc5026221ac1620James Dong    }
254050b28a593350047845a45a14cc5026221ac1620James Dong
255050b28a593350047845a45a14cc5026221ac1620James Dong    // For a successful return, the string must contain nothing but a valid
256050b28a593350047845a45a14cc5026221ac1620James Dong    // int64 literal optionally surrounded by whitespace.
257050b28a593350047845a45a14cc5026221ac1620James Dong
258050b28a593350047845a45a14cc5026221ac1620James Dong    return *end == '\0';
259050b28a593350047845a45a14cc5026221ac1620James Dong}
260050b28a593350047845a45a14cc5026221ac1620James Dong
261ef9d0cd72e476a4b7556833fb09505a51b626797James Dong// Return true if the value is in [0, 0x007FFFFFFF]
262ef9d0cd72e476a4b7556833fb09505a51b626797James Dongstatic bool safe_strtoi32(const char *s, int32_t *val) {
263ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    int64_t temp;
264ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (safe_strtoi64(s, &temp)) {
265ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (temp >= 0 && temp <= 0x007FFFFFFF) {
266ef9d0cd72e476a4b7556833fb09505a51b626797James Dong            *val = static_cast<int32_t>(temp);
267ef9d0cd72e476a4b7556833fb09505a51b626797James Dong            return true;
268ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        }
269ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
270ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    return false;
271ef9d0cd72e476a4b7556833fb09505a51b626797James Dong}
272ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
273050b28a593350047845a45a14cc5026221ac1620James Dong// Trim both leading and trailing whitespace from the given string.
274050b28a593350047845a45a14cc5026221ac1620James Dongstatic void TrimString(String8 *s) {
275050b28a593350047845a45a14cc5026221ac1620James Dong    size_t num_bytes = s->bytes();
276050b28a593350047845a45a14cc5026221ac1620James Dong    const char *data = s->string();
277050b28a593350047845a45a14cc5026221ac1620James Dong
278050b28a593350047845a45a14cc5026221ac1620James Dong    size_t leading_space = 0;
279050b28a593350047845a45a14cc5026221ac1620James Dong    while (leading_space < num_bytes && isspace(data[leading_space])) {
280050b28a593350047845a45a14cc5026221ac1620James Dong        ++leading_space;
281050b28a593350047845a45a14cc5026221ac1620James Dong    }
282050b28a593350047845a45a14cc5026221ac1620James Dong
283050b28a593350047845a45a14cc5026221ac1620James Dong    size_t i = num_bytes;
284050b28a593350047845a45a14cc5026221ac1620James Dong    while (i > leading_space && isspace(data[i - 1])) {
285050b28a593350047845a45a14cc5026221ac1620James Dong        --i;
286050b28a593350047845a45a14cc5026221ac1620James Dong    }
287050b28a593350047845a45a14cc5026221ac1620James Dong
288050b28a593350047845a45a14cc5026221ac1620James Dong    s->setTo(String8(&data[leading_space], i - leading_space));
289050b28a593350047845a45a14cc5026221ac1620James Dong}
290050b28a593350047845a45a14cc5026221ac1620James Dong
291050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParamAudioSamplingRate(int32_t sampleRate) {
292050b28a593350047845a45a14cc5026221ac1620James Dong    LOGV("setParamAudioSamplingRate: %d", sampleRate);
293ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (sampleRate <= 0) {
294ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        LOGE("Invalid audio sampling rate: %d", sampleRate);
295ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        return BAD_VALUE;
296ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
297ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
298ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // Additional check on the sample rate will be performed later.
299050b28a593350047845a45a14cc5026221ac1620James Dong    mSampleRate = sampleRate;
300050b28a593350047845a45a14cc5026221ac1620James Dong    return OK;
301050b28a593350047845a45a14cc5026221ac1620James Dong}
302050b28a593350047845a45a14cc5026221ac1620James Dong
303050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) {
304050b28a593350047845a45a14cc5026221ac1620James Dong    LOGV("setParamAudioNumberOfChannels: %d", channels);
305ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (channels <= 0 || channels >= 3) {
306ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        LOGE("Invalid number of audio channels: %d", channels);
307934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return BAD_VALUE;
308ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
309ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
310ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // Additional check on the number of channels will be performed later.
311050b28a593350047845a45a14cc5026221ac1620James Dong    mAudioChannels = channels;
312050b28a593350047845a45a14cc5026221ac1620James Dong    return OK;
313050b28a593350047845a45a14cc5026221ac1620James Dong}
314050b28a593350047845a45a14cc5026221ac1620James Dong
315050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParamAudioEncodingBitRate(int32_t bitRate) {
316050b28a593350047845a45a14cc5026221ac1620James Dong    LOGV("setParamAudioEncodingBitRate: %d", bitRate);
317ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (bitRate <= 0) {
318ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        LOGE("Invalid audio encoding bit rate: %d", bitRate);
319ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        return BAD_VALUE;
320ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
321ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
322ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // The target bit rate may not be exactly the same as the requested.
323ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // It depends on many factors, such as rate control, and the bit rate
324ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // range that a specific encoder supports. The mismatch between the
325ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // the target and requested bit rate will NOT be treated as an error.
326050b28a593350047845a45a14cc5026221ac1620James Dong    mAudioBitRate = bitRate;
327050b28a593350047845a45a14cc5026221ac1620James Dong    return OK;
328050b28a593350047845a45a14cc5026221ac1620James Dong}
329050b28a593350047845a45a14cc5026221ac1620James Dong
330050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) {
331050b28a593350047845a45a14cc5026221ac1620James Dong    LOGV("setParamVideoEncodingBitRate: %d", bitRate);
332ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (bitRate <= 0) {
333ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        LOGE("Invalid video encoding bit rate: %d", bitRate);
334ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        return BAD_VALUE;
335ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
336ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
337ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // The target bit rate may not be exactly the same as the requested.
338ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // It depends on many factors, such as rate control, and the bit rate
339ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // range that a specific encoder supports. The mismatch between the
340ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    // the target and requested bit rate will NOT be treated as an error.
341050b28a593350047845a45a14cc5026221ac1620James Dong    mVideoBitRate = bitRate;
342050b28a593350047845a45a14cc5026221ac1620James Dong    return OK;
343050b28a593350047845a45a14cc5026221ac1620James Dong}
344050b28a593350047845a45a14cc5026221ac1620James Dong
345934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dongstatus_t StagefrightRecorder::setParamMaxFileDurationUs(int64_t timeUs) {
346934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    LOGV("setParamMaxFileDurationUs: %lld us", timeUs);
347e4fc55de48241c5fb4c4b9d652fd2d4cd0b71138James Dong    if (timeUs <= 100000LL) {  // XXX: 100 milli-seconds
348934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        LOGE("Max file duration is too short: %lld us", timeUs);
349934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return BAD_VALUE;
350ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
351934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    mMaxFileDurationUs = timeUs;
352934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    return OK;
353934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong}
354934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong
355934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dongstatus_t StagefrightRecorder::setParamMaxFileSizeBytes(int64_t bytes) {
356934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    LOGV("setParamMaxFileSizeBytes: %lld bytes", bytes);
357934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    if (bytes <= 1024) {  // XXX: 1 kB
358934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        LOGE("Max file size is too small: %lld bytes", bytes);
359934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return BAD_VALUE;
360934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    }
361934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    mMaxFileSizeBytes = bytes;
362050b28a593350047845a45a14cc5026221ac1620James Dong    return OK;
363050b28a593350047845a45a14cc5026221ac1620James Dong}
364050b28a593350047845a45a14cc5026221ac1620James Dong
36513aec890216948b0c364f8f92792129d0335f506James Dongstatus_t StagefrightRecorder::setParamInterleaveDuration(int32_t durationUs) {
36613aec890216948b0c364f8f92792129d0335f506James Dong    LOGV("setParamInterleaveDuration: %d", durationUs);
367ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    if (durationUs <= 500000) {           //  500 ms
368ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        // If interleave duration is too small, it is very inefficient to do
369ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        // interleaving since the metadata overhead will count for a significant
370ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        // portion of the saved contents
371ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        LOGE("Audio/video interleave duration is too small: %d us", durationUs);
372ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        return BAD_VALUE;
373ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    } else if (durationUs >= 10000000) {  // 10 seconds
374ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        // If interleaving duration is too large, it can cause the recording
375ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        // session to use too much memory since we have to save the output
376ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        // data before we write them out
377ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        LOGE("Audio/video interleave duration is too large: %d us", durationUs);
378ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        return BAD_VALUE;
379ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
38013aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
38113aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
38213aec890216948b0c364f8f92792129d0335f506James Dong}
383ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
3848f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong// If seconds <  0, only the first frame is I frame, and rest are all P frames
3858f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong// If seconds == 0, all frames are encoded as I frames. No P frames
3868f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong// If seconds >  0, it is the time spacing (seconds) between 2 neighboring I frames
3878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dongstatus_t StagefrightRecorder::setParamVideoIFramesInterval(int32_t seconds) {
3888f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    LOGV("setParamVideoIFramesInterval: %d seconds", seconds);
3898f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    mIFramesIntervalSec = seconds;
390ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    return OK;
391ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong}
392ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong
3932dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t StagefrightRecorder::setParam64BitFileOffset(bool use64Bit) {
3942dec2b5be2056c6d9428897dc672185872d30d17James Dong    LOGV("setParam64BitFileOffset: %s",
3952dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64Bit? "use 64 bit file offset": "use 32 bit file offset");
3962dec2b5be2056c6d9428897dc672185872d30d17James Dong    mUse64BitFileOffset = use64Bit;
3972dec2b5be2056c6d9428897dc672185872d30d17James Dong    return OK;
3982dec2b5be2056c6d9428897dc672185872d30d17James Dong}
3992dec2b5be2056c6d9428897dc672185872d30d17James Dong
40093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t StagefrightRecorder::setParamVideoCameraId(int32_t cameraId) {
40193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    LOGV("setParamVideoCameraId: %d", cameraId);
40293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    if (cameraId < 0) {
40393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        return BAD_VALUE;
40493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
40593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mCameraId = cameraId;
40693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    return OK;
40793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
40893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
40993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t StagefrightRecorder::setParamTrackTimeStatus(int64_t timeDurationUs) {
41093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    LOGV("setParamTrackTimeStatus: %lld", timeDurationUs);
41193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    if (timeDurationUs < 20000) {  // Infeasible if shorter than 20 ms?
412934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        LOGE("Tracking time duration too short: %lld us", timeDurationUs);
41393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        return BAD_VALUE;
41493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
41593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = timeDurationUs;
41693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    return OK;
41793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
41893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
419145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dongstatus_t StagefrightRecorder::setParamVideoEncoderProfile(int32_t profile) {
420145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    LOGV("setParamVideoEncoderProfile: %d", profile);
421145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong
422145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    // Additional check will be done later when we load the encoder.
423145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    // For now, we are accepting values defined in OpenMAX IL.
424145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    mVideoEncoderProfile = profile;
425145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    return OK;
426145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong}
427145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong
428145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dongstatus_t StagefrightRecorder::setParamVideoEncoderLevel(int32_t level) {
429145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    LOGV("setParamVideoEncoderLevel: %d", level);
430145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong
431145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    // Additional check will be done later when we load the encoder.
432145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    // For now, we are accepting values defined in OpenMAX IL.
433145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    mVideoEncoderLevel = level;
434145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    return OK;
435145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong}
436145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong
4378f5f2fcee5c12d08df71d17017410c50951fc2e3James Dongstatus_t StagefrightRecorder::setParamMovieTimeScale(int32_t timeScale) {
4388f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    LOGV("setParamMovieTimeScale: %d", timeScale);
4398f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
4408f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    // The range is set to be the same as the audio's time scale range
4418f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    // since audio's time scale has a wider range.
4428f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (timeScale < 600 || timeScale > 96000) {
4438f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        LOGE("Time scale (%d) for movie is out of range [600, 96000]", timeScale);
4448f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        return BAD_VALUE;
4458f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
4468f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    mMovieTimeScale = timeScale;
4478f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    return OK;
4488f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong}
4498f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
4508f5f2fcee5c12d08df71d17017410c50951fc2e3James Dongstatus_t StagefrightRecorder::setParamVideoTimeScale(int32_t timeScale) {
4518f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    LOGV("setParamVideoTimeScale: %d", timeScale);
4528f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
4538f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    // 60000 is chosen to make sure that each video frame from a 60-fps
4548f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    // video has 1000 ticks.
4558f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (timeScale < 600 || timeScale > 60000) {
4568f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        LOGE("Time scale (%d) for video is out of range [600, 60000]", timeScale);
4578f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        return BAD_VALUE;
4588f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
4598f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    mVideoTimeScale = timeScale;
4608f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    return OK;
4618f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong}
4628f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
4638f5f2fcee5c12d08df71d17017410c50951fc2e3James Dongstatus_t StagefrightRecorder::setParamAudioTimeScale(int32_t timeScale) {
4648f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    LOGV("setParamAudioTimeScale: %d", timeScale);
4658f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
4668f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    // 96000 Hz is the highest sampling rate support in AAC.
4678f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (timeScale < 600 || timeScale > 96000) {
4688f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        LOGE("Time scale (%d) for audio is out of range [600, 96000]", timeScale);
4698f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        return BAD_VALUE;
4708f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
4718f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    mAudioTimeScale = timeScale;
4728f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    return OK;
4738f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong}
4748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
475050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParameter(
476050b28a593350047845a45a14cc5026221ac1620James Dong        const String8 &key, const String8 &value) {
477050b28a593350047845a45a14cc5026221ac1620James Dong    LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
478050b28a593350047845a45a14cc5026221ac1620James Dong    if (key == "max-duration") {
479ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        int64_t max_duration_ms;
480050b28a593350047845a45a14cc5026221ac1620James Dong        if (safe_strtoi64(value.string(), &max_duration_ms)) {
481934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            return setParamMaxFileDurationUs(1000LL * max_duration_ms);
482050b28a593350047845a45a14cc5026221ac1620James Dong        }
483050b28a593350047845a45a14cc5026221ac1620James Dong    } else if (key == "max-filesize") {
484ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        int64_t max_filesize_bytes;
485050b28a593350047845a45a14cc5026221ac1620James Dong        if (safe_strtoi64(value.string(), &max_filesize_bytes)) {
486934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            return setParamMaxFileSizeBytes(max_filesize_bytes);
487050b28a593350047845a45a14cc5026221ac1620James Dong        }
48893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    } else if (key == "interleave-duration-us") {
48993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int32_t durationUs;
49093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (safe_strtoi32(value.string(), &durationUs)) {
49193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return setParamInterleaveDuration(durationUs);
49293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
4938f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    } else if (key == "param-movie-time-scale") {
4948f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t timeScale;
4958f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (safe_strtoi32(value.string(), &timeScale)) {
4968f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            return setParamMovieTimeScale(timeScale);
4978f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        }
49893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    } else if (key == "param-use-64bit-offset") {
49993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int32_t use64BitOffset;
50093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (safe_strtoi32(value.string(), &use64BitOffset)) {
50193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return setParam64BitFileOffset(use64BitOffset != 0);
50293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
50393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    } else if (key == "param-track-time-status") {
50493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeDurationUs;
50593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (safe_strtoi64(value.string(), &timeDurationUs)) {
50693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return setParamTrackTimeStatus(timeDurationUs);
50793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
508050b28a593350047845a45a14cc5026221ac1620James Dong    } else if (key == "audio-param-sampling-rate") {
509050b28a593350047845a45a14cc5026221ac1620James Dong        int32_t sampling_rate;
510ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (safe_strtoi32(value.string(), &sampling_rate)) {
511050b28a593350047845a45a14cc5026221ac1620James Dong            return setParamAudioSamplingRate(sampling_rate);
512050b28a593350047845a45a14cc5026221ac1620James Dong        }
513050b28a593350047845a45a14cc5026221ac1620James Dong    } else if (key == "audio-param-number-of-channels") {
514050b28a593350047845a45a14cc5026221ac1620James Dong        int32_t number_of_channels;
515ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (safe_strtoi32(value.string(), &number_of_channels)) {
516050b28a593350047845a45a14cc5026221ac1620James Dong            return setParamAudioNumberOfChannels(number_of_channels);
517050b28a593350047845a45a14cc5026221ac1620James Dong        }
518050b28a593350047845a45a14cc5026221ac1620James Dong    } else if (key == "audio-param-encoding-bitrate") {
519050b28a593350047845a45a14cc5026221ac1620James Dong        int32_t audio_bitrate;
520ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (safe_strtoi32(value.string(), &audio_bitrate)) {
521050b28a593350047845a45a14cc5026221ac1620James Dong            return setParamAudioEncodingBitRate(audio_bitrate);
522050b28a593350047845a45a14cc5026221ac1620James Dong        }
5238f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    } else if (key == "audio-param-time-scale") {
5248f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t timeScale;
5258f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (safe_strtoi32(value.string(), &timeScale)) {
5268f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            return setParamAudioTimeScale(timeScale);
5278f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        }
528050b28a593350047845a45a14cc5026221ac1620James Dong    } else if (key == "video-param-encoding-bitrate") {
529050b28a593350047845a45a14cc5026221ac1620James Dong        int32_t video_bitrate;
530ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (safe_strtoi32(value.string(), &video_bitrate)) {
531050b28a593350047845a45a14cc5026221ac1620James Dong            return setParamVideoEncodingBitRate(video_bitrate);
532050b28a593350047845a45a14cc5026221ac1620James Dong        }
53393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    } else if (key == "video-param-i-frames-interval") {
5348f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t seconds;
5358f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (safe_strtoi32(value.string(), &seconds)) {
5368f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            return setParamVideoIFramesInterval(seconds);
537ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong        }
538145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    } else if (key == "video-param-encoder-profile") {
539145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong        int32_t profile;
540145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong        if (safe_strtoi32(value.string(), &profile)) {
541145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong            return setParamVideoEncoderProfile(profile);
542145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong        }
543145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    } else if (key == "video-param-encoder-level") {
544145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong        int32_t level;
545145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong        if (safe_strtoi32(value.string(), &level)) {
546145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong            return setParamVideoEncoderLevel(level);
547145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong        }
54893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    } else if (key == "video-param-camera-id") {
54993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int32_t cameraId;
55093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (safe_strtoi32(value.string(), &cameraId)) {
55193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return setParamVideoCameraId(cameraId);
5522dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
5538f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    } else if (key == "video-param-time-scale") {
5548f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int32_t timeScale;
5558f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (safe_strtoi32(value.string(), &timeScale)) {
5568f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            return setParamVideoTimeScale(timeScale);
5578f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        }
558050b28a593350047845a45a14cc5026221ac1620James Dong    } else {
559050b28a593350047845a45a14cc5026221ac1620James Dong        LOGE("setParameter: failed to find key %s", key.string());
560050b28a593350047845a45a14cc5026221ac1620James Dong    }
561ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    return BAD_VALUE;
562050b28a593350047845a45a14cc5026221ac1620James Dong}
56330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
564050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParameters(const String8 &params) {
565050b28a593350047845a45a14cc5026221ac1620James Dong    LOGV("setParameters: %s", params.string());
566050b28a593350047845a45a14cc5026221ac1620James Dong    const char *cparams = params.string();
567050b28a593350047845a45a14cc5026221ac1620James Dong    const char *key_start = cparams;
568050b28a593350047845a45a14cc5026221ac1620James Dong    for (;;) {
569050b28a593350047845a45a14cc5026221ac1620James Dong        const char *equal_pos = strchr(key_start, '=');
570050b28a593350047845a45a14cc5026221ac1620James Dong        if (equal_pos == NULL) {
571050b28a593350047845a45a14cc5026221ac1620James Dong            LOGE("Parameters %s miss a value", cparams);
572050b28a593350047845a45a14cc5026221ac1620James Dong            return BAD_VALUE;
573050b28a593350047845a45a14cc5026221ac1620James Dong        }
574050b28a593350047845a45a14cc5026221ac1620James Dong        String8 key(key_start, equal_pos - key_start);
575050b28a593350047845a45a14cc5026221ac1620James Dong        TrimString(&key);
576050b28a593350047845a45a14cc5026221ac1620James Dong        if (key.length() == 0) {
577050b28a593350047845a45a14cc5026221ac1620James Dong            LOGE("Parameters %s contains an empty key", cparams);
578050b28a593350047845a45a14cc5026221ac1620James Dong            return BAD_VALUE;
579050b28a593350047845a45a14cc5026221ac1620James Dong        }
580050b28a593350047845a45a14cc5026221ac1620James Dong        const char *value_start = equal_pos + 1;
581050b28a593350047845a45a14cc5026221ac1620James Dong        const char *semicolon_pos = strchr(value_start, ';');
582050b28a593350047845a45a14cc5026221ac1620James Dong        String8 value;
583050b28a593350047845a45a14cc5026221ac1620James Dong        if (semicolon_pos == NULL) {
584050b28a593350047845a45a14cc5026221ac1620James Dong            value.setTo(value_start);
585050b28a593350047845a45a14cc5026221ac1620James Dong        } else {
586050b28a593350047845a45a14cc5026221ac1620James Dong            value.setTo(value_start, semicolon_pos - value_start);
587050b28a593350047845a45a14cc5026221ac1620James Dong        }
588050b28a593350047845a45a14cc5026221ac1620James Dong        if (setParameter(key, value) != OK) {
589050b28a593350047845a45a14cc5026221ac1620James Dong            return BAD_VALUE;
590050b28a593350047845a45a14cc5026221ac1620James Dong        }
591050b28a593350047845a45a14cc5026221ac1620James Dong        if (semicolon_pos == NULL) {
592050b28a593350047845a45a14cc5026221ac1620James Dong            break;  // Reaches the end
593050b28a593350047845a45a14cc5026221ac1620James Dong        }
594050b28a593350047845a45a14cc5026221ac1620James Dong        key_start = semicolon_pos + 1;
595050b28a593350047845a45a14cc5026221ac1620James Dong    }
59630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
59730ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
59830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
59937047fceba836f341d0108beed0991b0f8dfc543James Dongstatus_t StagefrightRecorder::setListener(const sp<IMediaRecorderClient> &listener) {
60030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mListener = listener;
60130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
60230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
60330ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
60430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
60530ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::prepare() {
60630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
60730ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
60830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
60930ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::start() {
610934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    CHECK(mOutputFd >= 0);
611934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong
61230ab66297501757d745b9ae10da61adcd891f497Andreas Huber    if (mWriter != NULL) {
613934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        LOGE("File writer is not avaialble");
61430ab66297501757d745b9ae10da61adcd891f497Andreas Huber        return UNKNOWN_ERROR;
61530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    }
61630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
6172dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    switch (mOutputFormat) {
6182dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        case OUTPUT_FORMAT_DEFAULT:
6192dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        case OUTPUT_FORMAT_THREE_GPP:
6202dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        case OUTPUT_FORMAT_MPEG_4:
6212dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber            return startMPEG4Recording();
6222dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
6232dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        case OUTPUT_FORMAT_AMR_NB:
6242dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        case OUTPUT_FORMAT_AMR_WB:
6252dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber            return startAMRRecording();
6262dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
627ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        case OUTPUT_FORMAT_AAC_ADIF:
628ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        case OUTPUT_FORMAT_AAC_ADTS:
629ef9d0cd72e476a4b7556833fb09505a51b626797James Dong            return startAACRecording();
630ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
6312dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        default:
632934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            LOGE("Unsupported output file format: %d", mOutputFormat);
6332dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber            return UNKNOWN_ERROR;
6342dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    }
6352dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber}
6362dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
637050b28a593350047845a45a14cc5026221ac1620James Dongsp<MediaSource> StagefrightRecorder::createAudioSource() {
6382dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    sp<AudioSource> audioSource =
6392dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        new AudioSource(
6402dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber                mAudioSource,
641050b28a593350047845a45a14cc5026221ac1620James Dong                mSampleRate,
642be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong                mAudioChannels);
6432dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
6442dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    status_t err = audioSource->initCheck();
6452dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
6462dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    if (err != OK) {
647050b28a593350047845a45a14cc5026221ac1620James Dong        LOGE("audio source is not initialized");
6482dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        return NULL;
6492dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    }
6502dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
6512dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    sp<MetaData> encMeta = new MetaData;
652050b28a593350047845a45a14cc5026221ac1620James Dong    const char *mime;
653050b28a593350047845a45a14cc5026221ac1620James Dong    switch (mAudioEncoder) {
654050b28a593350047845a45a14cc5026221ac1620James Dong        case AUDIO_ENCODER_AMR_NB:
655050b28a593350047845a45a14cc5026221ac1620James Dong        case AUDIO_ENCODER_DEFAULT:
656050b28a593350047845a45a14cc5026221ac1620James Dong            mime = MEDIA_MIMETYPE_AUDIO_AMR_NB;
657050b28a593350047845a45a14cc5026221ac1620James Dong            break;
658050b28a593350047845a45a14cc5026221ac1620James Dong        case AUDIO_ENCODER_AMR_WB:
659050b28a593350047845a45a14cc5026221ac1620James Dong            mime = MEDIA_MIMETYPE_AUDIO_AMR_WB;
660050b28a593350047845a45a14cc5026221ac1620James Dong            break;
661050b28a593350047845a45a14cc5026221ac1620James Dong        case AUDIO_ENCODER_AAC:
662050b28a593350047845a45a14cc5026221ac1620James Dong            mime = MEDIA_MIMETYPE_AUDIO_AAC;
663050b28a593350047845a45a14cc5026221ac1620James Dong            break;
664050b28a593350047845a45a14cc5026221ac1620James Dong        default:
665050b28a593350047845a45a14cc5026221ac1620James Dong            LOGE("Unknown audio encoder: %d", mAudioEncoder);
666050b28a593350047845a45a14cc5026221ac1620James Dong            return NULL;
667050b28a593350047845a45a14cc5026221ac1620James Dong    }
668050b28a593350047845a45a14cc5026221ac1620James Dong    encMeta->setCString(kKeyMIMEType, mime);
6692dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
670b45c62c8e9b05c2703bdae18cc298ae55550db8aAndreas Huber    int32_t maxInputSize;
671b45c62c8e9b05c2703bdae18cc298ae55550db8aAndreas Huber    CHECK(audioSource->getFormat()->findInt32(
672b45c62c8e9b05c2703bdae18cc298ae55550db8aAndreas Huber                kKeyMaxInputSize, &maxInputSize));
673b45c62c8e9b05c2703bdae18cc298ae55550db8aAndreas Huber
674b45c62c8e9b05c2703bdae18cc298ae55550db8aAndreas Huber    encMeta->setInt32(kKeyMaxInputSize, maxInputSize);
675050b28a593350047845a45a14cc5026221ac1620James Dong    encMeta->setInt32(kKeyChannelCount, mAudioChannels);
676050b28a593350047845a45a14cc5026221ac1620James Dong    encMeta->setInt32(kKeySampleRate, mSampleRate);
677ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    encMeta->setInt32(kKeyBitRate, mAudioBitRate);
6788f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    encMeta->setInt32(kKeyTimeScale, mAudioTimeScale);
6792dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
6802dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    OMXClient client;
6812dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    CHECK_EQ(client.connect(), OK);
6822dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
6832dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    sp<MediaSource> audioEncoder =
6842dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        OMXCodec::Create(client.interface(), encMeta,
6852dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber                         true /* createEncoder */, audioSource);
686d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    mAudioSourceNode = audioSource;
6872dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
6882dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return audioEncoder;
6892dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber}
6902dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
691ef9d0cd72e476a4b7556833fb09505a51b626797James Dongstatus_t StagefrightRecorder::startAACRecording() {
692ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    CHECK(mOutputFormat == OUTPUT_FORMAT_AAC_ADIF ||
693ef9d0cd72e476a4b7556833fb09505a51b626797James Dong          mOutputFormat == OUTPUT_FORMAT_AAC_ADTS);
694ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
695ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    CHECK(mAudioEncoder == AUDIO_ENCODER_AAC);
696ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    CHECK(mAudioSource != AUDIO_SOURCE_LIST_END);
697ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
698ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    CHECK(0 == "AACWriter is not implemented yet");
699ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
700ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    return OK;
701ef9d0cd72e476a4b7556833fb09505a51b626797James Dong}
702ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
7032dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t StagefrightRecorder::startAMRRecording() {
704ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    CHECK(mOutputFormat == OUTPUT_FORMAT_AMR_NB ||
705ef9d0cd72e476a4b7556833fb09505a51b626797James Dong          mOutputFormat == OUTPUT_FORMAT_AMR_WB);
706ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
707ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (mOutputFormat == OUTPUT_FORMAT_AMR_NB) {
708ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (mAudioEncoder != AUDIO_ENCODER_DEFAULT &&
709ef9d0cd72e476a4b7556833fb09505a51b626797James Dong            mAudioEncoder != AUDIO_ENCODER_AMR_NB) {
710ef9d0cd72e476a4b7556833fb09505a51b626797James Dong            LOGE("Invalid encoder %d used for AMRNB recording",
711ef9d0cd72e476a4b7556833fb09505a51b626797James Dong                    mAudioEncoder);
712934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            return BAD_VALUE;
713ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        }
714ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (mSampleRate != 8000) {
715ef9d0cd72e476a4b7556833fb09505a51b626797James Dong            LOGE("Invalid sampling rate %d used for AMRNB recording",
716ef9d0cd72e476a4b7556833fb09505a51b626797James Dong                    mSampleRate);
717934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            return BAD_VALUE;
718ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        }
719ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    } else {  // mOutputFormat must be OUTPUT_FORMAT_AMR_WB
720ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
721ef9d0cd72e476a4b7556833fb09505a51b626797James Dong            LOGE("Invlaid encoder %d used for AMRWB recording",
722ef9d0cd72e476a4b7556833fb09505a51b626797James Dong                    mAudioEncoder);
723934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            return BAD_VALUE;
724ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        }
725ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        if (mSampleRate != 16000) {
726ef9d0cd72e476a4b7556833fb09505a51b626797James Dong            LOGE("Invalid sample rate %d used for AMRWB recording",
727ef9d0cd72e476a4b7556833fb09505a51b626797James Dong                    mSampleRate);
728934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            return BAD_VALUE;
729ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        }
730ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    }
731ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (mAudioChannels != 1) {
732ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        LOGE("Invalid number of audio channels %d used for amr recording",
733ef9d0cd72e476a4b7556833fb09505a51b626797James Dong                mAudioChannels);
734934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return BAD_VALUE;
7352dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    }
7362dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
737ef9d0cd72e476a4b7556833fb09505a51b626797James Dong    if (mAudioSource >= AUDIO_SOURCE_LIST_END) {
738ef9d0cd72e476a4b7556833fb09505a51b626797James Dong        LOGE("Invalid audio source: %d", mAudioSource);
739934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return BAD_VALUE;
7402dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    }
7412dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
742050b28a593350047845a45a14cc5026221ac1620James Dong    sp<MediaSource> audioEncoder = createAudioSource();
7432dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
7442dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    if (audioEncoder == NULL) {
7452dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber        return UNKNOWN_ERROR;
7462dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    }
7472dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
7482dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    mWriter = new AMRWriter(dup(mOutputFd));
7492dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    mWriter->addSource(audioEncoder);
750d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
751d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationUs != 0) {
752d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        mWriter->setMaxFileDuration(mMaxFileDurationUs);
753d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
754d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeBytes != 0) {
755d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        mWriter->setMaxFileSize(mMaxFileSizeBytes);
756d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
757d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    mWriter->setListener(mListener);
7582dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    mWriter->start();
7592dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
7602dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
7612dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber}
7622dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
76399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dongvoid StagefrightRecorder::clipVideoFrameRate() {
76499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    LOGV("clipVideoFrameRate: encoder %d", mVideoEncoder);
76599c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int minFrameRate = mEncoderProfiles->getVideoEncoderParamByName(
76699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.fps.min", mVideoEncoder);
76799c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int maxFrameRate = mEncoderProfiles->getVideoEncoderParamByName(
76899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.fps.max", mVideoEncoder);
76999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    if (mFrameRate < minFrameRate) {
77099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        LOGW("Intended video encoding frame rate (%d fps) is too small"
77199c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d fps)", mFrameRate, minFrameRate);
77299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mFrameRate = minFrameRate;
77399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    } else if (mFrameRate > maxFrameRate) {
77499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        LOGW("Intended video encoding frame rate (%d fps) is too large"
77599c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d fps)", mFrameRate, maxFrameRate);
77699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mFrameRate = maxFrameRate;
77799c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    }
77899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong}
77999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong
78099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dongvoid StagefrightRecorder::clipVideoBitRate() {
78199c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    LOGV("clipVideoBitRate: encoder %d", mVideoEncoder);
78299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int minBitRate = mEncoderProfiles->getVideoEncoderParamByName(
78399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.bps.min", mVideoEncoder);
78499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int maxBitRate = mEncoderProfiles->getVideoEncoderParamByName(
78599c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.bps.max", mVideoEncoder);
78699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    if (mVideoBitRate < minBitRate) {
78799c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        LOGW("Intended video encoding bit rate (%d bps) is too small"
78899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d bps)", mVideoBitRate, minBitRate);
78999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mVideoBitRate = minBitRate;
79099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    } else if (mVideoBitRate > maxBitRate) {
79199c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        LOGW("Intended video encoding bit rate (%d bps) is too large"
79299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d bps)", mVideoBitRate, maxBitRate);
79399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mVideoBitRate = maxBitRate;
79499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    }
79599c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong}
79699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong
79799c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dongvoid StagefrightRecorder::clipVideoFrameWidth() {
79899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    LOGV("clipVideoFrameWidth: encoder %d", mVideoEncoder);
79999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int minFrameWidth = mEncoderProfiles->getVideoEncoderParamByName(
80099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.width.min", mVideoEncoder);
80199c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int maxFrameWidth = mEncoderProfiles->getVideoEncoderParamByName(
80299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.width.max", mVideoEncoder);
80399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    if (mVideoWidth < minFrameWidth) {
80499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        LOGW("Intended video encoding frame width (%d) is too small"
80599c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d)", mVideoWidth, minFrameWidth);
80699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mVideoWidth = minFrameWidth;
80799c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    } else if (mVideoWidth > maxFrameWidth) {
80899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        LOGW("Intended video encoding frame width (%d) is too large"
80999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d)", mVideoWidth, maxFrameWidth);
81099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mVideoWidth = maxFrameWidth;
81199c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    }
81299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong}
81399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong
814934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dongstatus_t StagefrightRecorder::setupCameraSource() {
815934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    clipVideoBitRate();
816934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    clipVideoFrameRate();
817934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    clipVideoFrameWidth();
818934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    clipVideoFrameHeight();
819934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong
820934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    int64_t token = IPCThreadState::self()->clearCallingIdentity();
821934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    if (mCamera == 0) {
822934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        mCamera = Camera::connect(mCameraId);
823934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        if (mCamera == 0) {
824934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            LOGE("Camera connection could not be established.");
825934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            return -EBUSY;
826934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        }
827934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        mFlags &= ~FLAGS_HOT_CAMERA;
828934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        mCamera->lock();
829934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    }
830934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong
831934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    // Set the actual video recording frame size
832934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    CameraParameters params(mCamera->getParameters());
833934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    params.setPreviewSize(mVideoWidth, mVideoHeight);
834934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    params.setPreviewFrameRate(mFrameRate);
835934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    String8 s = params.flatten();
83648f6ce0e17297c575dcbb25671a7bee80ba13061James Dong    if (OK != mCamera->setParameters(s)) {
83748f6ce0e17297c575dcbb25671a7bee80ba13061James Dong        LOGE("Could not change settings."
83848f6ce0e17297c575dcbb25671a7bee80ba13061James Dong             " Someone else is using camera %d?", mCameraId);
83948f6ce0e17297c575dcbb25671a7bee80ba13061James Dong        return -EBUSY;
84048f6ce0e17297c575dcbb25671a7bee80ba13061James Dong    }
841934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    CameraParameters newCameraParams(mCamera->getParameters());
842934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong
843934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    // Check on video frame size
844934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    int frameWidth = 0, frameHeight = 0;
845934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    newCameraParams.getPreviewSize(&frameWidth, &frameHeight);
846934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    if (frameWidth  < 0 || frameWidth  != mVideoWidth ||
847934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        frameHeight < 0 || frameHeight != mVideoHeight) {
848934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        LOGE("Failed to set the video frame size to %dx%d",
849934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong                mVideoWidth, mVideoHeight);
850934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        IPCThreadState::self()->restoreCallingIdentity(token);
851934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return UNKNOWN_ERROR;
852934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    }
853934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong
854934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    // Check on video frame rate
855934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    int frameRate = newCameraParams.getPreviewFrameRate();
856934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    if (frameRate < 0 || (frameRate - mFrameRate) != 0) {
857934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        LOGE("Failed to set frame rate to %d fps. The actual "
858934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong             "frame rate is %d", mFrameRate, frameRate);
859934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    }
860934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong
86148f6ce0e17297c575dcbb25671a7bee80ba13061James Dong    // This CHECK is good, since we just passed the lock/unlock
86248f6ce0e17297c575dcbb25671a7bee80ba13061James Dong    // check earlier by calling mCamera->setParameters().
863934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    CHECK_EQ(OK, mCamera->setPreviewDisplay(mPreviewSurface));
864934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    IPCThreadState::self()->restoreCallingIdentity(token);
865934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    return OK;
866934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong}
867934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong
86899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dongvoid StagefrightRecorder::clipVideoFrameHeight() {
86999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    LOGV("clipVideoFrameHeight: encoder %d", mVideoEncoder);
87099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int minFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
87199c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.height.min", mVideoEncoder);
87299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    int maxFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
87399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong                        "enc.vid.height.max", mVideoEncoder);
87499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    if (mVideoHeight < minFrameHeight) {
87599c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        LOGW("Intended video encoding frame height (%d) is too small"
87699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d)", mVideoHeight, minFrameHeight);
87799c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mVideoHeight = minFrameHeight;
87899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    } else if (mVideoHeight > maxFrameHeight) {
87999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        LOGW("Intended video encoding frame height (%d) is too large"
88099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong             " and will be set to (%d)", mVideoHeight, maxFrameHeight);
88199c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong        mVideoHeight = maxFrameHeight;
88299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    }
88399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong}
88499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong
885934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dongstatus_t StagefrightRecorder::setupVideoEncoder(const sp<MediaWriter>& writer) {
886934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    status_t err = setupCameraSource();
887934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    if (err != OK) return err;
8882dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
889934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    sp<CameraSource> cameraSource = CameraSource::CreateFromCamera(mCamera);
890934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    CHECK(cameraSource != NULL);
891050b28a593350047845a45a14cc5026221ac1620James Dong
892934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    sp<MetaData> enc_meta = new MetaData;
893934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    enc_meta->setInt32(kKeyBitRate, mVideoBitRate);
894934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    enc_meta->setInt32(kKeySampleRate, mFrameRate);
895ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
896934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    switch (mVideoEncoder) {
897934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        case VIDEO_ENCODER_H263:
898934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
899934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            break;
90065ae665befd929efd1a7d1c9addac41c699f04b2James Dong
901934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        case VIDEO_ENCODER_MPEG_4_SP:
902934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
903934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            break;
90430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
905934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        case VIDEO_ENCODER_H264:
906934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
907934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            break;
90830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
909934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        default:
910934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            CHECK(!"Should not be here, unsupported video encoding.");
911934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            break;
912934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    }
913ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
914934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    sp<MetaData> meta = cameraSource->getFormat();
91530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
91629a84457aed4c45bc900998b5e11c03023264208James Dong    int32_t width, height, stride, sliceHeight, colorFormat;
917934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    CHECK(meta->findInt32(kKeyWidth, &width));
918934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    CHECK(meta->findInt32(kKeyHeight, &height));
919934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    CHECK(meta->findInt32(kKeyStride, &stride));
920934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight));
92129a84457aed4c45bc900998b5e11c03023264208James Dong    CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));
92230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
923934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    enc_meta->setInt32(kKeyWidth, width);
924934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    enc_meta->setInt32(kKeyHeight, height);
9258f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    enc_meta->setInt32(kKeyIFramesInterval, mIFramesIntervalSec);
926934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    enc_meta->setInt32(kKeyStride, stride);
927934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    enc_meta->setInt32(kKeySliceHeight, sliceHeight);
92829a84457aed4c45bc900998b5e11c03023264208James Dong    enc_meta->setInt32(kKeyColorFormat, colorFormat);
9298f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    enc_meta->setInt32(kKeyTimeScale, mVideoTimeScale);
930145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    if (mVideoEncoderProfile != -1) {
931145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong        enc_meta->setInt32(kKeyVideoProfile, mVideoEncoderProfile);
932145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    }
933145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    if (mVideoEncoderLevel != -1) {
934145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong        enc_meta->setInt32(kKeyVideoLevel, mVideoEncoderLevel);
935145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    }
93630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
937934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    OMXClient client;
938934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    CHECK_EQ(client.connect(), OK);
93930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
940934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    sp<MediaSource> encoder = OMXCodec::Create(
941934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            client.interface(), enc_meta,
942934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            true /* createEncoder */, cameraSource);
943934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    if (encoder == NULL) {
944934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return UNKNOWN_ERROR;
945934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    }
94630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
947934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    writer->addSource(encoder);
948934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    return OK;
949934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong}
95030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
951934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dongstatus_t StagefrightRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) {
952934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    sp<MediaSource> audioEncoder;
953934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    switch(mAudioEncoder) {
954934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        case AUDIO_ENCODER_AMR_NB:
955934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        case AUDIO_ENCODER_AMR_WB:
956934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        case AUDIO_ENCODER_AAC:
957934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            audioEncoder = createAudioSource();
958934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            break;
959934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        default:
960934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            LOGE("Unsupported audio encoder: %d", mAudioEncoder);
961934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            return UNKNOWN_ERROR;
962934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    }
96330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
964934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    if (audioEncoder == NULL) {
965934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        return UNKNOWN_ERROR;
966934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    }
9678f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
968934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    writer->addSource(audioEncoder);
969934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    return OK;
970934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong}
97130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
972934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dongstatus_t StagefrightRecorder::startMPEG4Recording() {
973934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    int32_t totalBitRate = 0;
974934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    status_t err = OK;
975934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    sp<MediaWriter> writer = new MPEG4Writer(dup(mOutputFd));
97630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
977934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    // Add audio source first if it exists
978934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    if (mAudioSource != AUDIO_SOURCE_LIST_END) {
979934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        err = setupAudioEncoder(writer);
980934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        if (err != OK) return err;
981934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        totalBitRate += mAudioBitRate;
982934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    }
983934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    if (mVideoSource == VIDEO_SOURCE_DEFAULT
984934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong            || mVideoSource == VIDEO_SOURCE_CAMERA) {
985934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        err = setupVideoEncoder(writer);
986934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        if (err != OK) return err;
9872dec2b5be2056c6d9428897dc672185872d30d17James Dong        totalBitRate += mVideoBitRate;
98830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    }
98930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
990f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong    if (mInterleaveDurationUs > 0) {
991f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong        reinterpret_cast<MPEG4Writer *>(writer.get())->
992f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong            setInterleaveDuration(mInterleaveDurationUs);
993f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong    }
994ef9d0cd72e476a4b7556833fb09505a51b626797James Dong
995d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationUs != 0) {
996934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        writer->setMaxFileDuration(mMaxFileDurationUs);
997d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
998d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeBytes != 0) {
999934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        writer->setMaxFileSize(mMaxFileSizeBytes);
1000d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
10012dec2b5be2056c6d9428897dc672185872d30d17James Dong    sp<MetaData> meta = new MetaData;
100293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    meta->setInt64(kKeyTime, systemTime() / 1000);
100393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    meta->setInt32(kKeyFileType, mOutputFormat);
10042dec2b5be2056c6d9428897dc672185872d30d17James Dong    meta->setInt32(kKeyBitRate, totalBitRate);
10052dec2b5be2056c6d9428897dc672185872d30d17James Dong    meta->setInt32(kKey64BitFileOffset, mUse64BitFileOffset);
10068f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    meta->setInt32(kKeyTimeScale, mMovieTimeScale);
100793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    if (mTrackEveryTimeDurationUs > 0) {
100893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        meta->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs);
100993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
1010934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    writer->setListener(mListener);
1011934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    mWriter = writer;
1012934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong    return mWriter->start(meta.get());
101330ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
101430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1015a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongstatus_t StagefrightRecorder::pause() {
1016d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    LOGV("pause");
1017a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mWriter == NULL) {
1018a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return UNKNOWN_ERROR;
1019a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
1020a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mWriter->pause();
1021a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
1022a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
1023a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
102430ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::stop() {
1025d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    LOGV("stop");
1026d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (mWriter != NULL) {
1027d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        mWriter->stop();
1028934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        mWriter.clear();
102930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    }
103030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1031c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    if (mCamera != 0) {
1032d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        LOGV("Disconnect camera");
10339d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong        int64_t token = IPCThreadState::self()->clearCallingIdentity();
1034c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        if ((mFlags & FLAGS_HOT_CAMERA) == 0) {
1035c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong            LOGV("Camera was cold when we started, stopping preview");
1036c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong            mCamera->stopPreview();
1037c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        }
10389d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong        mCamera->unlock();
1039934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong        mCamera.clear();
10409d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong        IPCThreadState::self()->restoreCallingIdentity(token);
1041c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        mFlags = 0;
1042c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
1043d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
1044d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    return OK;
1045d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong}
1046d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
1047d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dongstatus_t StagefrightRecorder::close() {
1048d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    LOGV("close");
1049d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    stop();
1050d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
105130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
105230ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
105330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
105430ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::reset() {
1055d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    LOGV("reset");
105630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    stop();
105730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1058050b28a593350047845a45a14cc5026221ac1620James Dong    // No audio or video source by default
105930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mAudioSource = AUDIO_SOURCE_LIST_END;
106030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mVideoSource = VIDEO_SOURCE_LIST_END;
1061050b28a593350047845a45a14cc5026221ac1620James Dong
1062050b28a593350047845a45a14cc5026221ac1620James Dong    // Default parameters
1063050b28a593350047845a45a14cc5026221ac1620James Dong    mOutputFormat  = OUTPUT_FORMAT_THREE_GPP;
1064050b28a593350047845a45a14cc5026221ac1620James Dong    mAudioEncoder  = AUDIO_ENCODER_AMR_NB;
1065050b28a593350047845a45a14cc5026221ac1620James Dong    mVideoEncoder  = VIDEO_ENCODER_H263;
1066050b28a593350047845a45a14cc5026221ac1620James Dong    mVideoWidth    = 176;
1067050b28a593350047845a45a14cc5026221ac1620James Dong    mVideoHeight   = 144;
1068050b28a593350047845a45a14cc5026221ac1620James Dong    mFrameRate     = 20;
1069050b28a593350047845a45a14cc5026221ac1620James Dong    mVideoBitRate  = 192000;
1070050b28a593350047845a45a14cc5026221ac1620James Dong    mSampleRate    = 8000;
1071050b28a593350047845a45a14cc5026221ac1620James Dong    mAudioChannels = 1;
1072050b28a593350047845a45a14cc5026221ac1620James Dong    mAudioBitRate  = 12200;
1073e136c3bb38e88315bf8797a464ebf2c788296b22James Dong    mInterleaveDurationUs = 0;
10748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    mIFramesIntervalSec = 1;
1075d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    mAudioSourceNode = 0;
10762dec2b5be2056c6d9428897dc672185872d30d17James Dong    mUse64BitFileOffset = false;
10778f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    mMovieTimeScale  = 1000;
10788f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    mAudioTimeScale  = 1000;
10798f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    mVideoTimeScale  = 1000;
108093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mCameraId        = 0;
1081145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    mVideoEncoderProfile = -1;
1082145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    mVideoEncoderLevel   = -1;
1083145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    mMaxFileDurationUs = 0;
1084145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong    mMaxFileSizeBytes = 0;
108593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
108699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong    mEncoderProfiles = MediaProfiles::getInstance();
1087050b28a593350047845a45a14cc5026221ac1620James Dong
108830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    mOutputFd = -1;
1089c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    mFlags = 0;
109030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
109130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return OK;
109230ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
109330ab66297501757d745b9ae10da61adcd891f497Andreas Huber
109430ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::getMaxAmplitude(int *max) {
1095d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    LOGV("getMaxAmplitude");
1096d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
1097d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    if (max == NULL) {
1098d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        LOGE("Null pointer argument");
1099d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong        return BAD_VALUE;
1100d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong    }
1101d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong
1102d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    if (mAudioSourceNode != 0) {
1103d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        *max = mAudioSourceNode->getMaxAmplitude();
1104d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    } else {
1105d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        *max = 0;
1106d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    }
11072dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
11082dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
110930ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
111030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1111b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dongstatus_t StagefrightRecorder::dump(int fd, const Vector<String16>& args) const {
1112b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    const size_t SIZE = 256;
1113b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    char buffer[SIZE];
1114b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    String8 result;
1115b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "   Recorder: %p", this);
1116b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "   Output file (fd %d):\n", mOutputFd);
1117b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1118b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     File format: %d\n", mOutputFormat);
1119b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1120b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Max file size (bytes): %lld\n", mMaxFileSizeBytes);
1121b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1122b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Max file duration (us): %lld\n", mMaxFileDurationUs);
1123b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1124b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     File offset length (bits): %d\n", mUse64BitFileOffset? 64: 32);
1125b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1126b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Interleave duration (us): %d\n", mInterleaveDurationUs);
1127b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1128b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Progress notification: %lld us\n", mTrackEveryTimeDurationUs);
1129b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1130b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "   Audio\n");
1131b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1132b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Source: %d\n", mAudioSource);
1133b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1134b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Encoder: %d\n", mAudioEncoder);
1135b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1136b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Bit rate (bps): %d\n", mAudioBitRate);
1137b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1138b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Sampling rate (hz): %d\n", mSampleRate);
1139b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1140b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Number of channels: %d\n", mAudioChannels);
1141b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1142b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Max amplitude: %d\n", mAudioSourceNode == 0? 0: mAudioSourceNode->getMaxAmplitude());
1143b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1144b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "   Video\n");
1145b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1146b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Source: %d\n", mVideoSource);
1147b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1148b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Camera Id: %d\n", mCameraId);
1149b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1150b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Camera flags: %d\n", mFlags);
1151b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1152b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Encoder: %d\n", mVideoEncoder);
1153b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1154b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Encoder profile: %d\n", mVideoEncoderProfile);
1155b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1156b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Encoder level: %d\n", mVideoEncoderLevel);
1157b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
11588f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    snprintf(buffer, SIZE, "     I frames interval (s): %d\n", mIFramesIntervalSec);
1159b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1160b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Frame size (pixels): %dx%d\n", mVideoWidth, mVideoHeight);
1161b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1162b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Frame rate (fps): %d\n", mFrameRate);
1163b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1164b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    snprintf(buffer, SIZE, "     Bit rate (bps): %d\n", mVideoBitRate);
1165b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    result.append(buffer);
1166b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    ::write(fd, result.string(), result.size());
1167b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong    return OK;
1168b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong}
116930ab66297501757d745b9ae10da61adcd891f497Andreas Huber}  // namespace android
1170