diff --git a/webrtc/modules/video_coding/frame_buffer2.cc b/webrtc/modules/video_coding/frame_buffer2.cc index 584c2f03c4..de96a52b1b 100644 --- a/webrtc/modules/video_coding/frame_buffer2.cc +++ b/webrtc/modules/video_coding/frame_buffer2.cc @@ -141,6 +141,13 @@ FrameBuffer::ReturnReason FrameBuffer::NextFrame( timing_->UpdateCurrentDelay(frame->RenderTime(), now_ms); } + // Gracefully handle bad RTP timestamps and render time issues. + if (HasBadRenderTiming(*frame, now_ms)) { + jitter_estimator_->Reset(); + timing_->Reset(); + frame->SetRenderTime(timing_->RenderTimeMs(frame->timestamp, now_ms)); + } + UpdateJitterDelay(); PropagateDecodability(next_frame_it_->second); @@ -189,6 +196,29 @@ FrameBuffer::ReturnReason FrameBuffer::NextFrame( return kTimeout; } +bool FrameBuffer::HasBadRenderTiming(const FrameObject& frame, int64_t now_ms) { + // Assume that render timing errors are due to changes in the video stream. + int64_t render_time_ms = frame.RenderTimeMs(); + const int64_t kMaxVideoDelayMs = 10000; + if (render_time_ms < 0) { + return true; + } + if (std::abs(render_time_ms - now_ms) > kMaxVideoDelayMs) { + int frame_delay = static_cast(std::abs(render_time_ms - now_ms)); + LOG(LS_WARNING) << "A frame about to be decoded is out of the configured " + << "delay bounds (" << frame_delay << " > " + << kMaxVideoDelayMs + << "). Resetting the video jitter buffer."; + return true; + } + if (static_cast(timing_->TargetVideoDelay()) > kMaxVideoDelayMs) { + LOG(LS_WARNING) << "The video target delay has grown larger than " + << kMaxVideoDelayMs << " ms."; + return true; + } + return false; +} + void FrameBuffer::SetProtectionMode(VCMVideoProtection mode) { TRACE_EVENT0("webrtc", "FrameBuffer::SetProtectionMode"); rtc::CritScope lock(&crit_); diff --git a/webrtc/modules/video_coding/frame_buffer2.h b/webrtc/modules/video_coding/frame_buffer2.h index 4695631ec5..6ce3b4be57 100644 --- a/webrtc/modules/video_coding/frame_buffer2.h +++ b/webrtc/modules/video_coding/frame_buffer2.h @@ -150,6 +150,9 @@ class FrameBuffer { void ClearFramesAndHistory() EXCLUSIVE_LOCKS_REQUIRED(crit_); + bool HasBadRenderTiming(const FrameObject& frame, int64_t now_ms) + EXCLUSIVE_LOCKS_REQUIRED(crit_); + FrameMap frames_ GUARDED_BY(crit_); rtc::CriticalSection crit_;