Bug 1307546 - Ensure we don't set timers with negative intervals in to update A/V sync. r=jya

Our logic to do A/V sync sets a timer to drop expired frames based on the
start time of the next frame in the queue. If the frames in the queue are
badly muxed and don't have monotonically increasing start times, we can
end up setting a timer with a negative interval. This causes us to reevaluate
the frames in the VideoSink's queue immediately, set the same timer again,
and so we end up hot-looping.

This is a simple low-risk fix that detects when we're about to set a negative
interval timer, and instead sets the timer 1/30th of a second in the future.

This fix is deliberately low risk, such that it's suitable for uplift. I have
an idea how to do this better, but the lower risk this is most suitable for
uplift.

MozReview-Commit-ID: CDOqJJodx4l

--HG--
extra : rebase_source : b2833382d95143ee1845f2ea32dcc77a1903dc00
This commit is contained in:
Chris Pearce 2016-11-04 16:42:24 +13:00
Родитель c30b70be6d
Коммит d2ec5f2f3e
1 изменённых файлов: 9 добавлений и 1 удалений

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

@ -24,6 +24,12 @@ using namespace mozilla::layers;
namespace media {
// For badly muxed files, if we try to set a timeout to discard expired
// frames, but the start time of the next frame is less than the clock time,
// we instead just set a timeout FAILOVER_UPDATE_INTERVAL_US in the future,
// and run UpdateRenderedVideoFrames() then.
static const int64_t FAILOVER_UPDATE_INTERVAL_US = 1000000 / 30;
VideoSink::VideoSink(AbstractThread* aThread,
MediaSink* aAudioSink,
MediaQueue<MediaData>& aVideoQueue,
@ -441,8 +447,10 @@ VideoSink::UpdateRenderedVideoFrames()
}
int64_t nextFrameTime = frames[1]->mTime;
int64_t delta = (nextFrameTime > clockTime) ? (nextFrameTime - clockTime)
: FAILOVER_UPDATE_INTERVAL_US;
TimeStamp target = nowTime + TimeDuration::FromMicroseconds(
(nextFrameTime - clockTime) / mAudioSink->GetPlaybackParams().mPlaybackRate);
delta / mAudioSink->GetPlaybackParams().mPlaybackRate);
RefPtr<VideoSink> self = this;
mUpdateScheduler.Ensure(target, [self] () {