Bug 1157797 - Use state-watching machinery for UpdateNextFrameStatus. r=jww

The ergonomics here aren't ideal. I'm going to file a bug to improve them.
This commit is contained in:
Bobby Holley 2015-04-27 11:51:46 -07:00
Родитель 7a1c7f2705
Коммит 23925f4fdc
3 изменённых файлов: 19 добавлений и 12 удалений

Просмотреть файл

@ -205,11 +205,12 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mRealTime(aRealTime),
mDispatchedStateMachine(false),
mDelayedScheduler(this),
mState(DECODER_STATE_DECODING_NONE),
mState(DECODER_STATE_DECODING_NONE, "MediaDecoderStateMachine::mState"),
mPlayDuration(0),
mStartTime(-1),
mEndTime(-1),
mDurationSet(false),
mNextFrameStatusUpdater("MediaDecoderStateMachine::mNextFrameStatusUpdater"),
mFragmentEndTime(-1),
mReader(aReader),
mCurrentFrameTime(0),
@ -228,7 +229,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mIsVideoPrerolling(false),
mAudioCaptured(false),
mPositionChangeQueued(false),
mAudioCompleted(false),
mAudioCompleted(false, "MediaDecoderStateMachine::mAudioCompleted"),
mGotDurationFromMetaData(false),
mDispatchedEventToDecode(false),
mStopAudioThread(true),
@ -257,6 +258,12 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mNextFrameStatus.Init(mTaskQueue, MediaDecoderOwner::NEXT_FRAME_UNINITIALIZED,
"MediaDecoderStateMachine::mNextFrameStatus (Canonical)");
// Skip the initial notification we get when we Watch the value, since we're
// not on the right thread yet.
mNextFrameStatusUpdater->Watch(mState, /* aSkipInitialNotify = */ true);
mNextFrameStatusUpdater->Watch(mAudioCompleted, /* aSkipInitialNotify = */ true);
mNextFrameStatusUpdater->AddWeakCallback(this, &MediaDecoderStateMachine::UpdateNextFrameStatus);
static bool sPrefCacheInit = false;
if (!sPrefCacheInit) {
sPrefCacheInit = true;
@ -1321,8 +1328,6 @@ void MediaDecoderStateMachine::SetState(State aState)
mState = aState;
UpdateNextFrameStatus();
// Clear state-scoped state.
mSentPlaybackEndedEvent = false;
}
@ -3182,7 +3187,7 @@ void MediaDecoderStateMachine::SetStartTime(int64_t aStartTimeUsecs)
void MediaDecoderStateMachine::UpdateNextFrameStatus() {
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor();
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
MediaDecoderOwner::NextFrameStatus status;
const char* statusString;
@ -3424,7 +3429,6 @@ void MediaDecoderStateMachine::OnAudioSinkComplete()
}
ResyncAudioClock();
mAudioCompleted = true;
UpdateNextFrameStatus();
// Kick the decode thread; it may be sleeping waiting for this to finish.
mDecoder->GetReentrantMonitor().NotifyAll();
}

Просмотреть файл

@ -844,7 +844,7 @@ public:
// NotifyAll on the monitor must be called when the state is changed so
// that interested threads can wake up and alter behaviour if appropriate
// Accessed on state machine, audio, main, and AV thread.
State mState;
Watchable<State> mState;
// The task queue in which we run decode tasks. This is referred to as
// the "decode thread", though in practise tasks can run on a different
@ -887,6 +887,7 @@ public:
// The status of our next frame. Mirrored on the main thread and used to
// compute ready state.
WatcherHolder mNextFrameStatusUpdater;
Canonical<NextFrameStatus>::Holder mNextFrameStatus;
public:
AbstractCanonical<NextFrameStatus>* CanonicalNextFrameStatus() { return &mNextFrameStatus; }
@ -1155,7 +1156,7 @@ protected:
// the state machine thread. Synchronised via decoder monitor.
// When data is being sent to a MediaStream, this is true when all data has
// been written to the MediaStream.
bool mAudioCompleted;
Watchable<bool> mAudioCompleted;
// True if mDuration has a value obtained from an HTTP header, or from
// the media index/metadata. Accessed on the state machine thread.

Просмотреть файл

@ -70,7 +70,7 @@ void EnsureStateWatchingLog();
class AbstractWatcher
{
public:
NS_INLINE_DECL_REFCOUNTING(AbstractWatcher)
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AbstractWatcher)
AbstractWatcher() : mDestroyed(false) {}
bool IsDestroyed() { return mDestroyed; }
virtual void Notify() = 0;
@ -104,12 +104,14 @@ class WatchTarget
public:
explicit WatchTarget(const char* aName) : mName(aName) {}
void AddWatcher(AbstractWatcher* aWatcher)
void AddWatcher(AbstractWatcher* aWatcher, bool aSkipInitialNotify)
{
MOZ_ASSERT(!mWatchers.Contains(aWatcher));
mWatchers.AppendElement(aWatcher);
if (!aSkipInitialNotify) {
aWatcher->Notify();
}
}
void RemoveWatcher(AbstractWatcher* aWatcher)
{
@ -204,7 +206,7 @@ public:
AbstractThread::GetCurrent()->TailDispatcher().AddDirectTask(r.forget());
}
void Watch(WatchTarget& aTarget) { aTarget.AddWatcher(this); }
void Watch(WatchTarget& aTarget, bool aSkipInitialNotify = false) { aTarget.AddWatcher(this, aSkipInitialNotify); }
void Unwatch(WatchTarget& aTarget) { aTarget.RemoveWatcher(this); }
template<typename ThisType>