summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmds/stagefright/Android.mk1
-rw-r--r--cmds/stagefright/JPEGSource.cpp2
-rw-r--r--cmds/stagefright/SineSource.cpp100
-rw-r--r--cmds/stagefright/SineSource.h39
-rw-r--r--cmds/stagefright/record.cpp63
-rw-r--r--include/media/stagefright/MetaData.h2
-rw-r--r--include/media/stagefright/OMXCodec.h5
-rw-r--r--media/libstagefright/OMXCodec.cpp192
8 files changed, 328 insertions, 76 deletions
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index ef67611..51a0649 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -24,6 +24,7 @@ include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
+ SineSource.cpp \
record.cpp
LOCAL_SHARED_LIBRARIES := \
diff --git a/cmds/stagefright/JPEGSource.cpp b/cmds/stagefright/JPEGSource.cpp
index a7994ed..4e9ca4e 100644
--- a/cmds/stagefright/JPEGSource.cpp
+++ b/cmds/stagefright/JPEGSource.cpp
@@ -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;
}
diff --git a/cmds/stagefright/SineSource.cpp b/cmds/stagefright/SineSource.cpp
new file mode 100644
index 0000000..3c25a7f
--- /dev/null
+++ b/cmds/stagefright/SineSource.cpp
@@ -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
diff --git a/cmds/stagefright/SineSource.h b/cmds/stagefright/SineSource.h
new file mode 100644
index 0000000..76ab669
--- /dev/null
+++ b/cmds/stagefright/SineSource.h
@@ -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_
diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp
index 4b44761..c049594 100644
--- a/cmds/stagefright/record.cpp
+++ b/cmds/stagefright/record.cpp
@@ -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;
+}
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index be60565..abb45a9 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -45,7 +45,7 @@ enum {
kKeyPlatformPrivate = 'priv',
kKeyDecoderComponent = 'decC',
kKeyBufferID = 'bfID',
- kKeyCompressedSize = 'cmpS',
+ kKeyMaxInputSize = 'inpS',
};
enum {
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 5b0e0b4..6ddf2fe 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -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);
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 7c8defc..a132c66 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -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,59 +1524,34 @@ 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;
+ setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
+ }
+}
- status_t err = mOMX->get_parameter(
- mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
+void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate) {
+ 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);
- 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;
- }
+ profile.nChannels = numChannels;
+ profile.nSampleRate = sampleRate;
+ profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
err = mOMX->set_parameter(
- mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
-
+ mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
CHECK_EQ(err, OK);
}
}
-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;
-
- 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;
-
- err = mOMX->set_parameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
- CHECK_EQ(err, OK);
-}
-
void OMXCodec::setImageOutputFormat(
OMX_COLOR_FORMATTYPE format, OMX_U32 width, OMX_U32 height) {
LOGV("setImageOutputFormat(%ld, %ld)", width, height);
@@ -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);
-
- OMX_AUDIO_PARAM_PCMMODETYPE params;
- params.nSize = sizeof(params);
- params.nVersion.s.nVersionMajor = 1;
- params.nVersion.s.nVersionMinor = 1;
- params.nPortIndex = kPortIndexOutput;
+ 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;
- 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");
+ 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);
+ // 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);
+ // 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.");
+ }
break;
}