1ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber/*
2ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber * Copyright (C) 2009 The Android Open Source Project
3ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber *
4ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber * you may not use this file except in compliance with the License.
6ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber * You may obtain a copy of the License at
7ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber *
8ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber *
10ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber * Unless required by applicable law or agreed to in writing, software
11ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber * See the License for the specific language governing permissions and
14ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber * limitations under the License.
15ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber */
16ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
17ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber//#define LOG_NDEBUG 0
18ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber#define LOG_TAG "StagefrightRecorder"
19ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber#include <utils/Log.h>
20ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
21ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber#include "StagefrightRecorder.h"
22ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
23996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber#include <media/stagefright/AudioSource.h>
24996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber#include <media/stagefright/AMRWriter.h>
25ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber#include <media/stagefright/CameraSource.h>
26ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber#include <media/stagefright/MPEG4Writer.h>
27ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber#include <media/stagefright/MediaDebug.h>
28ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber#include <media/stagefright/MediaDefs.h>
29ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber#include <media/stagefright/MetaData.h>
30ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber#include <media/stagefright/OMXClient.h>
31ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber#include <media/stagefright/OMXCodec.h>
32000479f9e325b4e426a67033abd92d47da412725Mathias Agopian#include <camera/ICamera.h>
33000479f9e325b4e426a67033abd92d47da412725Mathias Agopian#include <surfaceflinger/ISurface.h>
34ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber#include <utils/Errors.h>
35ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
36ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Hubernamespace android {
37ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
38ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas HuberStagefrightRecorder::StagefrightRecorder() {
39ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    reset();
40ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
41ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
42ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas HuberStagefrightRecorder::~StagefrightRecorder() {
43ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    stop();
44ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
45ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    if (mOutputFd >= 0) {
46ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        ::close(mOutputFd);
47ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        mOutputFd = -1;
48ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    }
49ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
50ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
51ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huberstatus_t StagefrightRecorder::init() {
52ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    return OK;
53ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
54ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
55ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huberstatus_t StagefrightRecorder::setAudioSource(audio_source as) {
56ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mAudioSource = as;
57ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
58ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    return OK;
59ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
60ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
61ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huberstatus_t StagefrightRecorder::setVideoSource(video_source vs) {
62ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mVideoSource = vs;
63ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
64ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    return OK;
65ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
66ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
67ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huberstatus_t StagefrightRecorder::setOutputFormat(output_format of) {
68ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mOutputFormat = of;
69ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
70ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    return OK;
71ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
72ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
73ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huberstatus_t StagefrightRecorder::setAudioEncoder(audio_encoder ae) {
74ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mAudioEncoder = ae;
75ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
76ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    return OK;
77ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
78ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
79ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huberstatus_t StagefrightRecorder::setVideoEncoder(video_encoder ve) {
80ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mVideoEncoder = ve;
81ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
82ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    return OK;
83ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
84ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
85ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huberstatus_t StagefrightRecorder::setVideoSize(int width, int height) {
86ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mVideoWidth = width;
87ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mVideoHeight = height;
88ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
89ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    return OK;
90ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
91ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
92ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huberstatus_t StagefrightRecorder::setVideoFrameRate(int frames_per_second) {
93ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mFrameRate = frames_per_second;
94ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
95ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    return OK;
96ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
97ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
98ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huberstatus_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) {
99ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mCamera = camera;
100ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
101ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    return OK;
102ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
103ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
104ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huberstatus_t StagefrightRecorder::setPreviewSurface(const sp<ISurface> &surface) {
105ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mPreviewSurface = surface;
106ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
107ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    return OK;
108ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
109ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
110ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huberstatus_t StagefrightRecorder::setOutputFile(const char *path) {
111ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    // We don't actually support this at all, as the media_server process
112ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    // no longer has permissions to create files.
113ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
114ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    return UNKNOWN_ERROR;
115ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
116ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
117ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huberstatus_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t length) {
118ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    // These don't make any sense, do they?
119ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    CHECK_EQ(offset, 0);
120ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    CHECK_EQ(length, 0);
121ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
122ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    if (mOutputFd >= 0) {
123ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        ::close(mOutputFd);
124ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    }
125ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mOutputFd = dup(fd);
126ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
127ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    return OK;
128ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
129ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
130ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huberstatus_t StagefrightRecorder::setParameters(const String8 &params) {
131ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mParams = params;
132ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
133ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    return OK;
134ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
135ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
136ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huberstatus_t StagefrightRecorder::setListener(const sp<IMediaPlayerClient> &listener) {
137ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mListener = listener;
138ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
139ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    return OK;
140ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
141ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
142ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huberstatus_t StagefrightRecorder::prepare() {
143ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    return OK;
144ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
145ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
146ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huberstatus_t StagefrightRecorder::start() {
147ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    if (mWriter != NULL) {
148ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        return UNKNOWN_ERROR;
149ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    }
150ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
151996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    switch (mOutputFormat) {
152996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber        case OUTPUT_FORMAT_DEFAULT:
153996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber        case OUTPUT_FORMAT_THREE_GPP:
154996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber        case OUTPUT_FORMAT_MPEG_4:
155996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber            return startMPEG4Recording();
156996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
157996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber        case OUTPUT_FORMAT_AMR_NB:
158996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber        case OUTPUT_FORMAT_AMR_WB:
159996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber            return startAMRRecording();
160996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
161996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber        default:
162996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber            return UNKNOWN_ERROR;
163996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    }
164996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber}
165996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
166996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Hubersp<MediaSource> StagefrightRecorder::createAMRAudioSource() {
167996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    uint32_t sampleRate =
168996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber        mAudioEncoder == AUDIO_ENCODER_AMR_NB ? 8000 : 16000;
169996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
170996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    sp<AudioSource> audioSource =
171996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber        new AudioSource(
172996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber                mAudioSource,
173996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber                sampleRate,
174996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber                AudioSystem::CHANNEL_IN_MONO);
175996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
176996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    status_t err = audioSource->initCheck();
177996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
178996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    if (err != OK) {
179996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber        return NULL;
180996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    }
181996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
182996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    sp<MetaData> encMeta = new MetaData;
183996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    encMeta->setCString(
184996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber            kKeyMIMEType,
185996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber            mAudioEncoder == AUDIO_ENCODER_AMR_NB
186996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber                ? MEDIA_MIMETYPE_AUDIO_AMR_NB : MEDIA_MIMETYPE_AUDIO_AMR_WB);
187996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
188259b7c1c1bc40a4a47214944b8a0587c36e8c144Andreas Huber    int32_t maxInputSize;
189259b7c1c1bc40a4a47214944b8a0587c36e8c144Andreas Huber    CHECK(audioSource->getFormat()->findInt32(
190259b7c1c1bc40a4a47214944b8a0587c36e8c144Andreas Huber                kKeyMaxInputSize, &maxInputSize));
191259b7c1c1bc40a4a47214944b8a0587c36e8c144Andreas Huber
192259b7c1c1bc40a4a47214944b8a0587c36e8c144Andreas Huber    encMeta->setInt32(kKeyMaxInputSize, maxInputSize);
193996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    encMeta->setInt32(kKeyChannelCount, 1);
194996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    encMeta->setInt32(kKeySampleRate, sampleRate);
195996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
196996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    OMXClient client;
197996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    CHECK_EQ(client.connect(), OK);
198996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
199996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    sp<MediaSource> audioEncoder =
200996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber        OMXCodec::Create(client.interface(), encMeta,
201996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber                         true /* createEncoder */, audioSource);
202996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
203996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    return audioEncoder;
204996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber}
205996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
206996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huberstatus_t StagefrightRecorder::startAMRRecording() {
207996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    if (mAudioSource == AUDIO_SOURCE_LIST_END
208996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber        || mVideoSource != VIDEO_SOURCE_LIST_END) {
209996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber        return UNKNOWN_ERROR;
210996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    }
211996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
212996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    if (mOutputFormat == OUTPUT_FORMAT_AMR_NB
213996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber            && mAudioEncoder != AUDIO_ENCODER_DEFAULT
214996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber            && mAudioEncoder != AUDIO_ENCODER_AMR_NB) {
215996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber        return UNKNOWN_ERROR;
216996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    } else if (mOutputFormat == OUTPUT_FORMAT_AMR_WB
217996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber            && mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
218996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber        return UNKNOWN_ERROR;
219996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    }
220996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
221996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    sp<MediaSource> audioEncoder = createAMRAudioSource();
222996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
223996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    if (audioEncoder == NULL) {
224996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber        return UNKNOWN_ERROR;
225996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    }
226996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
227996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    CHECK(mOutputFd >= 0);
228996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    mWriter = new AMRWriter(dup(mOutputFd));
229996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    mWriter->addSource(audioEncoder);
230996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    mWriter->start();
231996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
232996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    return OK;
233996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber}
234996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
235996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huberstatus_t StagefrightRecorder::startMPEG4Recording() {
236996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    mWriter = new MPEG4Writer(dup(mOutputFd));
237996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
238996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    if (mVideoSource == VIDEO_SOURCE_DEFAULT
239996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber            || mVideoSource == VIDEO_SOURCE_CAMERA) {
240ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        CHECK(mCamera != NULL);
241ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
242ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        sp<CameraSource> cameraSource =
243ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber            CameraSource::CreateFromICamera(mCamera);
244ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
245ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        CHECK(cameraSource != NULL);
246ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
247ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        cameraSource->setPreviewSurface(mPreviewSurface);
248ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
249ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        sp<MetaData> enc_meta = new MetaData;
250ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        switch (mVideoEncoder) {
251ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber            case VIDEO_ENCODER_H263:
252ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber                enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
253ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber                break;
254ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
255ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber            case VIDEO_ENCODER_MPEG_4_SP:
256ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber                enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
257ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber                break;
258ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
259ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber            case VIDEO_ENCODER_H264:
260ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber                enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
261ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber                break;
262ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
263ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber            default:
264ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber                CHECK(!"Should not be here, unsupported video encoding.");
265ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber                break;
266ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        }
267ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
268ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        sp<MetaData> meta = cameraSource->getFormat();
269ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
270ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        int32_t width, height;
271ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        CHECK(meta->findInt32(kKeyWidth, &width));
272ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        CHECK(meta->findInt32(kKeyHeight, &height));
273ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
274ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        enc_meta->setInt32(kKeyWidth, width);
275ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        enc_meta->setInt32(kKeyHeight, height);
276ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
277ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        OMXClient client;
278ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        CHECK_EQ(client.connect(), OK);
279ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
280ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        sp<MediaSource> encoder =
281ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber            OMXCodec::Create(
282ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber                    client.interface(), enc_meta,
283ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber                    true /* createEncoder */, cameraSource);
284ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
285ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        CHECK(mOutputFd >= 0);
286ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        mWriter->addSource(encoder);
287ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    }
288ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
289996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    if (mAudioSource != AUDIO_SOURCE_LIST_END) {
290996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber        sp<MediaSource> audioEncoder = createAMRAudioSource();
291996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
292996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber        if (audioEncoder == NULL) {
293996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber            return UNKNOWN_ERROR;
294996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber        }
295996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
296996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber        mWriter->addSource(audioEncoder);
297996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    }
298996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
299996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    mWriter->start();
300ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    return OK;
301ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
302ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
303ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huberstatus_t StagefrightRecorder::stop() {
304ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    if (mWriter == NULL) {
305ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber        return UNKNOWN_ERROR;
306ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    }
307ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
308ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mWriter->stop();
309ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mWriter = NULL;
310ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
311ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    return OK;
312ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
313ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
314ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huberstatus_t StagefrightRecorder::close() {
315ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    stop();
316ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
317ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    return OK;
318ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
319ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
320ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huberstatus_t StagefrightRecorder::reset() {
321ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    stop();
322ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
323ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mAudioSource = AUDIO_SOURCE_LIST_END;
324ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mVideoSource = VIDEO_SOURCE_LIST_END;
325ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mOutputFormat = OUTPUT_FORMAT_LIST_END;
326ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mAudioEncoder = AUDIO_ENCODER_LIST_END;
327ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mVideoEncoder = VIDEO_ENCODER_LIST_END;
328ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mVideoWidth = -1;
329ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mVideoHeight = -1;
330ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mFrameRate = -1;
331ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    mOutputFd = -1;
332ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
333ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    return OK;
334ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
335ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
336ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huberstatus_t StagefrightRecorder::getMaxAmplitude(int *max) {
337996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    *max = 0;
338996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber
339996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    return OK;
340ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}
341ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber
342ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber}  // namespace android
343