From 7f498b90a4300ef9badf14d202b0a67c26e20931 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Fri, 2 Apr 2010 12:49:54 -0700 Subject: Coalesce multiple encoded AAC frames into a single input buffer on this particular OMX codec to increase throughput significantly. Change-Id: I90c7db6656a53339c5d454336548c4f00d0d9064 related-to-bug: 2548426 --- media/libstagefright/OMXCodec.cpp | 149 +++++++++++++++++++++++++++----------- 1 file changed, 108 insertions(+), 41 deletions(-) (limited to 'media/libstagefright/OMXCodec.cpp') diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 20d9540..2346639 100644 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -103,6 +103,7 @@ static const CodecInfo kDecoderInfo[] = { { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.TI.MP3.decode" }, { MEDIA_MIMETYPE_AUDIO_MPEG, "MP3Decoder" }, // { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.PV.mp3dec" }, +// { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.decode" }, { MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBDecoder" }, // { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.PV.amrdec" }, { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.decode" }, @@ -284,6 +285,7 @@ uint32_t OMXCodec::getComponentQuirks(const char *componentName) { if (!strcmp(componentName, "OMX.TI.AAC.decode")) { quirks |= kNeedsFlushBeforeDisable; quirks |= kRequiresFlushCompleteEmulation; + quirks |= kSupportsMultipleFramesPerInputBuffer; } if (!strncmp(componentName, "OMX.qcom.video.encoder.", 23)) { quirks |= kRequiresLoadedToIdleAfterAllocation; @@ -533,7 +535,28 @@ status_t OMXCodec::configureCodec(const sp &meta) { return err; } } + } else if (!strncasecmp(mMIME, "audio/", 6)) { + if ((mQuirks & kSupportsMultipleFramesPerInputBuffer) + && !strcmp(mComponentName, "OMX.TI.AAC.decode")) { + OMX_PARAM_PORTDEFINITIONTYPE def; + InitOMXParams(&def); + def.nPortIndex = kPortIndexInput; + + status_t err = mOMX->getParameter( + mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); + CHECK_EQ(err, OK); + + const size_t kMinBufferSize = 100 * 1024; + if (def.nBufferSize < kMinBufferSize) { + def.nBufferSize = kMinBufferSize; + } + + err = mOMX->setParameter( + mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); + CHECK_EQ(err, OK); + } } + if (!strcasecmp(mMIME, MEDIA_MIMETYPE_IMAGE_JPEG) && !strcmp(mComponentName, "OMX.TI.JPEG.decode")) { OMX_COLOR_FORMATTYPE format = @@ -1049,7 +1072,8 @@ OMXCodec::OMXCodec( mSignalledEOS(false), mNoMoreOutputData(false), mOutputPortSettingsHaveChanged(false), - mSeekTimeUs(-1) { + mSeekTimeUs(-1), + mLeftOverBuffer(NULL) { mPortStatus[kPortIndexInput] = ENABLED; mPortStatus[kPortIndexOutput] = ENABLED; @@ -1938,66 +1962,104 @@ void OMXCodec::drainInputBuffer(BufferInfo *info) { return; } - MediaBuffer *srcBuffer; status_t err; - if (mSeekTimeUs >= 0) { - MediaSource::ReadOptions options; - options.setSeekTo(mSeekTimeUs); - mSeekTimeUs = -1; - mBufferFilled.signal(); + bool signalEOS = false; + int64_t timestampUs = 0; - err = mSource->read(&srcBuffer, &options); - } else { - err = mSource->read(&srcBuffer); - } + size_t offset = 0; + int32_t n = 0; + for (;;) { + MediaBuffer *srcBuffer; + if (mSeekTimeUs >= 0) { + if (mLeftOverBuffer) { + mLeftOverBuffer->release(); + mLeftOverBuffer = NULL; + } - OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; - OMX_TICKS timestampUs = 0; - size_t srcLength = 0; + MediaSource::ReadOptions options; + options.setSeekTo(mSeekTimeUs); - if (err != OK) { - CODEC_LOGV("signalling end of input stream."); - flags |= OMX_BUFFERFLAG_EOS; + mSeekTimeUs = -1; + mBufferFilled.signal(); - mFinalStatus = err; - mSignalledEOS = true; - } else { - mNoMoreOutputData = false; + err = mSource->read(&srcBuffer, &options); + } else if (mLeftOverBuffer) { + srcBuffer = mLeftOverBuffer; + mLeftOverBuffer = NULL; + + err = OK; + } else { + err = mSource->read(&srcBuffer); + } - srcLength = srcBuffer->range_length(); + if (err != OK) { + signalEOS = true; + mFinalStatus = err; + mSignalledEOS = true; + break; + } - if (info->mSize < srcLength) { - CODEC_LOGE( - "Codec's input buffers are too small to accomodate " - "buffer read from source (info->mSize = %d, srcLength = %d)", - info->mSize, srcLength); + size_t remainingBytes = info->mSize - offset; - srcBuffer->release(); - srcBuffer = NULL; + if (srcBuffer->range_length() > remainingBytes) { + if (offset == 0) { + CODEC_LOGE( + "Codec's input buffers are too small to accomodate " + "buffer read from source (info->mSize = %d, srcLength = %d)", + info->mSize, srcBuffer->range_length()); - setState(ERROR); - return; + srcBuffer->release(); + srcBuffer = NULL; + + setState(ERROR); + return; + } + + mLeftOverBuffer = srcBuffer; + break; } - memcpy(info->mData, + + memcpy((uint8_t *)info->mData + offset, (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(), - srcLength); + srcBuffer->range_length()); - if (srcBuffer->meta_data()->findInt64(kKeyTime, ×tampUs)) { - CODEC_LOGV("Calling emptyBuffer on buffer %p (length %d), " - "timestamp %lld us (%.2f secs)", - info->mBuffer, srcLength, - timestampUs, timestampUs / 1E6); + if (offset == 0) { + CHECK(srcBuffer->meta_data()->findInt64(kKeyTime, ×tampUs)); + CHECK(timestampUs >= 0); } - } - if (srcBuffer != NULL) { + offset += srcBuffer->range_length(); + srcBuffer->release(); srcBuffer = NULL; + + ++n; + + if (!(mQuirks & kSupportsMultipleFramesPerInputBuffer)) { + break; + } } + if (n > 1) { + LOGV("coalesced %d frames into one input buffer", n); + } + + OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; + + if (signalEOS) { + flags |= OMX_BUFFERFLAG_EOS; + } else { + mNoMoreOutputData = false; + } + + CODEC_LOGV("Calling emptyBuffer on buffer %p (length %d), " + "timestamp %lld us (%.2f secs)", + info->mBuffer, offset, + timestampUs, timestampUs / 1E6); + err = mOMX->emptyBuffer( - mNode, info->mBuffer, 0, srcLength, + mNode, info->mBuffer, 0, offset, flags, timestampUs); if (err != OK) { @@ -2352,6 +2414,11 @@ status_t OMXCodec::stop() { } } + if (mLeftOverBuffer) { + mLeftOverBuffer->release(); + mLeftOverBuffer = NULL; + } + mSource->stop(); CODEC_LOGV("stopped"); -- cgit v1.1