diff --git a/src/modules/video_coding/main/source/decoding_state.cc b/src/modules/video_coding/main/source/decoding_state.cc index eea0a2c612..e347a2c768 100644 --- a/src/modules/video_coding/main/source/decoding_state.cc +++ b/src/modules/video_coding/main/source/decoding_state.cc @@ -127,10 +127,11 @@ void VCMDecodingState::UpdateSyncState(const VCMFrameBuffer* frame) { // Verify that we are still in sync. // Sync will be broken if continuity is true for layers but not for the // other methods (PictureId and SeqNum). - if (!ContinuousPictureId(frame->PictureId()) && - !ContinuousSeqNum(static_cast(frame->GetLowSeqNum()))) { - // Non-layered methods have failed. - full_sync_ = false; + if (UsingPictureId(frame)) { + full_sync_ = ContinuousPictureId(frame->PictureId()); + } else { + full_sync_ = ContinuousSeqNum(static_cast( + frame->GetLowSeqNum())); } } } @@ -152,17 +153,16 @@ bool VCMDecodingState::ContinuousFrame(const VCMFrameBuffer* frame) const { // continuity if sync can be restored by this frame. if (!full_sync_ && !frame->LayerSync()) return false; - else if (!ContinuousPictureId(frame->PictureId())) + else if (UsingPictureId(frame)) { + return ContinuousPictureId(frame->PictureId()); + } else { return ContinuousSeqNum(static_cast(frame->GetLowSeqNum())); + } } return true; } bool VCMDecodingState::ContinuousPictureId(int picture_id) const { - // First, check if applicable. - if (picture_id == kNoPictureId || picture_id_ == kNoPictureId) - return false; - int next_picture_id = picture_id_ + 1; if (picture_id < picture_id_) { // Wrap @@ -199,4 +199,8 @@ bool VCMDecodingState::ContinuousLayer(int temporal_id, return (static_cast(tl0_pic_id_ + 1) == tl0_pic_id); } +bool VCMDecodingState::UsingPictureId(const VCMFrameBuffer* frame) const { + return (frame->PictureId() != kNoPictureId && picture_id_ != kNoPictureId); +} + } // namespace webrtc diff --git a/src/modules/video_coding/main/source/decoding_state.h b/src/modules/video_coding/main/source/decoding_state.h index afec3ba44c..136bae6b68 100644 --- a/src/modules/video_coding/main/source/decoding_state.h +++ b/src/modules/video_coding/main/source/decoding_state.h @@ -52,6 +52,7 @@ class VCMDecodingState { bool ContinuousPictureId(int picture_id) const; bool ContinuousSeqNum(uint16_t seq_num) const; bool ContinuousLayer(int temporal_id, int tl0_pic_id) const; + bool UsingPictureId(const VCMFrameBuffer* frame) const; // Keep state of last decoded frame. // TODO(mikhal/stefan): create designated classes to handle these types. diff --git a/src/modules/video_coding/main/source/decoding_state_unittest.cc b/src/modules/video_coding/main/source/decoding_state_unittest.cc index 853f42ada2..5f0a59de5e 100644 --- a/src/modules/video_coding/main/source/decoding_state_unittest.cc +++ b/src/modules/video_coding/main/source/decoding_state_unittest.cc @@ -405,6 +405,38 @@ TEST(TestDecodingState, MultiLayerBehavior) { delete packet; } +TEST(TestDecodingState, DiscontinuousPicIdContinuousSeqNum) { + VCMDecodingState dec_state; + VCMFrameBuffer frame; + VCMPacket packet; + frame.Reset(); + frame.SetState(kStateEmpty); + packet.frameType = kVideoFrameKey; + packet.codecSpecificHeader.codec = kRTPVideoVP8; + packet.timestamp = 0; + packet.seqNum = 0; + packet.codecSpecificHeader.codecHeader.VP8.tl0PicIdx = 0; + packet.codecSpecificHeader.codecHeader.VP8.temporalIdx = 0; + packet.codecSpecificHeader.codecHeader.VP8.pictureId = 0; + frame.InsertPacket(packet, 0, false, 0); + dec_state.SetState(&frame); + EXPECT_TRUE(dec_state.full_sync()); + + // Continuous sequence number but discontinuous picture id. This implies a + // a loss and we have to fall back to only decoding the base layer. + frame.Reset(); + frame.SetState(kStateEmpty); + packet.frameType = kVideoFrameDelta; + packet.timestamp += 3000; + ++packet.seqNum; + packet.codecSpecificHeader.codecHeader.VP8.temporalIdx = 1; + packet.codecSpecificHeader.codecHeader.VP8.pictureId = 2; + frame.InsertPacket(packet, 0, false, 0); + EXPECT_FALSE(dec_state.ContinuousFrame(&frame)); + dec_state.SetState(&frame); + EXPECT_FALSE(dec_state.full_sync()); +} + TEST(TestDecodingState, OldInput) { VCMDecodingState dec_state; // Identify packets belonging to old frames/packets.