diff options
-rw-r--r-- | cmds/stagefright/Android.mk | 1 | ||||
-rw-r--r-- | cmds/stagefright/JPEGSource.cpp | 2 | ||||
-rw-r--r-- | cmds/stagefright/SineSource.cpp | 100 | ||||
-rw-r--r-- | cmds/stagefright/SineSource.h | 39 | ||||
-rw-r--r-- | cmds/stagefright/record.cpp | 63 | ||||
-rw-r--r-- | include/media/stagefright/MetaData.h | 2 | ||||
-rw-r--r-- | include/media/stagefright/OMXCodec.h | 5 | ||||
-rw-r--r-- | media/libstagefright/OMXCodec.cpp | 192 |
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, ¶ms, sizeof(params)); - CHECK_EQ(err, OK); + err = mOMX->get_parameter( + mNode, OMX_IndexParamAudioPcm, ¶ms, 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; } |