Loading include/media/stagefright/ACodec.h +9 −0 Original line number Diff line number Diff line Loading @@ -138,6 +138,7 @@ private: IOMX::buffer_id mBufferID; Status mStatus; unsigned mDequeuedAt; sp<ABuffer> mData; sp<GraphicBuffer> mGraphicBuffer; Loading Loading @@ -194,12 +195,20 @@ private: bool mChannelMaskPresent; int32_t mChannelMask; unsigned mDequeueCounter; bool mStoreMetaDataInOutputBuffers; int32_t mMetaDataBuffersToSubmit; status_t setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode); status_t allocateBuffersOnPort(OMX_U32 portIndex); status_t freeBuffersOnPort(OMX_U32 portIndex); status_t freeBuffer(OMX_U32 portIndex, size_t i); status_t configureOutputBuffersFromNativeWindow( OMX_U32 *nBufferCount, OMX_U32 *nBufferSize, OMX_U32 *nMinUndequeuedBuffers); status_t allocateOutputMetaDataBuffers(); status_t submitOutputMetaDataBuffer(); status_t allocateOutputBuffersFromNativeWindow(); status_t cancelBufferToNativeWindow(BufferInfo *info); status_t freeOutputBuffersNotOwnedByComponent(); Loading media/libstagefright/ACodec.cpp +186 −15 Original line number Diff line number Diff line Loading @@ -255,6 +255,8 @@ private: struct ACodec::ExecutingState : public ACodec::BaseState { ExecutingState(ACodec *codec); void submitRegularOutputBuffers(); void submitOutputMetaBuffers(); void submitOutputBuffers(); // Submit output buffers to the decoder, submit input buffers to client Loading Loading @@ -364,7 +366,10 @@ ACodec::ACodec() mEncoderDelay(0), mEncoderPadding(0), mChannelMaskPresent(false), mChannelMask(0) { mChannelMask(0), mDequeueCounter(0), mStoreMetaDataInOutputBuffers(false), mMetaDataBuffersToSubmit(0) { mUninitializedState = new UninitializedState(this); mLoadedState = new LoadedState(this); mLoadedToIdleState = new LoadedToIdleState(this); Loading Loading @@ -454,7 +459,11 @@ status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { status_t err; if (mNativeWindow != NULL && portIndex == kPortIndexOutput) { if (mStoreMetaDataInOutputBuffers) { err = allocateOutputMetaDataBuffers(); } else { err = allocateOutputBuffersFromNativeWindow(); } } else { OMX_PARAM_PORTDEFINITIONTYPE def; InitOMXParams(&def); Loading Loading @@ -536,7 +545,9 @@ status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { return OK; } status_t ACodec::allocateOutputBuffersFromNativeWindow() { status_t ACodec::configureOutputBuffersFromNativeWindow( OMX_U32 *bufferCount, OMX_U32 *bufferSize, OMX_U32 *minUndequeuedBuffers) { OMX_PARAM_PORTDEFINITIONTYPE def; InitOMXParams(&def); def.nPortIndex = kPortIndexOutput; Loading Loading @@ -601,10 +612,10 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() { return err; } int minUndequeuedBufs = 0; *minUndequeuedBuffers = 0; err = mNativeWindow->query( mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs); (int *)minUndequeuedBuffers); if (err != 0) { ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)", Loading @@ -615,8 +626,8 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() { // XXX: Is this the right logic to use? It's not clear to me what the OMX // buffer counts refer to - how do they account for the renderer holding on // to buffers? if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) { OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs; if (def.nBufferCountActual < def.nBufferCountMin + *minUndequeuedBuffers) { OMX_U32 newBufferCount = def.nBufferCountMin + *minUndequeuedBuffers; def.nBufferCountActual = newBufferCount; err = mOMX->setParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); Loading @@ -637,12 +648,24 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() { return err; } *bufferCount = def.nBufferCountActual; *bufferSize = def.nBufferSize; return err; } status_t ACodec::allocateOutputBuffersFromNativeWindow() { OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers; status_t err = configureOutputBuffersFromNativeWindow( &bufferCount, &bufferSize, &minUndequeuedBuffers); if (err != 0) return err; ALOGV("[%s] Allocating %lu buffers from a native window of size %lu on " "output port", mComponentName.c_str(), def.nBufferCountActual, def.nBufferSize); mComponentName.c_str(), bufferCount, bufferSize); // Dequeue buffers and send them to OMX for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) { for (OMX_U32 i = 0; i < bufferCount; i++) { ANativeWindowBuffer *buf; err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf); if (err != 0) { Loading @@ -653,7 +676,7 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() { sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false)); BufferInfo info; info.mStatus = BufferInfo::OWNED_BY_US; info.mData = new ABuffer(NULL /* data */, def.nBufferSize /* capacity */); info.mData = new ABuffer(NULL /* data */, bufferSize /* capacity */); info.mGraphicBuffer = graphicBuffer; mBuffers[kPortIndexOutput].push(info); Loading Loading @@ -682,9 +705,9 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() { cancelStart = 0; cancelEnd = mBuffers[kPortIndexOutput].size(); } else { // Return the last two buffers to the native window. cancelStart = def.nBufferCountActual - minUndequeuedBufs; cancelEnd = def.nBufferCountActual; // Return the required minimum undequeued buffers to the native window. cancelStart = bufferCount - minUndequeuedBuffers; cancelEnd = bufferCount; } for (OMX_U32 i = cancelStart; i < cancelEnd; i++) { Loading @@ -695,6 +718,65 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() { return err; } status_t ACodec::allocateOutputMetaDataBuffers() { OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers; status_t err = configureOutputBuffersFromNativeWindow( &bufferCount, &bufferSize, &minUndequeuedBuffers); if (err != 0) return err; ALOGV("[%s] Allocating %lu meta buffers on output port", mComponentName.c_str(), bufferCount); size_t totalSize = bufferCount * 8; mDealer[kPortIndexOutput] = new MemoryDealer(totalSize, "ACodec"); // Dequeue buffers and send them to OMX for (OMX_U32 i = 0; i < bufferCount; i++) { BufferInfo info; info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; info.mGraphicBuffer = NULL; info.mDequeuedAt = mDequeueCounter; sp<IMemory> mem = mDealer[kPortIndexOutput]->allocate( sizeof(struct VideoDecoderOutputMetaData)); CHECK(mem.get() != NULL); info.mData = new ABuffer(mem->pointer(), mem->size()); // we use useBuffer for metadata regardless of quirks err = mOMX->useBuffer( mNode, kPortIndexOutput, mem, &info.mBufferID); mBuffers[kPortIndexOutput].push(info); ALOGV("[%s] allocated meta buffer with ID %p (pointer = %p)", mComponentName.c_str(), info.mBufferID, mem->pointer()); } mMetaDataBuffersToSubmit = bufferCount - minUndequeuedBuffers; return err; } status_t ACodec::submitOutputMetaDataBuffer() { CHECK(mStoreMetaDataInOutputBuffers); if (mMetaDataBuffersToSubmit == 0) return OK; BufferInfo *info = dequeueBufferFromNativeWindow(); if (info == NULL) return ERROR_IO; ALOGV("[%s] submitting output meta buffer ID %p for graphic buffer %p", mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer.get()); --mMetaDataBuffersToSubmit; CHECK_EQ(mOMX->fillBuffer(mNode, info->mBufferID), (status_t)OK); info->mStatus = BufferInfo::OWNED_BY_COMPONENT; return OK; } status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) { CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); Loading @@ -714,16 +796,19 @@ status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) { ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() { ANativeWindowBuffer *buf; int fenceFd = -1; CHECK(mNativeWindow.get() != NULL); if (native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf) != 0) { ALOGE("dequeueBuffer failed."); return NULL; } BufferInfo *oldest = NULL; for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); if (info->mGraphicBuffer->handle == buf->handle) { if (info->mGraphicBuffer != NULL && info->mGraphicBuffer->handle == buf->handle) { CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_NATIVE_WINDOW); Loading @@ -731,6 +816,34 @@ ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() { return info; } if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW && (oldest == NULL || // avoid potential issues from counter rolling over mDequeueCounter - info->mDequeuedAt > mDequeueCounter - oldest->mDequeuedAt)) { oldest = info; } } if (oldest) { CHECK(mStoreMetaDataInOutputBuffers); // discard buffer in LRU info and replace with new buffer oldest->mGraphicBuffer = new GraphicBuffer(buf, false); oldest->mStatus = BufferInfo::OWNED_BY_US; struct VideoDecoderOutputMetaData metaData; metaData.eType = kMetadataBufferTypeGrallocSource; metaData.pHandle = oldest->mGraphicBuffer->handle; memcpy(oldest->mData->base(), &metaData, sizeof(metaData)); ALOGV("replaced oldest buffer #%u with age %u (%p stored in %p)", oldest - &mBuffers[kPortIndexOutput][0], mDequeueCounter - oldest->mDequeuedAt, metaData.pHandle, oldest->mData->base()); return oldest; } TRESPASS(); Loading Loading @@ -971,6 +1084,24 @@ status_t ACodec::configureCodec( } } // Always try to enable dynamic output buffers on native surface sp<RefBase> obj; int32_t haveNativeWindow = msg->findObject("native-window", &obj) && obj != NULL; mStoreMetaDataInOutputBuffers = false; if (!encoder && video && haveNativeWindow) { err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, OMX_TRUE); if (err != OK) { // allow failure ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d", mComponentName.c_str(), err); err = OK; } else { ALOGV("[%s] storeMetaDataInBuffers succeeded", mComponentName.c_str()); mStoreMetaDataInOutputBuffers = true; } } if (video) { if (encoder) { err = setupVideoEncoder(mime, msg); Loading Loading @@ -2949,6 +3080,20 @@ void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { mCodec->mBufferStats.add(timeUs, stats); #endif if (mCodec->mStoreMetaDataInOutputBuffers) { // try to submit an output buffer for each input buffer PortMode outputMode = getPortMode(kPortIndexOutput); ALOGV("MetaDataBuffersToSubmit=%u portMode=%s", mCodec->mMetaDataBuffersToSubmit, (outputMode == FREE_BUFFERS ? "FREE" : outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT")); if (outputMode == RESUBMIT_BUFFERS) { CHECK_EQ(mCodec->submitOutputMetaDataBuffer(), (status_t)OK); } } CHECK_EQ(mCodec->mOMX->emptyBuffer( mCodec->mNode, bufferID, Loading Loading @@ -3066,6 +3211,7 @@ bool ACodec::BaseState::onOMXFillBufferDone( CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); info->mDequeuedAt = ++mCodec->mDequeueCounter; info->mStatus = BufferInfo::OWNED_BY_US; PortMode mode = getPortMode(kPortIndexOutput); Loading Loading @@ -3447,6 +3593,9 @@ void ACodec::LoadedState::stateEntered() { mCodec->mInputEOSResult = OK; mCodec->mDequeueCounter = 0; mCodec->mMetaDataBuffersToSubmit = 0; if (mCodec->mShutdownInProgress) { bool keepComponentAllocated = mCodec->mKeepComponentAllocated; Loading Loading @@ -3764,7 +3913,20 @@ ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( return RESUBMIT_BUFFERS; } void ACodec::ExecutingState::submitOutputBuffers() { void ACodec::ExecutingState::submitOutputMetaBuffers() { // submit as many buffers as there are input buffers with the codec // in case we are in port reconfiguring for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) { if (mCodec->submitOutputMetaDataBuffer() != OK) break; } } } void ACodec::ExecutingState::submitRegularOutputBuffers() { for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); Loading @@ -3789,6 +3951,14 @@ void ACodec::ExecutingState::submitOutputBuffers() { } } void ACodec::ExecutingState::submitOutputBuffers() { if (mCodec->mStoreMetaDataInOutputBuffers) { submitOutputMetaBuffers(); } else { submitRegularOutputBuffers(); } } void ACodec::ExecutingState::resume() { if (mActive) { ALOGV("[%s] We're already active, no need to resume.", Loading Loading @@ -3955,6 +4125,7 @@ bool ACodec::ExecutingState::onOMXEvent( CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { mCodec->mMetaDataBuffersToSubmit = 0; CHECK_EQ(mCodec->mOMX->sendCommand( mCodec->mNode, OMX_CommandPortDisable, kPortIndexOutput), Loading Loading
include/media/stagefright/ACodec.h +9 −0 Original line number Diff line number Diff line Loading @@ -138,6 +138,7 @@ private: IOMX::buffer_id mBufferID; Status mStatus; unsigned mDequeuedAt; sp<ABuffer> mData; sp<GraphicBuffer> mGraphicBuffer; Loading Loading @@ -194,12 +195,20 @@ private: bool mChannelMaskPresent; int32_t mChannelMask; unsigned mDequeueCounter; bool mStoreMetaDataInOutputBuffers; int32_t mMetaDataBuffersToSubmit; status_t setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode); status_t allocateBuffersOnPort(OMX_U32 portIndex); status_t freeBuffersOnPort(OMX_U32 portIndex); status_t freeBuffer(OMX_U32 portIndex, size_t i); status_t configureOutputBuffersFromNativeWindow( OMX_U32 *nBufferCount, OMX_U32 *nBufferSize, OMX_U32 *nMinUndequeuedBuffers); status_t allocateOutputMetaDataBuffers(); status_t submitOutputMetaDataBuffer(); status_t allocateOutputBuffersFromNativeWindow(); status_t cancelBufferToNativeWindow(BufferInfo *info); status_t freeOutputBuffersNotOwnedByComponent(); Loading
media/libstagefright/ACodec.cpp +186 −15 Original line number Diff line number Diff line Loading @@ -255,6 +255,8 @@ private: struct ACodec::ExecutingState : public ACodec::BaseState { ExecutingState(ACodec *codec); void submitRegularOutputBuffers(); void submitOutputMetaBuffers(); void submitOutputBuffers(); // Submit output buffers to the decoder, submit input buffers to client Loading Loading @@ -364,7 +366,10 @@ ACodec::ACodec() mEncoderDelay(0), mEncoderPadding(0), mChannelMaskPresent(false), mChannelMask(0) { mChannelMask(0), mDequeueCounter(0), mStoreMetaDataInOutputBuffers(false), mMetaDataBuffersToSubmit(0) { mUninitializedState = new UninitializedState(this); mLoadedState = new LoadedState(this); mLoadedToIdleState = new LoadedToIdleState(this); Loading Loading @@ -454,7 +459,11 @@ status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { status_t err; if (mNativeWindow != NULL && portIndex == kPortIndexOutput) { if (mStoreMetaDataInOutputBuffers) { err = allocateOutputMetaDataBuffers(); } else { err = allocateOutputBuffersFromNativeWindow(); } } else { OMX_PARAM_PORTDEFINITIONTYPE def; InitOMXParams(&def); Loading Loading @@ -536,7 +545,9 @@ status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { return OK; } status_t ACodec::allocateOutputBuffersFromNativeWindow() { status_t ACodec::configureOutputBuffersFromNativeWindow( OMX_U32 *bufferCount, OMX_U32 *bufferSize, OMX_U32 *minUndequeuedBuffers) { OMX_PARAM_PORTDEFINITIONTYPE def; InitOMXParams(&def); def.nPortIndex = kPortIndexOutput; Loading Loading @@ -601,10 +612,10 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() { return err; } int minUndequeuedBufs = 0; *minUndequeuedBuffers = 0; err = mNativeWindow->query( mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs); (int *)minUndequeuedBuffers); if (err != 0) { ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)", Loading @@ -615,8 +626,8 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() { // XXX: Is this the right logic to use? It's not clear to me what the OMX // buffer counts refer to - how do they account for the renderer holding on // to buffers? if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) { OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs; if (def.nBufferCountActual < def.nBufferCountMin + *minUndequeuedBuffers) { OMX_U32 newBufferCount = def.nBufferCountMin + *minUndequeuedBuffers; def.nBufferCountActual = newBufferCount; err = mOMX->setParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); Loading @@ -637,12 +648,24 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() { return err; } *bufferCount = def.nBufferCountActual; *bufferSize = def.nBufferSize; return err; } status_t ACodec::allocateOutputBuffersFromNativeWindow() { OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers; status_t err = configureOutputBuffersFromNativeWindow( &bufferCount, &bufferSize, &minUndequeuedBuffers); if (err != 0) return err; ALOGV("[%s] Allocating %lu buffers from a native window of size %lu on " "output port", mComponentName.c_str(), def.nBufferCountActual, def.nBufferSize); mComponentName.c_str(), bufferCount, bufferSize); // Dequeue buffers and send them to OMX for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) { for (OMX_U32 i = 0; i < bufferCount; i++) { ANativeWindowBuffer *buf; err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf); if (err != 0) { Loading @@ -653,7 +676,7 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() { sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false)); BufferInfo info; info.mStatus = BufferInfo::OWNED_BY_US; info.mData = new ABuffer(NULL /* data */, def.nBufferSize /* capacity */); info.mData = new ABuffer(NULL /* data */, bufferSize /* capacity */); info.mGraphicBuffer = graphicBuffer; mBuffers[kPortIndexOutput].push(info); Loading Loading @@ -682,9 +705,9 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() { cancelStart = 0; cancelEnd = mBuffers[kPortIndexOutput].size(); } else { // Return the last two buffers to the native window. cancelStart = def.nBufferCountActual - minUndequeuedBufs; cancelEnd = def.nBufferCountActual; // Return the required minimum undequeued buffers to the native window. cancelStart = bufferCount - minUndequeuedBuffers; cancelEnd = bufferCount; } for (OMX_U32 i = cancelStart; i < cancelEnd; i++) { Loading @@ -695,6 +718,65 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() { return err; } status_t ACodec::allocateOutputMetaDataBuffers() { OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers; status_t err = configureOutputBuffersFromNativeWindow( &bufferCount, &bufferSize, &minUndequeuedBuffers); if (err != 0) return err; ALOGV("[%s] Allocating %lu meta buffers on output port", mComponentName.c_str(), bufferCount); size_t totalSize = bufferCount * 8; mDealer[kPortIndexOutput] = new MemoryDealer(totalSize, "ACodec"); // Dequeue buffers and send them to OMX for (OMX_U32 i = 0; i < bufferCount; i++) { BufferInfo info; info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; info.mGraphicBuffer = NULL; info.mDequeuedAt = mDequeueCounter; sp<IMemory> mem = mDealer[kPortIndexOutput]->allocate( sizeof(struct VideoDecoderOutputMetaData)); CHECK(mem.get() != NULL); info.mData = new ABuffer(mem->pointer(), mem->size()); // we use useBuffer for metadata regardless of quirks err = mOMX->useBuffer( mNode, kPortIndexOutput, mem, &info.mBufferID); mBuffers[kPortIndexOutput].push(info); ALOGV("[%s] allocated meta buffer with ID %p (pointer = %p)", mComponentName.c_str(), info.mBufferID, mem->pointer()); } mMetaDataBuffersToSubmit = bufferCount - minUndequeuedBuffers; return err; } status_t ACodec::submitOutputMetaDataBuffer() { CHECK(mStoreMetaDataInOutputBuffers); if (mMetaDataBuffersToSubmit == 0) return OK; BufferInfo *info = dequeueBufferFromNativeWindow(); if (info == NULL) return ERROR_IO; ALOGV("[%s] submitting output meta buffer ID %p for graphic buffer %p", mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer.get()); --mMetaDataBuffersToSubmit; CHECK_EQ(mOMX->fillBuffer(mNode, info->mBufferID), (status_t)OK); info->mStatus = BufferInfo::OWNED_BY_COMPONENT; return OK; } status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) { CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); Loading @@ -714,16 +796,19 @@ status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) { ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() { ANativeWindowBuffer *buf; int fenceFd = -1; CHECK(mNativeWindow.get() != NULL); if (native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf) != 0) { ALOGE("dequeueBuffer failed."); return NULL; } BufferInfo *oldest = NULL; for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); if (info->mGraphicBuffer->handle == buf->handle) { if (info->mGraphicBuffer != NULL && info->mGraphicBuffer->handle == buf->handle) { CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_NATIVE_WINDOW); Loading @@ -731,6 +816,34 @@ ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() { return info; } if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW && (oldest == NULL || // avoid potential issues from counter rolling over mDequeueCounter - info->mDequeuedAt > mDequeueCounter - oldest->mDequeuedAt)) { oldest = info; } } if (oldest) { CHECK(mStoreMetaDataInOutputBuffers); // discard buffer in LRU info and replace with new buffer oldest->mGraphicBuffer = new GraphicBuffer(buf, false); oldest->mStatus = BufferInfo::OWNED_BY_US; struct VideoDecoderOutputMetaData metaData; metaData.eType = kMetadataBufferTypeGrallocSource; metaData.pHandle = oldest->mGraphicBuffer->handle; memcpy(oldest->mData->base(), &metaData, sizeof(metaData)); ALOGV("replaced oldest buffer #%u with age %u (%p stored in %p)", oldest - &mBuffers[kPortIndexOutput][0], mDequeueCounter - oldest->mDequeuedAt, metaData.pHandle, oldest->mData->base()); return oldest; } TRESPASS(); Loading Loading @@ -971,6 +1084,24 @@ status_t ACodec::configureCodec( } } // Always try to enable dynamic output buffers on native surface sp<RefBase> obj; int32_t haveNativeWindow = msg->findObject("native-window", &obj) && obj != NULL; mStoreMetaDataInOutputBuffers = false; if (!encoder && video && haveNativeWindow) { err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, OMX_TRUE); if (err != OK) { // allow failure ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d", mComponentName.c_str(), err); err = OK; } else { ALOGV("[%s] storeMetaDataInBuffers succeeded", mComponentName.c_str()); mStoreMetaDataInOutputBuffers = true; } } if (video) { if (encoder) { err = setupVideoEncoder(mime, msg); Loading Loading @@ -2949,6 +3080,20 @@ void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { mCodec->mBufferStats.add(timeUs, stats); #endif if (mCodec->mStoreMetaDataInOutputBuffers) { // try to submit an output buffer for each input buffer PortMode outputMode = getPortMode(kPortIndexOutput); ALOGV("MetaDataBuffersToSubmit=%u portMode=%s", mCodec->mMetaDataBuffersToSubmit, (outputMode == FREE_BUFFERS ? "FREE" : outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT")); if (outputMode == RESUBMIT_BUFFERS) { CHECK_EQ(mCodec->submitOutputMetaDataBuffer(), (status_t)OK); } } CHECK_EQ(mCodec->mOMX->emptyBuffer( mCodec->mNode, bufferID, Loading Loading @@ -3066,6 +3211,7 @@ bool ACodec::BaseState::onOMXFillBufferDone( CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); info->mDequeuedAt = ++mCodec->mDequeueCounter; info->mStatus = BufferInfo::OWNED_BY_US; PortMode mode = getPortMode(kPortIndexOutput); Loading Loading @@ -3447,6 +3593,9 @@ void ACodec::LoadedState::stateEntered() { mCodec->mInputEOSResult = OK; mCodec->mDequeueCounter = 0; mCodec->mMetaDataBuffersToSubmit = 0; if (mCodec->mShutdownInProgress) { bool keepComponentAllocated = mCodec->mKeepComponentAllocated; Loading Loading @@ -3764,7 +3913,20 @@ ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( return RESUBMIT_BUFFERS; } void ACodec::ExecutingState::submitOutputBuffers() { void ACodec::ExecutingState::submitOutputMetaBuffers() { // submit as many buffers as there are input buffers with the codec // in case we are in port reconfiguring for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) { if (mCodec->submitOutputMetaDataBuffer() != OK) break; } } } void ACodec::ExecutingState::submitRegularOutputBuffers() { for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); Loading @@ -3789,6 +3951,14 @@ void ACodec::ExecutingState::submitOutputBuffers() { } } void ACodec::ExecutingState::submitOutputBuffers() { if (mCodec->mStoreMetaDataInOutputBuffers) { submitOutputMetaBuffers(); } else { submitRegularOutputBuffers(); } } void ACodec::ExecutingState::resume() { if (mActive) { ALOGV("[%s] We're already active, no need to resume.", Loading Loading @@ -3955,6 +4125,7 @@ bool ACodec::ExecutingState::onOMXEvent( CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { mCodec->mMetaDataBuffersToSubmit = 0; CHECK_EQ(mCodec->mOMX->sendCommand( mCodec->mNode, OMX_CommandPortDisable, kPortIndexOutput), Loading