diff options
author | Bill Yi <byi@google.com> | 2014-04-29 11:34:16 -0700 |
---|---|---|
committer | Bill Yi <byi@google.com> | 2014-04-29 11:34:16 -0700 |
commit | 1a7be1ec9c769203e6c8e26378de0ab8e2ad493d (patch) | |
tree | 68773b199cc4adcb96124270863244477570c78e /media/libstagefright/ACodec.cpp | |
parent | f131f87369ec06fc27fc1f14ea72f0ca1a066509 (diff) | |
parent | 91820d46b5f3065c2fded3cdf65d305715b33bb1 (diff) | |
download | frameworks_av-1a7be1ec9c769203e6c8e26378de0ab8e2ad493d.zip frameworks_av-1a7be1ec9c769203e6c8e26378de0ab8e2ad493d.tar.gz frameworks_av-1a7be1ec9c769203e6c8e26378de0ab8e2ad493d.tar.bz2 |
Merge commit '91820d46b5f3065c2fded3cdf65d305715b33bb1' into HEAD
Diffstat (limited to 'media/libstagefright/ACodec.cpp')
-rw-r--r-- | media/libstagefright/ACodec.cpp | 111 |
1 files changed, 85 insertions, 26 deletions
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index dfe6c56..2d04bbb 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -363,6 +363,7 @@ ACodec::ACodec() mIsEncoder(false), mUseMetadataOnEncoderOutput(false), mShutdownInProgress(false), + mIsConfiguredForAdaptivePlayback(false), mEncoderDelay(0), mEncoderPadding(0), mChannelMaskPresent(false), @@ -370,7 +371,8 @@ ACodec::ACodec() mDequeueCounter(0), mStoreMetaDataInOutputBuffers(false), mMetaDataBuffersToSubmit(0), - mRepeatFrameDelayUs(-1ll) { + mRepeatFrameDelayUs(-1ll), + mMaxPtsGapUs(-1l) { mUninitializedState = new UninitializedState(this); mLoadedState = new LoadedState(this); mLoadedToIdleState = new LoadedToIdleState(this); @@ -452,6 +454,18 @@ void ACodec::signalRequestIDRFrame() { (new AMessage(kWhatRequestIDRFrame, id()))->post(); } +// *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** +// Some codecs may return input buffers before having them processed. +// This causes a halt if we already signaled an EOS on the input +// port. For now keep submitting an output buffer if there was an +// EOS on the input port, but not yet on the output port. +void ACodec::signalSubmitOutputMetaDataBufferIfEOS_workaround() { + if (mPortEOS[kPortIndexInput] && !mPortEOS[kPortIndexOutput] && + mMetaDataBuffersToSubmit > 0) { + (new AMessage(kWhatSubmitOutputMetaDataBufferIfEOS, id()))->post(); + } +} + status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); @@ -624,18 +638,34 @@ status_t ACodec::configureOutputBuffersFromNativeWindow( return err; } - // 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 + *minUndequeuedBuffers) { - OMX_U32 newBufferCount = def.nBufferCountMin + *minUndequeuedBuffers; + // FIXME: assume that surface is controlled by app (native window + // returns the number for the case when surface is not controlled by app) + // FIXME2: This means that minUndeqeueudBufs can be 1 larger than reported + // For now, try to allocate 1 more buffer, but don't fail if unsuccessful + + // Use conservative allocation while also trying to reduce starvation + // + // 1. allocate at least nBufferCountMin + minUndequeuedBuffers - that is the + // minimum needed for the consumer to be able to work + // 2. try to allocate two (2) additional buffers to reduce starvation from + // the consumer + // plus an extra buffer to account for incorrect minUndequeuedBufs + for (OMX_U32 extraBuffers = 2 + 1; /* condition inside loop */; extraBuffers--) { + OMX_U32 newBufferCount = + def.nBufferCountMin + *minUndequeuedBuffers + extraBuffers; def.nBufferCountActual = newBufferCount; err = mOMX->setParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - if (err != OK) { - ALOGE("[%s] setting nBufferCountActual to %lu failed: %d", - mComponentName.c_str(), newBufferCount, err); + if (err == OK) { + *minUndequeuedBuffers += extraBuffers; + break; + } + + ALOGW("[%s] setting nBufferCountActual to %lu failed: %d", + mComponentName.c_str(), newBufferCount, err); + /* exit condition */ + if (extraBuffers == 0) { return err; } } @@ -660,6 +690,7 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() { &bufferCount, &bufferSize, &minUndequeuedBuffers); if (err != 0) return err; + mNumUndequeuedBuffers = minUndequeuedBuffers; ALOGV("[%s] Allocating %lu buffers from a native window of size %lu on " "output port", @@ -725,6 +756,7 @@ status_t ACodec::allocateOutputMetaDataBuffers() { &bufferCount, &bufferSize, &minUndequeuedBuffers); if (err != 0) return err; + mNumUndequeuedBuffers = minUndequeuedBuffers; ALOGV("[%s] Allocating %lu meta buffers on output port", mComponentName.c_str(), bufferCount); @@ -1096,6 +1128,10 @@ status_t ACodec::configureCodec( &mRepeatFrameDelayUs)) { mRepeatFrameDelayUs = -1ll; } + + if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) { + mMaxPtsGapUs = -1l; + } } // Always try to enable dynamic output buffers on native surface @@ -1103,6 +1139,7 @@ status_t ACodec::configureCodec( int32_t haveNativeWindow = msg->findObject("native-window", &obj) && obj != NULL; mStoreMetaDataInOutputBuffers = false; + mIsConfiguredForAdaptivePlayback = false; if (!encoder && video && haveNativeWindow) { err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, OMX_TRUE); if (err != OK) { @@ -1147,12 +1184,14 @@ status_t ACodec::configureCodec( ALOGW_IF(err != OK, "[%s] prepareForAdaptivePlayback failed w/ err %d", mComponentName.c_str(), err); + mIsConfiguredForAdaptivePlayback = (err == OK); } // allow failure err = OK; } else { ALOGV("[%s] storeMetaDataInBuffers succeeded", mComponentName.c_str()); mStoreMetaDataInOutputBuffers = true; + mIsConfiguredForAdaptivePlayback = true; } int32_t push; @@ -2408,19 +2447,7 @@ void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() { return; } - int minUndequeuedBufs = 0; - status_t err = mNativeWindow->query( - mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, - &minUndequeuedBufs); - - if (err != OK) { - ALOGE("[%s] NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)", - mComponentName.c_str(), strerror(-err), -err); - - minUndequeuedBufs = 0; - } - - while (countBuffersOwnedByNativeWindow() > (size_t)minUndequeuedBufs + while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers && dequeueBufferFromNativeWindow() != NULL) { // these buffers will be submitted as regular buffers; account for this if (mStoreMetaDataInOutputBuffers && mMetaDataBuffersToSubmit > 0) { @@ -3235,11 +3262,11 @@ void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { mCodec->mInputEOSResult = err; } break; - - default: - CHECK_EQ((int)mode, (int)FREE_BUFFERS); - break; } + + default: + CHECK_EQ((int)mode, (int)FREE_BUFFERS); + break; } } @@ -3690,6 +3717,7 @@ void ACodec::LoadedState::stateEntered() { mCodec->mDequeueCounter = 0; mCodec->mMetaDataBuffersToSubmit = 0; mCodec->mRepeatFrameDelayUs = -1ll; + mCodec->mIsConfiguredForAdaptivePlayback = false; if (mCodec->mShutdownInProgress) { bool keepComponentAllocated = mCodec->mKeepComponentAllocated; @@ -3838,6 +3866,21 @@ void ACodec::LoadedState::onCreateInputSurface( } } + if (err == OK && mCodec->mMaxPtsGapUs > 0l) { + err = mCodec->mOMX->setInternalOption( + mCodec->mNode, + kPortIndexInput, + IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP, + &mCodec->mMaxPtsGapUs, + sizeof(mCodec->mMaxPtsGapUs)); + + if (err != OK) { + ALOGE("[%s] Unable to configure max timestamp gap (err %d)", + mCodec->mComponentName.c_str(), + err); + } + } + if (err == OK) { notify->setObject("input-surface", new BufferProducerWrapper(bufferProducer)); @@ -4036,6 +4079,9 @@ void ACodec::ExecutingState::submitOutputMetaBuffers() { break; } } + + // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** + mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround(); } void ACodec::ExecutingState::submitRegularOutputBuffers() { @@ -4184,6 +4230,19 @@ bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { break; } + // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** + case kWhatSubmitOutputMetaDataBufferIfEOS: + { + if (mCodec->mPortEOS[kPortIndexInput] && + !mCodec->mPortEOS[kPortIndexOutput]) { + status_t err = mCodec->submitOutputMetaDataBuffer(); + if (err == OK) { + mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround(); + } + } + return true; + } + default: handled = BaseState::onMessageReceived(msg); break; |