summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/omx
diff options
context:
space:
mode:
authorChong Zhang <chz@google.com>2015-04-30 18:15:52 -0700
committerChong Zhang <chz@google.com>2015-05-01 19:06:38 -0700
commitd291c222357303b9611cab89d0c3b047584ef377 (patch)
tree953551d93d5a215cefb14470387ff7494c9b60e5 /media/libstagefright/omx
parent64da6f045b1a1d1b8f01391b6e37287f77f85d1e (diff)
downloadframeworks_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.cpp105
-rw-r--r--media/libstagefright/omx/GraphicBufferSource.h13
-rw-r--r--media/libstagefright/omx/OMX.cpp15
-rw-r--r--media/libstagefright/omx/OMXNodeInstance.cpp71
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