diff options
author | James Dong <jdong@google.com> | 2010-04-22 17:27:04 -0700 |
---|---|---|
committer | James Dong <jdong@google.com> | 2010-05-03 15:47:41 -0700 |
commit | 050b28a593350047845a45a14cc5026221ac1620 (patch) | |
tree | 118de60bec960d36dd3784439f84e2bc1bba6d9f /media | |
parent | 86f69c1f41dcf4e0826b17ecf7fd71eb353b0782 (diff) | |
download | frameworks_av-050b28a593350047845a45a14cc5026221ac1620.zip frameworks_av-050b28a593350047845a45a14cc5026221ac1620.tar.gz frameworks_av-050b28a593350047845a45a14cc5026221ac1620.tar.bz2 |
Support AAC recording
- Extend the audio recording to AAC format
- Add support for setting some recording parameters
- Add stss box to the meta data in the recorded file
Change-Id: I41167bfd9d70ef9cd33906f8437b39c232b6d3b7
Diffstat (limited to 'media')
-rw-r--r-- | media/libmediaplayerservice/StagefrightRecorder.cpp | 230 | ||||
-rw-r--r-- | media/libmediaplayerservice/StagefrightRecorder.h | 17 | ||||
-rw-r--r-- | media/libstagefright/AudioSource.cpp | 4 | ||||
-rw-r--r-- | media/libstagefright/MPEG4Writer.cpp | 107 | ||||
-rw-r--r-- | media/libstagefright/OMXCodec.cpp | 80 |
5 files changed, 380 insertions, 58 deletions
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index a63d94b..682ff3a 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -36,6 +36,7 @@ #include <utils/Errors.h> #include <sys/types.h> #include <unistd.h> +#include <ctype.h> namespace android { @@ -149,9 +150,149 @@ status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t leng return OK; } -status_t StagefrightRecorder::setParameters(const String8 ¶ms) { - mParams = params; +// Attempt to parse an int64 literal optionally surrounded by whitespace, +// returns true on success, false otherwise. +static bool safe_strtoi64(const char *s, int32_t *val) { + char *end; + *val = static_cast<int32_t>(strtoll(s, &end, 10)); + + if (end == s || errno == ERANGE) { + return false; + } + + // Skip trailing whitespace + while (isspace(*end)) { + ++end; + } + + // For a successful return, the string must contain nothing but a valid + // int64 literal optionally surrounded by whitespace. + + return *end == '\0'; +} + +// Trim both leading and trailing whitespace from the given string. +static void TrimString(String8 *s) { + size_t num_bytes = s->bytes(); + const char *data = s->string(); + + size_t leading_space = 0; + while (leading_space < num_bytes && isspace(data[leading_space])) { + ++leading_space; + } + + size_t i = num_bytes; + while (i > leading_space && isspace(data[i - 1])) { + --i; + } + + s->setTo(String8(&data[leading_space], i - leading_space)); +} + +status_t StagefrightRecorder::setParamAudioSamplingRate(int32_t sampleRate) { + LOGV("setParamAudioSamplingRate: %d", sampleRate); + mSampleRate = sampleRate; + return OK; +} + +status_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) { + LOGV("setParamAudioNumberOfChannels: %d", channels); + mAudioChannels = channels; + return OK; +} + +status_t StagefrightRecorder::setParamAudioEncodingBitRate(int32_t bitRate) { + LOGV("setParamAudioEncodingBitRate: %d", bitRate); + mAudioBitRate = bitRate; + return OK; +} + +status_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) { + LOGV("setParamVideoEncodingBitRate: %d", bitRate); + mVideoBitRate = bitRate; + return OK; +} + +status_t StagefrightRecorder::setMaxDurationOrFileSize(int32_t limit, bool limit_is_duration) { + LOGV("setMaxDurationOrFileSize: limit (%d) for %s", + limit, limit_is_duration?"duration":"size"); + return OK; +} + +status_t StagefrightRecorder::setParameter( + const String8 &key, const String8 &value) { + LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string()); + if (key == "max-duration") { + int32_t max_duration_ms; + if (safe_strtoi64(value.string(), &max_duration_ms)) { + return setMaxDurationOrFileSize( + max_duration_ms, true /* limit_is_duration */); + } + } else if (key == "max-filesize") { + int32_t max_filesize_bytes; + if (safe_strtoi64(value.string(), &max_filesize_bytes)) { + return setMaxDurationOrFileSize( + max_filesize_bytes, false /* limit is filesize */); + } + } else if (key == "audio-param-sampling-rate") { + int32_t sampling_rate; + if (safe_strtoi64(value.string(), &sampling_rate)) { + return setParamAudioSamplingRate(sampling_rate); + } + } else if (key == "audio-param-number-of-channels") { + int32_t number_of_channels; + if (safe_strtoi64(value.string(), &number_of_channels)) { + return setParamAudioNumberOfChannels(number_of_channels); + } + } else if (key == "audio-param-encoding-bitrate") { + int32_t audio_bitrate; + if (safe_strtoi64(value.string(), &audio_bitrate)) { + return setParamAudioEncodingBitRate(audio_bitrate); + } + } else if (key == "video-param-encoding-bitrate") { + int32_t video_bitrate; + if (safe_strtoi64(value.string(), &video_bitrate)) { + return setParamVideoEncodingBitRate(video_bitrate); + } + } else { + LOGE("setParameter: failed to find key %s", key.string()); + return BAD_VALUE; + } + return OK; +} +status_t StagefrightRecorder::setParameters(const String8 ¶ms) { + LOGV("setParameters: %s", params.string()); + const char *cparams = params.string(); + const char *key_start = cparams; + for (;;) { + const char *equal_pos = strchr(key_start, '='); + if (equal_pos == NULL) { + LOGE("Parameters %s miss a value", cparams); + return BAD_VALUE; + } + String8 key(key_start, equal_pos - key_start); + TrimString(&key); + if (key.length() == 0) { + LOGE("Parameters %s contains an empty key", cparams); + return BAD_VALUE; + } + const char *value_start = equal_pos + 1; + const char *semicolon_pos = strchr(value_start, ';'); + String8 value; + if (semicolon_pos == NULL) { + value.setTo(value_start); + } else { + value.setTo(value_start, semicolon_pos - value_start); + } + if (setParameter(key, value) != OK) { + return BAD_VALUE; + } + if (semicolon_pos == NULL) { + break; // Reaches the end + } + key_start = semicolon_pos + 1; + } return OK; } @@ -185,35 +326,46 @@ status_t StagefrightRecorder::start() { } } -sp<MediaSource> StagefrightRecorder::createAMRAudioSource() { - uint32_t sampleRate = - mAudioEncoder == AUDIO_ENCODER_AMR_NB ? 8000 : 16000; - +sp<MediaSource> StagefrightRecorder::createAudioSource() { sp<AudioSource> audioSource = new AudioSource( mAudioSource, - sampleRate, + mSampleRate, AudioSystem::CHANNEL_IN_MONO); status_t err = audioSource->initCheck(); if (err != OK) { + LOGE("audio source is not initialized"); 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); + const char *mime; + switch (mAudioEncoder) { + case AUDIO_ENCODER_AMR_NB: + case AUDIO_ENCODER_DEFAULT: + mime = MEDIA_MIMETYPE_AUDIO_AMR_NB; + break; + case AUDIO_ENCODER_AMR_WB: + mime = MEDIA_MIMETYPE_AUDIO_AMR_WB; + break; + case AUDIO_ENCODER_AAC: + mime = MEDIA_MIMETYPE_AUDIO_AAC; + break; + default: + LOGE("Unknown audio encoder: %d", mAudioEncoder); + return NULL; + } + encMeta->setCString(kKeyMIMEType, mime); int32_t maxInputSize; CHECK(audioSource->getFormat()->findInt32( kKeyMaxInputSize, &maxInputSize)); encMeta->setInt32(kKeyMaxInputSize, maxInputSize); - encMeta->setInt32(kKeyChannelCount, 1); - encMeta->setInt32(kKeySampleRate, sampleRate); + encMeta->setInt32(kKeyChannelCount, mAudioChannels); + encMeta->setInt32(kKeySampleRate, mSampleRate); OMXClient client; CHECK_EQ(client.connect(), OK); @@ -240,7 +392,7 @@ status_t StagefrightRecorder::startAMRRecording() { return UNKNOWN_ERROR; } - sp<MediaSource> audioEncoder = createAMRAudioSource(); + sp<MediaSource> audioEncoder = createAudioSource(); if (audioEncoder == NULL) { return UNKNOWN_ERROR; @@ -257,6 +409,26 @@ status_t StagefrightRecorder::startAMRRecording() { status_t StagefrightRecorder::startMPEG4Recording() { mWriter = new MPEG4Writer(dup(mOutputFd)); + // Add audio source first if it exists + if (mAudioSource != AUDIO_SOURCE_LIST_END) { + sp<MediaSource> audioEncoder; + switch(mAudioEncoder) { + case AUDIO_ENCODER_AMR_NB: + case AUDIO_ENCODER_AMR_WB: + case AUDIO_ENCODER_AAC: + audioEncoder = createAudioSource(); + break; + default: + LOGE("Unsupported audio encoder: %d", mAudioEncoder); + return UNKNOWN_ERROR; + } + + if (audioEncoder == NULL) { + return UNKNOWN_ERROR; + } + + mWriter->addSource(audioEncoder); + } if (mVideoSource == VIDEO_SOURCE_DEFAULT || mVideoSource == VIDEO_SOURCE_CAMERA) { CHECK(mCamera != NULL); @@ -308,16 +480,6 @@ status_t StagefrightRecorder::startMPEG4Recording() { mWriter->addSource(encoder); } - if (mAudioSource != AUDIO_SOURCE_LIST_END) { - sp<MediaSource> audioEncoder = createAMRAudioSource(); - - if (audioEncoder == NULL) { - return UNKNOWN_ERROR; - } - - mWriter->addSource(audioEncoder); - } - mWriter->start(); return OK; } @@ -353,14 +515,22 @@ status_t StagefrightRecorder::close() { status_t StagefrightRecorder::reset() { stop(); + // No audio or video source by default mAudioSource = AUDIO_SOURCE_LIST_END; mVideoSource = VIDEO_SOURCE_LIST_END; - mOutputFormat = OUTPUT_FORMAT_LIST_END; - mAudioEncoder = AUDIO_ENCODER_LIST_END; - mVideoEncoder = VIDEO_ENCODER_LIST_END; - mVideoWidth = -1; - mVideoHeight = -1; - mFrameRate = -1; + + // Default parameters + mOutputFormat = OUTPUT_FORMAT_THREE_GPP; + mAudioEncoder = AUDIO_ENCODER_AMR_NB; + mVideoEncoder = VIDEO_ENCODER_H263; + mVideoWidth = 176; + mVideoHeight = 144; + mFrameRate = 20; + mVideoBitRate = 192000; + mSampleRate = 8000; + mAudioChannels = 1; + mAudioBitRate = 12200; + mOutputFd = -1; mFlags = 0; diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h index 2f2f748..ad1153c 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.h +++ b/media/libmediaplayerservice/StagefrightRecorder.h @@ -68,15 +68,26 @@ private: output_format mOutputFormat; audio_encoder mAudioEncoder; video_encoder mVideoEncoder; - int mVideoWidth, mVideoHeight; - int mFrameRate; + int32_t mVideoWidth, mVideoHeight; + int32_t mFrameRate; + int32_t mVideoBitRate; + int32_t mAudioBitRate; + int32_t mAudioChannels; + int32_t mSampleRate; + String8 mParams; int mOutputFd; int32_t mFlags; status_t startMPEG4Recording(); status_t startAMRRecording(); - sp<MediaSource> createAMRAudioSource(); + sp<MediaSource> createAudioSource(); + status_t setParameter(const String8 &key, const String8 &value); + status_t setParamVideoEncodingBitRate(int32_t bitRate); + status_t setParamAudioEncodingBitRate(int32_t bitRate); + status_t setParamAudioNumberOfChannels(int32_t channles); + status_t setParamAudioSamplingRate(int32_t sampleRate); + status_t setMaxDurationOrFileSize(int32_t limit, bool limit_is_duration); StagefrightRecorder(const StagefrightRecorder &); StagefrightRecorder &operator=(const StagefrightRecorder &); diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp index edabaf9..abd8abc 100644 --- a/media/libstagefright/AudioSource.cpp +++ b/media/libstagefright/AudioSource.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +//#define LOG_NDEBUG 0 +#define LOG_TAG "AudioSource" +#include <utils/Log.h> + #include <media/stagefright/AudioSource.h> #include <media/AudioRecord.h> diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp index 5ff2abe..e6336e7 100644 --- a/media/libstagefright/MPEG4Writer.cpp +++ b/media/libstagefright/MPEG4Writer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +//#define LOG_NDEBUG 0 +#define LOG_TAG "MPEG4Writer" +#include <utils/Log.h> + #include <arpa/inet.h> #include <ctype.h> @@ -58,6 +62,8 @@ private: }; List<SampleInfo> mSampleInfos; + List<int32_t> mStssTableEntries; + void *mCodecSpecificData; size_t mCodecSpecificDataSize; bool mGotAllCodecSpecificData; @@ -522,7 +528,8 @@ void MPEG4Writer::Track::threadEntry() { sp<MetaData> meta = mSource->getFormat(); const char *mime; meta->findCString(kKeyMIMEType, &mime); - bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4); + bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || + !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); bool is_avc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); int32_t count = 0; @@ -668,6 +675,9 @@ void MPEG4Writer::Track::threadEntry() { info.offset = offset; + + bool is_audio = !strncasecmp(mime, "audio/", 6); + int64_t timestampUs; CHECK(buffer->meta_data()->findInt64(kKeyTime, ×tampUs)); @@ -680,6 +690,12 @@ void MPEG4Writer::Track::threadEntry() { mSampleInfos.push_back(info); + int32_t isSync = false; + buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync); + if (isSync) { + mStssTableEntries.push_back(mSampleInfos.size()); + } + // Our timestamp is in ms. buffer->release(); buffer = NULL; } @@ -735,8 +751,8 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { success = success && mMeta->findInt32(kKeyHeight, &height); CHECK(success); - mOwner->writeInt32(width); - mOwner->writeInt32(height); + mOwner->writeInt32(width << 16); // 32-bit fixed-point value + mOwner->writeInt32(height << 16); // 32-bit fixed-point value } mOwner->endBox(); // tkhd @@ -754,26 +770,15 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { mOwner->beginBox("hdlr"); mOwner->writeInt32(0); // version=0, flags=0 - mOwner->writeInt32(0); // predefined - mOwner->writeFourcc(is_audio ? "soun" : "vide"); + mOwner->writeInt32(0); // component type: should be mhlr + mOwner->writeFourcc(is_audio ? "soun" : "vide"); // component subtype mOwner->writeInt32(0); // reserved mOwner->writeInt32(0); // reserved mOwner->writeInt32(0); // reserved - mOwner->writeCString(""); // name + mOwner->writeCString("SoundHandler"); // name mOwner->endBox(); mOwner->beginBox("minf"); - - mOwner->beginBox("dinf"); - mOwner->beginBox("dref"); - mOwner->writeInt32(0); // version=0, flags=0 - mOwner->writeInt32(1); - mOwner->beginBox("url "); - mOwner->writeInt32(1); // version=0, flags=1 - mOwner->endBox(); // url - mOwner->endBox(); // dref - mOwner->endBox(); // dinf - if (is_audio) { mOwner->beginBox("smhd"); mOwner->writeInt32(0); // version=0, flags=0 @@ -789,7 +794,18 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { mOwner->writeInt16(0); mOwner->endBox(); } - mOwner->endBox(); // minf + + mOwner->beginBox("dinf"); + mOwner->beginBox("dref"); + mOwner->writeInt32(0); // version=0, flags=0 + mOwner->writeInt32(1); + mOwner->beginBox("url "); + mOwner->writeInt32(1); // version=0, flags=1 + mOwner->endBox(); // url + mOwner->endBox(); // dref + mOwner->endBox(); // dinf + + mOwner->endBox(); // minf mOwner->beginBox("stbl"); @@ -802,6 +818,8 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { fourcc = "samr"; } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { fourcc = "sawb"; + } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { + fourcc = "mp4a"; } else { LOGE("Unknown mime type '%s'.", mime); CHECK(!"should not be here, unknown mime type."); @@ -810,10 +828,12 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { mOwner->beginBox(fourcc); // audio format mOwner->writeInt32(0); // reserved mOwner->writeInt16(0); // reserved - mOwner->writeInt16(0); // data ref index + mOwner->writeInt16(0x1); // data ref index mOwner->writeInt32(0); // reserved mOwner->writeInt32(0); // reserved - mOwner->writeInt16(2); // channel count + int32_t nChannels; + CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); + mOwner->writeInt16(nChannels); // channel count mOwner->writeInt16(16); // sample size mOwner->writeInt16(0); // predefined mOwner->writeInt16(0); // reserved @@ -823,6 +843,38 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { CHECK(success); mOwner->writeInt32(samplerate << 16); + if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { + mOwner->beginBox("esds"); + + mOwner->writeInt32(0); // version=0, flags=0 + mOwner->writeInt8(0x03); // ES_DescrTag + mOwner->writeInt8(23 + mCodecSpecificDataSize); + mOwner->writeInt16(0x0000);// ES_ID + mOwner->writeInt8(0x00); + + mOwner->writeInt8(0x04); // DecoderConfigDescrTag + mOwner->writeInt8(15 + mCodecSpecificDataSize); + mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 + mOwner->writeInt8(0x15); // streamType AudioStream + + mOwner->writeInt16(0x03); // XXX + mOwner->writeInt8(0x00); // buffer size 24-bit + mOwner->writeInt32(96000); // max bit rate + mOwner->writeInt32(96000); // avg bit rate + + mOwner->writeInt8(0x05); // DecoderSpecificInfoTag + mOwner->writeInt8(mCodecSpecificDataSize); + mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); + + static const uint8_t kData2[] = { + 0x06, // SLConfigDescriptorTag + 0x01, + 0x02 + }; + mOwner->write(kData2, sizeof(kData2)); + + mOwner->endBox(); // esds + } mOwner->endBox(); } else { if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { @@ -883,7 +935,7 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { 0x00, 0x03, 0xe8, 0x00 }; mOwner->write(kData, sizeof(kData)); - + mOwner->writeInt8(0x05); // DecoderSpecificInfoTag mOwner->writeInt8(mCodecSpecificDataSize); @@ -943,6 +995,17 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { mOwner->endBox(); // stts + if (!is_audio) { + mOwner->beginBox("stss"); + mOwner->writeInt32(0); // version=0, flags=0 + mOwner->writeInt32(mStssTableEntries.size()); // number of sync frames + for (List<int32_t>::iterator it = mStssTableEntries.begin(); + it != mStssTableEntries.end(); ++it) { + mOwner->writeInt32(*it); + } + mOwner->endBox(); // stss + } + mOwner->beginBox("stsz"); mOwner->writeInt32(0); // version=0, flags=0 mOwner->writeInt32(0); // default sample size @@ -969,7 +1032,7 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { mOwner->writeInt32(0); // version=0, flags=0 mOwner->writeInt32(mSampleInfos.size()); for (List<SampleInfo>::iterator it = mSampleInfos.begin(); - it != mSampleInfos.end(); ++it, ++n) { + it != mSampleInfos.end(); ++it) { mOwner->writeInt64((*it).offset); } mOwner->endBox(); // co64 diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 41be9ac..b7d6d42 100644 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -520,6 +520,7 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) { setAACFormat(numChannels, sampleRate); } + if (!strncasecmp(mMIME, "video/", 6)) { int32_t width, height; bool success = meta->findInt32(kKeyWidth, &width); @@ -567,7 +568,8 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) { } if (!strcmp(mComponentName, "OMX.TI.AMR.encode") - || !strcmp(mComponentName, "OMX.TI.WBAMR.encode")) { + || !strcmp(mComponentName, "OMX.TI.WBAMR.encode") + || !strcmp(mComponentName, "OMX.TI.AAC.encode")) { setMinBufferSize(kPortIndexOutput, 8192); // XXX } @@ -708,7 +710,7 @@ void OMXCodec::setVideoInputFormat( OMX_COLOR_FORMATTYPE colorFormat = OMX_COLOR_FormatYUV420SemiPlanar; if (!strcasecmp("OMX.TI.Video.encoder", mComponentName)) { - colorFormat = OMX_COLOR_FormatYUV420Planar; + colorFormat = OMX_COLOR_FormatYCbYCr; } @@ -2127,11 +2129,24 @@ void OMXCodec::setState(State newState) { void OMXCodec::setRawAudioFormat( OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) { + + // port definition + OMX_PARAM_PORTDEFINITIONTYPE def; + InitOMXParams(&def); + def.nPortIndex = portIndex; + status_t err = mOMX->getParameter( + mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); + CHECK_EQ(err, OK); + def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; + CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition, + &def, sizeof(def)), OK); + + // pcm param OMX_AUDIO_PARAM_PCMMODETYPE pcmParams; InitOMXParams(&pcmParams); pcmParams.nPortIndex = portIndex; - status_t err = mOMX->getParameter( + err = mOMX->getParameter( mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); CHECK_EQ(err, OK); @@ -2171,6 +2186,8 @@ void OMXCodec::setAMRFormat(bool isWAMR) { CHECK_EQ(err, OK); def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; + + // XXX: Select bandmode based on bit rate def.eAMRBandMode = isWAMR ? OMX_AUDIO_AMRBandModeWB0 : OMX_AUDIO_AMRBandModeNB0; @@ -2191,8 +2208,60 @@ void OMXCodec::setAMRFormat(bool isWAMR) { } void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate) { + CHECK(numChannels == 1 || numChannels == 2); if (mIsEncoder) { + //////////////// input port //////////////////// setRawAudioFormat(kPortIndexInput, sampleRate, numChannels); + + //////////////// output port //////////////////// + // format + OMX_AUDIO_PARAM_PORTFORMATTYPE format; + format.nPortIndex = kPortIndexOutput; + format.nIndex = 0; + status_t err = OMX_ErrorNone; + while (OMX_ErrorNone == err) { + CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioPortFormat, + &format, sizeof(format)), OK); + if (format.eEncoding == OMX_AUDIO_CodingAAC) { + break; + } + format.nIndex++; + } + CHECK_EQ(OK, err); + CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioPortFormat, + &format, sizeof(format)), OK); + + // port definition + OMX_PARAM_PORTDEFINITIONTYPE def; + InitOMXParams(&def); + def.nPortIndex = kPortIndexOutput; + CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamPortDefinition, + &def, sizeof(def)), OK); + def.format.audio.bFlagErrorConcealment = OMX_TRUE; + def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; + CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition, + &def, sizeof(def)), OK); + + // profile + OMX_AUDIO_PARAM_AACPROFILETYPE profile; + InitOMXParams(&profile); + profile.nPortIndex = kPortIndexOutput; + CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioAac, + &profile, sizeof(profile)), OK); + profile.nChannels = numChannels; + profile.eChannelMode = (numChannels == 1? + OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo); + profile.nSampleRate = sampleRate; + profile.nBitRate = 96000; // XXX + profile.nAudioBandWidth = 0; + profile.nFrameLength = 0; + profile.nAACtools = OMX_AUDIO_AACToolAll; + profile.nAACERtools = OMX_AUDIO_AACERNone; + profile.eAACProfile = OMX_AUDIO_AACObjectLC; + profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF; + CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioAac, + &profile, sizeof(profile)), OK); + } else { OMX_AUDIO_PARAM_AACPROFILETYPE profile; InitOMXParams(&profile); @@ -2961,6 +3030,11 @@ void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) { } else if (audio_def->eEncoding == OMX_AUDIO_CodingAAC) { mOutputFormat->setCString( kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC); + int32_t numChannels, sampleRate; + inputFormat->findInt32(kKeyChannelCount, &numChannels); + inputFormat->findInt32(kKeySampleRate, &sampleRate); + mOutputFormat->setInt32(kKeyChannelCount, numChannels); + mOutputFormat->setInt32(kKeySampleRate, sampleRate); } else { CHECK(!"Should not be here. Unknown audio encoding."); } |