summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2011-09-28 12:37:36 -0700
committerAndreas Huber <andih@google.com>2011-09-28 12:37:36 -0700
commit729de186450f78c099637e1fce743fe531862c52 (patch)
treebf05611a1943104189abce2f9b09514f2ec2adeb
parentac4d4d3698e920b9f5c648a781df5b6af8bcfdf0 (diff)
Support AMR, G.711 and vorbis audio in ACodec and friends.
Change-Id: I08c03219bf2d60fc5c6e89957bd4b4c615570983
-rw-r--r--cmds/stagefright/sf2.cpp51
-rw-r--r--include/media/stagefright/ACodec.h6
-rw-r--r--media/libstagefright/ACodec.cpp96
-rwxr-xr-xmedia/libstagefright/OMXCodec.cpp2
4 files changed, 147 insertions, 8 deletions
diff --git a/cmds/stagefright/sf2.cpp b/cmds/stagefright/sf2.cpp
index 263ecd14..f547e019 100644
--- a/cmds/stagefright/sf2.cpp
+++ b/cmds/stagefright/sf2.cpp
@@ -46,7 +46,8 @@ struct Controller : public AHandler {
mDecodeAudio(decodeAudio),
mSurface(surface),
mRenderToSurface(renderToSurface),
- mCodec(new ACodec) {
+ mCodec(new ACodec),
+ mIsVorbis(false) {
CHECK(!mDecodeAudio || mSurface == NULL);
}
@@ -85,6 +86,12 @@ protected:
if (!strncasecmp(mDecodeAudio ? "audio/" : "video/",
mime, 6)) {
mSource = extractor->getTrack(i);
+
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
+ mIsVorbis = true;
+ } else {
+ mIsVorbis = false;
+ }
break;
}
}
@@ -227,6 +234,7 @@ private:
bool mRenderToSurface;
sp<ACodec> mCodec;
sp<MediaSource> mSource;
+ bool mIsVorbis;
Vector<sp<ABuffer> > mCSD;
size_t mCSDIndex;
@@ -369,6 +377,20 @@ private:
buffer->meta()->setInt32("csd", true);
mCSD.push(buffer);
+ } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) {
+ sp<ABuffer> buffer = new ABuffer(size);
+ memcpy(buffer->data(), data, size);
+
+ buffer->meta()->setInt32("csd", true);
+ mCSD.push(buffer);
+
+ CHECK(meta->findData(kKeyVorbisBooks, &type, &data, &size));
+
+ buffer = new ABuffer(size);
+ memcpy(buffer->data(), data, size);
+
+ buffer->meta()->setInt32("csd", true);
+ mCSD.push(buffer);
}
int32_t maxInputSize;
@@ -423,10 +445,17 @@ private:
}
}
- if (inBuffer->range_length() > sizeLeft) {
+ size_t sizeNeeded = inBuffer->range_length();
+ if (mIsVorbis) {
+ // Vorbis data is suffixed with the number of
+ // valid samples on the page.
+ sizeNeeded += sizeof(int32_t);
+ }
+
+ if (sizeNeeded > sizeLeft) {
if (outBuffer->size() == 0) {
LOGE("Unable to fit even a single input buffer of size %d.",
- inBuffer->range_length());
+ sizeNeeded);
}
CHECK_GT(outBuffer->size(), 0u);
@@ -448,10 +477,22 @@ private:
+ inBuffer->range_offset(),
inBuffer->range_length());
+ if (mIsVorbis) {
+ int32_t numPageSamples;
+ if (!inBuffer->meta_data()->findInt32(
+ kKeyValidSamples, &numPageSamples)) {
+ numPageSamples = -1;
+ }
+
+ memcpy(outBuffer->data()
+ + outBuffer->size() + inBuffer->range_length(),
+ &numPageSamples, sizeof(numPageSamples));
+ }
+
outBuffer->setRange(
- 0, outBuffer->size() + inBuffer->range_length());
+ 0, outBuffer->size() + sizeNeeded);
- sizeLeft -= inBuffer->range_length();
+ sizeLeft -= sizeNeeded;
inBuffer->release();
inBuffer = NULL;
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 9da99077..58228772 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -151,6 +151,12 @@ private:
OMX_VIDEO_CODINGTYPE compressionFormat);
status_t setupAACDecoder(int32_t numChannels, int32_t sampleRate);
+ status_t setupAMRDecoder(bool isWAMR);
+ status_t setupG711Decoder(int32_t numChannels);
+
+ status_t setupRawAudioFormat(
+ OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels);
+
status_t setMinBufferSize(OMX_U32 portIndex, size_t size);
status_t initNativeWindow();
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index a3746cdc..9cb18de2 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -687,6 +687,8 @@ void ACodec::setComponentRole(
"audio_decoder.amrwb", "audio_encoder.amrwb" },
{ MEDIA_MIMETYPE_AUDIO_AAC,
"audio_decoder.aac", "audio_encoder.aac" },
+ { MEDIA_MIMETYPE_AUDIO_VORBIS,
+ "audio_decoder.vorbis", "audio_encoder.vorbis" },
{ MEDIA_MIMETYPE_VIDEO_AVC,
"video_decoder.avc", "video_encoder.avc" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4,
@@ -750,9 +752,19 @@ void ACodec::configureCodec(
CHECK(msg->findInt32("sample-rate", &sampleRate));
CHECK_EQ(setupAACDecoder(numChannels, sampleRate), (status_t)OK);
- } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
- } else {
- TRESPASS();
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
+ CHECK_EQ(setupAMRDecoder(false /* isWAMR */), (status_t)OK);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
+ CHECK_EQ(setupAMRDecoder(true /* isWAMR */), (status_t)OK);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
+ || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
+ // These are PCM-like formats with a fixed sample rate but
+ // a variable number of channels.
+
+ int32_t numChannels;
+ CHECK(msg->findInt32("channel-count", &numChannels));
+
+ CHECK_EQ(setupG711Decoder(numChannels), (status_t)OK);
}
int32_t maxInputSize;
@@ -824,6 +836,84 @@ status_t ACodec::setupAACDecoder(int32_t numChannels, int32_t sampleRate) {
return err;
}
+status_t ACodec::setupAMRDecoder(bool isWAMR) {
+ OMX_AUDIO_PARAM_AMRTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = kPortIndexInput;
+
+ status_t err =
+ mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
+
+ if (err != OK) {
+ return err;
+ }
+
+ def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
+
+ def.eAMRBandMode =
+ isWAMR ? OMX_AUDIO_AMRBandModeWB0 : OMX_AUDIO_AMRBandModeNB0;
+
+ return mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
+}
+
+status_t ACodec::setupG711Decoder(int32_t numChannels) {
+ return setupRawAudioFormat(
+ kPortIndexInput, 8000 /* sampleRate */, numChannels);
+}
+
+status_t ACodec::setupRawAudioFormat(
+ OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = portIndex;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ if (err != OK) {
+ return err;
+ }
+
+ def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ if (err != OK) {
+ return err;
+ }
+
+ OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
+ InitOMXParams(&pcmParams);
+ pcmParams.nPortIndex = portIndex;
+
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
+
+ if (err != OK) {
+ return err;
+ }
+
+ 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;
+ }
+
+ return mOMX->setParameter(
+ mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
+}
+
status_t ACodec::setVideoPortFormatType(
OMX_U32 portIndex,
OMX_VIDEO_CODINGTYPE compressionFormat,
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 9eb1469c..e94a8d71 100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1485,6 +1485,8 @@ void OMXCodec::setComponentRole(
"audio_decoder.amrwb", "audio_encoder.amrwb" },
{ MEDIA_MIMETYPE_AUDIO_AAC,
"audio_decoder.aac", "audio_encoder.aac" },
+ { MEDIA_MIMETYPE_AUDIO_VORBIS,
+ "audio_decoder.vorbis", "audio_encoder.vorbis" },
{ MEDIA_MIMETYPE_VIDEO_AVC,
"video_decoder.avc", "video_encoder.avc" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4,