From 8b432b1d85259a463198db3efa5c50e59c254686 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Wed, 7 Oct 2009 13:36:52 -0700 Subject: [PATCH] Workaround for avc decoder misreporting output buffer size requirements if the content is not a multiple-16 width/height. --- include/media/stagefright/OMXCodec.h | 1 + media/libstagefright/OMXCodec.cpp | 32 ++++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h index ff7e34a886a7a..e19830bb6c60f 100644 --- a/include/media/stagefright/OMXCodec.h +++ b/include/media/stagefright/OMXCodec.h @@ -90,6 +90,7 @@ private: kRequiresFlushCompleteEmulation = 16, kRequiresAllocateBufferOnOutputPorts = 32, kRequiresFlushBeforeShutdown = 64, + kAlwaysAllocateOutputWithPadding = 128, }; struct BufferInfo { diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index c4c6149df9475..26c6a9e066782 100644 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -39,6 +39,8 @@ namespace android { +static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00; + struct CodecInfo { const char *mime; const char *codec; @@ -243,6 +245,15 @@ sp OMXCodec::Create( quirks |= kRequiresAllocateBufferOnOutputPorts; } + if (!strcmp(componentName, "OMX.qcom.video.decoder.avc")) { + // This decoder misreports the required output buffer size if + // the content in question is not a multiple-16 width/height. + + // XXX Not enabled by default to make the bug reproducible by + // the vendor. + // quirks |= kAlwaysAllocateOutputWithPadding; + } + sp codec = new OMXCodec( omx, node, quirks, createEncoder, mime, componentName, source); @@ -837,6 +848,25 @@ status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) { return err; } + if ((portIndex == kPortIndexOutput) + && (mQuirks & kAlwaysAllocateOutputWithPadding)) { + CHECK_EQ(def.eDomain, OMX_PortDomainVideo); + const OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; + CHECK_EQ(videoDef->eColorFormat, OMX_QCOM_COLOR_FormatYVU420SemiPlanar); + + OMX_U32 width = (videoDef->nFrameWidth + 15) & ~0x0f; + OMX_U32 height = (videoDef->nFrameHeight + 15) & ~0x0f; + + size_t newBufferSize = (width * height * 3) / 2; + CHECK(newBufferSize >= def.nBufferSize); + if (newBufferSize > def.nBufferSize) { + CODEC_LOGV("Rounding up output buffersize from %ld to %ld " + "to accomodate multiple-of-16 alignment.", + def.nBufferSize, newBufferSize); + } + def.nBufferSize = newBufferSize; + } + size_t totalSize = def.nBufferCountActual * def.nBufferSize; mDealer[portIndex] = new MemoryDealer(totalSize); @@ -2017,8 +2047,6 @@ static const char *colorFormatString(OMX_COLOR_FORMATTYPE type) { size_t numNames = sizeof(kNames) / sizeof(kNames[0]); - static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00; - if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) { return "OMX_QCOM_COLOR_FormatYVU420SemiPlanar"; } else if (type < 0 || (size_t)type >= numNames) {