StagefrightRecorder.cpp revision 13aec890216948b0c364f8f92792129d0335f506
1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "StagefrightRecorder"
19#include <utils/Log.h>
20
21#include "StagefrightRecorder.h"
22
23#include <binder/IPCThreadState.h>
24#include <media/stagefright/AudioSource.h>
25#include <media/stagefright/AMRWriter.h>
26#include <media/stagefright/CameraSource.h>
27#include <media/stagefright/MPEG4Writer.h>
28#include <media/stagefright/MediaDebug.h>
29#include <media/stagefright/MediaDefs.h>
30#include <media/stagefright/MetaData.h>
31#include <media/stagefright/OMXClient.h>
32#include <media/stagefright/OMXCodec.h>
33#include <camera/ICamera.h>
34#include <camera/Camera.h>
35#include <surfaceflinger/ISurface.h>
36#include <utils/Errors.h>
37#include <sys/types.h>
38#include <unistd.h>
39#include <ctype.h>
40
41namespace android {
42
43StagefrightRecorder::StagefrightRecorder() {
44    reset();
45}
46
47StagefrightRecorder::~StagefrightRecorder() {
48    stop();
49
50    if (mOutputFd >= 0) {
51        ::close(mOutputFd);
52        mOutputFd = -1;
53    }
54}
55
56status_t StagefrightRecorder::init() {
57    return OK;
58}
59
60status_t StagefrightRecorder::setAudioSource(audio_source as) {
61    mAudioSource = as;
62
63    return OK;
64}
65
66status_t StagefrightRecorder::setVideoSource(video_source vs) {
67    mVideoSource = vs;
68
69    return OK;
70}
71
72status_t StagefrightRecorder::setOutputFormat(output_format of) {
73    mOutputFormat = of;
74
75    return OK;
76}
77
78status_t StagefrightRecorder::setAudioEncoder(audio_encoder ae) {
79    mAudioEncoder = ae;
80
81    return OK;
82}
83
84status_t StagefrightRecorder::setVideoEncoder(video_encoder ve) {
85    mVideoEncoder = ve;
86
87    return OK;
88}
89
90status_t StagefrightRecorder::setVideoSize(int width, int height) {
91    mVideoWidth = width;
92    mVideoHeight = height;
93
94    return OK;
95}
96
97status_t StagefrightRecorder::setVideoFrameRate(int frames_per_second) {
98    mFrameRate = frames_per_second;
99
100    return OK;
101}
102
103status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) {
104    LOGV("setCamera: pid %d pid %d", IPCThreadState::self()->getCallingPid(), getpid());
105    if (camera == 0) {
106        LOGE("camera is NULL");
107        return UNKNOWN_ERROR;
108    }
109
110    mFlags &= ~ FLAGS_SET_CAMERA | FLAGS_HOT_CAMERA;
111    mCamera = Camera::create(camera);
112    if (mCamera == 0) {
113        LOGE("Unable to connect to camera");
114        return UNKNOWN_ERROR;
115    }
116
117    LOGV("Connected to camera");
118    mFlags |= FLAGS_SET_CAMERA;
119    if (mCamera->previewEnabled()) {
120        LOGV("camera is hot");
121        mFlags |= FLAGS_HOT_CAMERA;
122    }
123
124    return OK;
125}
126
127status_t StagefrightRecorder::setPreviewSurface(const sp<ISurface> &surface) {
128    mPreviewSurface = surface;
129
130    return OK;
131}
132
133status_t StagefrightRecorder::setOutputFile(const char *path) {
134    // We don't actually support this at all, as the media_server process
135    // no longer has permissions to create files.
136
137    return UNKNOWN_ERROR;
138}
139
140status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t length) {
141    // These don't make any sense, do they?
142    CHECK_EQ(offset, 0);
143    CHECK_EQ(length, 0);
144
145    if (mOutputFd >= 0) {
146        ::close(mOutputFd);
147    }
148    mOutputFd = dup(fd);
149
150    return OK;
151}
152
153// Attempt to parse an int64 literal optionally surrounded by whitespace,
154// returns true on success, false otherwise.
155static bool safe_strtoi64(const char *s, int32_t *val) {
156    char *end;
157    *val = static_cast<int32_t>(strtoll(s, &end, 10));
158
159    if (end == s || errno == ERANGE) {
160        return false;
161    }
162
163    // Skip trailing whitespace
164    while (isspace(*end)) {
165        ++end;
166    }
167
168    // For a successful return, the string must contain nothing but a valid
169    // int64 literal optionally surrounded by whitespace.
170
171    return *end == '\0';
172}
173
174// Trim both leading and trailing whitespace from the given string.
175static void TrimString(String8 *s) {
176    size_t num_bytes = s->bytes();
177    const char *data = s->string();
178
179    size_t leading_space = 0;
180    while (leading_space < num_bytes && isspace(data[leading_space])) {
181        ++leading_space;
182    }
183
184    size_t i = num_bytes;
185    while (i > leading_space && isspace(data[i - 1])) {
186        --i;
187    }
188
189    s->setTo(String8(&data[leading_space], i - leading_space));
190}
191
192status_t StagefrightRecorder::setParamAudioSamplingRate(int32_t sampleRate) {
193    LOGV("setParamAudioSamplingRate: %d", sampleRate);
194    mSampleRate = sampleRate;
195    return OK;
196}
197
198status_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) {
199    LOGV("setParamAudioNumberOfChannels: %d", channels);
200    mAudioChannels = channels;
201    return OK;
202}
203
204status_t StagefrightRecorder::setParamAudioEncodingBitRate(int32_t bitRate) {
205    LOGV("setParamAudioEncodingBitRate: %d", bitRate);
206    mAudioBitRate = bitRate;
207    return OK;
208}
209
210status_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) {
211    LOGV("setParamVideoEncodingBitRate: %d", bitRate);
212    mVideoBitRate = bitRate;
213    return OK;
214}
215
216status_t StagefrightRecorder::setParamMaxDurationOrFileSize(int32_t limit,
217        bool limit_is_duration) {
218    LOGV("setParamMaxDurationOrFileSize: limit (%d) for %s",
219            limit, limit_is_duration?"duration":"size");
220    return OK;
221}
222
223status_t StagefrightRecorder::setParamInterleaveDuration(int32_t durationUs) {
224    LOGV("setParamInterleaveDuration: %d", durationUs);
225    mInterleaveDurationUs = durationUs;
226    return OK;
227}
228status_t StagefrightRecorder::setParameter(
229        const String8 &key, const String8 &value) {
230    LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
231    if (key == "max-duration") {
232        int32_t max_duration_ms;
233        if (safe_strtoi64(value.string(), &max_duration_ms)) {
234            return setParamMaxDurationOrFileSize(
235                    max_duration_ms, true /* limit_is_duration */);
236        }
237    } else if (key == "max-filesize") {
238        int32_t max_filesize_bytes;
239        if (safe_strtoi64(value.string(), &max_filesize_bytes)) {
240            return setParamMaxDurationOrFileSize(
241                    max_filesize_bytes, false /* limit is filesize */);
242        }
243    } else if (key == "audio-param-sampling-rate") {
244        int32_t sampling_rate;
245        if (safe_strtoi64(value.string(), &sampling_rate)) {
246            return setParamAudioSamplingRate(sampling_rate);
247        }
248    } else if (key == "audio-param-number-of-channels") {
249        int32_t number_of_channels;
250        if (safe_strtoi64(value.string(), &number_of_channels)) {
251            return setParamAudioNumberOfChannels(number_of_channels);
252        }
253    } else if (key == "audio-param-encoding-bitrate") {
254        int32_t audio_bitrate;
255        if (safe_strtoi64(value.string(), &audio_bitrate)) {
256            return setParamAudioEncodingBitRate(audio_bitrate);
257        }
258    } else if (key == "video-param-encoding-bitrate") {
259        int32_t video_bitrate;
260        if (safe_strtoi64(value.string(), &video_bitrate)) {
261            return setParamVideoEncodingBitRate(video_bitrate);
262        }
263    } else if (key == "param-interleave-duration-us") {
264        int32_t durationUs;
265        if (safe_strtoi64(value.string(), &durationUs)) {
266            return setParamInterleaveDuration(durationUs);
267        }
268    } else {
269        LOGE("setParameter: failed to find key %s", key.string());
270        return BAD_VALUE;
271    }
272    return OK;
273}
274
275status_t StagefrightRecorder::setParameters(const String8 &params) {
276    LOGV("setParameters: %s", params.string());
277    const char *cparams = params.string();
278    const char *key_start = cparams;
279    for (;;) {
280        const char *equal_pos = strchr(key_start, '=');
281        if (equal_pos == NULL) {
282            LOGE("Parameters %s miss a value", cparams);
283            return BAD_VALUE;
284        }
285        String8 key(key_start, equal_pos - key_start);
286        TrimString(&key);
287        if (key.length() == 0) {
288            LOGE("Parameters %s contains an empty key", cparams);
289            return BAD_VALUE;
290        }
291        const char *value_start = equal_pos + 1;
292        const char *semicolon_pos = strchr(value_start, ';');
293        String8 value;
294        if (semicolon_pos == NULL) {
295            value.setTo(value_start);
296        } else {
297            value.setTo(value_start, semicolon_pos - value_start);
298        }
299        if (setParameter(key, value) != OK) {
300            return BAD_VALUE;
301        }
302        if (semicolon_pos == NULL) {
303            break;  // Reaches the end
304        }
305        key_start = semicolon_pos + 1;
306    }
307    return OK;
308}
309
310status_t StagefrightRecorder::setListener(const sp<IMediaPlayerClient> &listener) {
311    mListener = listener;
312
313    return OK;
314}
315
316status_t StagefrightRecorder::prepare() {
317    return OK;
318}
319
320status_t StagefrightRecorder::start() {
321    if (mWriter != NULL) {
322        return UNKNOWN_ERROR;
323    }
324
325    switch (mOutputFormat) {
326        case OUTPUT_FORMAT_DEFAULT:
327        case OUTPUT_FORMAT_THREE_GPP:
328        case OUTPUT_FORMAT_MPEG_4:
329            return startMPEG4Recording();
330
331        case OUTPUT_FORMAT_AMR_NB:
332        case OUTPUT_FORMAT_AMR_WB:
333            return startAMRRecording();
334
335        default:
336            return UNKNOWN_ERROR;
337    }
338}
339
340sp<MediaSource> StagefrightRecorder::createAudioSource() {
341    sp<AudioSource> audioSource =
342        new AudioSource(
343                mAudioSource,
344                mSampleRate,
345                AudioSystem::CHANNEL_IN_MONO);
346
347    status_t err = audioSource->initCheck();
348
349    if (err != OK) {
350        LOGE("audio source is not initialized");
351        return NULL;
352    }
353
354    sp<MetaData> encMeta = new MetaData;
355    const char *mime;
356    switch (mAudioEncoder) {
357        case AUDIO_ENCODER_AMR_NB:
358        case AUDIO_ENCODER_DEFAULT:
359            mime = MEDIA_MIMETYPE_AUDIO_AMR_NB;
360            break;
361        case AUDIO_ENCODER_AMR_WB:
362            mime = MEDIA_MIMETYPE_AUDIO_AMR_WB;
363            break;
364        case AUDIO_ENCODER_AAC:
365            mime = MEDIA_MIMETYPE_AUDIO_AAC;
366            break;
367        default:
368            LOGE("Unknown audio encoder: %d", mAudioEncoder);
369            return NULL;
370    }
371    encMeta->setCString(kKeyMIMEType, mime);
372
373    int32_t maxInputSize;
374    CHECK(audioSource->getFormat()->findInt32(
375                kKeyMaxInputSize, &maxInputSize));
376
377    encMeta->setInt32(kKeyMaxInputSize, maxInputSize);
378    encMeta->setInt32(kKeyChannelCount, mAudioChannels);
379    encMeta->setInt32(kKeySampleRate, mSampleRate);
380
381    OMXClient client;
382    CHECK_EQ(client.connect(), OK);
383
384    sp<MediaSource> audioEncoder =
385        OMXCodec::Create(client.interface(), encMeta,
386                         true /* createEncoder */, audioSource);
387
388    return audioEncoder;
389}
390
391status_t StagefrightRecorder::startAMRRecording() {
392    if (mAudioSource == AUDIO_SOURCE_LIST_END
393        || mVideoSource != VIDEO_SOURCE_LIST_END) {
394        return UNKNOWN_ERROR;
395    }
396
397    if (mOutputFormat == OUTPUT_FORMAT_AMR_NB
398            && mAudioEncoder != AUDIO_ENCODER_DEFAULT
399            && mAudioEncoder != AUDIO_ENCODER_AMR_NB) {
400        return UNKNOWN_ERROR;
401    } else if (mOutputFormat == OUTPUT_FORMAT_AMR_WB
402            && mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
403        return UNKNOWN_ERROR;
404    }
405
406    sp<MediaSource> audioEncoder = createAudioSource();
407
408    if (audioEncoder == NULL) {
409        return UNKNOWN_ERROR;
410    }
411
412    CHECK(mOutputFd >= 0);
413    mWriter = new AMRWriter(dup(mOutputFd));
414    mWriter->addSource(audioEncoder);
415    mWriter->start();
416
417    return OK;
418}
419
420status_t StagefrightRecorder::startMPEG4Recording() {
421    mWriter = new MPEG4Writer(dup(mOutputFd));
422
423    // Add audio source first if it exists
424    if (mAudioSource != AUDIO_SOURCE_LIST_END) {
425        sp<MediaSource> audioEncoder;
426        switch(mAudioEncoder) {
427            case AUDIO_ENCODER_AMR_NB:
428            case AUDIO_ENCODER_AMR_WB:
429            case AUDIO_ENCODER_AAC:
430                audioEncoder = createAudioSource();
431                break;
432            default:
433                LOGE("Unsupported audio encoder: %d", mAudioEncoder);
434                return UNKNOWN_ERROR;
435        }
436
437        if (audioEncoder == NULL) {
438            return UNKNOWN_ERROR;
439        }
440
441        mWriter->addSource(audioEncoder);
442    }
443    if (mVideoSource == VIDEO_SOURCE_DEFAULT
444            || mVideoSource == VIDEO_SOURCE_CAMERA) {
445        CHECK(mCamera != NULL);
446
447        sp<CameraSource> cameraSource =
448            CameraSource::CreateFromCamera(mCamera);
449
450        CHECK(cameraSource != NULL);
451
452        cameraSource->setPreviewSurface(mPreviewSurface);
453
454        sp<MetaData> enc_meta = new MetaData;
455        switch (mVideoEncoder) {
456            case VIDEO_ENCODER_H263:
457                enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
458                break;
459
460            case VIDEO_ENCODER_MPEG_4_SP:
461                enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
462                break;
463
464            case VIDEO_ENCODER_H264:
465                enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
466                break;
467
468            default:
469                CHECK(!"Should not be here, unsupported video encoding.");
470                break;
471        }
472
473        sp<MetaData> meta = cameraSource->getFormat();
474
475        int32_t width, height;
476        CHECK(meta->findInt32(kKeyWidth, &width));
477        CHECK(meta->findInt32(kKeyHeight, &height));
478
479        enc_meta->setInt32(kKeyWidth, width);
480        enc_meta->setInt32(kKeyHeight, height);
481
482        OMXClient client;
483        CHECK_EQ(client.connect(), OK);
484
485        sp<MediaSource> encoder =
486            OMXCodec::Create(
487                    client.interface(), enc_meta,
488                    true /* createEncoder */, cameraSource);
489
490        CHECK(mOutputFd >= 0);
491        mWriter->addSource(encoder);
492    }
493
494    ((MPEG4Writer *)mWriter.get())->setInterleaveDuration(mInterleaveDurationUs);
495    mWriter->start();
496    return OK;
497}
498
499status_t StagefrightRecorder::stop() {
500    if (mWriter == NULL) {
501        return UNKNOWN_ERROR;
502    }
503
504    mWriter->stop();
505    mWriter = NULL;
506
507    return OK;
508}
509
510status_t StagefrightRecorder::close() {
511    stop();
512
513    if (mCamera != 0) {
514        if ((mFlags & FLAGS_HOT_CAMERA) == 0) {
515            LOGV("Camera was cold when we started, stopping preview");
516            mCamera->stopPreview();
517        }
518        if (mFlags & FLAGS_SET_CAMERA) {
519            LOGV("Unlocking camera");
520            mCamera->unlock();
521        }
522        mFlags = 0;
523    }
524    return OK;
525}
526
527status_t StagefrightRecorder::reset() {
528    stop();
529
530    // No audio or video source by default
531    mAudioSource = AUDIO_SOURCE_LIST_END;
532    mVideoSource = VIDEO_SOURCE_LIST_END;
533
534    // Default parameters
535    mOutputFormat  = OUTPUT_FORMAT_THREE_GPP;
536    mAudioEncoder  = AUDIO_ENCODER_AMR_NB;
537    mVideoEncoder  = VIDEO_ENCODER_H263;
538    mVideoWidth    = 176;
539    mVideoHeight   = 144;
540    mFrameRate     = 20;
541    mVideoBitRate  = 192000;
542    mSampleRate    = 8000;
543    mAudioChannels = 1;
544    mAudioBitRate  = 12200;
545
546    mOutputFd = -1;
547    mFlags = 0;
548
549    return OK;
550}
551
552status_t StagefrightRecorder::getMaxAmplitude(int *max) {
553    *max = 0;
554
555    return OK;
556}
557
558}  // namespace android
559