| Index: media/filters/video_renderer_algorithm.cc
|
| diff --git a/media/filters/video_renderer_algorithm.cc b/media/filters/video_renderer_algorithm.cc
|
| index 052321dae5366fe152acc1e61627bfd750324c12..8df9e5c90fe91b0b4af65961b26eb16012e4f496 100644
|
| --- a/media/filters/video_renderer_algorithm.cc
|
| +++ b/media/filters/video_renderer_algorithm.cc
|
| @@ -11,7 +11,7 @@ namespace media {
|
|
|
| // The number of frames to store for moving average calculations. Value picked
|
| // after experimenting with playback of various local media and YouTube clips.
|
| -const int kMovingAverageSamples = 25;
|
| +const int kMovingAverageSamples = 32;
|
|
|
| VideoRendererAlgorithm::ReadyFrame::ReadyFrame(
|
| const scoped_refptr<VideoFrame>& ready_frame)
|
| @@ -94,12 +94,11 @@ scoped_refptr<VideoFrame> VideoRendererAlgorithm::Render(
|
| base::TimeDelta selected_frame_drift;
|
|
|
| // Step 4: Attempt to find the best frame by cadence.
|
| - bool was_frame_selected_by_cadence = false;
|
| int cadence_overage = 0;
|
| - int frame_to_render =
|
| + const int cadence_frame =
|
| FindBestFrameByCadence(first_frame_ ? nullptr : &cadence_overage);
|
| + int frame_to_render = cadence_frame;
|
| if (frame_to_render >= 0) {
|
| - was_frame_selected_by_cadence = true;
|
| selected_frame_drift =
|
| CalculateAbsoluteDriftForFrame(deadline_min, frame_to_render);
|
| }
|
| @@ -123,12 +122,6 @@ scoped_refptr<VideoFrame> VideoRendererAlgorithm::Render(
|
| }
|
|
|
| if (frame_to_render >= 0) {
|
| - if (was_frame_selected_by_cadence) {
|
| - cadence_overage = 0;
|
| - was_frame_selected_by_cadence = false;
|
| - DVLOG(2) << "Overriding frame selected by cadence because of drift: "
|
| - << selected_frame_drift;
|
| - }
|
| selected_frame_drift =
|
| CalculateAbsoluteDriftForFrame(deadline_min, frame_to_render);
|
| }
|
| @@ -138,12 +131,14 @@ scoped_refptr<VideoFrame> VideoRendererAlgorithm::Render(
|
| // least crappy option based on the drift from the deadline. If we're here the
|
| // selection is going to be bad because it means no suitable frame has any
|
| // coverage of the deadline interval.
|
| - if (frame_to_render < 0 || selected_frame_drift > max_acceptable_drift_) {
|
| - if (was_frame_selected_by_cadence) {
|
| - cadence_overage = 0;
|
| - was_frame_selected_by_cadence = false;
|
| - }
|
| + if (frame_to_render < 0 || selected_frame_drift > max_acceptable_drift_)
|
| frame_to_render = FindBestFrameByDrift(deadline_min, &selected_frame_drift);
|
| +
|
| + const bool ignored_cadence_frame =
|
| + cadence_frame >= 0 && frame_to_render != cadence_frame;
|
| + if (ignored_cadence_frame) {
|
| + cadence_overage = 0;
|
| + DVLOG(2) << "Cadence frame overridden by drift: " << selected_frame_drift;
|
| }
|
|
|
| last_render_had_glitch_ = selected_frame_drift > max_acceptable_drift_;
|
| @@ -226,12 +221,18 @@ scoped_refptr<VideoFrame> VideoRendererAlgorithm::Render(
|
| // start time is at most |render_interval_| / 2 before |deadline_min|.
|
| if (!first_frame_ ||
|
| deadline_min >= frame_queue_.front().start_time - render_interval_ / 2) {
|
| + // Ignore one frame of overage if the last call to Render() ignored the
|
| + // frame selected by cadence due to drift.
|
| + if (last_render_ignored_cadence_frame_ && cadence_overage > 0)
|
| + cadence_overage -= 1;
|
| +
|
| + last_render_ignored_cadence_frame_ = ignored_cadence_frame;
|
| frame_queue_.front().render_count += cadence_overage + 1;
|
| frame_queue_.front().drop_count += cadence_overage;
|
|
|
| // Once we reach a glitch in our cadence sequence, reset the base frame
|
| // number used for defining the cadence sequence.
|
| - if (!was_frame_selected_by_cadence && cadence_estimator_.has_cadence()) {
|
| + if (ignored_cadence_frame) {
|
| cadence_frame_counter_ = 0;
|
| UpdateCadenceForFrames();
|
| }
|
| @@ -306,6 +307,7 @@ void VideoRendererAlgorithm::Reset() {
|
| frame_duration_calculator_.Reset();
|
| first_frame_ = true;
|
| cadence_frame_counter_ = 0;
|
| + last_render_ignored_cadence_frame_ = false;
|
|
|
| // Default to ATSC IS/191 recommendations for maximum acceptable drift before
|
| // we have enough frames to base the maximum on frame duration.
|
| @@ -431,8 +433,8 @@ void VideoRendererAlgorithm::AccountForMissedIntervals(
|
| // If the frame was never really rendered since it was dropped each attempt,
|
| // we need to increase the drop count as well to match the new render count.
|
| // Otherwise we won't properly count the frame as dropped when it's discarded.
|
| - // We always update the render count so FindBestFrameByCadenceInternal() can
|
| - // properly account for potentially over-rendered frames.
|
| + // We always update the render count so FindBestFrameByCadence() can properly
|
| + // account for potentially over-rendered frames.
|
| if (ready_frame.render_count == ready_frame.drop_count)
|
| ready_frame.drop_count += render_cycle_count;
|
| ready_frame.render_count += render_cycle_count;
|
| @@ -480,10 +482,11 @@ bool VideoRendererAlgorithm::UpdateFrameStatistics() {
|
| // duration; there are other asymmetric, more lenient measures, that we're
|
| // forgoing in favor of simplicity.
|
| //
|
| - // We'll always allow at least 8.33ms of drift since literature suggests it's
|
| - // well below the floor of detection.
|
| + // We'll always allow at least 16.66ms of drift since literature suggests it's
|
| + // well below the floor of detection and is high enough to ensure stability
|
| + // for 60fps content.
|
| max_acceptable_drift_ = std::max(average_frame_duration_ / 2,
|
| - base::TimeDelta::FromSecondsD(1.0 / 120));
|
| + base::TimeDelta::FromSecondsD(1.0 / 60));
|
|
|
| // If we were called via RemoveExpiredFrames() and Render() was never called,
|
| // we may not have a render interval yet.
|
|
|