Bug 907162 - Fix MediaDecoderStateMachine might dispatch MediaDecoder::PlaybackEnded more than once and trigger multiple 'ended' events in HTMLMediaElement. r=cpearce

This commit is contained in:
JW Wang 2014-03-17 10:12:20 +08:00
Родитель 909e49d702
Коммит 895f37b1d8
1 изменённых файлов: 17 добавлений и 4 удалений

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

@ -1521,7 +1521,7 @@ void
MediaDecoderStateMachine::DispatchDecodeTasksIfNeeded()
{
AssertCurrentThreadInMonitor();
// NeedToDecodeAudio() can go from false to true while we hold the
// monitor, but it can't go from true to false. This can happen because
// NeedToDecodeAudio() takes into account the amount of decoded audio
@ -2274,9 +2274,16 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
int64_t clockTime = std::max(mEndTime, std::max(videoTime, GetAudioClock()));
UpdatePlaybackPosition(clockTime);
nsCOMPtr<nsIRunnable> event =
NS_NewRunnableMethod(mDecoder, &MediaDecoder::PlaybackEnded);
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
{
// Wait for the state change is completed in the main thread,
// otherwise we might see |mDecoder->GetState() == MediaDecoder::PLAY_STATE_PLAYING|
// in next loop and send |MediaDecoder::PlaybackEnded| again to trigger 'ended'
// event twice in the media element.
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
nsCOMPtr<nsIRunnable> event =
NS_NewRunnableMethod(mDecoder, &MediaDecoder::PlaybackEnded);
NS_DispatchToMainThread(event, NS_DISPATCH_SYNC);
}
}
return NS_OK;
}
@ -2756,6 +2763,12 @@ nsresult MediaDecoderStateMachine::ScheduleStateMachine(int64_t aUsecs) {
return NS_OK;
}
// Since there is already a pending task that will run immediately,
// we don't need to schedule a timer task.
if (mRunAgain) {
return NS_OK;
}
mTimeout = timeout;
nsresult res;