Skip to content

Commit

Permalink
Improve vide orender algorithm to avoid dropped frames
Browse files Browse the repository at this point in the history
  • Loading branch information
Marek Biolik committed Dec 10, 2024
1 parent d5047e3 commit 7ad0965
Showing 1 changed file with 41 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,48 @@ void VideoRenderAlgorithmImpl::RenderWithCadence(
SbTime media_time = media_time_provider->GetCurrentMediaTime(
&is_audio_playing, &is_audio_eos_played, &is_underflow, &playback_rate);

// Video frames are synced to the audio timestamp. However, the audio
// timestamp is not queried at a consistent interval. For example, if the
// query intervals are 16ms, 17ms, 16ms, 17ms, etc., then a 60fps video may
// display even frames twice and drop odd frames.
//
// The following diagram illustrates the situation using frames that should
// last 10 units of time:
// frame timestamp: 10 20 30 40 50
// sample timestamp: 11 19 31 40 51
// Using logic which drops frames whose timestamp is less than the sample
// timestamp:
// * The frame with timestamp 20 is displayed twice (for sample timestamps
// 11 and 19).
// * Then the frame with timestamp 30 is dropped.
// * Then the frame with timestamp 40 is displayed twice (for sample
// timestamps 31 and 40).
// * Then the frame with timestamp 50 is dropped.
const SbTime kMediaTimeThreshold = kSbTimeSecond / 250;

// Favor advancing the frame sooner. This addresses the situation where the
// audio timestamp query interval is a little shorter than a frame. This
// favors displaying the next frame over displaying the current frame twice.
//
// In the above example, this ensures advancement from frame timestamp 20
// to frame timestamp 30 when the sample time is 19.
if (is_audio_playing && frames->size() > 1 &&
frames->front()->timestamp() == last_frame_timestamp_ &&
last_frame_timestamp_ - kMediaTimeThreshold < media_time) {
frames->pop_front();
}

// Favor displaying the frame for a little longer. This addresses the
// situation where the audio timestamp query interval is a little longer
// than a frame.
//
// In the above example, this allows frames with timestamps 30 and 50 to be
// displayed for sample timestamps 31 and 51, respectively. This may sound
// like frame 30 is displayed twice (for sample timestamps 19 and 31);
// however, the "early advance" logic from above would force frame 30 to
// move onto frame 40 on sample timestamp 31.
while (frames->size() > 1 && !frames->front()->is_end_of_stream() &&
frames->front()->timestamp() < media_time) {
frames->front()->timestamp() + kMediaTimeThreshold < media_time) {
auto second_iter = frames->begin();
++second_iter;

Expand Down

0 comments on commit 7ad0965

Please sign in to comment.