From e3635355e4cae5af7550b49888c6a0e3530b8aea Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Fri, 10 Jul 2015 18:59:06 -0700 Subject: MediaCodec: consider usage bits when changing surface. The new surface cannot add usage bits not already present (as already existing buffers may become unusable for the surface). Bug: 22414343 Change-Id: Id8169c79cd0994be134a16782dd04687e46ca1dd --- include/media/stagefright/ACodec.h | 4 +++- media/libstagefright/ACodec.cpp | 24 ++++++++++++++++++++---- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h index a4b24d7..2ca3f1c 100644 --- a/include/media/stagefright/ACodec.h +++ b/include/media/stagefright/ACodec.h @@ -215,6 +215,7 @@ private: sp mDealer[2]; sp mNativeWindow; + int mNativeWindowUsageBits; sp mInputFormat; sp mOutputFormat; sp mBaseOutputFormat; @@ -266,7 +267,8 @@ private: status_t freeBuffer(OMX_U32 portIndex, size_t i); status_t handleSetSurface(const sp &surface); - status_t setupNativeWindowSizeFormatAndUsage(ANativeWindow *nativeWindow /* nonnull */); + status_t setupNativeWindowSizeFormatAndUsage( + ANativeWindow *nativeWindow /* nonnull */, int *finalUsage /* nonnull */); status_t configureOutputBuffersFromNativeWindow( OMX_U32 *nBufferCount, OMX_U32 *nBufferSize, diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 9206b5c..ffd90b3 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -493,6 +493,7 @@ void ACodec::BufferInfo::checkReadFence(const char *dbg) { ACodec::ACodec() : mQuirks(0), mNode(0), + mNativeWindowUsageBits(0), mSentFormat(false), mIsVideo(false), mIsEncoder(false), @@ -642,7 +643,7 @@ status_t ACodec::handleSetSurface(const sp &surface) { return OK; } - // allow keeping unset surface + // cannot switch from bytebuffers to surface if (mNativeWindow == NULL) { ALOGW("component was not configured with a surface"); return INVALID_OPERATION; @@ -661,11 +662,20 @@ status_t ACodec::handleSetSurface(const sp &surface) { return INVALID_OPERATION; } - status_t err = setupNativeWindowSizeFormatAndUsage(nativeWindow); + int usageBits = 0; + status_t err = setupNativeWindowSizeFormatAndUsage(nativeWindow, &usageBits); if (err != OK) { return err; } + int ignoredFlags = (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER + | GRALLOC_USAGE_EXTERNAL_DISP); + // New output surface is not allowed to add new usage flag except ignored ones. + if ((usageBits & ~(mNativeWindowUsageBits | ignoredFlags)) != 0) { + ALOGW("cannot change usage from %#x to %#x", mNativeWindowUsageBits, usageBits); + return BAD_VALUE; + } + // get min undequeued count. We cannot switch to a surface that has a higher // undequeued count than we allocated. int minUndequeuedBuffers = 0; @@ -747,6 +757,7 @@ status_t ACodec::handleSetSurface(const sp &surface) { } mNativeWindow = nativeWindow; + mNativeWindowUsageBits = usageBits; return OK; } @@ -868,7 +879,8 @@ status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { return OK; } -status_t ACodec::setupNativeWindowSizeFormatAndUsage(ANativeWindow *nativeWindow /* nonnull */) { +status_t ACodec::setupNativeWindowSizeFormatAndUsage( + ANativeWindow *nativeWindow /* nonnull */, int *finalUsage /* nonnull */) { OMX_PARAM_PORTDEFINITIONTYPE def; InitOMXParams(&def); def.nPortIndex = kPortIndexOutput; @@ -894,6 +906,7 @@ status_t ACodec::setupNativeWindowSizeFormatAndUsage(ANativeWindow *nativeWindow } usage |= GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP; + *finalUsage = usage; ALOGV("gralloc usage: %#x(OMX) => %#x(ACodec)", omxUsage, usage); return setNativeWindowSizeFormatAndUsage( @@ -916,9 +929,10 @@ status_t ACodec::configureOutputBuffersFromNativeWindow( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); if (err == OK) { - err = setupNativeWindowSizeFormatAndUsage(mNativeWindow.get()); + err = setupNativeWindowSizeFormatAndUsage(mNativeWindow.get(), &mNativeWindowUsageBits); } if (err != OK) { + mNativeWindowUsageBits = 0; return err; } @@ -1937,6 +1951,7 @@ status_t ACodec::configureCodec( // to SW renderer ALOGI("[%s] Falling back to software renderer", mComponentName.c_str()); mNativeWindow.clear(); + mNativeWindowUsageBits = 0; haveNativeWindow = false; usingSwRenderer = true; if (storingMetadataInDecodedBuffers()) { @@ -5341,6 +5356,7 @@ void ACodec::UninitializedState::stateEntered() { } mCodec->mNativeWindow.clear(); + mCodec->mNativeWindowUsageBits = 0; mCodec->mNode = 0; mCodec->mOMX.clear(); mCodec->mQuirks = 0; -- cgit v1.1