If present, only use picture ids to identify missing frames.
This is necessary in some scenarios to avoid false non-zero loss reports when doing stream thinning. BUG= Review URL: https://webrtc-codereview.appspot.com/793008 git-svn-id: http://webrtc.googlecode.com/svn/trunk@2784 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
2db85bcba7
commit
e72e9ee12a
@ -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<uint16_t>(frame->GetLowSeqNum()))) {
|
||||
// Non-layered methods have failed.
|
||||
full_sync_ = false;
|
||||
if (UsingPictureId(frame)) {
|
||||
full_sync_ = ContinuousPictureId(frame->PictureId());
|
||||
} else {
|
||||
full_sync_ = ContinuousSeqNum(static_cast<uint16_t>(
|
||||
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<uint16_t>(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<uint8_t>(tl0_pic_id_ + 1) == tl0_pic_id);
|
||||
}
|
||||
|
||||
bool VCMDecodingState::UsingPictureId(const VCMFrameBuffer* frame) const {
|
||||
return (frame->PictureId() != kNoPictureId && picture_id_ != kNoPictureId);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user