diff --git a/webrtc/modules/video_coding/frame_buffer2.cc b/webrtc/modules/video_coding/frame_buffer2.cc index 279c613424..58c41bf1d0 100644 --- a/webrtc/modules/video_coding/frame_buffer2.cc +++ b/webrtc/modules/video_coding/frame_buffer2.cc @@ -135,6 +135,7 @@ FrameBuffer::ReturnReason FrameBuffer::NextFrame( PropagateDecodability(next_frame_it->second); AdvanceLastDecodedFrame(next_frame_it); + last_decoded_frame_timestamp_ = frame->timestamp; *frame_out = std::move(frame); return kFrameFound; } else { @@ -189,14 +190,27 @@ int FrameBuffer::InsertFrame(std::unique_ptr frame) { if (last_decoded_frame_it_ != frames_.end() && key < last_decoded_frame_it_->first) { - LOG(LS_WARNING) << "Frame with (picture_id:spatial_id) (" << key.picture_id - << ":" << static_cast(key.spatial_layer) - << ") inserted after frame (" - << last_decoded_frame_it_->first.picture_id << ":" - << static_cast( - last_decoded_frame_it_->first.spatial_layer) - << ") was handed off for decoding, dropping frame."; - return last_continuous_picture_id; + if (AheadOf(frame->timestamp, last_decoded_frame_timestamp_) && + frame->num_references == 0) { + // If this frame has a newer timestamp but an earlier picture id then we + // assume there has been a jump in the picture id due to some encoder + // reconfiguration or some other reason. Even though this is not according + // to spec we can still continue to decode from this frame if it is a + // keyframe. + LOG(LS_WARNING) << "A jump in picture id was detected, clearing buffer."; + ClearFramesAndHistory(); + last_continuous_picture_id = -1; + } else { + LOG(LS_WARNING) << "Frame with (picture_id:spatial_id) (" + << key.picture_id << ":" + << static_cast(key.spatial_layer) + << ") inserted after frame (" + << last_decoded_frame_it_->first.picture_id << ":" + << static_cast( + last_decoded_frame_it_->first.spatial_layer) + << ") was handed off for decoding, dropping frame."; + return last_continuous_picture_id; + } } auto info = frames_.insert(std::make_pair(key, FrameInfo())).first; @@ -390,5 +404,13 @@ void FrameBuffer::UpdateHistograms() const { } } +void FrameBuffer::ClearFramesAndHistory() { + frames_.clear(); + last_decoded_frame_it_ = frames_.end(); + last_continuous_frame_it_ = frames_.end(); + num_frames_history_ = 0; + num_frames_buffered_ = 0; +} + } // namespace video_coding } // namespace webrtc diff --git a/webrtc/modules/video_coding/frame_buffer2.h b/webrtc/modules/video_coding/frame_buffer2.h index b41ef2ff34..f667fd532c 100644 --- a/webrtc/modules/video_coding/frame_buffer2.h +++ b/webrtc/modules/video_coding/frame_buffer2.h @@ -143,6 +143,8 @@ class FrameBuffer { void UpdateHistograms() const; + void ClearFramesAndHistory() EXCLUSIVE_LOCKS_REQUIRED(crit_); + FrameMap frames_ GUARDED_BY(crit_); rtc::CriticalSection crit_; @@ -151,6 +153,7 @@ class FrameBuffer { VCMJitterEstimator* const jitter_estimator_ GUARDED_BY(crit_); VCMTiming* const timing_ GUARDED_BY(crit_); VCMInterFrameDelay inter_frame_delay_ GUARDED_BY(crit_); + uint32_t last_decoded_frame_timestamp_ GUARDED_BY(crit_); FrameMap::iterator last_decoded_frame_it_ GUARDED_BY(crit_); FrameMap::iterator last_continuous_frame_it_ GUARDED_BY(crit_); int num_frames_history_ GUARDED_BY(crit_); diff --git a/webrtc/modules/video_coding/frame_buffer2_unittest.cc b/webrtc/modules/video_coding/frame_buffer2_unittest.cc index 6079bb95dd..96be01f83d 100644 --- a/webrtc/modules/video_coding/frame_buffer2_unittest.cc +++ b/webrtc/modules/video_coding/frame_buffer2_unittest.cc @@ -419,5 +419,22 @@ TEST_F(TestFrameBuffer2, LastContinuousFrameTwoLayers) { EXPECT_EQ(pid + 3, InsertFrame(pid + 3, 1, ts, true, pid + 2)); } +TEST_F(TestFrameBuffer2, PictureIdJumpBack) { + uint16_t pid = Rand(); + uint32_t ts = Rand(); + + EXPECT_EQ(pid, InsertFrame(pid, 0, ts, false)); + EXPECT_EQ(pid + 1, InsertFrame(pid + 1, 0, ts + 1, false, pid)); + ExtractFrame(); + CheckFrame(0, pid, 0); + + // Jump back in pid but increase ts. + EXPECT_EQ(pid - 1, InsertFrame(pid - 1, 0, ts + 2, false)); + ExtractFrame(); + ExtractFrame(); + CheckFrame(1, pid - 1, 0); + CheckNoFrame(2); +} + } // namespace video_coding } // namespace webrtc