Bug 1050667 - fix the non-synchronous waiting state between MediaDecoderStataMachine and MediaOmxReader and OmxDecoder. r=sotaro

This commit is contained in:
Benjamin Chen 2014-09-18 15:28:33 +08:00
parent b9e39edae5
commit c36b5a4a96
6 changed files with 60 additions and 25 deletions

View File

@ -1419,11 +1419,21 @@ void MediaDecoderStateMachine::StartWaitForResources()
void MediaDecoderStateMachine::NotifyWaitingForResourcesStatusChanged() void MediaDecoderStateMachine::NotifyWaitingForResourcesStatusChanged()
{ {
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
if (mState != DECODER_STATE_WAIT_FOR_RESOURCES || DECODER_LOG("NotifyWaitingForResourcesStatusChanged");
mReader->IsWaitingMediaResources()) { RefPtr<nsIRunnable> task(
NS_NewRunnableMethod(this,
&MediaDecoderStateMachine::DoNotifyWaitingForResourcesStatusChanged));
mDecodeTaskQueue->Dispatch(task);
}
void MediaDecoderStateMachine::DoNotifyWaitingForResourcesStatusChanged()
{
NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
if (mState != DECODER_STATE_WAIT_FOR_RESOURCES) {
return; return;
} }
DECODER_LOG("NotifyWaitingForResourcesStatusChanged"); DECODER_LOG("DoNotifyWaitingForResourcesStatusChanged");
// The reader is no longer waiting for resources (say a hardware decoder), // The reader is no longer waiting for resources (say a hardware decoder),
// we can now proceed to decode metadata. // we can now proceed to decode metadata.
SetState(DECODER_STATE_DECODING_NONE); SetState(DECODER_STATE_DECODING_NONE);

View File

@ -327,9 +327,9 @@ public:
// be held. // be held.
bool IsPlaying(); bool IsPlaying();
// Dispatch DoNotifyWaitingForResourcesStatusChanged task to mDecodeTaskQueue.
// Called when the reader may have acquired the hardware resources required // Called when the reader may have acquired the hardware resources required
// to begin decoding. The state machine may move into DECODING_METADATA if // to begin decoding. The decoder monitor must be held while calling this.
// appropriate. The decoder monitor must be held while calling this.
void NotifyWaitingForResourcesStatusChanged(); void NotifyWaitingForResourcesStatusChanged();
// Notifies the state machine that should minimize the number of samples // Notifies the state machine that should minimize the number of samples
@ -636,6 +636,10 @@ protected:
// and the sink is shutting down. // and the sink is shutting down.
void OnAudioSinkComplete(); void OnAudioSinkComplete();
// The state machine may move into DECODING_METADATA if we are in
// DECODER_STATE_WAIT_FOR_RESOURCES.
void DoNotifyWaitingForResourcesStatusChanged();
// The decoder object that created this state machine. The state machine // The decoder object that created this state machine. The state machine
// holds a strong reference to the decoder to ensure that the decoder stays // holds a strong reference to the decoder to ensure that the decoder stays
// alive once media element has started the decoder shutdown process, and has // alive once media element has started the decoder shutdown process, and has

View File

@ -135,6 +135,7 @@ MediaOmxReader::MediaOmxReader(AbstractMediaDecoder *aDecoder)
, mSkipCount(0) , mSkipCount(0)
, mUseParserDuration(false) , mUseParserDuration(false)
, mLastParserDuration(-1) , mLastParserDuration(-1)
, mIsWaitingResources(false)
{ {
#ifdef PR_LOGGING #ifdef PR_LOGGING
if (!gMediaDecoderLog) { if (!gMediaDecoderLog) {
@ -172,10 +173,16 @@ void MediaOmxReader::Shutdown()
bool MediaOmxReader::IsWaitingMediaResources() bool MediaOmxReader::IsWaitingMediaResources()
{ {
if (!mOmxDecoder.get()) { return mIsWaitingResources;
return false; }
void MediaOmxReader::UpdateIsWaitingMediaResources()
{
if (mOmxDecoder.get()) {
mIsWaitingResources = mOmxDecoder->IsWaitingMediaResources();
} else {
mIsWaitingResources = false;
} }
return mOmxDecoder->IsWaitingMediaResources();
} }
bool MediaOmxReader::IsDormantNeeded() bool MediaOmxReader::IsDormantNeeded()
@ -245,13 +252,21 @@ nsresult MediaOmxReader::ReadMetadata(MediaInfo* aInfo,
ProcessCachedData(0, true); ProcessCachedData(0, true);
} }
if (!mOmxDecoder->TryLoad()) { if (!mOmxDecoder->AllocateMediaResources()) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
// Bug 1050667, both MediaDecoderStateMachine and MediaOmxReader
// relies on IsWaitingMediaResources() function. And the waiting state will be
// changed by binder thread, so we store the waiting state in a cache value to
// make them in the same waiting state.
UpdateIsWaitingMediaResources();
if (IsWaitingMediaResources()) { if (IsWaitingMediaResources()) {
return NS_OK; return NS_OK;
} }
// After resources are available, set the metadata.
if (!mOmxDecoder->EnsureMetadata()) {
return NS_ERROR_FAILURE;
}
if (isMP3 && mMP3FrameParser.IsMP3()) { if (isMP3 && mMP3FrameParser.IsMP3()) {
int64_t duration = mMP3FrameParser.GetDuration(); int64_t duration = mMP3FrameParser.GetDuration();

View File

@ -44,6 +44,11 @@ protected:
android::sp<android::OmxDecoder> mOmxDecoder; android::sp<android::OmxDecoder> mOmxDecoder;
android::sp<android::MediaExtractor> mExtractor; android::sp<android::MediaExtractor> mExtractor;
MP3FrameParser mMP3FrameParser; MP3FrameParser mMP3FrameParser;
// A cache value updated by UpdateIsWaitingMediaResources(), makes the
// "waiting resources state" is synchronous to StateMachine.
bool mIsWaitingResources;
// Called by ReadMetadata() during MediaDecoderStateMachine::DecodeMetadata() // Called by ReadMetadata() during MediaDecoderStateMachine::DecodeMetadata()
// on decode thread. It create and initialize the OMX decoder including // on decode thread. It create and initialize the OMX decoder including
// setting up custom extractor. The extractor provide the essential // setting up custom extractor. The extractor provide the essential
@ -54,6 +59,11 @@ protected:
// to activate the decoder automatically. // to activate the decoder automatically.
virtual void EnsureActive(); virtual void EnsureActive();
// Check the underlying HW resources are available and store the result in
// mIsWaitingResources. The result might be changed by binder thread,
// Can only called by ReadMetadata.
void UpdateIsWaitingMediaResources();
public: public:
MediaOmxReader(AbstractMediaDecoder* aDecoder); MediaOmxReader(AbstractMediaDecoder* aDecoder);
~MediaOmxReader(); ~MediaOmxReader();
@ -76,7 +86,8 @@ public:
return mHasVideo; return mHasVideo;
} }
virtual bool IsWaitingMediaResources(); // Return mIsWaitingResources.
virtual bool IsWaitingMediaResources() MOZ_OVERRIDE;
virtual bool IsDormantNeeded(); virtual bool IsDormantNeeded();
virtual void ReleaseMediaResources(); virtual void ReleaseMediaResources();

View File

@ -162,19 +162,7 @@ bool OmxDecoder::Init(sp<MediaExtractor>& extractor) {
return true; return true;
} }
bool OmxDecoder::TryLoad() { bool OmxDecoder::EnsureMetadata() {
if (!AllocateMediaResources()) {
return false;
}
//check if video is waiting resources
if (mVideoSource.get()) {
if (mVideoSource->IsWaitingResources()) {
return true;
}
}
// calculate duration // calculate duration
int64_t totalDurationUs = 0; int64_t totalDurationUs = 0;
int64_t durationUs = 0; int64_t durationUs = 0;

View File

@ -152,9 +152,16 @@ public:
// Note: RTSP requires a custom extractor because it doesn't have a container. // Note: RTSP requires a custom extractor because it doesn't have a container.
bool Init(sp<MediaExtractor>& extractor); bool Init(sp<MediaExtractor>& extractor);
bool TryLoad();
bool IsDormantNeeded(); bool IsDormantNeeded();
// Called after resources(video/audio codec) are allocated, set the
// mDurationUs and video/audio metadata.
bool EnsureMetadata();
// Only called by MediaOmxDecoder, do not call this function arbitrarily.
// See bug 1050667.
bool IsWaitingMediaResources(); bool IsWaitingMediaResources();
bool AllocateMediaResources(); bool AllocateMediaResources();
void ReleaseMediaResources(); void ReleaseMediaResources();
bool SetVideoFormat(); bool SetVideoFormat();