Skip to content

Commit 5ded5fc

Browse files
Jamie GennisAndroid Git Automerger
authored andcommitted
am b7b4eaa: Merge "Stagefright: push blank buffers when tearing down" into ics-mr0
* commit 'b7b4eaaa05284634d50d581d924a250f1194f66d': Stagefright: push blank buffers when tearing down
2 parents 6f44442 + b7b4eaa commit 5ded5fc

File tree

2 files changed

+161
-0
lines changed

2 files changed

+161
-0
lines changed

include/media/stagefright/OMXCodec.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ struct OMXCodec : public MediaSource,
277277
status_t queueBufferToNativeWindow(BufferInfo *info);
278278
status_t cancelBufferToNativeWindow(BufferInfo *info);
279279
BufferInfo* dequeueBufferFromNativeWindow();
280+
status_t pushBlankBuffersToNativeWindow();
280281

281282
status_t freeBuffersOnPort(
282283
OMX_U32 portIndex, bool onlyThoseWeOwn = false);

media/libstagefright/OMXCodec.cpp

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2010,6 +2010,157 @@ OMXCodec::BufferInfo* OMXCodec::dequeueBufferFromNativeWindow() {
20102010
return bufInfo;
20112011
}
20122012

2013+
status_t OMXCodec::pushBlankBuffersToNativeWindow() {
2014+
status_t err = NO_ERROR;
2015+
ANativeWindowBuffer* anb = NULL;
2016+
int numBufs = 0;
2017+
int minUndequeuedBufs = 0;
2018+
2019+
// We need to reconnect to the ANativeWindow as a CPU client to ensure that
2020+
// no frames get dropped by SurfaceFlinger assuming that these are video
2021+
// frames.
2022+
err = native_window_api_disconnect(mNativeWindow.get(),
2023+
NATIVE_WINDOW_API_MEDIA);
2024+
if (err != NO_ERROR) {
2025+
LOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
2026+
strerror(-err), -err);
2027+
return err;
2028+
}
2029+
2030+
err = native_window_api_connect(mNativeWindow.get(),
2031+
NATIVE_WINDOW_API_CPU);
2032+
if (err != NO_ERROR) {
2033+
LOGE("error pushing blank frames: api_connect failed: %s (%d)",
2034+
strerror(-err), -err);
2035+
return err;
2036+
}
2037+
2038+
err = native_window_set_scaling_mode(mNativeWindow.get(),
2039+
NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
2040+
if (err != NO_ERROR) {
2041+
LOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)",
2042+
strerror(-err), -err);
2043+
goto error;
2044+
}
2045+
2046+
err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1,
2047+
HAL_PIXEL_FORMAT_RGBX_8888);
2048+
if (err != NO_ERROR) {
2049+
LOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)",
2050+
strerror(-err), -err);
2051+
goto error;
2052+
}
2053+
2054+
err = native_window_set_usage(mNativeWindow.get(),
2055+
GRALLOC_USAGE_SW_WRITE_OFTEN);
2056+
if (err != NO_ERROR) {
2057+
LOGE("error pushing blank frames: set_usage failed: %s (%d)",
2058+
strerror(-err), -err);
2059+
goto error;
2060+
}
2061+
2062+
err = mNativeWindow->query(mNativeWindow.get(),
2063+
NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
2064+
if (err != NO_ERROR) {
2065+
LOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
2066+
"failed: %s (%d)", strerror(-err), -err);
2067+
goto error;
2068+
}
2069+
2070+
numBufs = minUndequeuedBufs + 1;
2071+
err = native_window_set_buffer_count(mNativeWindow.get(), numBufs);
2072+
if (err != NO_ERROR) {
2073+
LOGE("error pushing blank frames: set_buffer_count failed: %s (%d)",
2074+
strerror(-err), -err);
2075+
goto error;
2076+
}
2077+
2078+
// We push numBufs + 1 buffers to ensure that we've drawn into the same
2079+
// buffer twice. This should guarantee that the buffer has been displayed
2080+
// on the screen and then been replaced, so an previous video frames are
2081+
// guaranteed NOT to be currently displayed.
2082+
for (int i = 0; i < numBufs + 1; i++) {
2083+
err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &anb);
2084+
if (err != NO_ERROR) {
2085+
LOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
2086+
strerror(-err), -err);
2087+
goto error;
2088+
}
2089+
2090+
sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
2091+
err = mNativeWindow->lockBuffer(mNativeWindow.get(),
2092+
buf->getNativeBuffer());
2093+
if (err != NO_ERROR) {
2094+
LOGE("error pushing blank frames: lockBuffer failed: %s (%d)",
2095+
strerror(-err), -err);
2096+
goto error;
2097+
}
2098+
2099+
// Fill the buffer with the a 1x1 checkerboard pattern ;)
2100+
uint32_t* img = NULL;
2101+
err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
2102+
if (err != NO_ERROR) {
2103+
LOGE("error pushing blank frames: lock failed: %s (%d)",
2104+
strerror(-err), -err);
2105+
goto error;
2106+
}
2107+
2108+
*img = 0;
2109+
2110+
err = buf->unlock();
2111+
if (err != NO_ERROR) {
2112+
LOGE("error pushing blank frames: unlock failed: %s (%d)",
2113+
strerror(-err), -err);
2114+
goto error;
2115+
}
2116+
2117+
err = mNativeWindow->queueBuffer(mNativeWindow.get(),
2118+
buf->getNativeBuffer());
2119+
if (err != NO_ERROR) {
2120+
LOGE("error pushing blank frames: queueBuffer failed: %s (%d)",
2121+
strerror(-err), -err);
2122+
goto error;
2123+
}
2124+
2125+
anb = NULL;
2126+
}
2127+
2128+
error:
2129+
2130+
if (err != NO_ERROR) {
2131+
// Clean up after an error.
2132+
if (anb != NULL) {
2133+
mNativeWindow->cancelBuffer(mNativeWindow.get(), anb);
2134+
}
2135+
2136+
native_window_api_disconnect(mNativeWindow.get(),
2137+
NATIVE_WINDOW_API_CPU);
2138+
native_window_api_connect(mNativeWindow.get(),
2139+
NATIVE_WINDOW_API_MEDIA);
2140+
2141+
return err;
2142+
} else {
2143+
// Clean up after success.
2144+
err = native_window_api_disconnect(mNativeWindow.get(),
2145+
NATIVE_WINDOW_API_CPU);
2146+
if (err != NO_ERROR) {
2147+
LOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
2148+
strerror(-err), -err);
2149+
return err;
2150+
}
2151+
2152+
err = native_window_api_connect(mNativeWindow.get(),
2153+
NATIVE_WINDOW_API_MEDIA);
2154+
if (err != NO_ERROR) {
2155+
LOGE("error pushing blank frames: api_connect failed: %s (%d)",
2156+
strerror(-err), -err);
2157+
return err;
2158+
}
2159+
2160+
return NO_ERROR;
2161+
}
2162+
}
2163+
20132164
int64_t OMXCodec::retrieveDecodingTimeUs(bool isCodecSpecific) {
20142165
CHECK(mIsEncoder);
20152166

@@ -2598,6 +2749,15 @@ void OMXCodec::onStateChange(OMX_STATETYPE newState) {
25982749
mPortStatus[kPortIndexInput] = ENABLED;
25992750
mPortStatus[kPortIndexOutput] = ENABLED;
26002751

2752+
if ((mFlags & kEnableGrallocUsageProtected) &&
2753+
mNativeWindow != NULL) {
2754+
// We push enough 1x1 blank buffers to ensure that one of
2755+
// them has made it to the display. This allows the OMX
2756+
// component teardown to zero out any protected buffers
2757+
// without the risk of scanning out one of those buffers.
2758+
pushBlankBuffersToNativeWindow();
2759+
}
2760+
26012761
setState(IDLE_TO_LOADED);
26022762
}
26032763
break;

0 commit comments

Comments
 (0)