summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Dong <jdong@google.com>2010-04-22 17:27:04 -0700
committerJames Dong <jdong@google.com>2010-05-03 15:47:41 -0700
commit050b28a593350047845a45a14cc5026221ac1620 (patch)
tree118de60bec960d36dd3784439f84e2bc1bba6d9f
parent86f69c1f41dcf4e0826b17ecf7fd71eb353b0782 (diff)
downloadframeworks_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
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp230
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.h17
-rw-r--r--media/libstagefright/AudioSource.cpp4
-rw-r--r--media/libstagefright/MPEG4Writer.cpp107
-rw-r--r--media/libstagefright/OMXCodec.cpp80
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 &params) {
- 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 &params) {
+ 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, &timestampUs));
@@ -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.");
}