diff options
author | Lajos Molnar <lajos@google.com> | 2015-06-01 10:54:31 -0700 |
---|---|---|
committer | Lajos Molnar <lajos@google.com> | 2015-06-02 19:04:16 -0700 |
commit | 15ab4996019387f27a48b81cb4774c21502bc0e5 (patch) | |
tree | cff50b03c2785db5944f0bc310f9c8afaae17b2e /media/libstagefright/omx | |
parent | 40b26470dd29e44f1601ceb6e60948586a4d9f88 (diff) | |
download | frameworks_av-15ab4996019387f27a48b81cb4774c21502bc0e5.zip frameworks_av-15ab4996019387f27a48b81cb4774c21502bc0e5.tar.gz frameworks_av-15ab4996019387f27a48b81cb4774c21502bc0e5.tar.bz2 |
stagefright: add support for fences in OMX
Pass Fence between Surface and ACodec, and between ACodec and IOMX.
Bug: 12386081
Change-Id: Ifdc566979dec0d91ed8b07c3b69d2cf092accc73
Diffstat (limited to 'media/libstagefright/omx')
-rw-r--r-- | media/libstagefright/omx/GraphicBufferSource.cpp | 50 | ||||
-rw-r--r-- | media/libstagefright/omx/GraphicBufferSource.h | 3 | ||||
-rw-r--r-- | media/libstagefright/omx/OMX.cpp | 15 | ||||
-rw-r--r-- | media/libstagefright/omx/OMXNodeInstance.cpp | 105 | ||||
-rw-r--r-- | media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp | 10 |
5 files changed, 134 insertions, 49 deletions
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp index f797e63..be91510 100644 --- a/media/libstagefright/omx/GraphicBufferSource.cpp +++ b/media/libstagefright/omx/GraphicBufferSource.cpp @@ -64,6 +64,7 @@ GraphicBufferSource::GraphicBufferSource( mLatestBufferId(-1), mLatestBufferFrameNum(0), mLatestBufferUseCount(0), + mLatestBufferFence(Fence::NO_FENCE), mRepeatBufferDeferred(false), mTimePerCaptureUs(-1ll), mTimePerFrameUs(-1ll), @@ -226,9 +227,8 @@ void GraphicBufferSource::addCodecBuffer(OMX_BUFFERHEADERTYPE* header) { mCodecBuffers.add(codecBuffer); } -void GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header) { +void GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header, int fenceFd) { Mutex::Autolock autoLock(mMutex); - if (!mExecuting) { return; } @@ -237,6 +237,9 @@ void GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header) { if (cbi < 0) { // This should never happen. ALOGE("codecBufferEmptied: buffer not recognized (h=%p)", header); + if (fenceFd >= 0) { + ::close(fenceFd); + } return; } @@ -258,6 +261,9 @@ void GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header) { } // No GraphicBuffer to deal with, no additional input or output is // expected, so just return. + if (fenceFd >= 0) { + ::close(fenceFd); + } return; } @@ -291,6 +297,7 @@ void GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header) { // If we find a match, release that slot. If we don't, the BufferQueue // has dropped that GraphicBuffer, and there's nothing for us to release. int id = codecBuffer.mBuf; + sp<Fence> fence = new Fence(fenceFd); if (mBufferSlot[id] != NULL && mBufferSlot[id]->handle == codecBuffer.mGraphicBuffer->handle) { ALOGV("cbi %d matches bq slot %d, handle=%p", @@ -304,15 +311,16 @@ void GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header) { int outSlot; mConsumer->attachBuffer(&outSlot, mBufferSlot[id]); mConsumer->releaseBuffer(outSlot, 0, - EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); + EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence); } else { mConsumer->releaseBuffer(id, codecBuffer.mFrameNumber, - EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); + EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence); } } } else { ALOGV("codecBufferEmptied: no match for emptied buffer in cbi %d", cbi); + // we will not reuse codec buffer, so there is no need to wait for fence } // Mark the codec buffer as available by clearing the GraphicBuffer ref. @@ -394,7 +402,7 @@ void GraphicBufferSource::suspend(bool suspend) { 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); + EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence); } else { mConsumer->releaseBuffer(item.mBuf, item.mFrameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence); @@ -447,13 +455,6 @@ bool GraphicBufferSource::fillCodecBuffer_l() { mNumFramesAvailable--; - // Wait for it to become available. - err = item.mFence->waitForever("GraphicBufferSource::fillCodecBuffer_l"); - if (err != OK) { - ALOGW("failed to wait for buffer fence: %d", err); - // keep going - } - // If this is the first time we're seeing this buffer, add it to our // slot table. if (item.mGraphicBuffer != NULL) { @@ -489,11 +490,12 @@ bool GraphicBufferSource::fillCodecBuffer_l() { 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); + EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence); } else { mConsumer->releaseBuffer(item.mBuf, item.mFrameNumber, - EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); + EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence); } + // item.mFence is released at the end of this method } else { ALOGV("buffer submitted (bq %d, cbi %d)", item.mBuf, cbi); setLatestBuffer_l(item, dropped); @@ -520,9 +522,10 @@ bool GraphicBufferSource::repeatLatestBuffer_l() { mLatestBufferFrameNum, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, - Fence::NO_FENCE); + mLatestBufferFence); mLatestBufferId = -1; mLatestBufferFrameNum = 0; + mLatestBufferFence = Fence::NO_FENCE; return false; } @@ -537,6 +540,7 @@ bool GraphicBufferSource::repeatLatestBuffer_l() { item.mBuf = mLatestBufferId; item.mFrameNumber = mLatestBufferFrameNum; item.mTimestamp = mRepeatLastFrameTimestamp; + item.mFence = mLatestBufferFence; status_t err = submitBuffer_l(item, cbi); @@ -576,12 +580,13 @@ void GraphicBufferSource::setLatestBuffer_l( mConsumer->attachBuffer(&outSlot, mBufferSlot[mLatestBufferId]); mConsumer->releaseBuffer(outSlot, 0, - EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); + EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, mLatestBufferFence); } else { mConsumer->releaseBuffer( mLatestBufferId, mLatestBufferFrameNum, - EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); + EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, mLatestBufferFence); } + // mLatestBufferFence will be set to new fence just below } } @@ -592,6 +597,7 @@ void GraphicBufferSource::setLatestBuffer_l( mLatestBufferUseCount = dropped ? 0 : 1; mRepeatBufferDeferred = false; mRepeatLastFrameCount = kRepeatLastFrameCount; + mLatestBufferFence = item.mFence; if (mReflector != NULL) { sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector); @@ -687,8 +693,7 @@ int64_t GraphicBufferSource::getTimestamp(const BufferItem &item) { return timeUs; } -status_t GraphicBufferSource::submitBuffer_l( - const BufferItem &item, int cbi) { +status_t GraphicBufferSource::submitBuffer_l(const BufferItem &item, int cbi) { ALOGV("submitBuffer_l cbi=%d", cbi); int64_t timeUs = getTimestamp(item); @@ -704,7 +709,8 @@ status_t GraphicBufferSource::submitBuffer_l( OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader; sp<GraphicBuffer> buffer = codecBuffer.mGraphicBuffer; status_t err = mNodeInstance->emptyGraphicBuffer( - header, buffer, OMX_BUFFERFLAG_ENDOFFRAME, timeUs); + header, buffer, OMX_BUFFERFLAG_ENDOFFRAME, timeUs, + item.mFence->isValid() ? item.mFence->dup() : -1); if (err != OK) { ALOGW("WARNING: emptyNativeWindowBuffer failed: 0x%x", err); codecBuffer.mGraphicBuffer = NULL; @@ -737,7 +743,7 @@ void GraphicBufferSource::submitEndOfInputStream_l() { OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader; status_t err = mNodeInstance->emptyGraphicBuffer( header, NULL /* buffer */, OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS, - 0 /* timestamp */); + 0 /* timestamp */, -1 /* fenceFd */); if (err != OK) { ALOGW("emptyDirectBuffer EOS failed: 0x%x", err); } else { @@ -799,7 +805,7 @@ void GraphicBufferSource::onFrameAvailable(const BufferItem& /*item*/) { 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); + EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence); } else { mConsumer->releaseBuffer(item.mBuf, item.mFrameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence); diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h index 21ee96a..555bbec 100644 --- a/media/libstagefright/omx/GraphicBufferSource.h +++ b/media/libstagefright/omx/GraphicBufferSource.h @@ -93,7 +93,7 @@ public: // Called from OnEmptyBufferDone. If we have a BQ buffer available, // fill it with a new frame of data; otherwise, just mark it as available. - void codecBufferEmptied(OMX_BUFFERHEADERTYPE* header); + void codecBufferEmptied(OMX_BUFFERHEADERTYPE* header, int fenceFd); // Called when omx_message::FILL_BUFFER_DONE is received. (Currently the // buffer source will fix timestamp in the header if needed.) @@ -274,6 +274,7 @@ private: int mLatestBufferId; uint64_t mLatestBufferFrameNum; int32_t mLatestBufferUseCount; + sp<Fence> mLatestBufferFence; // The previous buffer should've been repeated but // no codec buffer was available at the time. diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp index 4ca827c..76217ec 100644 --- a/media/libstagefright/omx/OMX.cpp +++ b/media/libstagefright/omx/OMX.cpp @@ -415,17 +415,17 @@ status_t OMX::freeBuffer(node_id node, OMX_U32 port_index, buffer_id buffer) { port_index, buffer); } -status_t OMX::fillBuffer(node_id node, buffer_id buffer) { - return findInstance(node)->fillBuffer(buffer); +status_t OMX::fillBuffer(node_id node, buffer_id buffer, int fenceFd) { + return findInstance(node)->fillBuffer(buffer, fenceFd); } status_t OMX::emptyBuffer( node_id node, buffer_id buffer, OMX_U32 range_offset, OMX_U32 range_length, - OMX_U32 flags, OMX_TICKS timestamp) { + OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) { return findInstance(node)->emptyBuffer( - buffer, range_offset, range_length, flags, timestamp); + buffer, range_offset, range_length, flags, timestamp, fenceFd); } status_t OMX::getExtensionIndex( @@ -459,6 +459,7 @@ OMX_ERRORTYPE OMX::OnEvent( omx_message msg; msg.type = omx_message::EVENT; msg.node = node; + msg.fenceFd = -1; msg.u.event_data.event = eEvent; msg.u.event_data.data1 = nData1; msg.u.event_data.data2 = nData2; @@ -469,12 +470,13 @@ OMX_ERRORTYPE OMX::OnEvent( } OMX_ERRORTYPE OMX::OnEmptyBufferDone( - node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) { + node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer, int fenceFd) { ALOGV("OnEmptyBufferDone buffer=%p", pBuffer); omx_message msg; msg.type = omx_message::EMPTY_BUFFER_DONE; msg.node = node; + msg.fenceFd = fenceFd; msg.u.buffer_data.buffer = buffer; findDispatcher(node)->post(msg); @@ -483,12 +485,13 @@ OMX_ERRORTYPE OMX::OnEmptyBufferDone( } OMX_ERRORTYPE OMX::OnFillBufferDone( - node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) { + node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer, int fenceFd) { ALOGV("OnFillBufferDone buffer=%p", pBuffer); omx_message msg; msg.type = omx_message::FILL_BUFFER_DONE; msg.node = node; + msg.fenceFd = fenceFd; msg.u.extended_buffer_data.buffer = buffer; msg.u.extended_buffer_data.range_offset = pBuffer->nOffset; msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen; diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp index e4b2de4..4ba4aeb 100644 --- a/media/libstagefright/omx/OMXNodeInstance.cpp +++ b/media/libstagefright/omx/OMXNodeInstance.cpp @@ -76,11 +76,11 @@ static const OMX_U32 kPortIndexOutput = 1; #define SIMPLE_NEW_BUFFER(buffer_id, port, size, data) \ NEW_BUFFER_FMT(buffer_id, port, "%zu@%p", (size), (data)) -#define EMPTY_BUFFER(addr, header) "%#x [%u@%p]", \ - (addr), (header)->nAllocLen, (header)->pBuffer -#define FULL_BUFFER(addr, header) "%#" PRIxPTR " [%u@%p (%u..+%u) f=%x ts=%lld]", \ +#define EMPTY_BUFFER(addr, header, fenceFd) "%#x [%u@%p fc=%d]", \ + (addr), (header)->nAllocLen, (header)->pBuffer, (fenceFd) +#define FULL_BUFFER(addr, header, fenceFd) "%#" PRIxPTR " [%u@%p (%u..+%u) f=%x ts=%lld fc=%d]", \ (intptr_t)(addr), (header)->nAllocLen, (header)->pBuffer, \ - (header)->nOffset, (header)->nFilledLen, (header)->nFlags, (header)->nTimeStamp + (header)->nOffset, (header)->nFilledLen, (header)->nFlags, (header)->nTimeStamp, (fenceFd) #define WITH_STATS_WRAPPER(fmt, ...) fmt " { IN=%zu/%zu OUT=%zu/%zu }", ##__VA_ARGS__, \ mInputBuffersWithCodec.size(), mNumPortBuffers[kPortIndexInput], \ @@ -1050,7 +1050,7 @@ status_t OMXNodeInstance::freeBuffer( return StatusFromOMXError(err); } -status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) { +status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer, int fenceFd) { Mutex::Autolock autoLock(mLock); OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); @@ -1058,15 +1058,22 @@ status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) { header->nOffset = 0; header->nFlags = 0; + // meta now owns fenceFd + status_t res = storeFenceInMeta_l(header, fenceFd, kPortIndexOutput); + if (res != OK) { + CLOG_ERROR(fillBuffer::storeFenceInMeta, res, EMPTY_BUFFER(buffer, header, fenceFd)); + return res; + } + { Mutex::Autolock _l(mDebugLock); mOutputBuffersWithCodec.add(header); - CLOG_BUMPED_BUFFER(fillBuffer, WITH_STATS(EMPTY_BUFFER(buffer, header))); + CLOG_BUMPED_BUFFER(fillBuffer, WITH_STATS(EMPTY_BUFFER(buffer, header, fenceFd))); } OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header); if (err != OMX_ErrorNone) { - CLOG_ERROR(fillBuffer, err, EMPTY_BUFFER(buffer, header)); + CLOG_ERROR(fillBuffer, err, EMPTY_BUFFER(buffer, header, fenceFd)); Mutex::Autolock _l(mDebugLock); mOutputBuffersWithCodec.remove(header); } @@ -1076,7 +1083,7 @@ status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) { status_t OMXNodeInstance::emptyBuffer( OMX::buffer_id buffer, OMX_U32 rangeOffset, OMX_U32 rangeLength, - OMX_U32 flags, OMX_TICKS timestamp) { + OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) { Mutex::Autolock autoLock(mLock); OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); @@ -1084,6 +1091,9 @@ status_t OMXNodeInstance::emptyBuffer( // corner case: we permit rangeOffset == end-of-buffer with rangeLength == 0. if (rangeOffset > header->nAllocLen || rangeLength > header->nAllocLen - rangeOffset) { + if (fenceFd >= 0) { + ::close(fenceFd); + } return BAD_VALUE; } header->nFilledLen = rangeLength; @@ -1110,7 +1120,7 @@ status_t OMXNodeInstance::emptyBuffer( buffer_meta->CopyToOMX(header); } - return emptyBuffer_l(header, flags, timestamp, (intptr_t)buffer); + return emptyBuffer_l(header, flags, timestamp, (intptr_t)buffer, fenceFd); } // log queued buffer activity for the next few input and/or output frames @@ -1137,11 +1147,62 @@ void OMXNodeInstance::unbumpDebugLevel_l(size_t portIndex) { } } +status_t OMXNodeInstance::storeFenceInMeta_l( + OMX_BUFFERHEADERTYPE *header, int fenceFd, OMX_U32 portIndex) { + // propagate fence if component supports it; wait for it otherwise + OMX_U32 metaSize = portIndex == kPortIndexInput ? header->nFilledLen : header->nAllocLen; + if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer + && metaSize >= sizeof(VideoNativeMetadata)) { + VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)(header->pBuffer); + if (nativeMeta.nFenceFd >= 0) { + ALOGE("fence (%d) already exists in meta", nativeMeta.nFenceFd); + if (fenceFd >= 0) { + ::close(fenceFd); + } + return ALREADY_EXISTS; + } + nativeMeta.nFenceFd = fenceFd; + } else if (fenceFd >= 0) { + CLOG_BUFFER(storeFenceInMeta, "waiting for fence %d", fenceFd); + sp<Fence> fence = new Fence(fenceFd); + return fence->wait(IOMX::kFenceTimeoutMs); + } + return OK; +} + +int OMXNodeInstance::retrieveFenceFromMeta_l( + OMX_BUFFERHEADERTYPE *header, OMX_U32 portIndex) { + OMX_U32 metaSize = portIndex == kPortIndexInput ? header->nAllocLen : header->nFilledLen; + int fenceFd = -1; + if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer + && header->nAllocLen >= sizeof(VideoNativeMetadata)) { + VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)(header->pBuffer); + if (nativeMeta.eType == kMetadataBufferTypeANWBuffer) { + fenceFd = nativeMeta.nFenceFd; + nativeMeta.nFenceFd = -1; + } + if (metaSize < sizeof(nativeMeta) && fenceFd >= 0) { + CLOG_ERROR(foundFenceInEmptyMeta, BAD_VALUE, FULL_BUFFER( + NULL, header, nativeMeta.nFenceFd)); + fenceFd = -1; + } + } + return fenceFd; +} + status_t OMXNodeInstance::emptyBuffer_l( - OMX_BUFFERHEADERTYPE *header, OMX_U32 flags, OMX_TICKS timestamp, intptr_t debugAddr) { + OMX_BUFFERHEADERTYPE *header, OMX_U32 flags, OMX_TICKS timestamp, + intptr_t debugAddr, int fenceFd) { header->nFlags = flags; header->nTimeStamp = timestamp; + status_t res = storeFenceInMeta_l(header, fenceFd, kPortIndexInput); + if (res != OK) { + CLOG_ERROR(emptyBuffer::storeFenceInMeta, res, WITH_STATS( + FULL_BUFFER(debugAddr, header, fenceFd))); + return res; + } + { Mutex::Autolock _l(mDebugLock); mInputBuffersWithCodec.add(header); @@ -1151,11 +1212,11 @@ status_t OMXNodeInstance::emptyBuffer_l( bumpDebugLevel_l(2 /* numInputBuffers */, 0 /* numOutputBuffers */); } - CLOG_BUMPED_BUFFER(emptyBuffer, WITH_STATS(FULL_BUFFER(debugAddr, header))); + CLOG_BUMPED_BUFFER(emptyBuffer, WITH_STATS(FULL_BUFFER(debugAddr, header, fenceFd))); } OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header); - CLOG_IF_ERROR(emptyBuffer, err, FULL_BUFFER(debugAddr, header)); + CLOG_IF_ERROR(emptyBuffer, err, FULL_BUFFER(debugAddr, header, fenceFd)); { Mutex::Autolock _l(mDebugLock); @@ -1172,18 +1233,19 @@ status_t OMXNodeInstance::emptyBuffer_l( // like emptyBuffer, but the data is already in header->pBuffer status_t OMXNodeInstance::emptyGraphicBuffer( OMX_BUFFERHEADERTYPE *header, const sp<GraphicBuffer> &graphicBuffer, - OMX_U32 flags, OMX_TICKS timestamp) { + OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) { Mutex::Autolock autoLock(mLock); OMX::buffer_id buffer = findBufferID(header); status_t err = updateGraphicBufferInMeta_l(kPortIndexInput, graphicBuffer, buffer, header); if (err != OK) { - CLOG_ERROR(emptyGraphicBuffer, err, FULL_BUFFER((intptr_t)header->pBuffer, header)); + CLOG_ERROR(emptyGraphicBuffer, err, FULL_BUFFER( + (intptr_t)header->pBuffer, header, fenceFd)); return err; } header->nOffset = 0; header->nFilledLen = graphicBuffer == NULL ? 0 : header->nAllocLen; - return emptyBuffer_l(header, flags, timestamp, (intptr_t)header->pBuffer); + return emptyBuffer_l(header, flags, timestamp, (intptr_t)header->pBuffer, fenceFd); } status_t OMXNodeInstance::getExtensionIndex( @@ -1307,7 +1369,8 @@ void OMXNodeInstance::onMessage(const omx_message &msg) { mOutputBuffersWithCodec.remove(buffer); CLOG_BUMPED_BUFFER( - FBD, WITH_STATS(FULL_BUFFER(msg.u.extended_buffer_data.buffer, buffer))); + FBD, WITH_STATS(FULL_BUFFER( + msg.u.extended_buffer_data.buffer, buffer, msg.fenceFd))); unbumpDebugLevel_l(kPortIndexOutput); } @@ -1335,7 +1398,7 @@ void OMXNodeInstance::onMessage(const omx_message &msg) { mInputBuffersWithCodec.remove(buffer); CLOG_BUMPED_BUFFER( - EBD, WITH_STATS(EMPTY_BUFFER(msg.u.buffer_data.buffer, buffer))); + EBD, WITH_STATS(EMPTY_BUFFER(msg.u.buffer_data.buffer, buffer, msg.fenceFd))); } if (bufferSource != NULL) { @@ -1344,7 +1407,7 @@ void OMXNodeInstance::onMessage(const omx_message &msg) { // Don't dispatch a message back to ACodec, since it doesn't // know that anyone asked to have the buffer emptied and will // be very confused. - bufferSource->codecBufferEmptied(buffer); + bufferSource->codecBufferEmptied(buffer, msg.fenceFd); return; } } @@ -1439,8 +1502,9 @@ OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone( if (instance->mDying) { return OMX_ErrorNone; } + int fenceFd = instance->retrieveFenceFromMeta_l(pBuffer, kPortIndexOutput); return instance->owner()->OnEmptyBufferDone(instance->nodeID(), - instance->findBufferID(pBuffer), pBuffer); + instance->findBufferID(pBuffer), pBuffer, fenceFd); } // static @@ -1452,8 +1516,9 @@ OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone( if (instance->mDying) { return OMX_ErrorNone; } + int fenceFd = instance->retrieveFenceFromMeta_l(pBuffer, kPortIndexOutput); return instance->owner()->OnFillBufferDone(instance->nodeID(), - instance->findBufferID(pBuffer), pBuffer); + instance->findBufferID(pBuffer), pBuffer, fenceFd); } void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) { diff --git a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp index 5f80cbc..cd1ac36 100644 --- a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp +++ b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp @@ -517,6 +517,16 @@ const uint8_t *SoftVideoEncoderOMXComponent::extractGraphicBuffer( // TODO do we need to support other formats? srcStride *= 4; } + + if (nativeMeta.nFenceFd >= 0) { + sp<Fence> fence = new Fence(nativeMeta.nFenceFd); + nativeMeta.nFenceFd = -1; + status_t err = fence->wait(IOMX::kFenceTimeoutMs); + if (err != OK) { + ALOGE("Timed out waiting on input fence"); + return NULL; + } + } } else { // TODO: remove this part. Check if anyone uses this. |