@@ -2001,6 +2001,157 @@ OMXCodec::BufferInfo* OMXCodec::dequeueBufferFromNativeWindow() {
20012001 return bufInfo;
20022002}
20032003
2004+ status_t OMXCodec::pushBlankBuffersToNativeWindow () {
2005+ status_t err = NO_ERROR;
2006+ ANativeWindowBuffer* anb = NULL ;
2007+ int numBufs = 0 ;
2008+ int minUndequeuedBufs = 0 ;
2009+
2010+ // We need to reconnect to the ANativeWindow as a CPU client to ensure that
2011+ // no frames get dropped by SurfaceFlinger assuming that these are video
2012+ // frames.
2013+ err = native_window_api_disconnect (mNativeWindow .get (),
2014+ NATIVE_WINDOW_API_MEDIA);
2015+ if (err != NO_ERROR) {
2016+ LOGE (" error pushing blank frames: api_disconnect failed: %s (%d)" ,
2017+ strerror (-err), -err);
2018+ return err;
2019+ }
2020+
2021+ err = native_window_api_connect (mNativeWindow .get (),
2022+ NATIVE_WINDOW_API_CPU);
2023+ if (err != NO_ERROR) {
2024+ LOGE (" error pushing blank frames: api_connect failed: %s (%d)" ,
2025+ strerror (-err), -err);
2026+ return err;
2027+ }
2028+
2029+ err = native_window_set_scaling_mode (mNativeWindow .get (),
2030+ NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
2031+ if (err != NO_ERROR) {
2032+ LOGE (" error pushing blank frames: set_buffers_geometry failed: %s (%d)" ,
2033+ strerror (-err), -err);
2034+ goto error;
2035+ }
2036+
2037+ err = native_window_set_buffers_geometry (mNativeWindow .get (), 1 , 1 ,
2038+ HAL_PIXEL_FORMAT_RGBX_8888);
2039+ if (err != NO_ERROR) {
2040+ LOGE (" error pushing blank frames: set_buffers_geometry failed: %s (%d)" ,
2041+ strerror (-err), -err);
2042+ goto error;
2043+ }
2044+
2045+ err = native_window_set_usage (mNativeWindow .get (),
2046+ GRALLOC_USAGE_SW_WRITE_OFTEN);
2047+ if (err != NO_ERROR) {
2048+ LOGE (" error pushing blank frames: set_usage failed: %s (%d)" ,
2049+ strerror (-err), -err);
2050+ goto error;
2051+ }
2052+
2053+ err = mNativeWindow ->query (mNativeWindow .get (),
2054+ NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
2055+ if (err != NO_ERROR) {
2056+ LOGE (" error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
2057+ " failed: %s (%d)" , strerror (-err), -err);
2058+ goto error;
2059+ }
2060+
2061+ numBufs = minUndequeuedBufs + 1 ;
2062+ err = native_window_set_buffer_count (mNativeWindow .get (), numBufs);
2063+ if (err != NO_ERROR) {
2064+ LOGE (" error pushing blank frames: set_buffer_count failed: %s (%d)" ,
2065+ strerror (-err), -err);
2066+ goto error;
2067+ }
2068+
2069+ // We push numBufs + 1 buffers to ensure that we've drawn into the same
2070+ // buffer twice. This should guarantee that the buffer has been displayed
2071+ // on the screen and then been replaced, so an previous video frames are
2072+ // guaranteed NOT to be currently displayed.
2073+ for (int i = 0 ; i < numBufs + 1 ; i++) {
2074+ err = mNativeWindow ->dequeueBuffer (mNativeWindow .get (), &anb);
2075+ if (err != NO_ERROR) {
2076+ LOGE (" error pushing blank frames: dequeueBuffer failed: %s (%d)" ,
2077+ strerror (-err), -err);
2078+ goto error;
2079+ }
2080+
2081+ sp<GraphicBuffer> buf (new GraphicBuffer (anb, false ));
2082+ err = mNativeWindow ->lockBuffer (mNativeWindow .get (),
2083+ buf->getNativeBuffer ());
2084+ if (err != NO_ERROR) {
2085+ LOGE (" error pushing blank frames: lockBuffer failed: %s (%d)" ,
2086+ strerror (-err), -err);
2087+ goto error;
2088+ }
2089+
2090+ // Fill the buffer with the a 1x1 checkerboard pattern ;)
2091+ uint32_t * img = NULL ;
2092+ err = buf->lock (GRALLOC_USAGE_SW_WRITE_OFTEN, (void **)(&img));
2093+ if (err != NO_ERROR) {
2094+ LOGE (" error pushing blank frames: lock failed: %s (%d)" ,
2095+ strerror (-err), -err);
2096+ goto error;
2097+ }
2098+
2099+ *img = 0 ;
2100+
2101+ err = buf->unlock ();
2102+ if (err != NO_ERROR) {
2103+ LOGE (" error pushing blank frames: unlock failed: %s (%d)" ,
2104+ strerror (-err), -err);
2105+ goto error;
2106+ }
2107+
2108+ err = mNativeWindow ->queueBuffer (mNativeWindow .get (),
2109+ buf->getNativeBuffer ());
2110+ if (err != NO_ERROR) {
2111+ LOGE (" error pushing blank frames: queueBuffer failed: %s (%d)" ,
2112+ strerror (-err), -err);
2113+ goto error;
2114+ }
2115+
2116+ anb = NULL ;
2117+ }
2118+
2119+ error:
2120+
2121+ if (err != NO_ERROR) {
2122+ // Clean up after an error.
2123+ if (anb != NULL ) {
2124+ mNativeWindow ->cancelBuffer (mNativeWindow .get (), anb);
2125+ }
2126+
2127+ native_window_api_disconnect (mNativeWindow .get (),
2128+ NATIVE_WINDOW_API_CPU);
2129+ native_window_api_connect (mNativeWindow .get (),
2130+ NATIVE_WINDOW_API_MEDIA);
2131+
2132+ return err;
2133+ } else {
2134+ // Clean up after success.
2135+ err = native_window_api_disconnect (mNativeWindow .get (),
2136+ NATIVE_WINDOW_API_CPU);
2137+ if (err != NO_ERROR) {
2138+ LOGE (" error pushing blank frames: api_disconnect failed: %s (%d)" ,
2139+ strerror (-err), -err);
2140+ return err;
2141+ }
2142+
2143+ err = native_window_api_connect (mNativeWindow .get (),
2144+ NATIVE_WINDOW_API_MEDIA);
2145+ if (err != NO_ERROR) {
2146+ LOGE (" error pushing blank frames: api_connect failed: %s (%d)" ,
2147+ strerror (-err), -err);
2148+ return err;
2149+ }
2150+
2151+ return NO_ERROR;
2152+ }
2153+ }
2154+
20042155int64_t OMXCodec::retrieveDecodingTimeUs (bool isCodecSpecific) {
20052156 CHECK (mIsEncoder );
20062157
@@ -2589,6 +2740,15 @@ void OMXCodec::onStateChange(OMX_STATETYPE newState) {
25892740 mPortStatus [kPortIndexInput ] = ENABLED;
25902741 mPortStatus [kPortIndexOutput ] = ENABLED;
25912742
2743+ if ((mFlags & kEnableGrallocUsageProtected ) &&
2744+ mNativeWindow != NULL ) {
2745+ // We push enough 1x1 blank buffers to ensure that one of
2746+ // them has made it to the display. This allows the OMX
2747+ // component teardown to zero out any protected buffers
2748+ // without the risk of scanning out one of those buffers.
2749+ pushBlankBuffersToNativeWindow ();
2750+ }
2751+
25922752 setState (IDLE_TO_LOADED);
25932753 }
25942754 break ;
0 commit comments