diff options
| author | Chong Zhang <chz@google.com> | 2015-06-08 22:18:55 +0000 | 
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-06-08 22:18:56 +0000 | 
| commit | dd488a23d37b71e3f87fe70bf966a6c967e14b60 (patch) | |
| tree | baebc9a5e0b95c684b19d573e0fa4331a08f54fa /media | |
| parent | 0b305f2d8f328426f5c59b5d5f2707ffefe35a5c (diff) | |
| parent | ffd8cbb288f096b53df0392bf40d99b89e34bea7 (diff) | |
| download | frameworks_av-dd488a23d37b71e3f87fe70bf966a6c967e14b60.zip frameworks_av-dd488a23d37b71e3f87fe70bf966a6c967e14b60.tar.gz frameworks_av-dd488a23d37b71e3f87fe70bf966a6c967e14b60.tar.bz2  | |
Merge "fix graphic buffer leak with persistent input surface" into mnc-dev
Diffstat (limited to 'media')
| -rw-r--r-- | media/libstagefright/omx/GraphicBufferSource.cpp | 79 | ||||
| -rw-r--r-- | media/libstagefright/omx/GraphicBufferSource.h | 25 | 
2 files changed, 102 insertions, 2 deletions
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp index d30bba5..ac6bf0d 100644 --- a/media/libstagefright/omx/GraphicBufferSource.cpp +++ b/media/libstagefright/omx/GraphicBufferSource.cpp @@ -38,6 +38,72 @@ namespace android {  static const bool EXTRA_CHECK = true; +GraphicBufferSource::PersistentProxyListener::PersistentProxyListener( +        const wp<IGraphicBufferConsumer> &consumer, +        const wp<ConsumerListener>& consumerListener) : +    mConsumerListener(consumerListener), +    mConsumer(consumer) {} + +GraphicBufferSource::PersistentProxyListener::~PersistentProxyListener() {} + +void GraphicBufferSource::PersistentProxyListener::onFrameAvailable( +        const BufferItem& item) { +    sp<ConsumerListener> listener(mConsumerListener.promote()); +    if (listener != NULL) { +        listener->onFrameAvailable(item); +    } else { +        sp<IGraphicBufferConsumer> consumer(mConsumer.promote()); +        if (consumer == NULL) { +            return; +        } +        BufferItem bi; +        status_t err = consumer->acquireBuffer(&bi, 0); +        if (err != OK) { +            ALOGE("PersistentProxyListener: acquireBuffer failed (%d)", err); +            return; +        } + +        err = consumer->detachBuffer(bi.mBuf); +        if (err != OK) { +            ALOGE("PersistentProxyListener: detachBuffer failed (%d)", err); +            return; +        } + +        err = consumer->attachBuffer(&bi.mBuf, bi.mGraphicBuffer); +        if (err != OK) { +            ALOGE("PersistentProxyListener: attachBuffer failed (%d)", err); +            return; +        } + +        err = consumer->releaseBuffer(bi.mBuf, 0, +                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, bi.mFence); +        if (err != OK) { +            ALOGE("PersistentProxyListener: releaseBuffer failed (%d)", err); +        } +    } +} + +void GraphicBufferSource::PersistentProxyListener::onFrameReplaced( +        const BufferItem& item) { +    sp<ConsumerListener> listener(mConsumerListener.promote()); +    if (listener != NULL) { +        listener->onFrameReplaced(item); +    } +} + +void GraphicBufferSource::PersistentProxyListener::onBuffersReleased() { +    sp<ConsumerListener> listener(mConsumerListener.promote()); +    if (listener != NULL) { +        listener->onBuffersReleased(); +    } +} + +void GraphicBufferSource::PersistentProxyListener::onSidebandStreamChanged() { +    sp<ConsumerListener> listener(mConsumerListener.promote()); +    if (listener != NULL) { +        listener->onSidebandStreamChanged(); +    } +}  GraphicBufferSource::GraphicBufferSource(          OMXNodeInstance* nodeInstance, @@ -101,7 +167,12 @@ GraphicBufferSource::GraphicBufferSource(      // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>      // that's what we create.      wp<BufferQueue::ConsumerListener> listener = static_cast<BufferQueue::ConsumerListener*>(this); -    sp<BufferQueue::ProxyConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener); +    sp<IConsumerListener> proxy; +    if (!mIsPersistent) { +        proxy = new BufferQueue::ProxyConsumerListener(listener); +    } else { +        proxy = new PersistentProxyListener(mConsumer, listener); +    }      mInitCheck = mConsumer->consumerConnect(proxy, false);      if (mInitCheck != NO_ERROR) { @@ -312,6 +383,7 @@ void GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header, int f                  mConsumer->attachBuffer(&outSlot, mBufferSlot[id]);                  mConsumer->releaseBuffer(outSlot, 0,                          EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence); +                mBufferSlot[id] = NULL;              } else {                  mConsumer->releaseBuffer(id, codecBuffer.mFrameNumber,                          EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence); @@ -400,6 +472,7 @@ void GraphicBufferSource::suspend(bool suspend) {              if (mIsPersistent) {                  mConsumer->detachBuffer(item.mBuf); +                mBufferSlot[item.mBuf] = NULL;                  mConsumer->attachBuffer(&item.mBuf, item.mGraphicBuffer);                  mConsumer->releaseBuffer(item.mBuf, 0,                          EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence); @@ -488,6 +561,7 @@ bool GraphicBufferSource::fillCodecBuffer_l() {          ALOGV("submitBuffer_l failed, releasing bq buf %d", item.mBuf);          if (mIsPersistent) {              mConsumer->detachBuffer(item.mBuf); +            mBufferSlot[item.mBuf] = NULL;              mConsumer->attachBuffer(&item.mBuf, item.mGraphicBuffer);              mConsumer->releaseBuffer(item.mBuf, 0,                      EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence); @@ -578,9 +652,9 @@ void GraphicBufferSource::setLatestBuffer_l(                  int outSlot;                  mConsumer->attachBuffer(&outSlot, mBufferSlot[mLatestBufferId]); -                  mConsumer->releaseBuffer(outSlot, 0,                          EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, mLatestBufferFence); +                mBufferSlot[mLatestBufferId] = NULL;              } else {                  mConsumer->releaseBuffer(                          mLatestBufferId, mLatestBufferFrameNum, @@ -803,6 +877,7 @@ void GraphicBufferSource::onFrameAvailable(const BufferItem& /*item*/) {              if (mIsPersistent) {                  mConsumer->detachBuffer(item.mBuf); +                mBufferSlot[item.mBuf] = NULL;                  mConsumer->attachBuffer(&item.mBuf, item.mGraphicBuffer);                  mConsumer->releaseBuffer(item.mBuf, 0,                          EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence); diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h index 555bbec..2a8c218 100644 --- a/media/libstagefright/omx/GraphicBufferSource.h +++ b/media/libstagefright/omx/GraphicBufferSource.h @@ -160,6 +160,31 @@ protected:      virtual void onSidebandStreamChanged();  private: +    // PersistentProxyListener is similar to BufferQueue::ProxyConsumerListener +    // except that it returns (acquire/detach/re-attache/release) buffers +    // in onFrameAvailable() if the actual consumer object is no longer valid. +    // +    // This class is used in persistent input surface case to prevent buffer +    // loss when onFrameAvailable() is received while we don't have a valid +    // consumer around. +    class PersistentProxyListener : public BnConsumerListener { +        public: +            PersistentProxyListener( +                    const wp<IGraphicBufferConsumer> &consumer, +                    const wp<ConsumerListener>& consumerListener); +            virtual ~PersistentProxyListener(); +            virtual void onFrameAvailable(const BufferItem& item) override; +            virtual void onFrameReplaced(const BufferItem& item) override; +            virtual void onBuffersReleased() override; +            virtual void onSidebandStreamChanged() override; +         private: +            // mConsumerListener is a weak reference to the IConsumerListener. +            wp<ConsumerListener> mConsumerListener; +            // mConsumer is a weak reference to the IGraphicBufferConsumer, use +            // a weak ref to avoid circular ref between mConsumer and this class +            wp<IGraphicBufferConsumer> mConsumer; +    }; +      // Keep track of codec input buffers.  They may either be available      // (mGraphicBuffer == NULL) or in use by the codec.      struct CodecBuffer {  | 
