diff options
author | Andreas Huber <andih@google.com> | 2013-07-31 13:50:42 -0700 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2013-08-13 10:11:46 -0700 |
commit | a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58 (patch) | |
tree | a360123ee73434ee45608b03a02d8fb6ff431c3b /media/libstagefright/omx/GraphicBufferSource.cpp | |
parent | 1b832c3d8f2b1b24f9bc7025afd2b4a8b4e6c6f9 (diff) | |
download | frameworks_av-a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58.zip frameworks_av-a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58.tar.gz frameworks_av-a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58.tar.bz2 |
Optionally repeat the previously submitted frame to the encoder
if no new frame has been delivered by surface flinger within the timeout
interval.
Change-Id: I282f1b726dfe5646b178d7858d6f5d4f5a264fde
Diffstat (limited to 'media/libstagefright/omx/GraphicBufferSource.cpp')
-rw-r--r-- | media/libstagefright/omx/GraphicBufferSource.cpp | 167 |
1 files changed, 164 insertions, 3 deletions
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp index 325ffcf..cf43e94 100644 --- a/media/libstagefright/omx/GraphicBufferSource.cpp +++ b/media/libstagefright/omx/GraphicBufferSource.cpp @@ -22,6 +22,7 @@ #include <OMX_Core.h> #include <media/stagefright/foundation/ADebug.h> +#include <media/stagefright/foundation/AMessage.h> #include <media/hardware/MetadataBufferType.h> #include <ui/GraphicBuffer.h> @@ -39,7 +40,13 @@ GraphicBufferSource::GraphicBufferSource(OMXNodeInstance* nodeInstance, mSuspended(false), mNumFramesAvailable(0), mEndOfStream(false), - mEndOfStreamSent(false) { + mEndOfStreamSent(false), + mRepeatAfterUs(-1ll), + mRepeatLastFrameGeneration(0), + mLatestSubmittedBufferId(-1), + mLatestSubmittedBufferFrameNum(0), + mLatestSubmittedBufferUseCount(0), + mRepeatBufferDeferred(false) { ALOGV("GraphicBufferSource w=%u h=%u c=%u", bufferWidth, bufferHeight, bufferCount); @@ -123,6 +130,22 @@ void GraphicBufferSource::omxExecuting() { if (mEndOfStream && mNumFramesAvailable == 0) { submitEndOfInputStream_l(); } + + if (mRepeatAfterUs > 0ll && mLooper == NULL) { + mReflector = new AHandlerReflector<GraphicBufferSource>(this); + + mLooper = new ALooper; + mLooper->registerHandler(mReflector); + mLooper->start(); + + if (mLatestSubmittedBufferId >= 0) { + sp<AMessage> msg = + new AMessage(kWhatRepeatLastFrame, mReflector->id()); + + msg->setInt32("generation", ++mRepeatLastFrameGeneration); + msg->post(mRepeatAfterUs); + } + } } void GraphicBufferSource::omxLoaded(){ @@ -132,6 +155,14 @@ void GraphicBufferSource::omxLoaded(){ ALOGW("Dropped back down to Loaded without Executing"); } + if (mLooper != NULL) { + mLooper->unregisterHandler(mReflector->id()); + mReflector.clear(); + + mLooper->stop(); + mLooper.clear(); + } + ALOGV("--> loaded; avail=%d eos=%d eosSent=%d", mNumFramesAvailable, mEndOfStream, mEndOfStreamSent); @@ -211,8 +242,12 @@ void GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header) { ALOGV("cbi %d matches bq slot %d, handle=%p", cbi, id, mBufferSlot[id]->handle); - mBufferQueue->releaseBuffer(id, codecBuffer.mFrameNumber, - EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); + if (id == mLatestSubmittedBufferId) { + CHECK_GT(mLatestSubmittedBufferUseCount--, 0); + } else { + mBufferQueue->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", cbi); @@ -232,7 +267,16 @@ void GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header) { // send that. ALOGV("buffer freed, EOS pending"); submitEndOfInputStream_l(); + } else if (mRepeatBufferDeferred) { + bool success = repeatLatestSubmittedBuffer_l(); + if (success) { + ALOGV("deferred repeatLatestSubmittedBuffer_l SUCCESS"); + } else { + ALOGV("deferred repeatLatestSubmittedBuffer_l FAILURE"); + } + mRepeatBufferDeferred = false; } + return; } @@ -264,6 +308,16 @@ void GraphicBufferSource::suspend(bool suspend) { } mSuspended = false; + + if (mExecuting && mNumFramesAvailable == 0 && mRepeatBufferDeferred) { + if (repeatLatestSubmittedBuffer_l()) { + ALOGV("suspend/deferred repeatLatestSubmittedBuffer_l SUCCESS"); + + mRepeatBufferDeferred = false; + } else { + ALOGV("suspend/deferred repeatLatestSubmittedBuffer_l FAILURE"); + } + } } bool GraphicBufferSource::fillCodecBuffer_l() { @@ -318,11 +372,68 @@ bool GraphicBufferSource::fillCodecBuffer_l() { EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); } else { ALOGV("buffer submitted (bq %d, cbi %d)", item.mBuf, cbi); + setLatestSubmittedBuffer_l(item); + } + + return true; +} + +bool GraphicBufferSource::repeatLatestSubmittedBuffer_l() { + CHECK(mExecuting && mNumFramesAvailable == 0); + + if (mLatestSubmittedBufferId < 0 || mSuspended) { + return false; + } + + int cbi = findAvailableCodecBuffer_l(); + if (cbi < 0) { + // No buffers available, bail. + ALOGV("repeatLatestSubmittedBuffer_l: no codec buffers."); + return false; + } + + BufferQueue::BufferItem item; + item.mBuf = mLatestSubmittedBufferId; + item.mFrameNumber = mLatestSubmittedBufferFrameNum; + + status_t err = submitBuffer_l(item, cbi); + + if (err != OK) { + return false; } + ++mLatestSubmittedBufferUseCount; + return true; } +void GraphicBufferSource::setLatestSubmittedBuffer_l( + const BufferQueue::BufferItem &item) { + ALOGV("setLatestSubmittedBuffer_l"); + + if (mLatestSubmittedBufferId >= 0) { + if (mLatestSubmittedBufferUseCount == 0) { + mBufferQueue->releaseBuffer( + mLatestSubmittedBufferId, + mLatestSubmittedBufferFrameNum, + EGL_NO_DISPLAY, + EGL_NO_SYNC_KHR, + Fence::NO_FENCE); + } + } + + mLatestSubmittedBufferId = item.mBuf; + mLatestSubmittedBufferFrameNum = item.mFrameNumber; + mLatestSubmittedBufferUseCount = 1; + mRepeatBufferDeferred = false; + + if (mReflector != NULL) { + sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector->id()); + msg->setInt32("generation", ++mRepeatLastFrameGeneration); + msg->post(mRepeatAfterUs); + } +} + status_t GraphicBufferSource::signalEndOfInputStream() { Mutex::Autolock autoLock(mMutex); ALOGV("signalEndOfInputStream: exec=%d avail=%d eos=%d", @@ -470,6 +581,9 @@ void GraphicBufferSource::onFrameAvailable() { mNumFramesAvailable++; + mRepeatBufferDeferred = false; + ++mRepeatLastFrameGeneration; + if (mExecuting) { fillCodecBuffer_l(); } @@ -495,4 +609,51 @@ void GraphicBufferSource::onBuffersReleased() { } } +status_t GraphicBufferSource::setRepeatPreviousFrameDelayUs( + int64_t repeatAfterUs) { + Mutex::Autolock autoLock(mMutex); + + if (mExecuting || repeatAfterUs <= 0ll) { + return INVALID_OPERATION; + } + + mRepeatAfterUs = repeatAfterUs; + + return OK; +} + +void GraphicBufferSource::onMessageReceived(const sp<AMessage> &msg) { + switch (msg->what()) { + case kWhatRepeatLastFrame: + { + Mutex::Autolock autoLock(mMutex); + + int32_t generation; + CHECK(msg->findInt32("generation", &generation)); + + if (generation != mRepeatLastFrameGeneration) { + // stale + break; + } + + if (!mExecuting || mNumFramesAvailable > 0) { + break; + } + + bool success = repeatLatestSubmittedBuffer_l(); + + if (success) { + ALOGV("repeatLatestSubmittedBuffer_l SUCCESS"); + } else { + ALOGV("repeatLatestSubmittedBuffer_l FAILURE"); + mRepeatBufferDeferred = true; + } + break; + } + + default: + TRESPASS(); + } +} + } // namespace android |