Support for audio recording into AMR NB/WB files as well as audio tracks in MPEG4 files.

related-to-bug: 2295449
This commit is contained in:
Andreas Huber
2010-01-25 15:30:31 -08:00
parent 03b58bdf0e
commit 996dddff64
7 changed files with 177 additions and 19 deletions

View File

@@ -20,23 +20,23 @@
#include <stdio.h>
#include <utils/RefBase.h>
#include <media/stagefright/MediaWriter.h>
#include <utils/threads.h>
namespace android {
struct MediaSource;
struct AMRWriter : public RefBase {
struct AMRWriter : public MediaWriter {
AMRWriter(const char *filename);
AMRWriter(int fd);
status_t initCheck() const;
status_t addSource(const sp<MediaSource> &source);
status_t start();
void stop();
virtual status_t addSource(const sp<MediaSource> &source);
virtual bool reachedEOS();
virtual status_t start();
virtual void stop();
protected:
virtual ~AMRWriter();
@@ -49,6 +49,7 @@ private:
sp<MediaSource> mSource;
bool mStarted;
volatile bool mDone;
bool mReachedEOS;
pthread_t mThread;
static void *ThreadWrapper(void *);

View File

@@ -20,8 +20,8 @@
#include <stdio.h>
#include <media/stagefright/MediaWriter.h>
#include <utils/List.h>
#include <utils/RefBase.h>
#include <utils/threads.h>
namespace android {
@@ -30,15 +30,15 @@ class MediaBuffer;
class MediaSource;
class MetaData;
class MPEG4Writer : public RefBase {
class MPEG4Writer : public MediaWriter {
public:
MPEG4Writer(const char *filename);
MPEG4Writer(int fd);
void addSource(const sp<MediaSource> &source);
status_t start();
bool reachedEOS();
void stop();
virtual status_t addSource(const sp<MediaSource> &source);
virtual status_t start();
virtual bool reachedEOS();
virtual void stop();
void beginBox(const char *fourcc);
void writeInt8(int8_t x);

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MEDIA_WRITER_H_
#define MEDIA_WRITER_H_
#include <utils/RefBase.h>
namespace android {
struct MediaSource;
struct MediaWriter : public RefBase {
MediaWriter() {}
virtual status_t addSource(const sp<MediaSource> &source) = 0;
virtual bool reachedEOS() = 0;
virtual status_t start() = 0;
virtual void stop() = 0;
protected:
virtual ~MediaWriter() {}
private:
MediaWriter(const MediaWriter &);
MediaWriter &operator=(const MediaWriter &);
};
} // namespace android
#endif // MEDIA_WRITER_H_

View File

@@ -20,6 +20,8 @@
#include "StagefrightRecorder.h"
#include <media/stagefright/AudioSource.h>
#include <media/stagefright/AMRWriter.h>
#include <media/stagefright/CameraSource.h>
#include <media/stagefright/MPEG4Writer.h>
#include <media/stagefright/MediaDebug.h>
@@ -146,7 +148,90 @@ status_t StagefrightRecorder::start() {
return UNKNOWN_ERROR;
}
if (mVideoSource == VIDEO_SOURCE_CAMERA) {
switch (mOutputFormat) {
case OUTPUT_FORMAT_DEFAULT:
case OUTPUT_FORMAT_THREE_GPP:
case OUTPUT_FORMAT_MPEG_4:
return startMPEG4Recording();
case OUTPUT_FORMAT_AMR_NB:
case OUTPUT_FORMAT_AMR_WB:
return startAMRRecording();
default:
return UNKNOWN_ERROR;
}
}
sp<MediaSource> StagefrightRecorder::createAMRAudioSource() {
uint32_t sampleRate =
mAudioEncoder == AUDIO_ENCODER_AMR_NB ? 8000 : 16000;
sp<AudioSource> audioSource =
new AudioSource(
mAudioSource,
sampleRate,
AudioSystem::CHANNEL_IN_MONO);
status_t err = audioSource->initCheck();
if (err != OK) {
return NULL;
}
sp<MetaData> encMeta = new MetaData;
encMeta->setCString(
kKeyMIMEType,
mAudioEncoder == AUDIO_ENCODER_AMR_NB
? MEDIA_MIMETYPE_AUDIO_AMR_NB : MEDIA_MIMETYPE_AUDIO_AMR_WB);
encMeta->setInt32(kKeyChannelCount, 1);
encMeta->setInt32(kKeySampleRate, sampleRate);
OMXClient client;
CHECK_EQ(client.connect(), OK);
sp<MediaSource> audioEncoder =
OMXCodec::Create(client.interface(), encMeta,
true /* createEncoder */, audioSource);
return audioEncoder;
}
status_t StagefrightRecorder::startAMRRecording() {
if (mAudioSource == AUDIO_SOURCE_LIST_END
|| mVideoSource != VIDEO_SOURCE_LIST_END) {
return UNKNOWN_ERROR;
}
if (mOutputFormat == OUTPUT_FORMAT_AMR_NB
&& mAudioEncoder != AUDIO_ENCODER_DEFAULT
&& mAudioEncoder != AUDIO_ENCODER_AMR_NB) {
return UNKNOWN_ERROR;
} else if (mOutputFormat == OUTPUT_FORMAT_AMR_WB
&& mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
return UNKNOWN_ERROR;
}
sp<MediaSource> audioEncoder = createAMRAudioSource();
if (audioEncoder == NULL) {
return UNKNOWN_ERROR;
}
CHECK(mOutputFd >= 0);
mWriter = new AMRWriter(dup(mOutputFd));
mWriter->addSource(audioEncoder);
mWriter->start();
return OK;
}
status_t StagefrightRecorder::startMPEG4Recording() {
mWriter = new MPEG4Writer(dup(mOutputFd));
if (mVideoSource == VIDEO_SOURCE_DEFAULT
|| mVideoSource == VIDEO_SOURCE_CAMERA) {
CHECK(mCamera != NULL);
sp<CameraSource> cameraSource =
@@ -193,11 +278,20 @@ status_t StagefrightRecorder::start() {
true /* createEncoder */, cameraSource);
CHECK(mOutputFd >= 0);
mWriter = new MPEG4Writer(dup(mOutputFd));
mWriter->addSource(encoder);
mWriter->start();
}
if (mAudioSource != AUDIO_SOURCE_LIST_END) {
sp<MediaSource> audioEncoder = createAMRAudioSource();
if (audioEncoder == NULL) {
return UNKNOWN_ERROR;
}
mWriter->addSource(audioEncoder);
}
mWriter->start();
return OK;
}
@@ -235,7 +329,9 @@ status_t StagefrightRecorder::reset() {
}
status_t StagefrightRecorder::getMaxAmplitude(int *max) {
return UNKNOWN_ERROR;
*max = 0;
return OK;
}
} // namespace android

View File

@@ -23,7 +23,8 @@
namespace android {
class MPEG4Writer;
struct MediaSource;
struct MediaWriter;
struct StagefrightRecorder : public MediaRecorderBase {
StagefrightRecorder();
@@ -54,7 +55,7 @@ private:
sp<ICamera> mCamera;
sp<ISurface> mPreviewSurface;
sp<IMediaPlayerClient> mListener;
sp<MPEG4Writer> mWriter;
sp<MediaWriter> mWriter;
audio_source mAudioSource;
video_source mVideoSource;
@@ -66,6 +67,10 @@ private:
String8 mParams;
int mOutputFd;
status_t startMPEG4Recording();
status_t startAMRRecording();
sp<MediaSource> createAMRAudioSource();
StagefrightRecorder(const StagefrightRecorder &);
StagefrightRecorder &operator=(const StagefrightRecorder &);
};

View File

@@ -115,6 +115,7 @@ status_t AMRWriter::start() {
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
mReachedEOS = false;
mDone = false;
pthread_create(&mThread, &attr, ThreadWrapper, this);
@@ -179,6 +180,14 @@ void AMRWriter::threadFunc() {
break;
}
}
Mutex::Autolock autoLock(mLock);
mReachedEOS = true;
}
bool AMRWriter::reachedEOS() {
Mutex::Autolock autoLock(mLock);
return mReachedEOS;
}
} // namespace android

View File

@@ -92,9 +92,11 @@ MPEG4Writer::~MPEG4Writer() {
mTracks.clear();
}
void MPEG4Writer::addSource(const sp<MediaSource> &source) {
status_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
Track *track = new Track(this, source);
mTracks.push_back(track);
return OK;
}
status_t MPEG4Writer::start() {