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:
@@ -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 *);
|
||||
|
||||
@@ -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);
|
||||
|
||||
45
include/media/stagefright/MediaWriter.h
Normal file
45
include/media/stagefright/MediaWriter.h
Normal 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_
|
||||
@@ -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
|
||||
|
||||
@@ -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 &);
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user