Merge change 23714 into eclair

* changes:
  Some work to make audio encoding work.
This commit is contained in:
Android (Google) Code Review
2009-09-03 09:40:08 -07:00
8 changed files with 330 additions and 78 deletions

View File

@@ -24,6 +24,7 @@ include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
SineSource.cpp \
record.cpp
LOCAL_SHARED_LIBRARIES := \

View File

@@ -102,7 +102,7 @@ sp<MetaData> JPEGSource::getFormat() {
meta->setCString(kKeyMIMEType, "image/jpeg");
meta->setInt32(kKeyWidth, mWidth);
meta->setInt32(kKeyHeight, mHeight);
meta->setInt32(kKeyCompressedSize, mSize);
meta->setInt32(kKeyMaxInputSize, mSize);
return meta;
}

View File

@@ -0,0 +1,100 @@
#include "SineSource.h"
#include <math.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MetaData.h>
namespace android {
SineSource::SineSource(int32_t sampleRate, int32_t numChannels)
: mStarted(false),
mSampleRate(sampleRate),
mNumChannels(numChannels),
mPhase(0),
mGroup(NULL) {
CHECK(numChannels == 1 || numChannels == 2);
}
SineSource::~SineSource() {
if (mStarted) {
stop();
}
}
status_t SineSource::start(MetaData *params) {
CHECK(!mStarted);
mGroup = new MediaBufferGroup;
mGroup->add_buffer(new MediaBuffer(kBufferSize));
mPhase = 0;
mStarted = true;
return OK;
}
status_t SineSource::stop() {
CHECK(mStarted);
delete mGroup;
mGroup = NULL;
mStarted = false;
return OK;
}
sp<MetaData> SineSource::getFormat() {
sp<MetaData> meta = new MetaData;
meta->setCString(kKeyMIMEType, "audio/raw");
meta->setInt32(kKeyChannelCount, mNumChannels);
meta->setInt32(kKeySampleRate, mSampleRate);
return meta;
}
status_t SineSource::read(
MediaBuffer **out, const ReadOptions *options) {
*out = NULL;
MediaBuffer *buffer;
status_t err = mGroup->acquire_buffer(&buffer);
if (err != OK) {
return err;
}
size_t frameSize = mNumChannels * sizeof(int16_t);
size_t numFramesPerBuffer = buffer->size() / frameSize;
int16_t *ptr = (int16_t *)buffer->data();
const double k = kFrequency / mSampleRate * (2.0 * M_PI);
double x = mPhase * k;
for (size_t i = 0; i < numFramesPerBuffer; ++i) {
int16_t amplitude = (int16_t)(32767.0 * sin(x));
*ptr++ = amplitude;
if (mNumChannels == 2) {
*ptr++ = amplitude;
}
x += k;
}
buffer->meta_data()->setInt32(kKeyTimeUnits, mPhase);
buffer->meta_data()->setInt32(kKeyTimeScale, mSampleRate);
mPhase += numFramesPerBuffer;
buffer->set_range(0, numFramesPerBuffer * frameSize);
*out = buffer;
return OK;
}
} // namespace android

View File

@@ -0,0 +1,39 @@
#ifndef SINE_SOURCE_H_
#define SINE_SOURCE_H_
#include <media/stagefright/MediaSource.h>
namespace android {
struct MediaBufferGroup;
struct SineSource : public MediaSource {
SineSource(int32_t sampleRate, int32_t numChannels);
virtual status_t start(MetaData *params);
virtual status_t stop();
virtual sp<MetaData> getFormat();
virtual status_t read(
MediaBuffer **out, const ReadOptions *options = NULL);
protected:
virtual ~SineSource();
private:
enum { kBufferSize = 8192 };
static const double kFrequency = 500.0;
bool mStarted;
int32_t mSampleRate;
int32_t mNumChannels;
size_t mPhase;
MediaBufferGroup *mGroup;
};
} // namespace android
#endif // SINE_SOURCE_H_

View File

@@ -14,7 +14,10 @@
* limitations under the License.
*/
#include "SineSource.h"
#include <binder/ProcessState.h>
#include <media/stagefright/AudioPlayer.h>
#include <media/stagefright/CameraSource.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDebug.h>
@@ -24,9 +27,11 @@
#include <media/stagefright/MmapSource.h>
#include <media/stagefright/OMXClient.h>
#include <media/stagefright/OMXCodec.h>
#include <media/MediaPlayerInterface.h>
using namespace android;
#if 0
class DummySource : public MediaSource {
public:
DummySource(int width, int height)
@@ -158,7 +163,7 @@ int main(int argc, char **argv) {
OMXCodec::Create(
client.interface(), enc_meta, true /* createEncoder */, decoder);
#if 1
#if 0
sp<MPEG4Writer> writer = new MPEG4Writer("/sdcard/output.mp4");
writer->addSource(enc_meta, encoder);
writer->start();
@@ -204,4 +209,60 @@ int main(int argc, char **argv) {
return 0;
}
#endif
int main(int argc, char **argv) {
android::ProcessState::self()->startThreadPool();
OMXClient client;
CHECK_EQ(client.connect(), OK);
const int32_t kSampleRate = 22050;
const int32_t kNumChannels = 2;
sp<MediaSource> audioSource = new SineSource(kSampleRate, kNumChannels);
#if 0
sp<MediaPlayerBase::AudioSink> audioSink;
AudioPlayer *player = new AudioPlayer(audioSink);
player->setSource(audioSource);
player->start();
sleep(10);
player->stop();
#endif
sp<MetaData> encMeta = new MetaData;
encMeta->setCString(kKeyMIMEType, 1 ? "audio/3gpp" : "audio/mp4a-latm");
encMeta->setInt32(kKeySampleRate, kSampleRate);
encMeta->setInt32(kKeyChannelCount, kNumChannels);
encMeta->setInt32(kKeyMaxInputSize, 8192);
sp<MediaSource> encoder =
OMXCodec::Create(client.interface(), encMeta, true, audioSource);
encoder->start();
int32_t n = 0;
status_t err;
MediaBuffer *buffer;
while ((err = encoder->read(&buffer)) == OK) {
printf(".");
fflush(stdout);
buffer->release();
buffer = NULL;
if (++n == 10000) {
break;
}
}
printf("$\n");
encoder->stop();
client.disconnect();
return 0;
}

View File

@@ -45,7 +45,7 @@ enum {
kKeyPlatformPrivate = 'priv',
kKeyDecoderComponent = 'decC',
kKeyBufferID = 'bfID',
kKeyCompressedSize = 'cmpS',
kKeyMaxInputSize = 'inpS',
};
enum {

View File

@@ -155,6 +155,11 @@ private:
void setJPEGInputFormat(
OMX_U32 width, OMX_U32 height, OMX_U32 compressedSize);
void setMinBufferSize(OMX_U32 portIndex, OMX_U32 size);
void setRawAudioFormat(
OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels);
status_t allocateBuffers();
status_t allocateBuffersOnPort(OMX_U32 portIndex);

View File

@@ -301,7 +301,7 @@ sp<OMXCodec> OMXCodec::Create(
if (!strcasecmp("audio/3gpp", mime)) {
codec->setAMRFormat();
}
if (!createEncoder && !strcasecmp("audio/mp4a-latm", mime)) {
if (!strcasecmp("audio/mp4a-latm", mime)) {
int32_t numChannels, sampleRate;
CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
@@ -334,7 +334,7 @@ sp<OMXCodec> OMXCodec::Create(
int32_t compressedSize;
success = success && meta->findInt32(
kKeyCompressedSize, &compressedSize);
kKeyMaxInputSize, &compressedSize);
CHECK(success);
CHECK(compressedSize > 0);
@@ -343,11 +343,42 @@ sp<OMXCodec> OMXCodec::Create(
codec->setJPEGInputFormat(width, height, (OMX_U32)compressedSize);
}
int32_t maxInputSize;
if (createEncoder && meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
codec->setMinBufferSize(kPortIndexInput, (OMX_U32)maxInputSize);
}
if (!strcmp(componentName, "OMX.TI.AMR.encode")
|| !strcmp(componentName, "OMX.TI.WBAMR.encode")) {
codec->setMinBufferSize(kPortIndexOutput, 8192); // XXX
}
codec->initOutputFormat(meta);
return codec;
}
void OMXCodec::setMinBufferSize(OMX_U32 portIndex, OMX_U32 size) {
OMX_PARAM_PORTDEFINITIONTYPE def;
def.nSize = sizeof(def);
def.nVersion.s.nVersionMajor = 1;
def.nVersion.s.nVersionMinor = 1;
def.nPortIndex = portIndex;
status_t err = mOMX->get_parameter(
mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
CHECK_EQ(err, OK);
if (def.nBufferSize < size) {
def.nBufferSize = size;
}
err = mOMX->set_parameter(
mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
CHECK_EQ(err, OK);
}
status_t OMXCodec::setVideoPortFormatType(
OMX_U32 portIndex,
OMX_VIDEO_CODINGTYPE compressionFormat,
@@ -689,7 +720,6 @@ status_t OMXCodec::init() {
if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) {
err = mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
CHECK_EQ(err, OK);
setState(LOADED_TO_IDLE);
}
@@ -1430,6 +1460,41 @@ void OMXCodec::setState(State newState) {
mBufferFilled.signal();
}
void OMXCodec::setRawAudioFormat(
OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
pcmParams.nSize = sizeof(pcmParams);
pcmParams.nVersion.s.nVersionMajor = 1;
pcmParams.nVersion.s.nVersionMinor = 1;
pcmParams.nPortIndex = portIndex;
status_t err = mOMX->get_parameter(
mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
CHECK_EQ(err, OK);
pcmParams.nChannels = numChannels;
pcmParams.eNumData = OMX_NumericalDataSigned;
pcmParams.bInterleaved = OMX_TRUE;
pcmParams.nBitPerSample = 16;
pcmParams.nSamplingRate = sampleRate;
pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
if (numChannels == 1) {
pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
} else {
CHECK_EQ(numChannels, 2);
pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
}
err = mOMX->set_parameter(
mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
CHECK_EQ(err, OK);
}
void OMXCodec::setAMRFormat() {
if (!mIsEncoder) {
OMX_AUDIO_PARAM_AMRTYPE def;
@@ -1459,57 +1524,32 @@ void OMXCodec::setAMRFormat() {
CHECK(format->findInt32(kKeySampleRate, &sampleRate));
CHECK(format->findInt32(kKeyChannelCount, &numChannels));
OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
pcmParams.nSize = sizeof(pcmParams);
pcmParams.nVersion.s.nVersionMajor = 1;
pcmParams.nVersion.s.nVersionMinor = 1;
pcmParams.nPortIndex = kPortIndexInput;
status_t err = mOMX->get_parameter(
mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
CHECK_EQ(err, OK);
pcmParams.nChannels = numChannels;
pcmParams.eNumData = OMX_NumericalDataSigned;
pcmParams.bInterleaved = OMX_TRUE;
pcmParams.nBitPerSample = 16;
pcmParams.nSamplingRate = sampleRate;
pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
if (numChannels == 1) {
pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
} else {
CHECK_EQ(numChannels, 2);
pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
}
err = mOMX->set_parameter(
mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
CHECK_EQ(err, OK);
setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
}
}
void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate) {
OMX_AUDIO_PARAM_AACPROFILETYPE profile;
profile.nSize = sizeof(profile);
profile.nVersion.s.nVersionMajor = 1;
profile.nVersion.s.nVersionMinor = 1;
profile.nPortIndex = kPortIndexInput;
if (mIsEncoder) {
setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
} else {
OMX_AUDIO_PARAM_AACPROFILETYPE profile;
profile.nSize = sizeof(profile);
profile.nVersion.s.nVersionMajor = 1;
profile.nVersion.s.nVersionMinor = 1;
profile.nPortIndex = kPortIndexInput;
status_t err =
mOMX->get_parameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
CHECK_EQ(err, OK);
status_t err = mOMX->get_parameter(
mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
CHECK_EQ(err, OK);
profile.nChannels = numChannels;
profile.nSampleRate = sampleRate;
profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
profile.nChannels = numChannels;
profile.nSampleRate = sampleRate;
profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
err = mOMX->set_parameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
CHECK_EQ(err, OK);
err = mOMX->set_parameter(
mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
CHECK_EQ(err, OK);
}
}
void OMXCodec::setImageOutputFormat(
@@ -2102,40 +2142,46 @@ void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
{
OMX_AUDIO_PORTDEFINITIONTYPE *audio_def = &def.format.audio;
CHECK_EQ(audio_def->eEncoding, OMX_AUDIO_CodingPCM);
if (audio_def->eEncoding == OMX_AUDIO_CodingPCM) {
OMX_AUDIO_PARAM_PCMMODETYPE params;
params.nSize = sizeof(params);
params.nVersion.s.nVersionMajor = 1;
params.nVersion.s.nVersionMinor = 1;
params.nPortIndex = kPortIndexOutput;
OMX_AUDIO_PARAM_PCMMODETYPE params;
params.nSize = sizeof(params);
params.nVersion.s.nVersionMajor = 1;
params.nVersion.s.nVersionMinor = 1;
params.nPortIndex = kPortIndexOutput;
err = mOMX->get_parameter(
mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
CHECK_EQ(err, OK);
err = mOMX->get_parameter(
mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
CHECK_EQ(err, OK);
CHECK_EQ(params.eNumData, OMX_NumericalDataSigned);
CHECK_EQ(params.nBitPerSample, 16);
CHECK_EQ(params.ePCMMode, OMX_AUDIO_PCMModeLinear);
CHECK_EQ(params.eNumData, OMX_NumericalDataSigned);
CHECK_EQ(params.nBitPerSample, 16);
CHECK_EQ(params.ePCMMode, OMX_AUDIO_PCMModeLinear);
int32_t numChannels, sampleRate;
inputFormat->findInt32(kKeyChannelCount, &numChannels);
inputFormat->findInt32(kKeySampleRate, &sampleRate);
int32_t numChannels, sampleRate;
inputFormat->findInt32(kKeyChannelCount, &numChannels);
inputFormat->findInt32(kKeySampleRate, &sampleRate);
if ((OMX_U32)numChannels != params.nChannels) {
LOGW("Codec outputs a different number of channels than "
"the input stream contains.");
}
if ((OMX_U32)numChannels != params.nChannels) {
LOGW("Codec outputs a different number of channels than "
"the input stream contains.");
mOutputFormat->setCString(kKeyMIMEType, "audio/raw");
// Use the codec-advertised number of channels, as some
// codecs appear to output stereo even if the input data is
// mono.
mOutputFormat->setInt32(kKeyChannelCount, params.nChannels);
// The codec-reported sampleRate is not reliable...
mOutputFormat->setInt32(kKeySampleRate, sampleRate);
} else if (audio_def->eEncoding == OMX_AUDIO_CodingAMR) {
mOutputFormat->setCString(kKeyMIMEType, "audio/3gpp");
} else if (audio_def->eEncoding == OMX_AUDIO_CodingAAC) {
mOutputFormat->setCString(kKeyMIMEType, "audio/mp4a-latm");
} else {
CHECK(!"Should not be here. Unknown audio encoding.");
}
mOutputFormat->setCString(kKeyMIMEType, "audio/raw");
// Use the codec-advertised number of channels, as some
// codecs appear to output stereo even if the input data is
// mono.
mOutputFormat->setInt32(kKeyChannelCount, params.nChannels);
// The codec-reported sampleRate is not reliable...
mOutputFormat->setInt32(kKeySampleRate, sampleRate);
break;
}