From 264bac95912efe121d6a60026612617f04f42966 Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Fri, 26 Jun 2015 15:33:17 -0700 Subject: stagefright: prevent allocating stale buffers for OMX decoders Also fix some issues encountered once using generationNumbers: - properly account outstanding buffers in MediaSync - don't release arbitrary frame if attach fails Bug: 11990461 Change-Id: Icee5ea188ca4eb856138feb5e6ec5d4ee5e44008 --- media/libstagefright/MediaCodec.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'media/libstagefright/MediaCodec.cpp') diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index b576cd9..69f44ed 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -2528,7 +2528,25 @@ status_t MediaCodec::connectToSurface(const sp &surface) { err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA); if (err == BAD_VALUE) { ALOGI("native window already connected. Assuming no change of surface"); - } else if (err != OK) { + } else if (err == OK) { + // Require a fresh set of buffers after each connect by using a unique generation + // number. Rely on the fact that max supported process id by Linux is 2^22. + // PID is never 0 so we don't have to worry that we use the default generation of 0. + // TODO: come up with a unique scheme if other producers also set the generation number. + static uint32_t mSurfaceGeneration = 0; + uint32_t generation = (getpid() << 10) | (++mSurfaceGeneration & ((1 << 10) - 1)); + surface->setGenerationNumber(generation); + ALOGI("[%s] setting surface generation to %u", mComponentName.c_str(), generation); + + // HACK: clear any free buffers. Remove when connect will automatically do this. + // This is needed as the consumer may be holding onto stale frames that it can reattach + // to this surface after disconnect/connect, and those free frames would inherit the new + // generation number. Disconnecting after setting a unique generation prevents this. + native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA); + err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA); + } + + if (err != OK) { ALOGE("native_window_api_connect returned an error: %s (%d)", strerror(-err), err); } } @@ -2538,6 +2556,8 @@ status_t MediaCodec::connectToSurface(const sp &surface) { status_t MediaCodec::disconnectFromSurface() { status_t err = OK; if (mSurface != NULL) { + // Resetting generation is not technically needed, but there is no need to keep it either + mSurface->setGenerationNumber(0); err = native_window_api_disconnect(mSurface.get(), NATIVE_WINDOW_API_MEDIA); if (err != OK) { ALOGW("native_window_api_disconnect returned an error: %s (%d)", strerror(-err), err); -- cgit v1.1