diff options
Diffstat (limited to 'media/libstagefright/omx/GraphicBufferSource.cpp')
-rw-r--r-- | media/libstagefright/omx/GraphicBufferSource.cpp | 119 |
1 files changed, 93 insertions, 26 deletions
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp index 3fe9c23..16f6c58 100644 --- a/media/libstagefright/omx/GraphicBufferSource.cpp +++ b/media/libstagefright/omx/GraphicBufferSource.cpp @@ -29,6 +29,8 @@ #include <media/hardware/MetadataBufferType.h> #include <ui/GraphicBuffer.h> +#include <inttypes.h> + namespace android { static const bool EXTRA_CHECK = true; @@ -43,16 +45,21 @@ GraphicBufferSource::GraphicBufferSource(OMXNodeInstance* nodeInstance, mNumFramesAvailable(0), mEndOfStream(false), mEndOfStreamSent(false), - mRepeatAfterUs(-1ll), mMaxTimestampGapUs(-1ll), mPrevOriginalTimeUs(-1ll), mPrevModifiedTimeUs(-1ll), + mSkipFramesBeforeNs(-1ll), + mRepeatAfterUs(-1ll), mRepeatLastFrameGeneration(0), mRepeatLastFrameTimestamp(-1ll), mLatestSubmittedBufferId(-1), mLatestSubmittedBufferFrameNum(0), mLatestSubmittedBufferUseCount(0), - mRepeatBufferDeferred(false) { + mRepeatBufferDeferred(false), + mTimePerCaptureUs(-1ll), + mTimePerFrameUs(-1ll), + mPrevCaptureUs(-1ll), + mPrevFrameUs(-1ll) { ALOGV("GraphicBufferSource w=%u h=%u c=%u", bufferWidth, bufferHeight, bufferCount); @@ -65,13 +72,13 @@ GraphicBufferSource::GraphicBufferSource(OMXNodeInstance* nodeInstance, String8 name("GraphicBufferSource"); - mBufferQueue = new BufferQueue(); - mBufferQueue->setConsumerName(name); - mBufferQueue->setDefaultBufferSize(bufferWidth, bufferHeight); - mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER | + BufferQueue::createBufferQueue(&mProducer, &mConsumer); + mConsumer->setConsumerName(name); + mConsumer->setDefaultBufferSize(bufferWidth, bufferHeight); + mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER | GRALLOC_USAGE_HW_TEXTURE); - mInitCheck = mBufferQueue->setMaxAcquiredBufferCount(bufferCount); + mInitCheck = mConsumer->setMaxAcquiredBufferCount(bufferCount); if (mInitCheck != NO_ERROR) { ALOGE("Unable to set BQ max acquired buffer count to %u: %d", bufferCount, mInitCheck); @@ -85,7 +92,7 @@ GraphicBufferSource::GraphicBufferSource(OMXNodeInstance* nodeInstance, wp<BufferQueue::ConsumerListener> listener = static_cast<BufferQueue::ConsumerListener*>(this); sp<BufferQueue::ProxyConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener); - mInitCheck = mBufferQueue->consumerConnect(proxy, false); + mInitCheck = mConsumer->consumerConnect(proxy, false); if (mInitCheck != NO_ERROR) { ALOGE("Error connecting to BufferQueue: %s (%d)", strerror(-mInitCheck), mInitCheck); @@ -97,8 +104,8 @@ GraphicBufferSource::GraphicBufferSource(OMXNodeInstance* nodeInstance, GraphicBufferSource::~GraphicBufferSource() { ALOGV("~GraphicBufferSource"); - if (mBufferQueue != NULL) { - status_t err = mBufferQueue->consumerDisconnect(); + if (mConsumer != NULL) { + status_t err = mConsumer->consumerDisconnect(); if (err != NO_ERROR) { ALOGW("consumerDisconnect failed: %d", err); } @@ -270,7 +277,7 @@ void GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header) { if (id == mLatestSubmittedBufferId) { CHECK_GT(mLatestSubmittedBufferUseCount--, 0); } else { - mBufferQueue->releaseBuffer(id, codecBuffer.mFrameNumber, + mConsumer->releaseBuffer(id, codecBuffer.mFrameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); } } else { @@ -339,7 +346,7 @@ void GraphicBufferSource::suspend(bool suspend) { while (mNumFramesAvailable > 0) { BufferQueue::BufferItem item; - status_t err = mBufferQueue->acquireBuffer(&item, 0); + status_t err = mConsumer->acquireBuffer(&item, 0); if (err == BufferQueue::NO_BUFFER_AVAILABLE) { // shouldn't happen. @@ -352,7 +359,7 @@ void GraphicBufferSource::suspend(bool suspend) { --mNumFramesAvailable; - mBufferQueue->releaseBuffer(item.mBuf, item.mFrameNumber, + mConsumer->releaseBuffer(item.mBuf, item.mFrameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence); } return; @@ -389,7 +396,7 @@ bool GraphicBufferSource::fillCodecBuffer_l() { ALOGV("fillCodecBuffer_l: acquiring buffer, avail=%d", mNumFramesAvailable); BufferQueue::BufferItem item; - status_t err = mBufferQueue->acquireBuffer(&item, 0); + status_t err = mConsumer->acquireBuffer(&item, 0); if (err == BufferQueue::NO_BUFFER_AVAILABLE) { // shouldn't happen ALOGW("fillCodecBuffer_l: frame was not available"); @@ -416,10 +423,21 @@ bool GraphicBufferSource::fillCodecBuffer_l() { mBufferSlot[item.mBuf] = item.mGraphicBuffer; } - err = submitBuffer_l(item, cbi); + err = UNKNOWN_ERROR; + + // only submit sample if start time is unspecified, or sample + // is queued after the specified start time + if (mSkipFramesBeforeNs < 0ll || item.mTimestamp >= mSkipFramesBeforeNs) { + // if start time is set, offset time stamp by start time + if (mSkipFramesBeforeNs > 0) { + item.mTimestamp -= mSkipFramesBeforeNs; + } + err = submitBuffer_l(item, cbi); + } + if (err != OK) { ALOGV("submitBuffer_l failed, releasing bq buf %d", item.mBuf); - mBufferQueue->releaseBuffer(item.mBuf, item.mFrameNumber, + 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); @@ -442,7 +460,7 @@ bool GraphicBufferSource::repeatLatestSubmittedBuffer_l() { // // To be on the safe side we try to release the buffer. ALOGD("repeatLatestSubmittedBuffer_l: slot was NULL"); - mBufferQueue->releaseBuffer( + mConsumer->releaseBuffer( mLatestSubmittedBufferId, mLatestSubmittedBufferFrameNum, EGL_NO_DISPLAY, @@ -496,7 +514,7 @@ void GraphicBufferSource::setLatestSubmittedBuffer_l( if (mLatestSubmittedBufferId >= 0) { if (mLatestSubmittedBufferUseCount == 0) { - mBufferQueue->releaseBuffer( + mConsumer->releaseBuffer( mLatestSubmittedBufferId, mLatestSubmittedBufferFrameNum, EGL_NO_DISPLAY, @@ -550,7 +568,30 @@ status_t GraphicBufferSource::signalEndOfInputStream() { int64_t GraphicBufferSource::getTimestamp(const BufferQueue::BufferItem &item) { int64_t timeUs = item.mTimestamp / 1000; - if (mMaxTimestampGapUs > 0ll) { + if (mTimePerCaptureUs > 0ll) { + // Time lapse or slow motion mode + if (mPrevCaptureUs < 0ll) { + // first capture + mPrevCaptureUs = timeUs; + mPrevFrameUs = timeUs; + } else { + // snap to nearest capture point + int64_t nFrames = (timeUs + mTimePerCaptureUs / 2 - mPrevCaptureUs) + / mTimePerCaptureUs; + if (nFrames <= 0) { + // skip this frame as it's too close to previous capture + ALOGV("skipping frame, timeUs %lld", timeUs); + return -1; + } + mPrevCaptureUs = mPrevCaptureUs + nFrames * mTimePerCaptureUs; + mPrevFrameUs += mTimePerFrameUs * nFrames; + } + + ALOGV("timeUs %lld, captureUs %lld, frameUs %lld", + timeUs, mPrevCaptureUs, mPrevFrameUs); + + return mPrevFrameUs; + } else if (mMaxTimestampGapUs > 0ll) { /* Cap timestamp gap between adjacent frames to specified max * * In the scenario of cast mirroring, encoding could be suspended for @@ -696,15 +737,15 @@ void GraphicBufferSource::onFrameAvailable() { } BufferQueue::BufferItem item; - status_t err = mBufferQueue->acquireBuffer(&item, 0); + status_t err = mConsumer->acquireBuffer(&item, 0); if (err == OK) { // If this is the first time we're seeing this buffer, add it to our // slot table. if (item.mGraphicBuffer != NULL) { - ALOGV("fillCodecBuffer_l: setting mBufferSlot %d", item.mBuf); + ALOGV("onFrameAvailable: setting mBufferSlot %d", item.mBuf); mBufferSlot[item.mBuf] = item.mGraphicBuffer; } - mBufferQueue->releaseBuffer(item.mBuf, item.mFrameNumber, + mConsumer->releaseBuffer(item.mBuf, item.mFrameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence); } return; @@ -724,13 +765,13 @@ void GraphicBufferSource::onFrameAvailable() { void GraphicBufferSource::onBuffersReleased() { Mutex::Autolock lock(mMutex); - uint32_t slotMask; - if (mBufferQueue->getReleasedBuffers(&slotMask) != NO_ERROR) { + uint64_t slotMask; + if (mConsumer->getReleasedBuffers(&slotMask) != NO_ERROR) { ALOGW("onBuffersReleased: unable to get released buffer set"); - slotMask = 0xffffffff; + slotMask = 0xffffffffffffffffULL; } - ALOGV("onBuffersReleased: 0x%08x", slotMask); + ALOGV("onBuffersReleased: 0x%016" PRIx64, slotMask); for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { if ((slotMask & 0x01) != 0) { @@ -740,6 +781,11 @@ void GraphicBufferSource::onBuffersReleased() { } } +// BufferQueue::ConsumerListener callback +void GraphicBufferSource::onSidebandStreamChanged() { + ALOG_ASSERT(false, "GraphicBufferSource can't consume sideband streams"); +} + status_t GraphicBufferSource::setRepeatPreviousFrameDelayUs( int64_t repeatAfterUs) { Mutex::Autolock autoLock(mMutex); @@ -764,6 +810,27 @@ status_t GraphicBufferSource::setMaxTimestampGapUs(int64_t maxGapUs) { return OK; } + +void GraphicBufferSource::setSkipFramesBeforeUs(int64_t skipFramesBeforeUs) { + Mutex::Autolock autoLock(mMutex); + + mSkipFramesBeforeNs = + (skipFramesBeforeUs > 0) ? (skipFramesBeforeUs * 1000) : -1ll; +} + +status_t GraphicBufferSource::setTimeLapseUs(int64_t* data) { + Mutex::Autolock autoLock(mMutex); + + if (mExecuting || data[0] <= 0ll || data[1] <= 0ll) { + return INVALID_OPERATION; + } + + mTimePerFrameUs = data[0]; + mTimePerCaptureUs = data[1]; + + return OK; +} + void GraphicBufferSource::onMessageReceived(const sp<AMessage> &msg) { switch (msg->what()) { case kWhatRepeatLastFrame: |