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
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 @@
sp<MemoryDealer> mDealer[2];
sp<ANativeWindow> mNativeWindow;
+ int mNativeWindowUsageBits;
sp<AMessage> mInputFormat;
sp<AMessage> mOutputFormat;
sp<AMessage> mBaseOutputFormat;
@@ -266,7 +267,8 @@
status_t freeBuffer(OMX_U32 portIndex, size_t i);
status_t handleSetSurface(const sp<Surface> &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 @@
ACodec::ACodec()
: mQuirks(0),
mNode(0),
+ mNativeWindowUsageBits(0),
mSentFormat(false),
mIsVideo(false),
mIsEncoder(false),
@@ -642,7 +643,7 @@
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 @@
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 @@
}
mNativeWindow = nativeWindow;
+ mNativeWindowUsageBits = usageBits;
return OK;
}
@@ -868,7 +879,8 @@
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 @@
}
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 @@
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 @@
// 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 @@
}
mCodec->mNativeWindow.clear();
+ mCodec->mNativeWindowUsageBits = 0;
mCodec->mNode = 0;
mCodec->mOMX.clear();
mCodec->mQuirks = 0;