diff options
author | Chong Zhang <chz@google.com> | 2015-04-30 18:15:52 -0700 |
---|---|---|
committer | Chong Zhang <chz@google.com> | 2015-05-01 19:06:38 -0700 |
commit | d291c222357303b9611cab89d0c3b047584ef377 (patch) | |
tree | 953551d93d5a215cefb14470387ff7494c9b60e5 /media/libstagefright/omx | |
parent | 64da6f045b1a1d1b8f01391b6e37287f77f85d1e (diff) | |
download | frameworks_av-d291c222357303b9611cab89d0c3b047584ef377.zip frameworks_av-d291c222357303b9611cab89d0c3b047584ef377.tar.gz frameworks_av-d291c222357303b9611cab89d0c3b047584ef377.tar.bz2 |
MediaCodec: implement persistent input surface APIs
Bug: 19127604
Bug: 19489395
Change-Id: Idaf1cc9008016f66903e93907a676f54e342e1a3
Diffstat (limited to 'media/libstagefright/omx')
-rw-r--r-- | media/libstagefright/omx/GraphicBufferSource.cpp | 105 | ||||
-rw-r--r-- | media/libstagefright/omx/GraphicBufferSource.h | 13 | ||||
-rw-r--r-- | media/libstagefright/omx/OMX.cpp | 15 | ||||
-rw-r--r-- | media/libstagefright/omx/OMXNodeInstance.cpp | 71 |
4 files changed, 163 insertions, 41 deletions
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp index 477cfc6..01cd8f0 100644 --- a/media/libstagefright/omx/GraphicBufferSource.cpp +++ b/media/libstagefright/omx/GraphicBufferSource.cpp @@ -38,13 +38,19 @@ namespace android { static const bool EXTRA_CHECK = true; -GraphicBufferSource::GraphicBufferSource(OMXNodeInstance* nodeInstance, - uint32_t bufferWidth, uint32_t bufferHeight, uint32_t bufferCount, - bool useGraphicBufferInMeta) : +GraphicBufferSource::GraphicBufferSource( + OMXNodeInstance* nodeInstance, + uint32_t bufferWidth, + uint32_t bufferHeight, + uint32_t bufferCount, + bool useGraphicBufferInMeta, + const sp<IGraphicBufferConsumer> &consumer) : mInitCheck(UNKNOWN_ERROR), mNodeInstance(nodeInstance), mExecuting(false), mSuspended(false), + mIsPersistent(false), + mConsumer(consumer), mNumFramesAvailable(0), mEndOfStream(false), mEndOfStreamSent(false), @@ -74,20 +80,22 @@ GraphicBufferSource::GraphicBufferSource(OMXNodeInstance* nodeInstance, return; } - String8 name("GraphicBufferSource"); + if (mConsumer == NULL) { + String8 name("GraphicBufferSource"); - BufferQueue::createBufferQueue(&mProducer, &mConsumer); - mConsumer->setConsumerName(name); - mConsumer->setDefaultBufferSize(bufferWidth, bufferHeight); - mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER); - - mInitCheck = mConsumer->setMaxAcquiredBufferCount(bufferCount); - if (mInitCheck != NO_ERROR) { - ALOGE("Unable to set BQ max acquired buffer count to %u: %d", - bufferCount, mInitCheck); - return; + BufferQueue::createBufferQueue(&mProducer, &mConsumer); + mConsumer->setConsumerName(name); + mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER); + mInitCheck = mConsumer->setMaxAcquiredBufferCount(bufferCount); + if (mInitCheck != NO_ERROR) { + ALOGE("Unable to set BQ max acquired buffer count to %u: %d", + bufferCount, mInitCheck); + return; + } + } else { + mIsPersistent = true; } - + mConsumer->setDefaultBufferSize(bufferWidth, bufferHeight); // Note that we can't create an sp<...>(this) in a ctor that will not keep a // reference once the ctor ends, as that would cause the refcount of 'this' // dropping to 0 at the end of the ctor. Since all we need is a wp<...> @@ -107,7 +115,7 @@ GraphicBufferSource::GraphicBufferSource(OMXNodeInstance* nodeInstance, GraphicBufferSource::~GraphicBufferSource() { ALOGV("~GraphicBufferSource"); - if (mConsumer != NULL) { + if (mConsumer != NULL && !mIsPersistent) { status_t err = mConsumer->consumerDisconnect(); if (err != NO_ERROR) { ALOGW("consumerDisconnect failed: %d", err); @@ -292,8 +300,16 @@ void GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header) { if (id == mLatestBufferId) { CHECK_GT(mLatestBufferUseCount--, 0); } else { - mConsumer->releaseBuffer(id, codecBuffer.mFrameNumber, - EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); + if (mIsPersistent) { + mConsumer->detachBuffer(id); + int outSlot; + mConsumer->attachBuffer(&outSlot, mBufferSlot[id]); + mConsumer->releaseBuffer(outSlot, 0, + EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); + } else { + mConsumer->releaseBuffer(id, codecBuffer.mFrameNumber, + EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); + } } } else { ALOGV("codecBufferEmptied: no match for emptied buffer in cbi %d", @@ -375,8 +391,15 @@ void GraphicBufferSource::suspend(bool suspend) { --mNumFramesAvailable; - mConsumer->releaseBuffer(item.mBuf, item.mFrameNumber, - EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence); + if (mIsPersistent) { + mConsumer->detachBuffer(item.mBuf); + mConsumer->attachBuffer(&item.mBuf, item.mGraphicBuffer); + mConsumer->releaseBuffer(item.mBuf, 0, + EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); + } else { + mConsumer->releaseBuffer(item.mBuf, item.mFrameNumber, + EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence); + } } return; } @@ -463,8 +486,15 @@ bool GraphicBufferSource::fillCodecBuffer_l() { if (err != OK) { ALOGV("submitBuffer_l failed, releasing bq buf %d", item.mBuf); - mConsumer->releaseBuffer(item.mBuf, item.mFrameNumber, - EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); + if (mIsPersistent) { + mConsumer->detachBuffer(item.mBuf); + mConsumer->attachBuffer(&item.mBuf, item.mGraphicBuffer); + mConsumer->releaseBuffer(item.mBuf, 0, + EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); + } else { + mConsumer->releaseBuffer(item.mBuf, item.mFrameNumber, + EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); + } } else { ALOGV("buffer submitted (bq %d, cbi %d)", item.mBuf, cbi); setLatestBuffer_l(item, dropped); @@ -540,12 +570,19 @@ void GraphicBufferSource::setLatestBuffer_l( if (mLatestBufferId >= 0) { if (mLatestBufferUseCount == 0) { - mConsumer->releaseBuffer( - mLatestBufferId, - mLatestBufferFrameNum, - EGL_NO_DISPLAY, - EGL_NO_SYNC_KHR, - Fence::NO_FENCE); + if (mIsPersistent) { + mConsumer->detachBuffer(mLatestBufferId); + + int outSlot; + mConsumer->attachBuffer(&outSlot, mBufferSlot[mLatestBufferId]); + + mConsumer->releaseBuffer(outSlot, 0, + EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); + } else { + mConsumer->releaseBuffer( + mLatestBufferId, mLatestBufferFrameNum, + EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); + } } } @@ -787,8 +824,16 @@ void GraphicBufferSource::onFrameAvailable(const BufferItem& /*item*/) { ALOGV("onFrameAvailable: setting mBufferSlot %d", item.mBuf); mBufferSlot[item.mBuf] = item.mGraphicBuffer; } - mConsumer->releaseBuffer(item.mBuf, item.mFrameNumber, - EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence); + + if (mIsPersistent) { + mConsumer->detachBuffer(item.mBuf); + mConsumer->attachBuffer(&item.mBuf, item.mGraphicBuffer); + mConsumer->releaseBuffer(item.mBuf, 0, + EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); + } else { + mConsumer->releaseBuffer(item.mBuf, item.mFrameNumber, + EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence); + } } return; } diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h index 718d2ee..1047fb3 100644 --- a/media/libstagefright/omx/GraphicBufferSource.h +++ b/media/libstagefright/omx/GraphicBufferSource.h @@ -50,9 +50,15 @@ struct FrameDropper; */ class GraphicBufferSource : public BufferQueue::ConsumerListener { public: - GraphicBufferSource(OMXNodeInstance* nodeInstance, - uint32_t bufferWidth, uint32_t bufferHeight, uint32_t bufferCount, - bool useGraphicBufferInMeta = false); + GraphicBufferSource( + OMXNodeInstance* nodeInstance, + uint32_t bufferWidth, + uint32_t bufferHeight, + uint32_t bufferCount, + bool useGraphicBufferInMeta = false, + const sp<IGraphicBufferConsumer> &consumer = NULL + ); + virtual ~GraphicBufferSource(); // We can't throw an exception if the constructor fails, so we just set @@ -219,6 +225,7 @@ private: // Our BufferQueue interfaces. mProducer is passed to the producer through // getIGraphicBufferProducer, and mConsumer is used internally to retrieve // the buffers queued by the producer. + bool mIsPersistent; sp<IGraphicBufferProducer> mProducer; sp<IGraphicBufferConsumer> mConsumer; diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp index f8d38ff..b9e2f9c 100644 --- a/media/libstagefright/omx/OMX.cpp +++ b/media/libstagefright/omx/OMX.cpp @@ -377,6 +377,21 @@ status_t OMX::createInputSurface( port_index, bufferProducer); } +status_t OMX::createPersistentInputSurface( + sp<IGraphicBufferProducer> *bufferProducer, + sp<IGraphicBufferConsumer> *bufferConsumer) { + return OMXNodeInstance::createPersistentInputSurface( + bufferProducer, bufferConsumer); +} + +status_t OMX::usePersistentInputSurface( + node_id node, OMX_U32 port_index, + const sp<IGraphicBufferConsumer> &bufferConsumer) { + return findInstance(node)->usePersistentInputSurface( + port_index, bufferConsumer); +} + + status_t OMX::signalEndOfInputStream(node_id node) { return findInstance(node)->signalEndOfInputStream(); } diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp index 4779d6a..5bc1972 100644 --- a/media/libstagefright/omx/OMXNodeInstance.cpp +++ b/media/libstagefright/omx/OMXNodeInstance.cpp @@ -787,9 +787,8 @@ status_t OMXNodeInstance::updateGraphicBufferInMeta( return OK; } -status_t OMXNodeInstance::createInputSurface( - OMX_U32 portIndex, sp<IGraphicBufferProducer> *bufferProducer) { - Mutex::Autolock autolock(mLock); +status_t OMXNodeInstance::createGraphicBufferSource( + OMX_U32 portIndex, sp<IGraphicBufferConsumer> bufferConsumer) { status_t err; const sp<GraphicBufferSource>& surfaceCheck = getGraphicBufferSource(); @@ -827,19 +826,75 @@ status_t OMXNodeInstance::createInputSurface( return INVALID_OPERATION; } - GraphicBufferSource* bufferSource = new GraphicBufferSource( - this, def.format.video.nFrameWidth, def.format.video.nFrameHeight, - def.nBufferCountActual, usingGraphicBuffer); + sp<GraphicBufferSource> bufferSource = new GraphicBufferSource(this, + def.format.video.nFrameWidth, + def.format.video.nFrameHeight, + def.nBufferCountActual, + usingGraphicBuffer, + bufferConsumer); + if ((err = bufferSource->initCheck()) != OK) { - delete bufferSource; return err; } setGraphicBufferSource(bufferSource); - *bufferProducer = bufferSource->getIGraphicBufferProducer(); return OK; } +status_t OMXNodeInstance::createInputSurface( + OMX_U32 portIndex, sp<IGraphicBufferProducer> *bufferProducer) { + Mutex::Autolock autolock(mLock); + status_t err = createGraphicBufferSource(portIndex); + + if (err != OK) { + return err; + } + + *bufferProducer = mGraphicBufferSource->getIGraphicBufferProducer(); + return OK; +} + +//static +status_t OMXNodeInstance::createPersistentInputSurface( + sp<IGraphicBufferProducer> *bufferProducer, + sp<IGraphicBufferConsumer> *bufferConsumer) { + String8 name("GraphicBufferSource"); + + sp<IGraphicBufferProducer> producer; + sp<IGraphicBufferConsumer> consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + consumer->setConsumerName(name); + consumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER); + + status_t err = consumer->setMaxAcquiredBufferCount( + BufferQueue::MAX_MAX_ACQUIRED_BUFFERS); + if (err != NO_ERROR) { + ALOGE("Unable to set BQ max acquired buffer count to %u: %d", + BufferQueue::MAX_MAX_ACQUIRED_BUFFERS, err); + return err; + } + + sp<BufferQueue::ProxyConsumerListener> proxy = + new BufferQueue::ProxyConsumerListener(NULL); + err = consumer->consumerConnect(proxy, false); + if (err != NO_ERROR) { + ALOGE("Error connecting to BufferQueue: %s (%d)", + strerror(-err), err); + return err; + } + + *bufferProducer = producer; + *bufferConsumer = consumer; + + return OK; +} + +status_t OMXNodeInstance::usePersistentInputSurface( + OMX_U32 portIndex, const sp<IGraphicBufferConsumer> &bufferConsumer) { + Mutex::Autolock autolock(mLock); + return createGraphicBufferSource(portIndex, bufferConsumer); +} + status_t OMXNodeInstance::signalEndOfInputStream() { // For non-Surface input, the MediaCodec should convert the call to a // pair of requests (dequeue input buffer, queue input buffer with EOS |