Bug 1079695 - Part 2 - remove audio clock wordaround from MediaDecoderStateMachine. r=kinetik.

This commit is contained in:
JW Wang 2014-11-02 18:06:00 +01:00
parent 35c50eef83
commit 85fc40ca05
2 changed files with 36 additions and 28 deletions

View File

@ -1814,6 +1814,9 @@ MediaDecoderStateMachine::StartAudioThread()
mStopAudioThread = false;
if (HasAudio() && !mAudioSink) {
// The audio end time should always be at least the audio start time.
mAudioEndTime = mAudioStartTime;
MOZ_ASSERT(mAudioStartTime == GetMediaTime());
mAudioCompleted = false;
mAudioSink = new AudioSink(this, mAudioStartTime,
mInfo.mAudio, mDecoder->GetAudioChannel());
@ -2564,6 +2567,15 @@ void MediaDecoderStateMachine::RenderVideoFrame(VideoData* aData,
}
}
void MediaDecoderStateMachine::ResyncAudioClock()
{
AssertCurrentThreadInMonitor();
if (IsPlaying()) {
SetPlayStartTime(TimeStamp::Now());
mPlayDuration = GetAudioClock() - mStartTime;
}
}
int64_t
MediaDecoderStateMachine::GetAudioClock()
{
@ -2571,14 +2583,9 @@ MediaDecoderStateMachine::GetAudioClock()
// audio sink to ensure that it doesn't get destroyed on the audio sink
// while we're using it.
AssertCurrentThreadInMonitor();
if (!HasAudio() || mAudioCaptured)
return -1;
if (!mAudioSink) {
// Audio sink hasn't played any data yet.
return mAudioStartTime;
}
int64_t t = mAudioSink->GetPosition();
return (t == -1) ? -1 : t + mAudioStartTime;
MOZ_ASSERT(HasAudio() && !mAudioCaptured);
return mAudioStartTime +
(mAudioSink ? mAudioSink->GetPosition() : 0);
}
int64_t MediaDecoderStateMachine::GetVideoStreamPosition()
@ -2605,27 +2612,23 @@ int64_t MediaDecoderStateMachine::GetClock()
// audio, or don't have audio, use the system clock. If our output is being
// fed to a MediaStream, use that stream as the source of the clock.
int64_t clock_time = -1;
DecodedStreamData* stream = mDecoder->GetDecodedStream();
if (!IsPlaying()) {
clock_time = mPlayDuration + mStartTime;
} else if (stream) {
} else if (mDecoder->GetDecodedStream()) {
clock_time = GetCurrentTimeViaMediaStreamSync();
} else {
int64_t audio_time = GetAudioClock();
if (HasAudio() && !mAudioCompleted && audio_time != -1) {
clock_time = audio_time;
// Resync against the audio clock, while we're trusting the
// audio clock. This ensures no "drift", particularly on Linux.
mPlayDuration = clock_time - mStartTime;
SetPlayStartTime(TimeStamp::Now());
if (HasAudio() && !mAudioCompleted && !mAudioCaptured) {
clock_time = GetAudioClock();
} else {
// Audio is disabled on this system. Sync to the system clock.
clock_time = GetVideoStreamPosition();
// Ensure the clock can never go backwards.
NS_ASSERTION(mCurrentFrameTime <= clock_time || mPlaybackRate <= 0,
"Clock should go forwards if the playback rate is > 0.");
}
// FIXME: This assertion should also apply the case of decoding to a stream.
// Ensure the clock can never go backwards.
NS_ASSERTION(GetMediaTime() <= clock_time || mPlaybackRate <= 0,
"Clock should go forwards if the playback rate is > 0.");
}
return clock_time;
}
@ -2646,7 +2649,7 @@ void MediaDecoderStateMachine::AdvanceFrame()
return;
}
int64_t clock_time = GetClock();
const int64_t clock_time = GetClock();
TimeStamp nowTime = TimeStamp::Now();
// Skip frames up to the frame at the playback position, and figure out
// the time remaining until it's time to display the next frame.
@ -2745,13 +2748,11 @@ void MediaDecoderStateMachine::AdvanceFrame()
// advance the clock to after the media end time.
if (mVideoFrameEndTime != -1 || mAudioEndTime != -1) {
// These will be non -1 if we've displayed a video frame, or played an audio frame.
clock_time = std::min(clock_time, std::max(mVideoFrameEndTime, mAudioEndTime));
if (clock_time > GetMediaTime()) {
// Only update the playback position if the clock time is greater
// than the previous playback position. The audio clock can
// sometimes report a time less than its previously reported in
// some situations, and we need to gracefully handle that.
UpdatePlaybackPosition(clock_time);
int64_t t = std::min(clock_time, std::max(mVideoFrameEndTime, mAudioEndTime));
// FIXME: Bug 1091422 - chained ogg files hit this assertion.
//MOZ_ASSERT(t >= GetMediaTime());
if (t > GetMediaTime()) {
UpdatePlaybackPosition(t);
}
}
@ -3141,6 +3142,7 @@ void MediaDecoderStateMachine::OnAudioSinkComplete()
if (mAudioCaptured) {
return;
}
ResyncAudioClock();
mAudioCompleted = true;
UpdateReadyState();
// Kick the decode thread; it may be sleeping waiting for this to finish.
@ -3155,6 +3157,7 @@ void MediaDecoderStateMachine::OnAudioSinkError()
return;
}
ResyncAudioClock();
mAudioCompleted = true;
// Make the best effort to continue playback when there is video.

View File

@ -450,6 +450,11 @@ protected:
// ResetPlayback() to discard all enqueued data.
void FlushDecoding();
// Called when AudioSink reaches the end. |mPlayStartTime| and
// |mPlayDuration| are updated to provide a good base for calculating video
// stream time.
void ResyncAudioClock();
// Returns the audio clock, if we have audio, or -1 if we don't.
// Called on the state machine thread.
int64_t GetAudioClock();