Delete all logic related to VCMDecodeErrorMode
Bug: webrtc:8064 Change-Id: I345f342a314d88390fff8b305b121076b45a51e8 Reviewed-on: https://webrtc-review.googlesource.com/c/116692 Reviewed-by: Philip Eliasson <philipel@webrtc.org> Reviewed-by: Erik Språng <sprang@webrtc.org> Commit-Queue: Niels Moller <nisse@webrtc.org> Cr-Commit-Position: refs/heads/master@{#26283}
This commit is contained in:
@ -46,12 +46,12 @@ TEST(TestDecodingState, FrameContinuity) {
|
|||||||
FrameData frame_data;
|
FrameData frame_data;
|
||||||
frame_data.rtt_ms = 0;
|
frame_data.rtt_ms = 0;
|
||||||
frame_data.rolling_average_packets_per_frame = -1;
|
frame_data.rolling_average_packets_per_frame = -1;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
// Always start with a key frame.
|
// Always start with a key frame.
|
||||||
dec_state.Reset();
|
dec_state.Reset();
|
||||||
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
||||||
packet.frameType = kVideoFrameKey;
|
packet.frameType = kVideoFrameKey;
|
||||||
EXPECT_LE(0, frame_key.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame_key.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame_key));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame_key));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
frame.Reset();
|
frame.Reset();
|
||||||
@ -59,26 +59,26 @@ TEST(TestDecodingState, FrameContinuity) {
|
|||||||
// Use pictureId
|
// Use pictureId
|
||||||
packet.is_first_packet_in_frame = false;
|
packet.is_first_packet_in_frame = false;
|
||||||
vp8_header.pictureId = 0x0002;
|
vp8_header.pictureId = 0x0002;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
||||||
frame.Reset();
|
frame.Reset();
|
||||||
vp8_header.pictureId = 0;
|
vp8_header.pictureId = 0;
|
||||||
packet.seqNum = 10;
|
packet.seqNum = 10;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
|
|
||||||
// Use sequence numbers.
|
// Use sequence numbers.
|
||||||
vp8_header.pictureId = kNoPictureId;
|
vp8_header.pictureId = kNoPictureId;
|
||||||
frame.Reset();
|
frame.Reset();
|
||||||
packet.seqNum = dec_state.sequence_num() - 1u;
|
packet.seqNum = dec_state.sequence_num() - 1u;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
||||||
frame.Reset();
|
frame.Reset();
|
||||||
packet.seqNum = dec_state.sequence_num() + 1u;
|
packet.seqNum = dec_state.sequence_num() + 1u;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
// Insert another packet to this frame
|
// Insert another packet to this frame
|
||||||
packet.seqNum++;
|
packet.seqNum++;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
// Verify wrap.
|
// Verify wrap.
|
||||||
EXPECT_LE(dec_state.sequence_num(), 0xffff);
|
EXPECT_LE(dec_state.sequence_num(), 0xffff);
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
@ -93,7 +93,7 @@ TEST(TestDecodingState, FrameContinuity) {
|
|||||||
packet.seqNum = 1;
|
packet.seqNum = 1;
|
||||||
packet.timestamp = 1;
|
packet.timestamp = 1;
|
||||||
EXPECT_TRUE(dec_state.full_sync());
|
EXPECT_TRUE(dec_state.full_sync());
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
EXPECT_TRUE(dec_state.full_sync());
|
EXPECT_TRUE(dec_state.full_sync());
|
||||||
frame.Reset();
|
frame.Reset();
|
||||||
@ -103,7 +103,7 @@ TEST(TestDecodingState, FrameContinuity) {
|
|||||||
vp8_header.pictureId = 1;
|
vp8_header.pictureId = 1;
|
||||||
packet.seqNum = 2;
|
packet.seqNum = 2;
|
||||||
packet.timestamp = 2;
|
packet.timestamp = 2;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
EXPECT_TRUE(dec_state.full_sync());
|
EXPECT_TRUE(dec_state.full_sync());
|
||||||
@ -114,7 +114,7 @@ TEST(TestDecodingState, FrameContinuity) {
|
|||||||
vp8_header.pictureId = 3;
|
vp8_header.pictureId = 3;
|
||||||
packet.seqNum = 4;
|
packet.seqNum = 4;
|
||||||
packet.timestamp = 4;
|
packet.timestamp = 4;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
||||||
// Now insert the next non-base layer (belonging to a next tl0PicId).
|
// Now insert the next non-base layer (belonging to a next tl0PicId).
|
||||||
frame.Reset();
|
frame.Reset();
|
||||||
@ -123,7 +123,7 @@ TEST(TestDecodingState, FrameContinuity) {
|
|||||||
vp8_header.pictureId = 4;
|
vp8_header.pictureId = 4;
|
||||||
packet.seqNum = 5;
|
packet.seqNum = 5;
|
||||||
packet.timestamp = 5;
|
packet.timestamp = 5;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
// Checking continuity and not updating the state - this should not trigger
|
// Checking continuity and not updating the state - this should not trigger
|
||||||
// an update of sync state.
|
// an update of sync state.
|
||||||
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
||||||
@ -135,7 +135,7 @@ TEST(TestDecodingState, FrameContinuity) {
|
|||||||
vp8_header.pictureId = 5;
|
vp8_header.pictureId = 5;
|
||||||
packet.seqNum = 6;
|
packet.seqNum = 6;
|
||||||
packet.timestamp = 6;
|
packet.timestamp = 6;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
EXPECT_FALSE(dec_state.full_sync());
|
EXPECT_FALSE(dec_state.full_sync());
|
||||||
@ -147,7 +147,7 @@ TEST(TestDecodingState, FrameContinuity) {
|
|||||||
vp8_header.pictureId = 6;
|
vp8_header.pictureId = 6;
|
||||||
packet.seqNum = 7;
|
packet.seqNum = 7;
|
||||||
packet.timestamp = 7;
|
packet.timestamp = 7;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
EXPECT_FALSE(dec_state.full_sync());
|
EXPECT_FALSE(dec_state.full_sync());
|
||||||
frame.Reset();
|
frame.Reset();
|
||||||
@ -156,7 +156,7 @@ TEST(TestDecodingState, FrameContinuity) {
|
|||||||
vp8_header.pictureId = 7;
|
vp8_header.pictureId = 7;
|
||||||
packet.seqNum = 8;
|
packet.seqNum = 8;
|
||||||
packet.timestamp = 8;
|
packet.timestamp = 8;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
// The current frame is not continuous
|
// The current frame is not continuous
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
@ -175,7 +175,7 @@ TEST(TestDecodingState, UpdateOldPacket) {
|
|||||||
FrameData frame_data;
|
FrameData frame_data;
|
||||||
frame_data.rtt_ms = 0;
|
frame_data.rtt_ms = 0;
|
||||||
frame_data.rolling_average_packets_per_frame = -1;
|
frame_data.rolling_average_packets_per_frame = -1;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
EXPECT_EQ(dec_state.sequence_num(), 1);
|
EXPECT_EQ(dec_state.sequence_num(), 1);
|
||||||
// Insert an empty packet that does not belong to the same frame.
|
// Insert an empty packet that does not belong to the same frame.
|
||||||
@ -227,7 +227,7 @@ TEST(TestDecodingState, MultiLayerBehavior) {
|
|||||||
FrameData frame_data;
|
FrameData frame_data;
|
||||||
frame_data.rtt_ms = 0;
|
frame_data.rtt_ms = 0;
|
||||||
frame_data.rolling_average_packets_per_frame = -1;
|
frame_data.rolling_average_packets_per_frame = -1;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
// tl0PicIdx 0, temporal id 1.
|
// tl0PicIdx 0, temporal id 1.
|
||||||
frame.Reset();
|
frame.Reset();
|
||||||
@ -236,7 +236,7 @@ TEST(TestDecodingState, MultiLayerBehavior) {
|
|||||||
vp8_header.tl0PicIdx = 0;
|
vp8_header.tl0PicIdx = 0;
|
||||||
vp8_header.temporalIdx = 1;
|
vp8_header.temporalIdx = 1;
|
||||||
vp8_header.pictureId = 1;
|
vp8_header.pictureId = 1;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
EXPECT_TRUE(dec_state.full_sync());
|
EXPECT_TRUE(dec_state.full_sync());
|
||||||
@ -248,7 +248,7 @@ TEST(TestDecodingState, MultiLayerBehavior) {
|
|||||||
vp8_header.tl0PicIdx = 0;
|
vp8_header.tl0PicIdx = 0;
|
||||||
vp8_header.temporalIdx = 3;
|
vp8_header.temporalIdx = 3;
|
||||||
vp8_header.pictureId = 3;
|
vp8_header.pictureId = 3;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
EXPECT_FALSE(dec_state.full_sync());
|
EXPECT_FALSE(dec_state.full_sync());
|
||||||
@ -259,7 +259,7 @@ TEST(TestDecodingState, MultiLayerBehavior) {
|
|||||||
vp8_header.tl0PicIdx = 1;
|
vp8_header.tl0PicIdx = 1;
|
||||||
vp8_header.temporalIdx = 0;
|
vp8_header.temporalIdx = 0;
|
||||||
vp8_header.pictureId = 4;
|
vp8_header.pictureId = 4;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
EXPECT_FALSE(dec_state.full_sync());
|
EXPECT_FALSE(dec_state.full_sync());
|
||||||
@ -273,7 +273,7 @@ TEST(TestDecodingState, MultiLayerBehavior) {
|
|||||||
vp8_header.tl0PicIdx = 2;
|
vp8_header.tl0PicIdx = 2;
|
||||||
vp8_header.temporalIdx = 0;
|
vp8_header.temporalIdx = 0;
|
||||||
vp8_header.pictureId = 5;
|
vp8_header.pictureId = 5;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
EXPECT_TRUE(dec_state.full_sync());
|
EXPECT_TRUE(dec_state.full_sync());
|
||||||
@ -286,7 +286,7 @@ TEST(TestDecodingState, MultiLayerBehavior) {
|
|||||||
vp8_header.tl0PicIdx = 3;
|
vp8_header.tl0PicIdx = 3;
|
||||||
vp8_header.temporalIdx = 0;
|
vp8_header.temporalIdx = 0;
|
||||||
vp8_header.pictureId = 6;
|
vp8_header.pictureId = 6;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
EXPECT_TRUE(dec_state.full_sync());
|
EXPECT_TRUE(dec_state.full_sync());
|
||||||
frame.Reset();
|
frame.Reset();
|
||||||
@ -297,7 +297,7 @@ TEST(TestDecodingState, MultiLayerBehavior) {
|
|||||||
vp8_header.tl0PicIdx = 4;
|
vp8_header.tl0PicIdx = 4;
|
||||||
vp8_header.temporalIdx = 0;
|
vp8_header.temporalIdx = 0;
|
||||||
vp8_header.pictureId = 8;
|
vp8_header.pictureId = 8;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
||||||
EXPECT_TRUE(dec_state.full_sync());
|
EXPECT_TRUE(dec_state.full_sync());
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
@ -313,7 +313,7 @@ TEST(TestDecodingState, MultiLayerBehavior) {
|
|||||||
vp8_header.temporalIdx = 2;
|
vp8_header.temporalIdx = 2;
|
||||||
vp8_header.pictureId = 9;
|
vp8_header.pictureId = 9;
|
||||||
vp8_header.layerSync = true;
|
vp8_header.layerSync = true;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
EXPECT_TRUE(dec_state.full_sync());
|
EXPECT_TRUE(dec_state.full_sync());
|
||||||
|
|
||||||
@ -334,7 +334,7 @@ TEST(TestDecodingState, MultiLayerBehavior) {
|
|||||||
vp8_header.temporalIdx = 0;
|
vp8_header.temporalIdx = 0;
|
||||||
vp8_header.pictureId = 0;
|
vp8_header.pictureId = 0;
|
||||||
vp8_header.layerSync = false;
|
vp8_header.layerSync = false;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
EXPECT_TRUE(dec_state.full_sync());
|
EXPECT_TRUE(dec_state.full_sync());
|
||||||
// Layer 2 - 2 packets (insert one, lose one).
|
// Layer 2 - 2 packets (insert one, lose one).
|
||||||
@ -348,7 +348,7 @@ TEST(TestDecodingState, MultiLayerBehavior) {
|
|||||||
vp8_header.temporalIdx = 2;
|
vp8_header.temporalIdx = 2;
|
||||||
vp8_header.pictureId = 1;
|
vp8_header.pictureId = 1;
|
||||||
vp8_header.layerSync = true;
|
vp8_header.layerSync = true;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
// Layer 1
|
// Layer 1
|
||||||
frame.Reset();
|
frame.Reset();
|
||||||
@ -361,7 +361,7 @@ TEST(TestDecodingState, MultiLayerBehavior) {
|
|||||||
vp8_header.temporalIdx = 1;
|
vp8_header.temporalIdx = 1;
|
||||||
vp8_header.pictureId = 2;
|
vp8_header.pictureId = 2;
|
||||||
vp8_header.layerSync = true;
|
vp8_header.layerSync = true;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
||||||
EXPECT_TRUE(dec_state.full_sync());
|
EXPECT_TRUE(dec_state.full_sync());
|
||||||
}
|
}
|
||||||
@ -383,7 +383,7 @@ TEST(TestDecodingState, DiscontinuousPicIdContinuousSeqNum) {
|
|||||||
FrameData frame_data;
|
FrameData frame_data;
|
||||||
frame_data.rtt_ms = 0;
|
frame_data.rtt_ms = 0;
|
||||||
frame_data.rolling_average_packets_per_frame = -1;
|
frame_data.rolling_average_packets_per_frame = -1;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
EXPECT_TRUE(dec_state.full_sync());
|
EXPECT_TRUE(dec_state.full_sync());
|
||||||
|
|
||||||
@ -395,7 +395,7 @@ TEST(TestDecodingState, DiscontinuousPicIdContinuousSeqNum) {
|
|||||||
++packet.seqNum;
|
++packet.seqNum;
|
||||||
vp8_header.temporalIdx = 1;
|
vp8_header.temporalIdx = 1;
|
||||||
vp8_header.pictureId = 2;
|
vp8_header.pictureId = 2;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
EXPECT_FALSE(dec_state.full_sync());
|
EXPECT_FALSE(dec_state.full_sync());
|
||||||
@ -412,13 +412,13 @@ TEST(TestDecodingState, OldInput) {
|
|||||||
FrameData frame_data;
|
FrameData frame_data;
|
||||||
frame_data.rtt_ms = 0;
|
frame_data.rtt_ms = 0;
|
||||||
frame_data.rolling_average_packets_per_frame = -1;
|
frame_data.rolling_average_packets_per_frame = -1;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
packet.timestamp = 9;
|
packet.timestamp = 9;
|
||||||
EXPECT_TRUE(dec_state.IsOldPacket(&packet));
|
EXPECT_TRUE(dec_state.IsOldPacket(&packet));
|
||||||
// Check for old frame
|
// Check for old frame
|
||||||
frame.Reset();
|
frame.Reset();
|
||||||
frame.InsertPacket(packet, 0, kNoErrors, frame_data);
|
frame.InsertPacket(packet, 0, frame_data);
|
||||||
EXPECT_TRUE(dec_state.IsOldFrame(&frame));
|
EXPECT_TRUE(dec_state.IsOldFrame(&frame));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,7 +438,7 @@ TEST(TestDecodingState, PictureIdRepeat) {
|
|||||||
FrameData frame_data;
|
FrameData frame_data;
|
||||||
frame_data.rtt_ms = 0;
|
frame_data.rtt_ms = 0;
|
||||||
frame_data.rolling_average_packets_per_frame = -1;
|
frame_data.rolling_average_packets_per_frame = -1;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
// tl0PicIdx 0, temporal id 1.
|
// tl0PicIdx 0, temporal id 1.
|
||||||
frame.Reset();
|
frame.Reset();
|
||||||
@ -446,14 +446,14 @@ TEST(TestDecodingState, PictureIdRepeat) {
|
|||||||
++packet.seqNum;
|
++packet.seqNum;
|
||||||
vp8_header.temporalIdx++;
|
vp8_header.temporalIdx++;
|
||||||
vp8_header.pictureId++;
|
vp8_header.pictureId++;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
frame.Reset();
|
frame.Reset();
|
||||||
// Testing only gap in tl0PicIdx when tl0PicIdx in continuous.
|
// Testing only gap in tl0PicIdx when tl0PicIdx in continuous.
|
||||||
vp8_header.tl0PicIdx += 3;
|
vp8_header.tl0PicIdx += 3;
|
||||||
vp8_header.temporalIdx++;
|
vp8_header.temporalIdx++;
|
||||||
vp8_header.tl0PicIdx = 1;
|
vp8_header.tl0PicIdx = 1;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -480,14 +480,14 @@ TEST(TestDecodingState, FrameContinuityFlexibleModeKeyFrame) {
|
|||||||
|
|
||||||
// Key frame as first frame
|
// Key frame as first frame
|
||||||
packet.frameType = kVideoFrameKey;
|
packet.frameType = kVideoFrameKey;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
|
|
||||||
// Key frame again
|
// Key frame again
|
||||||
vp9_hdr.picture_id = 11;
|
vp9_hdr.picture_id = 11;
|
||||||
frame.Reset();
|
frame.Reset();
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
|
|
||||||
@ -497,7 +497,7 @@ TEST(TestDecodingState, FrameContinuityFlexibleModeKeyFrame) {
|
|||||||
vp9_hdr.picture_id = 12;
|
vp9_hdr.picture_id = 12;
|
||||||
vp9_hdr.num_ref_pics = 1;
|
vp9_hdr.num_ref_pics = 1;
|
||||||
vp9_hdr.pid_diff[0] = 1;
|
vp9_hdr.pid_diff[0] = 1;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -524,7 +524,7 @@ TEST(TestDecodingState, FrameContinuityFlexibleModeOutOfOrderFrames) {
|
|||||||
|
|
||||||
// Key frame as first frame
|
// Key frame as first frame
|
||||||
packet.frameType = kVideoFrameKey;
|
packet.frameType = kVideoFrameKey;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
|
|
||||||
@ -534,7 +534,7 @@ TEST(TestDecodingState, FrameContinuityFlexibleModeOutOfOrderFrames) {
|
|||||||
vp9_hdr.picture_id = 15;
|
vp9_hdr.picture_id = 15;
|
||||||
vp9_hdr.num_ref_pics = 1;
|
vp9_hdr.num_ref_pics = 1;
|
||||||
vp9_hdr.pid_diff[0] = 5;
|
vp9_hdr.pid_diff[0] = 5;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
|
|
||||||
@ -542,7 +542,7 @@ TEST(TestDecodingState, FrameContinuityFlexibleModeOutOfOrderFrames) {
|
|||||||
frame.Reset();
|
frame.Reset();
|
||||||
vp9_hdr.picture_id = 12;
|
vp9_hdr.picture_id = 12;
|
||||||
vp9_hdr.pid_diff[0] = 2;
|
vp9_hdr.pid_diff[0] = 2;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
|
|
||||||
@ -553,7 +553,7 @@ TEST(TestDecodingState, FrameContinuityFlexibleModeOutOfOrderFrames) {
|
|||||||
vp9_hdr.pid_diff[0] = 10;
|
vp9_hdr.pid_diff[0] = 10;
|
||||||
vp9_hdr.pid_diff[1] = 8;
|
vp9_hdr.pid_diff[1] = 8;
|
||||||
vp9_hdr.pid_diff[2] = 5;
|
vp9_hdr.pid_diff[2] = 5;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -580,40 +580,40 @@ TEST(TestDecodingState, FrameContinuityFlexibleModeGeneral) {
|
|||||||
|
|
||||||
// Key frame as first frame
|
// Key frame as first frame
|
||||||
packet.frameType = kVideoFrameKey;
|
packet.frameType = kVideoFrameKey;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
|
|
||||||
// Delta frame as first frame
|
// Delta frame as first frame
|
||||||
frame.Reset();
|
frame.Reset();
|
||||||
packet.frameType = kVideoFrameDelta;
|
packet.frameType = kVideoFrameDelta;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
||||||
|
|
||||||
// Key frame then delta frame
|
// Key frame then delta frame
|
||||||
frame.Reset();
|
frame.Reset();
|
||||||
packet.frameType = kVideoFrameKey;
|
packet.frameType = kVideoFrameKey;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
frame.Reset();
|
frame.Reset();
|
||||||
packet.frameType = kVideoFrameDelta;
|
packet.frameType = kVideoFrameDelta;
|
||||||
vp9_hdr.num_ref_pics = 1;
|
vp9_hdr.num_ref_pics = 1;
|
||||||
vp9_hdr.picture_id = 15;
|
vp9_hdr.picture_id = 15;
|
||||||
vp9_hdr.pid_diff[0] = 5;
|
vp9_hdr.pid_diff[0] = 5;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
|
|
||||||
// Ref to 11, not continuous
|
// Ref to 11, not continuous
|
||||||
frame.Reset();
|
frame.Reset();
|
||||||
vp9_hdr.picture_id = 16;
|
vp9_hdr.picture_id = 16;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
||||||
|
|
||||||
// Ref to 15, continuous
|
// Ref to 15, continuous
|
||||||
frame.Reset();
|
frame.Reset();
|
||||||
vp9_hdr.picture_id = 16;
|
vp9_hdr.picture_id = 16;
|
||||||
vp9_hdr.pid_diff[0] = 1;
|
vp9_hdr.pid_diff[0] = 1;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
|
|
||||||
@ -623,7 +623,7 @@ TEST(TestDecodingState, FrameContinuityFlexibleModeGeneral) {
|
|||||||
vp9_hdr.num_ref_pics = 2;
|
vp9_hdr.num_ref_pics = 2;
|
||||||
vp9_hdr.pid_diff[0] = 9;
|
vp9_hdr.pid_diff[0] = 9;
|
||||||
vp9_hdr.pid_diff[1] = 5;
|
vp9_hdr.pid_diff[1] = 5;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
||||||
|
|
||||||
// Ref to 10, 15 and 16, continuous
|
// Ref to 10, 15 and 16, continuous
|
||||||
@ -633,7 +633,7 @@ TEST(TestDecodingState, FrameContinuityFlexibleModeGeneral) {
|
|||||||
vp9_hdr.pid_diff[0] = 12;
|
vp9_hdr.pid_diff[0] = 12;
|
||||||
vp9_hdr.pid_diff[1] = 7;
|
vp9_hdr.pid_diff[1] = 7;
|
||||||
vp9_hdr.pid_diff[2] = 6;
|
vp9_hdr.pid_diff[2] = 6;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
|
|
||||||
@ -642,7 +642,7 @@ TEST(TestDecodingState, FrameContinuityFlexibleModeGeneral) {
|
|||||||
packet.frameType = kVideoFrameKey;
|
packet.frameType = kVideoFrameKey;
|
||||||
vp9_hdr.picture_id = VCMDecodingState::kFrameDecodedLength - 2;
|
vp9_hdr.picture_id = VCMDecodingState::kFrameDecodedLength - 2;
|
||||||
vp9_hdr.num_ref_pics = 0;
|
vp9_hdr.num_ref_pics = 0;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
|
|
||||||
@ -652,7 +652,7 @@ TEST(TestDecodingState, FrameContinuityFlexibleModeGeneral) {
|
|||||||
vp9_hdr.picture_id = VCMDecodingState::kFrameDecodedLength - 1;
|
vp9_hdr.picture_id = VCMDecodingState::kFrameDecodedLength - 1;
|
||||||
vp9_hdr.num_ref_pics = 1;
|
vp9_hdr.num_ref_pics = 1;
|
||||||
vp9_hdr.pid_diff[0] = 1;
|
vp9_hdr.pid_diff[0] = 1;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
|
|
||||||
@ -661,7 +661,7 @@ TEST(TestDecodingState, FrameContinuityFlexibleModeGeneral) {
|
|||||||
vp9_hdr.picture_id = 0;
|
vp9_hdr.picture_id = 0;
|
||||||
vp9_hdr.num_ref_pics = 1;
|
vp9_hdr.num_ref_pics = 1;
|
||||||
vp9_hdr.pid_diff[0] = 1;
|
vp9_hdr.pid_diff[0] = 1;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
|
|
||||||
@ -670,7 +670,7 @@ TEST(TestDecodingState, FrameContinuityFlexibleModeGeneral) {
|
|||||||
vp9_hdr.picture_id = 20;
|
vp9_hdr.picture_id = 20;
|
||||||
vp9_hdr.num_ref_pics = 1;
|
vp9_hdr.num_ref_pics = 1;
|
||||||
vp9_hdr.pid_diff[0] = 20;
|
vp9_hdr.pid_diff[0] = 20;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
|
|
||||||
@ -679,7 +679,7 @@ TEST(TestDecodingState, FrameContinuityFlexibleModeGeneral) {
|
|||||||
vp9_hdr.picture_id = 23;
|
vp9_hdr.picture_id = 23;
|
||||||
vp9_hdr.num_ref_pics = 1;
|
vp9_hdr.num_ref_pics = 1;
|
||||||
vp9_hdr.pid_diff[0] = 13;
|
vp9_hdr.pid_diff[0] = 13;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
||||||
|
|
||||||
// Key frame, continuous
|
// Key frame, continuous
|
||||||
@ -687,7 +687,7 @@ TEST(TestDecodingState, FrameContinuityFlexibleModeGeneral) {
|
|||||||
packet.frameType = kVideoFrameKey;
|
packet.frameType = kVideoFrameKey;
|
||||||
vp9_hdr.picture_id = 25;
|
vp9_hdr.picture_id = 25;
|
||||||
vp9_hdr.num_ref_pics = 0;
|
vp9_hdr.num_ref_pics = 0;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
|
|
||||||
@ -697,7 +697,7 @@ TEST(TestDecodingState, FrameContinuityFlexibleModeGeneral) {
|
|||||||
vp9_hdr.picture_id = 26;
|
vp9_hdr.picture_id = 26;
|
||||||
vp9_hdr.num_ref_pics = 1;
|
vp9_hdr.num_ref_pics = 1;
|
||||||
vp9_hdr.pid_diff[0] = 1;
|
vp9_hdr.pid_diff[0] = 1;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
EXPECT_TRUE(dec_state.ContinuousFrame(&frame));
|
||||||
dec_state.SetState(&frame);
|
dec_state.SetState(&frame);
|
||||||
|
|
||||||
@ -706,7 +706,7 @@ TEST(TestDecodingState, FrameContinuityFlexibleModeGeneral) {
|
|||||||
vp9_hdr.picture_id = 30;
|
vp9_hdr.picture_id = 30;
|
||||||
vp9_hdr.num_ref_pics = 1;
|
vp9_hdr.num_ref_pics = 1;
|
||||||
vp9_hdr.pid_diff[0] = 30;
|
vp9_hdr.pid_diff[0] = 30;
|
||||||
EXPECT_LE(0, frame.InsertPacket(packet, 0, kNoErrors, frame_data));
|
EXPECT_LE(0, frame.InsertPacket(packet, 0, frame_data));
|
||||||
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
EXPECT_FALSE(dec_state.ContinuousFrame(&frame));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -80,7 +80,6 @@ bool VCMFrameBuffer::IsSessionComplete() const {
|
|||||||
VCMFrameBufferEnum VCMFrameBuffer::InsertPacket(
|
VCMFrameBufferEnum VCMFrameBuffer::InsertPacket(
|
||||||
const VCMPacket& packet,
|
const VCMPacket& packet,
|
||||||
int64_t timeInMs,
|
int64_t timeInMs,
|
||||||
VCMDecodeErrorMode decode_error_mode,
|
|
||||||
const FrameData& frame_data) {
|
const FrameData& frame_data) {
|
||||||
TRACE_EVENT0("webrtc", "VCMFrameBuffer::InsertPacket");
|
TRACE_EVENT0("webrtc", "VCMFrameBuffer::InsertPacket");
|
||||||
assert(!(NULL == packet.dataPtr && packet.sizeBytes > 0));
|
assert(!(NULL == packet.dataPtr && packet.sizeBytes > 0));
|
||||||
@ -129,8 +128,7 @@ VCMFrameBufferEnum VCMFrameBuffer::InsertPacket(
|
|||||||
if (packet.sizeBytes > 0)
|
if (packet.sizeBytes > 0)
|
||||||
CopyCodecSpecific(&packet.video_header);
|
CopyCodecSpecific(&packet.video_header);
|
||||||
|
|
||||||
int retVal =
|
int retVal = _sessionInfo.InsertPacket(packet, _buffer, frame_data);
|
||||||
_sessionInfo.InsertPacket(packet, _buffer, decode_error_mode, frame_data);
|
|
||||||
if (retVal == -1) {
|
if (retVal == -1) {
|
||||||
return kSizeError;
|
return kSizeError;
|
||||||
} else if (retVal == -2) {
|
} else if (retVal == -2) {
|
||||||
@ -182,9 +180,6 @@ VCMFrameBufferEnum VCMFrameBuffer::InsertPacket(
|
|||||||
if (_sessionInfo.complete()) {
|
if (_sessionInfo.complete()) {
|
||||||
SetState(kStateComplete);
|
SetState(kStateComplete);
|
||||||
return kCompleteSession;
|
return kCompleteSession;
|
||||||
} else if (_sessionInfo.decodable()) {
|
|
||||||
SetState(kStateDecodable);
|
|
||||||
return kDecodableSession;
|
|
||||||
}
|
}
|
||||||
return kIncomplete;
|
return kIncomplete;
|
||||||
}
|
}
|
||||||
@ -240,8 +235,7 @@ void VCMFrameBuffer::SetState(VCMFrameBufferStateEnum state) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case kStateComplete:
|
case kStateComplete:
|
||||||
assert(_state == kStateEmpty || _state == kStateIncomplete ||
|
assert(_state == kStateEmpty || _state == kStateIncomplete);
|
||||||
_state == kStateDecodable);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -249,10 +243,6 @@ void VCMFrameBuffer::SetState(VCMFrameBufferStateEnum state) {
|
|||||||
// Should only be set to empty through Reset().
|
// Should only be set to empty through Reset().
|
||||||
assert(false);
|
assert(false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kStateDecodable:
|
|
||||||
assert(_state == kStateEmpty || _state == kStateIncomplete);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
_state = state;
|
_state = state;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,7 +35,6 @@ class VCMFrameBuffer : public VCMEncodedFrame {
|
|||||||
|
|
||||||
VCMFrameBufferEnum InsertPacket(const VCMPacket& packet,
|
VCMFrameBufferEnum InsertPacket(const VCMPacket& packet,
|
||||||
int64_t timeInMs,
|
int64_t timeInMs,
|
||||||
VCMDecodeErrorMode decode_error_mode,
|
|
||||||
const FrameData& frame_data);
|
const FrameData& frame_data);
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|||||||
@ -27,19 +27,6 @@ class VideoDecoder;
|
|||||||
class VideoEncoder;
|
class VideoEncoder;
|
||||||
struct CodecSpecificInfo;
|
struct CodecSpecificInfo;
|
||||||
|
|
||||||
// Used to indicate which decode with errors mode should be used.
|
|
||||||
enum VCMDecodeErrorMode {
|
|
||||||
kNoErrors, // Never decode with errors. Video will freeze
|
|
||||||
// if nack is disabled.
|
|
||||||
kSelectiveErrors, // Frames that are determined decodable in
|
|
||||||
// VCMSessionInfo may be decoded with missing
|
|
||||||
// packets. As not all incomplete frames will be
|
|
||||||
// decodable, video will freeze if nack is disabled.
|
|
||||||
kWithErrors // Release frames as needed. Errors may be
|
|
||||||
// introduced as some encoded frames may not be
|
|
||||||
// complete.
|
|
||||||
};
|
|
||||||
|
|
||||||
class VideoCodingModule : public Module {
|
class VideoCodingModule : public Module {
|
||||||
public:
|
public:
|
||||||
enum SenderNackMode { kNackNone, kNackAll, kNackSelective };
|
enum SenderNackMode { kNackNone, kNackAll, kNackSelective };
|
||||||
@ -166,12 +153,7 @@ class VideoCodingModule : public Module {
|
|||||||
// Return value : VCM_OK, on success;
|
// Return value : VCM_OK, on success;
|
||||||
// < 0, on error.
|
// < 0, on error.
|
||||||
enum ReceiverRobustness { kNone, kHardNack };
|
enum ReceiverRobustness { kNone, kHardNack };
|
||||||
virtual int SetReceiverRobustnessMode(ReceiverRobustness robustnessMode,
|
virtual int SetReceiverRobustnessMode(ReceiverRobustness robustnessMode) = 0;
|
||||||
VCMDecodeErrorMode errorMode) = 0;
|
|
||||||
|
|
||||||
int SetReceiverRobustnessMode(ReceiverRobustness robustnessMode) {
|
|
||||||
return SetReceiverRobustnessMode(robustnessMode, kNoErrors);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets the maximum number of sequence numbers that we are allowed to NACK
|
// Sets the maximum number of sequence numbers that we are allowed to NACK
|
||||||
// and the oldest sequence number that we will consider to NACK. If a
|
// and the oldest sequence number that we will consider to NACK. If a
|
||||||
|
|||||||
@ -255,7 +255,6 @@ VCMJitterBuffer::VCMJitterBuffer(Clock* clock,
|
|||||||
max_nack_list_size_(0),
|
max_nack_list_size_(0),
|
||||||
max_packet_age_to_nack_(0),
|
max_packet_age_to_nack_(0),
|
||||||
max_incomplete_time_ms_(0),
|
max_incomplete_time_ms_(0),
|
||||||
decode_error_mode_(kNoErrors),
|
|
||||||
average_packets_per_frame_(0.0f),
|
average_packets_per_frame_(0.0f),
|
||||||
frame_counter_(0) {
|
frame_counter_(0) {
|
||||||
for (int i = 0; i < kStartNumberOfFrames; i++)
|
for (int i = 0; i < kStartNumberOfFrames; i++)
|
||||||
@ -494,43 +493,6 @@ VCMEncodedFrame* VCMJitterBuffer::NextCompleteFrame(uint32_t max_wait_time_ms) {
|
|||||||
return encoded_frame;
|
return encoded_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VCMJitterBuffer::NextMaybeIncompleteTimestamp(uint32_t* timestamp) {
|
|
||||||
rtc::CritScope cs(&crit_sect_);
|
|
||||||
if (!running_) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (decode_error_mode_ == kNoErrors) {
|
|
||||||
// No point to continue, as we are not decoding with errors.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CleanUpOldOrEmptyFrames();
|
|
||||||
|
|
||||||
VCMFrameBuffer* oldest_frame;
|
|
||||||
if (decodable_frames_.empty()) {
|
|
||||||
if (nack_mode_ != kNoNack || incomplete_frames_.size() <= 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
oldest_frame = incomplete_frames_.Front();
|
|
||||||
// Frame will only be removed from buffer if it is complete (or decodable).
|
|
||||||
if (oldest_frame->GetState() < kStateComplete) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
oldest_frame = decodable_frames_.Front();
|
|
||||||
// If we have exactly one frame in the buffer, release it only if it is
|
|
||||||
// complete. We know decodable_frames_ is not empty due to the previous
|
|
||||||
// check.
|
|
||||||
if (decodable_frames_.size() == 1 && incomplete_frames_.empty() &&
|
|
||||||
oldest_frame->GetState() != kStateComplete) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*timestamp = oldest_frame->Timestamp();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
VCMEncodedFrame* VCMJitterBuffer::ExtractAndSetDecode(uint32_t timestamp) {
|
VCMEncodedFrame* VCMJitterBuffer::ExtractAndSetDecode(uint32_t timestamp) {
|
||||||
rtc::CritScope cs(&crit_sect_);
|
rtc::CritScope cs(&crit_sect_);
|
||||||
if (!running_) {
|
if (!running_) {
|
||||||
@ -711,7 +673,7 @@ VCMFrameBufferEnum VCMJitterBuffer::InsertPacket(const VCMPacket& packet,
|
|||||||
frame_data.rtt_ms = rtt_ms_;
|
frame_data.rtt_ms = rtt_ms_;
|
||||||
frame_data.rolling_average_packets_per_frame = average_packets_per_frame_;
|
frame_data.rolling_average_packets_per_frame = average_packets_per_frame_;
|
||||||
VCMFrameBufferEnum buffer_state =
|
VCMFrameBufferEnum buffer_state =
|
||||||
frame->InsertPacket(packet, now_ms, decode_error_mode_, frame_data);
|
frame->InsertPacket(packet, now_ms, frame_data);
|
||||||
|
|
||||||
if (previous_state != kStateComplete) {
|
if (previous_state != kStateComplete) {
|
||||||
TRACE_EVENT_ASYNC_BEGIN1("webrtc", "Video", frame->Timestamp(), "timestamp",
|
TRACE_EVENT_ASYNC_BEGIN1("webrtc", "Video", frame->Timestamp(), "timestamp",
|
||||||
@ -747,18 +709,14 @@ VCMFrameBufferEnum VCMJitterBuffer::InsertPacket(const VCMPacket& packet,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case kCompleteSession: {
|
case kCompleteSession: {
|
||||||
if (previous_state != kStateDecodable &&
|
if (previous_state != kStateComplete) {
|
||||||
previous_state != kStateComplete) {
|
|
||||||
CountFrame(*frame);
|
CountFrame(*frame);
|
||||||
if (continuous) {
|
if (continuous) {
|
||||||
// Signal that we have a complete session.
|
// Signal that we have a complete session.
|
||||||
frame_event_->Set();
|
frame_event_->Set();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RTC_FALLTHROUGH();
|
|
||||||
}
|
|
||||||
// Note: There is no break here - continuing to kDecodableSession.
|
|
||||||
case kDecodableSession: {
|
|
||||||
*retransmitted = (frame->GetNackCount() > 0);
|
*retransmitted = (frame->GetNackCount() > 0);
|
||||||
if (continuous) {
|
if (continuous) {
|
||||||
decodable_frames_.InsertFrame(frame);
|
decodable_frames_.InsertFrame(frame);
|
||||||
@ -812,12 +770,8 @@ VCMFrameBufferEnum VCMJitterBuffer::InsertPacket(const VCMPacket& packet,
|
|||||||
bool VCMJitterBuffer::IsContinuousInState(
|
bool VCMJitterBuffer::IsContinuousInState(
|
||||||
const VCMFrameBuffer& frame,
|
const VCMFrameBuffer& frame,
|
||||||
const VCMDecodingState& decoding_state) const {
|
const VCMDecodingState& decoding_state) const {
|
||||||
// Is this frame (complete or decodable) and continuous?
|
// Is this frame complete and continuous?
|
||||||
// kStateDecodable will never be set when decode_error_mode_ is false
|
return (frame.GetState() == kStateComplete) &&
|
||||||
// as SessionInfo determines this state based on the error mode (and frame
|
|
||||||
// completeness).
|
|
||||||
return (frame.GetState() == kStateComplete ||
|
|
||||||
frame.GetState() == kStateDecodable) &&
|
|
||||||
decoding_state.ContinuousFrame(&frame);
|
decoding_state.ContinuousFrame(&frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1024,11 +978,6 @@ std::vector<uint16_t> VCMJitterBuffer::GetNackList(bool* request_key_frame) {
|
|||||||
return nack_list;
|
return nack_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VCMJitterBuffer::SetDecodeErrorMode(VCMDecodeErrorMode error_mode) {
|
|
||||||
rtc::CritScope cs(&crit_sect_);
|
|
||||||
decode_error_mode_ = error_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
VCMFrameBuffer* VCMJitterBuffer::NextFrame() const {
|
VCMFrameBuffer* VCMJitterBuffer::NextFrame() const {
|
||||||
if (!decodable_frames_.empty())
|
if (!decodable_frames_.empty())
|
||||||
return decodable_frames_.Front();
|
return decodable_frames_.Front();
|
||||||
|
|||||||
@ -145,11 +145,6 @@ class VCMJitterBuffer {
|
|||||||
// If found, a pointer to the frame is returned. Returns nullptr otherwise.
|
// If found, a pointer to the frame is returned. Returns nullptr otherwise.
|
||||||
VCMEncodedFrame* NextCompleteFrame(uint32_t max_wait_time_ms);
|
VCMEncodedFrame* NextCompleteFrame(uint32_t max_wait_time_ms);
|
||||||
|
|
||||||
// Locates a frame for decoding (even an incomplete) without delay.
|
|
||||||
// The function returns true once such a frame is found, its corresponding
|
|
||||||
// timestamp is returned. Otherwise, returns false.
|
|
||||||
bool NextMaybeIncompleteTimestamp(uint32_t* timestamp);
|
|
||||||
|
|
||||||
// Extract frame corresponding to input timestamp.
|
// Extract frame corresponding to input timestamp.
|
||||||
// Frame will be set to a decoding state.
|
// Frame will be set to a decoding state.
|
||||||
VCMEncodedFrame* ExtractAndSetDecode(uint32_t timestamp);
|
VCMEncodedFrame* ExtractAndSetDecode(uint32_t timestamp);
|
||||||
@ -195,11 +190,6 @@ class VCMJitterBuffer {
|
|||||||
// Returns a list of the sequence numbers currently missing.
|
// Returns a list of the sequence numbers currently missing.
|
||||||
std::vector<uint16_t> GetNackList(bool* request_key_frame);
|
std::vector<uint16_t> GetNackList(bool* request_key_frame);
|
||||||
|
|
||||||
// Set decode error mode - Should not be changed in the middle of the
|
|
||||||
// session. Changes will not influence frames already in the buffer.
|
|
||||||
void SetDecodeErrorMode(VCMDecodeErrorMode error_mode);
|
|
||||||
VCMDecodeErrorMode decode_error_mode() const { return decode_error_mode_; }
|
|
||||||
|
|
||||||
void RegisterStatsCallback(VCMReceiveStatisticsCallback* callback);
|
void RegisterStatsCallback(VCMReceiveStatisticsCallback* callback);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -367,7 +357,6 @@ class VCMJitterBuffer {
|
|||||||
int max_packet_age_to_nack_; // Measured in sequence numbers.
|
int max_packet_age_to_nack_; // Measured in sequence numbers.
|
||||||
int max_incomplete_time_ms_;
|
int max_incomplete_time_ms_;
|
||||||
|
|
||||||
VCMDecodeErrorMode decode_error_mode_;
|
|
||||||
// Estimated rolling average of packets per frame
|
// Estimated rolling average of packets per frame
|
||||||
float average_packets_per_frame_;
|
float average_packets_per_frame_;
|
||||||
// average_packets_per_frame converges fast if we have fewer than this many
|
// average_packets_per_frame converges fast if we have fewer than this many
|
||||||
|
|||||||
@ -44,7 +44,6 @@ enum VCMFrameBufferEnum {
|
|||||||
kNoError = 0,
|
kNoError = 0,
|
||||||
kIncomplete = 1, // Frame incomplete.
|
kIncomplete = 1, // Frame incomplete.
|
||||||
kCompleteSession = 3, // at least one layer in the frame complete.
|
kCompleteSession = 3, // at least one layer in the frame complete.
|
||||||
kDecodableSession = 4, // Frame incomplete, but ready to be decoded
|
|
||||||
kDuplicatePacket = 5 // We're receiving a duplicate packet.
|
kDuplicatePacket = 5 // We're receiving a duplicate packet.
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -52,7 +51,6 @@ enum VCMFrameBufferStateEnum {
|
|||||||
kStateEmpty, // frame popped by the RTP receiver
|
kStateEmpty, // frame popped by the RTP receiver
|
||||||
kStateIncomplete, // frame that have one or more packet(s) stored
|
kStateIncomplete, // frame that have one or more packet(s) stored
|
||||||
kStateComplete, // frame that have all packets
|
kStateComplete, // frame that have all packets
|
||||||
kStateDecodable // Hybrid mode - frame can be decoded
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum { kH264StartCodeLengthBytes = 4 };
|
enum { kH264StartCodeLengthBytes = 4 };
|
||||||
|
|||||||
@ -258,15 +258,6 @@ class TestBasicJitterBuffer : public ::testing::TestWithParam<std::string>,
|
|||||||
return jitter_buffer_->ExtractAndSetDecode(found_frame->Timestamp());
|
return jitter_buffer_->ExtractAndSetDecode(found_frame->Timestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
VCMEncodedFrame* DecodeIncompleteFrame() {
|
|
||||||
uint32_t timestamp = 0;
|
|
||||||
bool found_frame = jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp);
|
|
||||||
if (!found_frame)
|
|
||||||
return NULL;
|
|
||||||
VCMEncodedFrame* frame = jitter_buffer_->ExtractAndSetDecode(timestamp);
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckOutFrame(VCMEncodedFrame* frame_out,
|
void CheckOutFrame(VCMEncodedFrame* frame_out,
|
||||||
unsigned int size,
|
unsigned int size,
|
||||||
bool startCode) {
|
bool startCode) {
|
||||||
@ -413,17 +404,6 @@ class TestRunningJitterBuffer : public ::testing::TestWithParam<std::string>,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DecodeIncompleteFrame() {
|
|
||||||
uint32_t timestamp = 0;
|
|
||||||
bool found_frame = jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp);
|
|
||||||
if (!found_frame)
|
|
||||||
return false;
|
|
||||||
VCMEncodedFrame* frame = jitter_buffer_->ExtractAndSetDecode(timestamp);
|
|
||||||
bool ret = (frame != NULL);
|
|
||||||
jitter_buffer_->ReleaseFrame(frame);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
VCMJitterBuffer* jitter_buffer_;
|
VCMJitterBuffer* jitter_buffer_;
|
||||||
StreamGenerator* stream_generator_;
|
StreamGenerator* stream_generator_;
|
||||||
std::unique_ptr<SimulatedClock> clock_;
|
std::unique_ptr<SimulatedClock> clock_;
|
||||||
@ -446,26 +426,14 @@ class TestJitterBufferNack : public TestRunningJitterBuffer {
|
|||||||
TEST_F(TestBasicJitterBuffer, StopRunning) {
|
TEST_F(TestBasicJitterBuffer, StopRunning) {
|
||||||
jitter_buffer_->Stop();
|
jitter_buffer_->Stop();
|
||||||
EXPECT_TRUE(NULL == DecodeCompleteFrame());
|
EXPECT_TRUE(NULL == DecodeCompleteFrame());
|
||||||
EXPECT_TRUE(NULL == DecodeIncompleteFrame());
|
|
||||||
jitter_buffer_->Start();
|
jitter_buffer_->Start();
|
||||||
// Allow selective errors.
|
|
||||||
jitter_buffer_->SetDecodeErrorMode(kSelectiveErrors);
|
|
||||||
|
|
||||||
// No packets inserted.
|
// No packets inserted.
|
||||||
EXPECT_TRUE(NULL == DecodeCompleteFrame());
|
EXPECT_TRUE(NULL == DecodeCompleteFrame());
|
||||||
EXPECT_TRUE(NULL == DecodeIncompleteFrame());
|
|
||||||
|
|
||||||
// Allow decoding with errors.
|
|
||||||
jitter_buffer_->SetDecodeErrorMode(kWithErrors);
|
|
||||||
|
|
||||||
// No packets inserted.
|
|
||||||
EXPECT_TRUE(NULL == DecodeCompleteFrame());
|
|
||||||
EXPECT_TRUE(NULL == DecodeIncompleteFrame());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestBasicJitterBuffer, SinglePacketFrame) {
|
TEST_F(TestBasicJitterBuffer, SinglePacketFrame) {
|
||||||
// Always start with a complete key frame when not allowing errors.
|
// Always start with a complete key frame when not allowing errors.
|
||||||
jitter_buffer_->SetDecodeErrorMode(kNoErrors);
|
|
||||||
packet_->frameType = kVideoFrameKey;
|
packet_->frameType = kVideoFrameKey;
|
||||||
packet_->is_first_packet_in_frame = true;
|
packet_->is_first_packet_in_frame = true;
|
||||||
packet_->markerBit = true;
|
packet_->markerBit = true;
|
||||||
@ -484,7 +452,6 @@ TEST_F(TestBasicJitterBuffer, SinglePacketFrame) {
|
|||||||
TEST_F(TestBasicJitterBuffer, VerifyHistogramStats) {
|
TEST_F(TestBasicJitterBuffer, VerifyHistogramStats) {
|
||||||
metrics::Reset();
|
metrics::Reset();
|
||||||
// Always start with a complete key frame when not allowing errors.
|
// Always start with a complete key frame when not allowing errors.
|
||||||
jitter_buffer_->SetDecodeErrorMode(kNoErrors);
|
|
||||||
packet_->frameType = kVideoFrameKey;
|
packet_->frameType = kVideoFrameKey;
|
||||||
packet_->is_first_packet_in_frame = true;
|
packet_->is_first_packet_in_frame = true;
|
||||||
packet_->markerBit = true;
|
packet_->markerBit = true;
|
||||||
@ -864,7 +831,6 @@ TEST_F(TestBasicJitterBuffer, DuplicatePreviousDeltaFramePacket) {
|
|||||||
packet_->markerBit = true;
|
packet_->markerBit = true;
|
||||||
packet_->seqNum = seq_num_;
|
packet_->seqNum = seq_num_;
|
||||||
packet_->timestamp = timestamp_;
|
packet_->timestamp = timestamp_;
|
||||||
jitter_buffer_->SetDecodeErrorMode(kNoErrors);
|
|
||||||
EXPECT_EQ(0, jitter_buffer_->num_packets());
|
EXPECT_EQ(0, jitter_buffer_->num_packets());
|
||||||
EXPECT_EQ(0, jitter_buffer_->num_duplicated_packets());
|
EXPECT_EQ(0, jitter_buffer_->num_duplicated_packets());
|
||||||
|
|
||||||
@ -1162,8 +1128,6 @@ TEST_F(TestBasicJitterBuffer, H264InsertStartCode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestBasicJitterBuffer, SpsAndPpsHandling) {
|
TEST_F(TestBasicJitterBuffer, SpsAndPpsHandling) {
|
||||||
jitter_buffer_->SetDecodeErrorMode(kNoErrors);
|
|
||||||
|
|
||||||
auto& h264_header =
|
auto& h264_header =
|
||||||
packet_->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
|
packet_->video_header.video_type_header.emplace<RTPVideoHeaderH264>();
|
||||||
packet_->timestamp = timestamp_;
|
packet_->timestamp = timestamp_;
|
||||||
@ -1246,364 +1210,6 @@ TEST_F(TestBasicJitterBuffer, SpsAndPpsHandling) {
|
|||||||
jitter_buffer_->ReleaseFrame(frame_out);
|
jitter_buffer_->ReleaseFrame(frame_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test threshold conditions of decodable state.
|
|
||||||
TEST_F(TestBasicJitterBuffer, PacketLossWithSelectiveErrorsThresholdCheck) {
|
|
||||||
jitter_buffer_->SetDecodeErrorMode(kSelectiveErrors);
|
|
||||||
// Always start with a key frame. Use 10 packets to test Decodable State
|
|
||||||
// boundaries.
|
|
||||||
packet_->frameType = kVideoFrameKey;
|
|
||||||
packet_->is_first_packet_in_frame = true;
|
|
||||||
packet_->markerBit = false;
|
|
||||||
packet_->seqNum = seq_num_;
|
|
||||||
packet_->timestamp = timestamp_;
|
|
||||||
|
|
||||||
bool retransmitted = false;
|
|
||||||
EXPECT_EQ(kIncomplete,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
uint32_t timestamp = 0;
|
|
||||||
EXPECT_EQ(jitter_buffer_->NextCompleteFrame(0), nullptr);
|
|
||||||
EXPECT_FALSE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp));
|
|
||||||
|
|
||||||
packet_->is_first_packet_in_frame = false;
|
|
||||||
for (int i = 1; i < 9; ++i) {
|
|
||||||
packet_->seqNum++;
|
|
||||||
EXPECT_EQ(kIncomplete,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
EXPECT_EQ(jitter_buffer_->NextCompleteFrame(0), nullptr);
|
|
||||||
EXPECT_FALSE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp));
|
|
||||||
}
|
|
||||||
|
|
||||||
// last packet
|
|
||||||
packet_->markerBit = true;
|
|
||||||
packet_->seqNum++;
|
|
||||||
|
|
||||||
EXPECT_EQ(kCompleteSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
VCMEncodedFrame* frame_out = DecodeCompleteFrame();
|
|
||||||
CheckOutFrame(frame_out, 10 * size_, false);
|
|
||||||
EXPECT_EQ(kVideoFrameKey, frame_out->FrameType());
|
|
||||||
jitter_buffer_->ReleaseFrame(frame_out);
|
|
||||||
|
|
||||||
// An incomplete frame can only be decoded once a subsequent frame has begun
|
|
||||||
// to arrive. Insert packet in distant frame for this purpose.
|
|
||||||
packet_->frameType = kVideoFrameDelta;
|
|
||||||
packet_->is_first_packet_in_frame = true;
|
|
||||||
packet_->markerBit = false;
|
|
||||||
packet_->seqNum += 100;
|
|
||||||
packet_->timestamp += 33 * 90 * 8;
|
|
||||||
|
|
||||||
EXPECT_EQ(kDecodableSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
EXPECT_EQ(jitter_buffer_->NextCompleteFrame(0), nullptr);
|
|
||||||
EXPECT_FALSE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp));
|
|
||||||
|
|
||||||
// Insert second frame
|
|
||||||
packet_->seqNum -= 99;
|
|
||||||
packet_->timestamp -= 33 * 90 * 7;
|
|
||||||
|
|
||||||
EXPECT_EQ(kDecodableSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
EXPECT_EQ(jitter_buffer_->NextCompleteFrame(0), nullptr);
|
|
||||||
EXPECT_TRUE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp));
|
|
||||||
|
|
||||||
packet_->is_first_packet_in_frame = false;
|
|
||||||
for (int i = 1; i < 8; ++i) {
|
|
||||||
packet_->seqNum++;
|
|
||||||
EXPECT_EQ(kDecodableSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
EXPECT_EQ(jitter_buffer_->NextCompleteFrame(0), nullptr);
|
|
||||||
EXPECT_TRUE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp));
|
|
||||||
}
|
|
||||||
|
|
||||||
packet_->seqNum++;
|
|
||||||
EXPECT_EQ(kDecodableSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
EXPECT_EQ(jitter_buffer_->NextCompleteFrame(0), nullptr);
|
|
||||||
EXPECT_TRUE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp));
|
|
||||||
|
|
||||||
frame_out = DecodeIncompleteFrame();
|
|
||||||
ASSERT_FALSE(NULL == frame_out);
|
|
||||||
CheckOutFrame(frame_out, 9 * size_, false);
|
|
||||||
EXPECT_EQ(kVideoFrameDelta, frame_out->FrameType());
|
|
||||||
jitter_buffer_->ReleaseFrame(frame_out);
|
|
||||||
|
|
||||||
packet_->markerBit = true;
|
|
||||||
packet_->seqNum++;
|
|
||||||
EXPECT_EQ(kOldPacket, jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure first packet is present before a frame can be decoded.
|
|
||||||
TEST_F(TestBasicJitterBuffer, PacketLossWithSelectiveErrorsIncompleteKey) {
|
|
||||||
jitter_buffer_->SetDecodeErrorMode(kSelectiveErrors);
|
|
||||||
// Always start with a key frame.
|
|
||||||
packet_->frameType = kVideoFrameKey;
|
|
||||||
packet_->is_first_packet_in_frame = true;
|
|
||||||
packet_->markerBit = true;
|
|
||||||
packet_->seqNum = seq_num_;
|
|
||||||
packet_->timestamp = timestamp_;
|
|
||||||
|
|
||||||
bool retransmitted = false;
|
|
||||||
EXPECT_EQ(kCompleteSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
VCMEncodedFrame* frame_out = DecodeCompleteFrame();
|
|
||||||
CheckOutFrame(frame_out, size_, false);
|
|
||||||
EXPECT_EQ(kVideoFrameKey, frame_out->FrameType());
|
|
||||||
jitter_buffer_->ReleaseFrame(frame_out);
|
|
||||||
|
|
||||||
// An incomplete frame can only be decoded once a subsequent frame has begun
|
|
||||||
// to arrive. Insert packet in distant frame for this purpose.
|
|
||||||
packet_->frameType = kVideoFrameDelta;
|
|
||||||
packet_->is_first_packet_in_frame = false;
|
|
||||||
packet_->markerBit = false;
|
|
||||||
packet_->seqNum += 100;
|
|
||||||
packet_->timestamp += 33 * 90 * 8;
|
|
||||||
EXPECT_EQ(kIncomplete,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
uint32_t timestamp;
|
|
||||||
EXPECT_EQ(jitter_buffer_->NextCompleteFrame(0), nullptr);
|
|
||||||
EXPECT_FALSE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp));
|
|
||||||
|
|
||||||
// Insert second frame - an incomplete key frame.
|
|
||||||
packet_->frameType = kVideoFrameKey;
|
|
||||||
packet_->is_first_packet_in_frame = true;
|
|
||||||
packet_->seqNum -= 99;
|
|
||||||
packet_->timestamp -= 33 * 90 * 7;
|
|
||||||
|
|
||||||
EXPECT_EQ(kIncomplete,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
EXPECT_EQ(jitter_buffer_->NextCompleteFrame(0), nullptr);
|
|
||||||
EXPECT_FALSE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp));
|
|
||||||
|
|
||||||
// Insert a few more packets. Make sure we're waiting for the key frame to be
|
|
||||||
// complete.
|
|
||||||
packet_->is_first_packet_in_frame = false;
|
|
||||||
for (int i = 1; i < 5; ++i) {
|
|
||||||
packet_->seqNum++;
|
|
||||||
EXPECT_EQ(kIncomplete,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
EXPECT_EQ(jitter_buffer_->NextCompleteFrame(0), nullptr);
|
|
||||||
EXPECT_FALSE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Complete key frame.
|
|
||||||
packet_->markerBit = true;
|
|
||||||
packet_->seqNum++;
|
|
||||||
EXPECT_EQ(kCompleteSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
frame_out = DecodeCompleteFrame();
|
|
||||||
CheckOutFrame(frame_out, 6 * size_, false);
|
|
||||||
EXPECT_EQ(kVideoFrameKey, frame_out->FrameType());
|
|
||||||
jitter_buffer_->ReleaseFrame(frame_out);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure first packet is present before a frame can be decoded.
|
|
||||||
TEST_F(TestBasicJitterBuffer, PacketLossWithSelectiveErrorsMissingFirstPacket) {
|
|
||||||
jitter_buffer_->SetDecodeErrorMode(kSelectiveErrors);
|
|
||||||
// Always start with a key frame.
|
|
||||||
packet_->frameType = kVideoFrameKey;
|
|
||||||
packet_->is_first_packet_in_frame = true;
|
|
||||||
packet_->markerBit = true;
|
|
||||||
packet_->seqNum = seq_num_;
|
|
||||||
packet_->timestamp = timestamp_;
|
|
||||||
|
|
||||||
bool retransmitted = false;
|
|
||||||
EXPECT_EQ(kCompleteSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
VCMEncodedFrame* frame_out = DecodeCompleteFrame();
|
|
||||||
CheckOutFrame(frame_out, size_, false);
|
|
||||||
EXPECT_EQ(kVideoFrameKey, frame_out->FrameType());
|
|
||||||
jitter_buffer_->ReleaseFrame(frame_out);
|
|
||||||
|
|
||||||
// An incomplete frame can only be decoded once a subsequent frame has begun
|
|
||||||
// to arrive. Insert packet in distant frame for this purpose.
|
|
||||||
packet_->frameType = kVideoFrameDelta;
|
|
||||||
packet_->is_first_packet_in_frame = false;
|
|
||||||
packet_->markerBit = false;
|
|
||||||
packet_->seqNum += 100;
|
|
||||||
packet_->timestamp += 33 * 90 * 8;
|
|
||||||
EXPECT_EQ(kIncomplete,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
uint32_t timestamp;
|
|
||||||
EXPECT_EQ(jitter_buffer_->NextCompleteFrame(0), nullptr);
|
|
||||||
EXPECT_FALSE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp));
|
|
||||||
|
|
||||||
// Insert second frame with the first packet missing. Make sure we're waiting
|
|
||||||
// for the key frame to be complete.
|
|
||||||
packet_->seqNum -= 98;
|
|
||||||
packet_->timestamp -= 33 * 90 * 7;
|
|
||||||
|
|
||||||
EXPECT_EQ(kIncomplete,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
EXPECT_EQ(jitter_buffer_->NextCompleteFrame(0), nullptr);
|
|
||||||
EXPECT_FALSE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp));
|
|
||||||
|
|
||||||
for (int i = 0; i < 5; ++i) {
|
|
||||||
packet_->seqNum++;
|
|
||||||
EXPECT_EQ(kIncomplete,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
EXPECT_EQ(jitter_buffer_->NextCompleteFrame(0), nullptr);
|
|
||||||
EXPECT_FALSE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add first packet. Frame should now be decodable, but incomplete.
|
|
||||||
packet_->is_first_packet_in_frame = true;
|
|
||||||
packet_->seqNum -= 6;
|
|
||||||
EXPECT_EQ(kDecodableSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
EXPECT_EQ(jitter_buffer_->NextCompleteFrame(0), nullptr);
|
|
||||||
EXPECT_TRUE(jitter_buffer_->NextMaybeIncompleteTimestamp(×tamp));
|
|
||||||
|
|
||||||
frame_out = DecodeIncompleteFrame();
|
|
||||||
CheckOutFrame(frame_out, 7 * size_, false);
|
|
||||||
EXPECT_EQ(kVideoFrameDelta, frame_out->FrameType());
|
|
||||||
jitter_buffer_->ReleaseFrame(frame_out);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(TestBasicJitterBuffer, DiscontinuousStreamWhenDecodingWithErrors) {
|
|
||||||
// Will use one packet per frame.
|
|
||||||
jitter_buffer_->SetDecodeErrorMode(kWithErrors);
|
|
||||||
packet_->frameType = kVideoFrameKey;
|
|
||||||
packet_->is_first_packet_in_frame = true;
|
|
||||||
packet_->markerBit = true;
|
|
||||||
packet_->seqNum = seq_num_;
|
|
||||||
packet_->timestamp = timestamp_;
|
|
||||||
bool retransmitted = false;
|
|
||||||
EXPECT_EQ(kCompleteSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
uint32_t next_timestamp;
|
|
||||||
VCMEncodedFrame* frame = jitter_buffer_->NextCompleteFrame(0);
|
|
||||||
EXPECT_NE(frame, nullptr);
|
|
||||||
EXPECT_EQ(packet_->timestamp, frame->Timestamp());
|
|
||||||
frame = jitter_buffer_->ExtractAndSetDecode(frame->Timestamp());
|
|
||||||
EXPECT_TRUE(frame != NULL);
|
|
||||||
jitter_buffer_->ReleaseFrame(frame);
|
|
||||||
|
|
||||||
// Drop a complete frame.
|
|
||||||
timestamp_ += 2 * 33 * 90;
|
|
||||||
seq_num_ += 2;
|
|
||||||
packet_->frameType = kVideoFrameDelta;
|
|
||||||
packet_->is_first_packet_in_frame = true;
|
|
||||||
packet_->markerBit = false;
|
|
||||||
packet_->seqNum = seq_num_;
|
|
||||||
packet_->timestamp = timestamp_;
|
|
||||||
EXPECT_EQ(kDecodableSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
// Insert a packet (so the previous one will be released).
|
|
||||||
timestamp_ += 33 * 90;
|
|
||||||
seq_num_ += 2;
|
|
||||||
packet_->frameType = kVideoFrameDelta;
|
|
||||||
packet_->is_first_packet_in_frame = true;
|
|
||||||
packet_->markerBit = false;
|
|
||||||
packet_->seqNum = seq_num_;
|
|
||||||
packet_->timestamp = timestamp_;
|
|
||||||
EXPECT_EQ(kDecodableSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
EXPECT_EQ(jitter_buffer_->NextCompleteFrame(0), nullptr);
|
|
||||||
EXPECT_TRUE(jitter_buffer_->NextMaybeIncompleteTimestamp(&next_timestamp));
|
|
||||||
EXPECT_EQ(packet_->timestamp - 33 * 90, next_timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(TestBasicJitterBuffer, PacketLoss) {
|
|
||||||
// Verify missing packets statistics and not decodable packets statistics.
|
|
||||||
// Insert 10 frames consisting of 4 packets and remove one from all of them.
|
|
||||||
// The last packet is an empty (non-media) packet.
|
|
||||||
|
|
||||||
// Select a start seqNum which triggers a difficult wrap situation
|
|
||||||
// The JB will only output (incomplete)frames if the next one has started
|
|
||||||
// to arrive. Start by inserting one frame (key).
|
|
||||||
jitter_buffer_->SetDecodeErrorMode(kWithErrors);
|
|
||||||
seq_num_ = 0xffff - 4;
|
|
||||||
seq_num_++;
|
|
||||||
packet_->frameType = kVideoFrameKey;
|
|
||||||
packet_->is_first_packet_in_frame = true;
|
|
||||||
packet_->markerBit = false;
|
|
||||||
packet_->seqNum = seq_num_;
|
|
||||||
packet_->timestamp = timestamp_;
|
|
||||||
packet_->completeNALU = kNaluStart;
|
|
||||||
|
|
||||||
bool retransmitted = false;
|
|
||||||
EXPECT_EQ(kDecodableSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
for (int i = 0; i < 11; ++i) {
|
|
||||||
webrtc::FrameType frametype = kVideoFrameDelta;
|
|
||||||
seq_num_++;
|
|
||||||
timestamp_ += 33 * 90;
|
|
||||||
packet_->frameType = frametype;
|
|
||||||
packet_->is_first_packet_in_frame = true;
|
|
||||||
packet_->markerBit = false;
|
|
||||||
packet_->seqNum = seq_num_;
|
|
||||||
packet_->timestamp = timestamp_;
|
|
||||||
packet_->completeNALU = kNaluStart;
|
|
||||||
|
|
||||||
EXPECT_EQ(kDecodableSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
|
|
||||||
VCMEncodedFrame* frame_out = DecodeCompleteFrame();
|
|
||||||
|
|
||||||
// Should not be complete.
|
|
||||||
EXPECT_TRUE(frame_out == NULL);
|
|
||||||
|
|
||||||
seq_num_ += 2;
|
|
||||||
packet_->is_first_packet_in_frame = false;
|
|
||||||
packet_->markerBit = true;
|
|
||||||
packet_->seqNum = seq_num_;
|
|
||||||
packet_->completeNALU = kNaluEnd;
|
|
||||||
|
|
||||||
EXPECT_EQ(jitter_buffer_->InsertPacket(*packet_, &retransmitted),
|
|
||||||
kDecodableSession);
|
|
||||||
|
|
||||||
// Insert an empty (non-media) packet.
|
|
||||||
seq_num_++;
|
|
||||||
packet_->is_first_packet_in_frame = false;
|
|
||||||
packet_->markerBit = false;
|
|
||||||
packet_->seqNum = seq_num_;
|
|
||||||
packet_->completeNALU = kNaluEnd;
|
|
||||||
packet_->frameType = kEmptyFrame;
|
|
||||||
|
|
||||||
EXPECT_EQ(jitter_buffer_->InsertPacket(*packet_, &retransmitted),
|
|
||||||
kDecodableSession);
|
|
||||||
frame_out = DecodeIncompleteFrame();
|
|
||||||
|
|
||||||
// One of the packets has been discarded by the jitter buffer.
|
|
||||||
// Last frame can't be extracted yet.
|
|
||||||
if (i < 10) {
|
|
||||||
CheckOutFrame(frame_out, size_, false);
|
|
||||||
|
|
||||||
if (i == 0) {
|
|
||||||
EXPECT_EQ(kVideoFrameKey, frame_out->FrameType());
|
|
||||||
} else {
|
|
||||||
EXPECT_EQ(frametype, frame_out->FrameType());
|
|
||||||
}
|
|
||||||
EXPECT_FALSE(frame_out->Complete());
|
|
||||||
EXPECT_FALSE(frame_out->MissingFrame());
|
|
||||||
}
|
|
||||||
|
|
||||||
jitter_buffer_->ReleaseFrame(frame_out);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert 3 old packets and verify that we have 3 discarded packets
|
|
||||||
// Match value to actual latest timestamp decoded.
|
|
||||||
timestamp_ -= 33 * 90;
|
|
||||||
packet_->timestamp = timestamp_ - 1000;
|
|
||||||
|
|
||||||
EXPECT_EQ(kOldPacket, jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
|
|
||||||
packet_->timestamp = timestamp_ - 500;
|
|
||||||
|
|
||||||
EXPECT_EQ(kOldPacket, jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
|
|
||||||
packet_->timestamp = timestamp_ - 100;
|
|
||||||
|
|
||||||
EXPECT_EQ(kOldPacket, jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
|
|
||||||
EXPECT_EQ(3, jitter_buffer_->num_discarded_packets());
|
|
||||||
|
|
||||||
jitter_buffer_->Flush();
|
|
||||||
|
|
||||||
// This statistic shouldn't be reset by a flush.
|
|
||||||
EXPECT_EQ(3, jitter_buffer_->num_discarded_packets());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(TestBasicJitterBuffer, DeltaFrame100PacketsWithSeqNumWrap) {
|
TEST_F(TestBasicJitterBuffer, DeltaFrame100PacketsWithSeqNumWrap) {
|
||||||
seq_num_ = 0xfff0;
|
seq_num_ = 0xfff0;
|
||||||
packet_->frameType = kVideoFrameKey;
|
packet_->frameType = kVideoFrameKey;
|
||||||
@ -2016,7 +1622,6 @@ TEST_F(TestBasicJitterBuffer, ExceedNumOfFrameWithSeqNumWrap) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestBasicJitterBuffer, EmptyLastFrame) {
|
TEST_F(TestBasicJitterBuffer, EmptyLastFrame) {
|
||||||
jitter_buffer_->SetDecodeErrorMode(kWithErrors);
|
|
||||||
seq_num_ = 3;
|
seq_num_ = 3;
|
||||||
// Insert one empty packet per frame, should never return the last timestamp
|
// Insert one empty packet per frame, should never return the last timestamp
|
||||||
// inserted. Only return empty frames in the presence of subsequent frames.
|
// inserted. Only return empty frames in the presence of subsequent frames.
|
||||||
@ -2032,204 +1637,13 @@ TEST_F(TestBasicJitterBuffer, EmptyLastFrame) {
|
|||||||
packet_->frameType = kEmptyFrame;
|
packet_->frameType = kEmptyFrame;
|
||||||
|
|
||||||
EXPECT_EQ(kNoError, jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
EXPECT_EQ(kNoError, jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
||||||
VCMEncodedFrame* testFrame = DecodeIncompleteFrame();
|
|
||||||
// Timestamp should never be the last TS inserted.
|
|
||||||
if (testFrame != NULL) {
|
|
||||||
EXPECT_TRUE(testFrame->Timestamp() < timestamp_);
|
|
||||||
jitter_buffer_->ReleaseFrame(testFrame);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestBasicJitterBuffer, H264IncompleteNalu) {
|
|
||||||
jitter_buffer_->SetNackMode(kNoNack, -1, -1);
|
|
||||||
jitter_buffer_->SetDecodeErrorMode(kWithErrors);
|
|
||||||
++seq_num_;
|
|
||||||
timestamp_ += 33 * 90;
|
|
||||||
int insertedLength = 0;
|
|
||||||
packet_->seqNum = seq_num_;
|
|
||||||
packet_->timestamp = timestamp_;
|
|
||||||
packet_->frameType = kVideoFrameKey;
|
|
||||||
packet_->is_first_packet_in_frame = true;
|
|
||||||
packet_->completeNALU = kNaluStart;
|
|
||||||
packet_->markerBit = false;
|
|
||||||
bool retransmitted = false;
|
|
||||||
|
|
||||||
EXPECT_EQ(kDecodableSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
|
|
||||||
seq_num_ += 2; // Skip one packet.
|
|
||||||
packet_->seqNum = seq_num_;
|
|
||||||
packet_->frameType = kVideoFrameKey;
|
|
||||||
packet_->is_first_packet_in_frame = false;
|
|
||||||
packet_->completeNALU = kNaluIncomplete;
|
|
||||||
packet_->markerBit = false;
|
|
||||||
|
|
||||||
EXPECT_EQ(kDecodableSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
|
|
||||||
seq_num_++;
|
|
||||||
packet_->seqNum = seq_num_;
|
|
||||||
packet_->frameType = kVideoFrameKey;
|
|
||||||
packet_->is_first_packet_in_frame = false;
|
|
||||||
packet_->completeNALU = kNaluEnd;
|
|
||||||
packet_->markerBit = false;
|
|
||||||
|
|
||||||
EXPECT_EQ(kDecodableSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
|
|
||||||
seq_num_++;
|
|
||||||
packet_->seqNum = seq_num_;
|
|
||||||
packet_->completeNALU = kNaluComplete;
|
|
||||||
packet_->markerBit = true; // Last packet.
|
|
||||||
EXPECT_EQ(kDecodableSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
// The JB will only output (incomplete) frames if a packet belonging to a
|
|
||||||
// subsequent frame was already inserted. Insert one packet of a subsequent
|
|
||||||
// frame. place high timestamp so the JB would always have a next frame
|
|
||||||
// (otherwise, for every inserted frame we need to take care of the next
|
|
||||||
// frame as well).
|
|
||||||
packet_->seqNum = 1;
|
|
||||||
packet_->timestamp = timestamp_ + 33 * 90 * 10;
|
|
||||||
packet_->frameType = kVideoFrameDelta;
|
|
||||||
packet_->is_first_packet_in_frame = false;
|
|
||||||
packet_->completeNALU = kNaluStart;
|
|
||||||
packet_->markerBit = false;
|
|
||||||
|
|
||||||
EXPECT_EQ(kDecodableSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
|
|
||||||
VCMEncodedFrame* frame_out = DecodeIncompleteFrame();
|
|
||||||
|
|
||||||
// We can decode everything from a NALU until a packet has been lost.
|
|
||||||
// Thus we can decode the first packet of the first NALU and the second NALU
|
|
||||||
// which consists of one packet.
|
|
||||||
CheckOutFrame(frame_out, packet_->sizeBytes * 2, false);
|
|
||||||
jitter_buffer_->ReleaseFrame(frame_out);
|
|
||||||
|
|
||||||
// Test reordered start frame + 1 lost.
|
|
||||||
seq_num_ += 2; // Re-order 1 frame.
|
|
||||||
timestamp_ += 33 * 90;
|
|
||||||
insertedLength = 0;
|
|
||||||
|
|
||||||
packet_->seqNum = seq_num_;
|
|
||||||
packet_->timestamp = timestamp_;
|
|
||||||
packet_->frameType = kVideoFrameKey;
|
|
||||||
packet_->is_first_packet_in_frame = false;
|
|
||||||
packet_->completeNALU = kNaluEnd;
|
|
||||||
packet_->markerBit = false;
|
|
||||||
EXPECT_EQ(kDecodableSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
insertedLength += packet_->sizeBytes; // This packet should be decoded.
|
|
||||||
seq_num_--;
|
|
||||||
packet_->seqNum = seq_num_;
|
|
||||||
packet_->timestamp = timestamp_;
|
|
||||||
packet_->frameType = kVideoFrameKey;
|
|
||||||
packet_->is_first_packet_in_frame = true;
|
|
||||||
packet_->completeNALU = kNaluStart;
|
|
||||||
packet_->markerBit = false;
|
|
||||||
|
|
||||||
EXPECT_EQ(kDecodableSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
insertedLength += packet_->sizeBytes; // This packet should be decoded.
|
|
||||||
|
|
||||||
seq_num_ += 3; // One packet drop.
|
|
||||||
packet_->seqNum = seq_num_;
|
|
||||||
packet_->timestamp = timestamp_;
|
|
||||||
packet_->frameType = kVideoFrameKey;
|
|
||||||
packet_->is_first_packet_in_frame = false;
|
|
||||||
packet_->completeNALU = kNaluComplete;
|
|
||||||
packet_->markerBit = false;
|
|
||||||
EXPECT_EQ(kDecodableSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
insertedLength += packet_->sizeBytes; // This packet should be decoded.
|
|
||||||
seq_num_++;
|
|
||||||
packet_->seqNum = seq_num_;
|
|
||||||
packet_->timestamp = timestamp_;
|
|
||||||
packet_->frameType = kVideoFrameKey;
|
|
||||||
packet_->is_first_packet_in_frame = false;
|
|
||||||
packet_->completeNALU = kNaluStart;
|
|
||||||
packet_->markerBit = false;
|
|
||||||
EXPECT_EQ(kDecodableSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
// This packet should be decoded since it's the beginning of a NAL.
|
|
||||||
insertedLength += packet_->sizeBytes;
|
|
||||||
|
|
||||||
seq_num_ += 2;
|
|
||||||
packet_->seqNum = seq_num_;
|
|
||||||
packet_->timestamp = timestamp_;
|
|
||||||
packet_->frameType = kVideoFrameKey;
|
|
||||||
packet_->is_first_packet_in_frame = false;
|
|
||||||
packet_->completeNALU = kNaluEnd;
|
|
||||||
packet_->markerBit = true;
|
|
||||||
EXPECT_EQ(kDecodableSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
// This packet should not be decoded because it is an incomplete NAL if it
|
|
||||||
// is the last.
|
|
||||||
frame_out = DecodeIncompleteFrame();
|
|
||||||
// Only last NALU is complete.
|
|
||||||
CheckOutFrame(frame_out, insertedLength, false);
|
|
||||||
jitter_buffer_->ReleaseFrame(frame_out);
|
|
||||||
|
|
||||||
// Test to insert empty packet.
|
|
||||||
seq_num_++;
|
|
||||||
timestamp_ += 33 * 90;
|
|
||||||
WebRtcRTPHeader rtpHeader;
|
|
||||||
memset(&rtpHeader, 0, sizeof(rtpHeader));
|
|
||||||
rtpHeader.video_header().codec = kVideoCodecGeneric;
|
|
||||||
VCMPacket emptypacket(data_, 0, rtpHeader);
|
|
||||||
emptypacket.seqNum = seq_num_;
|
|
||||||
emptypacket.timestamp = timestamp_;
|
|
||||||
emptypacket.frameType = kVideoFrameKey;
|
|
||||||
emptypacket.is_first_packet_in_frame = true;
|
|
||||||
emptypacket.completeNALU = kNaluComplete;
|
|
||||||
emptypacket.markerBit = true;
|
|
||||||
EXPECT_EQ(kCompleteSession,
|
|
||||||
jitter_buffer_->InsertPacket(emptypacket, &retransmitted));
|
|
||||||
// This packet should not be decoded because it is an incomplete NAL if it
|
|
||||||
// is the last.
|
|
||||||
|
|
||||||
// Will be sent to the decoder, as a packet belonging to a subsequent frame
|
|
||||||
// has arrived.
|
|
||||||
frame_out = DecodeIncompleteFrame();
|
|
||||||
EXPECT_TRUE(frame_out != NULL);
|
|
||||||
jitter_buffer_->ReleaseFrame(frame_out);
|
|
||||||
|
|
||||||
// Test that a frame can include an empty packet.
|
|
||||||
seq_num_++;
|
|
||||||
timestamp_ += 33 * 90;
|
|
||||||
|
|
||||||
packet_->seqNum = seq_num_;
|
|
||||||
packet_->timestamp = timestamp_;
|
|
||||||
packet_->frameType = kVideoFrameKey;
|
|
||||||
packet_->is_first_packet_in_frame = true;
|
|
||||||
packet_->completeNALU = kNaluComplete;
|
|
||||||
packet_->markerBit = false;
|
|
||||||
|
|
||||||
EXPECT_EQ(kDecodableSession,
|
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
|
||||||
|
|
||||||
seq_num_++;
|
|
||||||
emptypacket.seqNum = seq_num_;
|
|
||||||
emptypacket.timestamp = timestamp_;
|
|
||||||
emptypacket.frameType = kVideoFrameKey;
|
|
||||||
emptypacket.is_first_packet_in_frame = true;
|
|
||||||
emptypacket.completeNALU = kNaluComplete;
|
|
||||||
emptypacket.markerBit = true;
|
|
||||||
EXPECT_EQ(kCompleteSession,
|
|
||||||
jitter_buffer_->InsertPacket(emptypacket, &retransmitted));
|
|
||||||
|
|
||||||
frame_out = DecodeCompleteFrame();
|
|
||||||
// Only last NALU is complete
|
|
||||||
CheckOutFrame(frame_out, packet_->sizeBytes, false);
|
|
||||||
jitter_buffer_->ReleaseFrame(frame_out);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(TestBasicJitterBuffer, NextFrameWhenIncomplete) {
|
TEST_F(TestBasicJitterBuffer, NextFrameWhenIncomplete) {
|
||||||
// Test that a we cannot get incomplete frames from the JB if we haven't
|
// Test that a we cannot get incomplete frames from the JB if we haven't
|
||||||
// received the marker bit, unless we have received a packet from a later
|
// received the marker bit, unless we have received a packet from a later
|
||||||
// timestamp.
|
// timestamp.
|
||||||
jitter_buffer_->SetDecodeErrorMode(kWithErrors);
|
|
||||||
// Start with a complete key frame - insert and decode.
|
// Start with a complete key frame - insert and decode.
|
||||||
packet_->frameType = kVideoFrameKey;
|
packet_->frameType = kVideoFrameKey;
|
||||||
packet_->is_first_packet_in_frame = true;
|
packet_->is_first_packet_in_frame = true;
|
||||||
@ -2248,22 +1662,15 @@ TEST_F(TestBasicJitterBuffer, NextFrameWhenIncomplete) {
|
|||||||
packet_->is_first_packet_in_frame = false;
|
packet_->is_first_packet_in_frame = false;
|
||||||
packet_->markerBit = false;
|
packet_->markerBit = false;
|
||||||
|
|
||||||
EXPECT_EQ(kDecodableSession,
|
EXPECT_EQ(kIncomplete,
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
||||||
|
|
||||||
frame_out = DecodeIncompleteFrame();
|
|
||||||
EXPECT_TRUE(frame_out == NULL);
|
|
||||||
|
|
||||||
packet_->seqNum += 2;
|
packet_->seqNum += 2;
|
||||||
packet_->timestamp += 33 * 90;
|
packet_->timestamp += 33 * 90;
|
||||||
packet_->is_first_packet_in_frame = true;
|
packet_->is_first_packet_in_frame = true;
|
||||||
|
|
||||||
EXPECT_EQ(kDecodableSession,
|
EXPECT_EQ(kIncomplete,
|
||||||
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
jitter_buffer_->InsertPacket(*packet_, &retransmitted));
|
||||||
|
|
||||||
frame_out = DecodeIncompleteFrame();
|
|
||||||
CheckOutFrame(frame_out, packet_->sizeBytes, false);
|
|
||||||
jitter_buffer_->ReleaseFrame(frame_out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestRunningJitterBuffer, Full) {
|
TEST_F(TestRunningJitterBuffer, Full) {
|
||||||
@ -2433,7 +1840,6 @@ TEST_F(TestJitterBufferNack, NackTooOldPackets) {
|
|||||||
EXPECT_GE(InsertFrame(kVideoFrameDelta), kNoError);
|
EXPECT_GE(InsertFrame(kVideoFrameDelta), kNoError);
|
||||||
// Waiting for a key frame.
|
// Waiting for a key frame.
|
||||||
EXPECT_FALSE(DecodeCompleteFrame());
|
EXPECT_FALSE(DecodeCompleteFrame());
|
||||||
EXPECT_FALSE(DecodeIncompleteFrame());
|
|
||||||
|
|
||||||
// The next complete continuous frame isn't a key frame, but we're waiting
|
// The next complete continuous frame isn't a key frame, but we're waiting
|
||||||
// for one.
|
// for one.
|
||||||
@ -2489,7 +1895,6 @@ TEST_F(TestJitterBufferNack, NackListFull) {
|
|||||||
// The next complete continuous frame isn't a key frame, but we're waiting
|
// The next complete continuous frame isn't a key frame, but we're waiting
|
||||||
// for one.
|
// for one.
|
||||||
EXPECT_FALSE(DecodeCompleteFrame());
|
EXPECT_FALSE(DecodeCompleteFrame());
|
||||||
EXPECT_FALSE(DecodeIncompleteFrame());
|
|
||||||
EXPECT_GE(InsertFrame(kVideoFrameKey), kNoError);
|
EXPECT_GE(InsertFrame(kVideoFrameKey), kNoError);
|
||||||
// Skipping ahead to the key frame.
|
// Skipping ahead to the key frame.
|
||||||
EXPECT_TRUE(DecodeCompleteFrame());
|
EXPECT_TRUE(DecodeCompleteFrame());
|
||||||
@ -2593,10 +1998,9 @@ TEST_F(TestJitterBufferNack, UseNackToRecoverFirstKeyFrameSecondInQueue) {
|
|||||||
|
|
||||||
TEST_F(TestJitterBufferNack, NormalOperation) {
|
TEST_F(TestJitterBufferNack, NormalOperation) {
|
||||||
EXPECT_EQ(kNack, jitter_buffer_->nack_mode());
|
EXPECT_EQ(kNack, jitter_buffer_->nack_mode());
|
||||||
jitter_buffer_->SetDecodeErrorMode(kWithErrors);
|
|
||||||
|
|
||||||
EXPECT_GE(InsertFrame(kVideoFrameKey), kNoError);
|
EXPECT_GE(InsertFrame(kVideoFrameKey), kNoError);
|
||||||
EXPECT_TRUE(DecodeIncompleteFrame());
|
EXPECT_TRUE(DecodeCompleteFrame());
|
||||||
|
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
// | 1 | 2 | .. | 8 | 9 | x | 11 | 12 | .. | 19 | x | 21 | .. | 100 |
|
// | 1 | 2 | .. | 8 | 9 | x | 11 | 12 | .. | 19 | x | 21 | .. | 100 |
|
||||||
@ -2604,20 +2008,19 @@ TEST_F(TestJitterBufferNack, NormalOperation) {
|
|||||||
stream_generator_->GenerateFrame(kVideoFrameKey, 100, 0,
|
stream_generator_->GenerateFrame(kVideoFrameKey, 100, 0,
|
||||||
clock_->TimeInMilliseconds());
|
clock_->TimeInMilliseconds());
|
||||||
clock_->AdvanceTimeMilliseconds(kDefaultFramePeriodMs);
|
clock_->AdvanceTimeMilliseconds(kDefaultFramePeriodMs);
|
||||||
EXPECT_EQ(kDecodableSession, InsertPacketAndPop(0));
|
EXPECT_EQ(kIncomplete, InsertPacketAndPop(0));
|
||||||
// Verify that the frame is incomplete.
|
// Verify that the frame is incomplete.
|
||||||
EXPECT_FALSE(DecodeCompleteFrame());
|
EXPECT_FALSE(DecodeCompleteFrame());
|
||||||
while (stream_generator_->PacketsRemaining() > 1) {
|
while (stream_generator_->PacketsRemaining() > 1) {
|
||||||
if (stream_generator_->NextSequenceNumber() % 10 != 0) {
|
if (stream_generator_->NextSequenceNumber() % 10 != 0) {
|
||||||
EXPECT_EQ(kDecodableSession, InsertPacketAndPop(0));
|
EXPECT_EQ(kIncomplete, InsertPacketAndPop(0));
|
||||||
} else {
|
} else {
|
||||||
stream_generator_->NextPacket(NULL); // Drop packet
|
stream_generator_->NextPacket(NULL); // Drop packet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPECT_EQ(kDecodableSession, InsertPacketAndPop(0));
|
EXPECT_EQ(kIncomplete, InsertPacketAndPop(0));
|
||||||
EXPECT_EQ(0, stream_generator_->PacketsRemaining());
|
EXPECT_EQ(0, stream_generator_->PacketsRemaining());
|
||||||
EXPECT_FALSE(DecodeCompleteFrame());
|
EXPECT_FALSE(DecodeCompleteFrame());
|
||||||
EXPECT_FALSE(DecodeIncompleteFrame());
|
|
||||||
bool request_key_frame = false;
|
bool request_key_frame = false;
|
||||||
|
|
||||||
// Verify the NACK list.
|
// Verify the NACK list.
|
||||||
|
|||||||
@ -140,8 +140,7 @@ VCMEncodedFrame* VCMReceiver::FrameForDecoding(uint16_t max_wait_time_ms,
|
|||||||
min_playout_delay_ms = found_frame->EncodedImage().playout_delay_.min_ms;
|
min_playout_delay_ms = found_frame->EncodedImage().playout_delay_.min_ms;
|
||||||
max_playout_delay_ms = found_frame->EncodedImage().playout_delay_.max_ms;
|
max_playout_delay_ms = found_frame->EncodedImage().playout_delay_.max_ms;
|
||||||
} else {
|
} else {
|
||||||
if (!jitter_buffer_.NextMaybeIncompleteTimestamp(&frame_timestamp))
|
return nullptr;
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (min_playout_delay_ms >= 0)
|
if (min_playout_delay_ms >= 0)
|
||||||
@ -260,14 +259,6 @@ std::vector<uint16_t> VCMReceiver::NackList(bool* request_key_frame) {
|
|||||||
return jitter_buffer_.GetNackList(request_key_frame);
|
return jitter_buffer_.GetNackList(request_key_frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VCMReceiver::SetDecodeErrorMode(VCMDecodeErrorMode decode_error_mode) {
|
|
||||||
jitter_buffer_.SetDecodeErrorMode(decode_error_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
VCMDecodeErrorMode VCMReceiver::DecodeErrorMode() const {
|
|
||||||
return jitter_buffer_.decode_error_mode();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VCMReceiver::RegisterStatsCallback(
|
void VCMReceiver::RegisterStatsCallback(
|
||||||
VCMReceiveStatisticsCallback* callback) {
|
VCMReceiveStatisticsCallback* callback) {
|
||||||
jitter_buffer_.RegisterStatsCallback(callback);
|
jitter_buffer_.RegisterStatsCallback(callback);
|
||||||
|
|||||||
@ -79,10 +79,6 @@ class VCMReceiver {
|
|||||||
VCMNackMode NackMode() const;
|
VCMNackMode NackMode() const;
|
||||||
std::vector<uint16_t> NackList(bool* request_key_frame);
|
std::vector<uint16_t> NackList(bool* request_key_frame);
|
||||||
|
|
||||||
// Decoding with errors.
|
|
||||||
void SetDecodeErrorMode(VCMDecodeErrorMode decode_error_mode);
|
|
||||||
VCMDecodeErrorMode DecodeErrorMode() const;
|
|
||||||
|
|
||||||
void RegisterStatsCallback(VCMReceiveStatisticsCallback* callback);
|
void RegisterStatsCallback(VCMReceiveStatisticsCallback* callback);
|
||||||
|
|
||||||
void TriggerDecoderShutdown();
|
void TriggerDecoderShutdown();
|
||||||
|
|||||||
@ -36,7 +36,6 @@ uint16_t BufferToUWord16(const uint8_t* dataBuffer) {
|
|||||||
|
|
||||||
VCMSessionInfo::VCMSessionInfo()
|
VCMSessionInfo::VCMSessionInfo()
|
||||||
: complete_(false),
|
: complete_(false),
|
||||||
decodable_(false),
|
|
||||||
frame_type_(kVideoFrameDelta),
|
frame_type_(kVideoFrameDelta),
|
||||||
packets_(),
|
packets_(),
|
||||||
empty_seq_num_low_(-1),
|
empty_seq_num_low_(-1),
|
||||||
@ -167,7 +166,6 @@ void VCMSessionInfo::SetGofInfo(const GofInfoVP9& gof_info, size_t idx) {
|
|||||||
|
|
||||||
void VCMSessionInfo::Reset() {
|
void VCMSessionInfo::Reset() {
|
||||||
complete_ = false;
|
complete_ = false;
|
||||||
decodable_ = false;
|
|
||||||
frame_type_ = kVideoFrameDelta;
|
frame_type_ = kVideoFrameDelta;
|
||||||
packets_.clear();
|
packets_.clear();
|
||||||
empty_seq_num_low_ = -1;
|
empty_seq_num_low_ = -1;
|
||||||
@ -291,37 +289,10 @@ void VCMSessionInfo::UpdateCompleteSession() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VCMSessionInfo::UpdateDecodableSession(const FrameData& frame_data) {
|
|
||||||
// Irrelevant if session is already complete or decodable
|
|
||||||
if (complete_ || decodable_)
|
|
||||||
return;
|
|
||||||
// TODO(agalusza): Account for bursty loss.
|
|
||||||
// TODO(agalusza): Refine these values to better approximate optimal ones.
|
|
||||||
// Do not decode frames if the RTT is lower than this.
|
|
||||||
const int64_t kRttThreshold = 100;
|
|
||||||
// Do not decode frames if the number of packets is between these two
|
|
||||||
// thresholds.
|
|
||||||
const float kLowPacketPercentageThreshold = 0.2f;
|
|
||||||
const float kHighPacketPercentageThreshold = 0.8f;
|
|
||||||
if (frame_data.rtt_ms < kRttThreshold || frame_type_ == kVideoFrameKey ||
|
|
||||||
!HaveFirstPacket() ||
|
|
||||||
(NumPackets() <= kHighPacketPercentageThreshold *
|
|
||||||
frame_data.rolling_average_packets_per_frame &&
|
|
||||||
NumPackets() > kLowPacketPercentageThreshold *
|
|
||||||
frame_data.rolling_average_packets_per_frame))
|
|
||||||
return;
|
|
||||||
|
|
||||||
decodable_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VCMSessionInfo::complete() const {
|
bool VCMSessionInfo::complete() const {
|
||||||
return complete_;
|
return complete_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VCMSessionInfo::decodable() const {
|
|
||||||
return decodable_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the end of the NAL unit which the packet pointed to by |packet_it|
|
// Find the end of the NAL unit which the packet pointed to by |packet_it|
|
||||||
// belongs to. Returns an iterator to the last packet of the frame if the end
|
// belongs to. Returns an iterator to the last packet of the frame if the end
|
||||||
// of the NAL unit wasn't found.
|
// of the NAL unit wasn't found.
|
||||||
@ -448,7 +419,6 @@ bool VCMSessionInfo::HaveLastPacket() const {
|
|||||||
|
|
||||||
int VCMSessionInfo::InsertPacket(const VCMPacket& packet,
|
int VCMSessionInfo::InsertPacket(const VCMPacket& packet,
|
||||||
uint8_t* frame_buffer,
|
uint8_t* frame_buffer,
|
||||||
VCMDecodeErrorMode decode_error_mode,
|
|
||||||
const FrameData& frame_data) {
|
const FrameData& frame_data) {
|
||||||
if (packet.frameType == kEmptyFrame) {
|
if (packet.frameType == kEmptyFrame) {
|
||||||
// Update sequence number of an empty packet.
|
// Update sequence number of an empty packet.
|
||||||
@ -526,10 +496,7 @@ int VCMSessionInfo::InsertPacket(const VCMPacket& packet,
|
|||||||
|
|
||||||
size_t returnLength = InsertBuffer(frame_buffer, packet_list_it);
|
size_t returnLength = InsertBuffer(frame_buffer, packet_list_it);
|
||||||
UpdateCompleteSession();
|
UpdateCompleteSession();
|
||||||
if (decode_error_mode == kWithErrors)
|
|
||||||
decodable_ = true;
|
|
||||||
else if (decode_error_mode == kSelectiveErrors)
|
|
||||||
UpdateDecodableSession(frame_data);
|
|
||||||
return static_cast<int>(returnLength);
|
return static_cast<int>(returnLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -40,10 +40,8 @@ class VCMSessionInfo {
|
|||||||
void Reset();
|
void Reset();
|
||||||
int InsertPacket(const VCMPacket& packet,
|
int InsertPacket(const VCMPacket& packet,
|
||||||
uint8_t* frame_buffer,
|
uint8_t* frame_buffer,
|
||||||
VCMDecodeErrorMode enable_decodable_state,
|
|
||||||
const FrameData& frame_data);
|
const FrameData& frame_data);
|
||||||
bool complete() const;
|
bool complete() const;
|
||||||
bool decodable() const;
|
|
||||||
|
|
||||||
// Makes the frame decodable. I.e., only contain decodable NALUs. All
|
// Makes the frame decodable. I.e., only contain decodable NALUs. All
|
||||||
// non-decodable NALUs will be deleted and packets will be moved to in
|
// non-decodable NALUs will be deleted and packets will be moved to in
|
||||||
@ -104,26 +102,7 @@ class VCMSessionInfo {
|
|||||||
size_t DeletePacketData(PacketIterator start, PacketIterator end);
|
size_t DeletePacketData(PacketIterator start, PacketIterator end);
|
||||||
void UpdateCompleteSession();
|
void UpdateCompleteSession();
|
||||||
|
|
||||||
// When enabled, determine if session is decodable, i.e. incomplete but
|
|
||||||
// would be sent to the decoder.
|
|
||||||
// Note: definition assumes random loss.
|
|
||||||
// A frame is defined to be decodable when:
|
|
||||||
// Round trip time is higher than threshold
|
|
||||||
// It is not a key frame
|
|
||||||
// It has the first packet: In VP8 the first packet contains all or part of
|
|
||||||
// the first partition, which consists of the most relevant information for
|
|
||||||
// decoding.
|
|
||||||
// Either more than the upper threshold of the average number of packets per
|
|
||||||
// frame is present
|
|
||||||
// or less than the lower threshold of the average number of packets per
|
|
||||||
// frame is present: suggests a small frame. Such a frame is unlikely
|
|
||||||
// to contain many motion vectors, so having the first packet will
|
|
||||||
// likely suffice. Once we have more than the lower threshold of the
|
|
||||||
// frame, we know that the frame is medium or large-sized.
|
|
||||||
void UpdateDecodableSession(const FrameData& frame_data);
|
|
||||||
|
|
||||||
bool complete_;
|
bool complete_;
|
||||||
bool decodable_;
|
|
||||||
webrtc::FrameType frame_type_;
|
webrtc::FrameType frame_type_;
|
||||||
// Packets in this frame.
|
// Packets in this frame.
|
||||||
PacketList packets_;
|
PacketList packets_;
|
||||||
|
|||||||
@ -118,18 +118,16 @@ TEST_F(TestSessionInfo, TestSimpleAPIs) {
|
|||||||
packet_.sizeBytes = packet_buffer_size();
|
packet_.sizeBytes = packet_buffer_size();
|
||||||
packet_.frameType = kVideoFrameKey;
|
packet_.frameType = kVideoFrameKey;
|
||||||
FillPacket(0);
|
FillPacket(0);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
EXPECT_FALSE(session_.HaveLastPacket());
|
EXPECT_FALSE(session_.HaveLastPacket());
|
||||||
EXPECT_EQ(kVideoFrameKey, session_.FrameType());
|
EXPECT_EQ(kVideoFrameKey, session_.FrameType());
|
||||||
|
|
||||||
packet_.is_first_packet_in_frame = false;
|
packet_.is_first_packet_in_frame = false;
|
||||||
packet_.markerBit = true;
|
packet_.markerBit = true;
|
||||||
packet_.seqNum += 1;
|
packet_.seqNum += 1;
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
EXPECT_TRUE(session_.HaveLastPacket());
|
EXPECT_TRUE(session_.HaveLastPacket());
|
||||||
EXPECT_EQ(packet_.seqNum, session_.HighSequenceNumber());
|
EXPECT_EQ(packet_.seqNum, session_.HighSequenceNumber());
|
||||||
EXPECT_EQ(0xFFFE, session_.LowSequenceNumber());
|
EXPECT_EQ(0xFFFE, session_.LowSequenceNumber());
|
||||||
@ -141,8 +139,7 @@ TEST_F(TestSessionInfo, TestSimpleAPIs) {
|
|||||||
packet_.seqNum = 2;
|
packet_.seqNum = 2;
|
||||||
packet_.sizeBytes = 0;
|
packet_.sizeBytes = 0;
|
||||||
packet_.frameType = kEmptyFrame;
|
packet_.frameType = kEmptyFrame;
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(0, session_.InsertPacket(packet_, frame_buffer_, frame_data));
|
||||||
0, session_.InsertPacket(packet_, frame_buffer_, kNoErrors, frame_data));
|
|
||||||
EXPECT_EQ(packet_.seqNum, session_.HighSequenceNumber());
|
EXPECT_EQ(packet_.seqNum, session_.HighSequenceNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,25 +148,22 @@ TEST_F(TestSessionInfo, NormalOperation) {
|
|||||||
packet_.is_first_packet_in_frame = true;
|
packet_.is_first_packet_in_frame = true;
|
||||||
packet_.markerBit = false;
|
packet_.markerBit = false;
|
||||||
FillPacket(0);
|
FillPacket(0);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
|
|
||||||
packet_.is_first_packet_in_frame = false;
|
packet_.is_first_packet_in_frame = false;
|
||||||
for (int i = 1; i < 9; ++i) {
|
for (int i = 1; i < 9; ++i) {
|
||||||
packet_.seqNum += 1;
|
packet_.seqNum += 1;
|
||||||
FillPacket(i);
|
FillPacket(i);
|
||||||
ASSERT_EQ(packet_buffer_size(),
|
ASSERT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(
|
packet_, frame_buffer_, frame_data)));
|
||||||
packet_, frame_buffer_, kNoErrors, frame_data)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
packet_.seqNum += 1;
|
packet_.seqNum += 1;
|
||||||
packet_.markerBit = true;
|
packet_.markerBit = true;
|
||||||
FillPacket(9);
|
FillPacket(9);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
|
|
||||||
EXPECT_EQ(10 * packet_buffer_size(), session_.SessionLength());
|
EXPECT_EQ(10 * packet_buffer_size(), session_.SessionLength());
|
||||||
for (int i = 0; i < 10; ++i) {
|
for (int i = 0; i < 10; ++i) {
|
||||||
@ -178,77 +172,24 @@ TEST_F(TestSessionInfo, NormalOperation) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestSessionInfo, ErrorsEqualDecodableState) {
|
|
||||||
packet_.seqNum = 0xFFFF;
|
|
||||||
packet_.is_first_packet_in_frame = false;
|
|
||||||
packet_.markerBit = false;
|
|
||||||
FillPacket(3);
|
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
|
||||||
static_cast<size_t>(session_.InsertPacket(
|
|
||||||
packet_, frame_buffer_, kWithErrors, frame_data)));
|
|
||||||
EXPECT_TRUE(session_.decodable());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(TestSessionInfo, SelectiveDecodableState) {
|
|
||||||
packet_.seqNum = 0xFFFF;
|
|
||||||
packet_.is_first_packet_in_frame = false;
|
|
||||||
packet_.markerBit = false;
|
|
||||||
FillPacket(1);
|
|
||||||
frame_data.rolling_average_packets_per_frame = 11;
|
|
||||||
frame_data.rtt_ms = 150;
|
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
|
||||||
static_cast<size_t>(session_.InsertPacket(
|
|
||||||
packet_, frame_buffer_, kSelectiveErrors, frame_data)));
|
|
||||||
EXPECT_FALSE(session_.decodable());
|
|
||||||
|
|
||||||
packet_.seqNum -= 1;
|
|
||||||
FillPacket(0);
|
|
||||||
packet_.is_first_packet_in_frame = true;
|
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
|
||||||
static_cast<size_t>(session_.InsertPacket(
|
|
||||||
packet_, frame_buffer_, kSelectiveErrors, frame_data)));
|
|
||||||
EXPECT_TRUE(session_.decodable());
|
|
||||||
|
|
||||||
packet_.is_first_packet_in_frame = false;
|
|
||||||
packet_.seqNum += 1;
|
|
||||||
for (int i = 2; i < 8; ++i) {
|
|
||||||
packet_.seqNum += 1;
|
|
||||||
FillPacket(i);
|
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
|
||||||
static_cast<size_t>(session_.InsertPacket(
|
|
||||||
packet_, frame_buffer_, kSelectiveErrors, frame_data)));
|
|
||||||
EXPECT_TRUE(session_.decodable());
|
|
||||||
}
|
|
||||||
|
|
||||||
packet_.seqNum += 1;
|
|
||||||
FillPacket(8);
|
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
|
||||||
static_cast<size_t>(session_.InsertPacket(
|
|
||||||
packet_, frame_buffer_, kSelectiveErrors, frame_data)));
|
|
||||||
EXPECT_TRUE(session_.decodable());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(TestSessionInfo, OutOfBoundsPackets1PacketFrame) {
|
TEST_F(TestSessionInfo, OutOfBoundsPackets1PacketFrame) {
|
||||||
packet_.seqNum = 0x0001;
|
packet_.seqNum = 0x0001;
|
||||||
packet_.is_first_packet_in_frame = true;
|
packet_.is_first_packet_in_frame = true;
|
||||||
packet_.markerBit = true;
|
packet_.markerBit = true;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
|
|
||||||
packet_.seqNum = 0x0004;
|
packet_.seqNum = 0x0004;
|
||||||
packet_.is_first_packet_in_frame = true;
|
packet_.is_first_packet_in_frame = true;
|
||||||
packet_.markerBit = true;
|
packet_.markerBit = true;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(-3, session_.InsertPacket(packet_, frame_buffer_, frame_data));
|
||||||
-3, session_.InsertPacket(packet_, frame_buffer_, kNoErrors, frame_data));
|
|
||||||
packet_.seqNum = 0x0000;
|
packet_.seqNum = 0x0000;
|
||||||
packet_.is_first_packet_in_frame = false;
|
packet_.is_first_packet_in_frame = false;
|
||||||
packet_.markerBit = false;
|
packet_.markerBit = false;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(-3, session_.InsertPacket(packet_, frame_buffer_, frame_data));
|
||||||
-3, session_.InsertPacket(packet_, frame_buffer_, kNoErrors, frame_data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestSessionInfo, SetMarkerBitOnce) {
|
TEST_F(TestSessionInfo, SetMarkerBitOnce) {
|
||||||
@ -256,15 +197,13 @@ TEST_F(TestSessionInfo, SetMarkerBitOnce) {
|
|||||||
packet_.is_first_packet_in_frame = false;
|
packet_.is_first_packet_in_frame = false;
|
||||||
packet_.markerBit = true;
|
packet_.markerBit = true;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
++packet_.seqNum;
|
++packet_.seqNum;
|
||||||
packet_.is_first_packet_in_frame = true;
|
packet_.is_first_packet_in_frame = true;
|
||||||
packet_.markerBit = true;
|
packet_.markerBit = true;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(-3, session_.InsertPacket(packet_, frame_buffer_, frame_data));
|
||||||
-3, session_.InsertPacket(packet_, frame_buffer_, kNoErrors, frame_data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestSessionInfo, OutOfBoundsPacketsBase) {
|
TEST_F(TestSessionInfo, OutOfBoundsPacketsBase) {
|
||||||
@ -273,29 +212,25 @@ TEST_F(TestSessionInfo, OutOfBoundsPacketsBase) {
|
|||||||
packet_.is_first_packet_in_frame = true;
|
packet_.is_first_packet_in_frame = true;
|
||||||
packet_.markerBit = false;
|
packet_.markerBit = false;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
// Insert an older packet with a first packet set.
|
// Insert an older packet with a first packet set.
|
||||||
packet_.seqNum = 0x0004;
|
packet_.seqNum = 0x0004;
|
||||||
packet_.is_first_packet_in_frame = true;
|
packet_.is_first_packet_in_frame = true;
|
||||||
packet_.markerBit = true;
|
packet_.markerBit = true;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(-3, session_.InsertPacket(packet_, frame_buffer_, frame_data));
|
||||||
-3, session_.InsertPacket(packet_, frame_buffer_, kNoErrors, frame_data));
|
|
||||||
packet_.seqNum = 0x0006;
|
packet_.seqNum = 0x0006;
|
||||||
packet_.is_first_packet_in_frame = true;
|
packet_.is_first_packet_in_frame = true;
|
||||||
packet_.markerBit = true;
|
packet_.markerBit = true;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
packet_.seqNum = 0x0008;
|
packet_.seqNum = 0x0008;
|
||||||
packet_.is_first_packet_in_frame = false;
|
packet_.is_first_packet_in_frame = false;
|
||||||
packet_.markerBit = true;
|
packet_.markerBit = true;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(-3, session_.InsertPacket(packet_, frame_buffer_, frame_data));
|
||||||
-3, session_.InsertPacket(packet_, frame_buffer_, kNoErrors, frame_data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestSessionInfo, OutOfBoundsPacketsWrap) {
|
TEST_F(TestSessionInfo, OutOfBoundsPacketsWrap) {
|
||||||
@ -303,36 +238,31 @@ TEST_F(TestSessionInfo, OutOfBoundsPacketsWrap) {
|
|||||||
packet_.is_first_packet_in_frame = true;
|
packet_.is_first_packet_in_frame = true;
|
||||||
packet_.markerBit = false;
|
packet_.markerBit = false;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
|
|
||||||
packet_.seqNum = 0x0004;
|
packet_.seqNum = 0x0004;
|
||||||
packet_.is_first_packet_in_frame = false;
|
packet_.is_first_packet_in_frame = false;
|
||||||
packet_.markerBit = true;
|
packet_.markerBit = true;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
packet_.seqNum = 0x0002;
|
packet_.seqNum = 0x0002;
|
||||||
packet_.is_first_packet_in_frame = false;
|
packet_.is_first_packet_in_frame = false;
|
||||||
packet_.markerBit = false;
|
packet_.markerBit = false;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
ASSERT_EQ(packet_buffer_size(),
|
ASSERT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
packet_.seqNum = 0xFFF0;
|
packet_.seqNum = 0xFFF0;
|
||||||
packet_.is_first_packet_in_frame = false;
|
packet_.is_first_packet_in_frame = false;
|
||||||
packet_.markerBit = false;
|
packet_.markerBit = false;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(-3, session_.InsertPacket(packet_, frame_buffer_, frame_data));
|
||||||
-3, session_.InsertPacket(packet_, frame_buffer_, kNoErrors, frame_data));
|
|
||||||
packet_.seqNum = 0x0006;
|
packet_.seqNum = 0x0006;
|
||||||
packet_.is_first_packet_in_frame = false;
|
packet_.is_first_packet_in_frame = false;
|
||||||
packet_.markerBit = false;
|
packet_.markerBit = false;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(-3, session_.InsertPacket(packet_, frame_buffer_, frame_data));
|
||||||
-3, session_.InsertPacket(packet_, frame_buffer_, kNoErrors, frame_data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestSessionInfo, OutOfBoundsOutOfOrder) {
|
TEST_F(TestSessionInfo, OutOfBoundsOutOfOrder) {
|
||||||
@ -342,44 +272,38 @@ TEST_F(TestSessionInfo, OutOfBoundsOutOfOrder) {
|
|||||||
packet_.is_first_packet_in_frame = false;
|
packet_.is_first_packet_in_frame = false;
|
||||||
packet_.markerBit = false;
|
packet_.markerBit = false;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
// Insert an older packet with a first packet set.
|
// Insert an older packet with a first packet set.
|
||||||
packet_.seqNum = 0x0005;
|
packet_.seqNum = 0x0005;
|
||||||
packet_.is_first_packet_in_frame = true;
|
packet_.is_first_packet_in_frame = true;
|
||||||
packet_.markerBit = false;
|
packet_.markerBit = false;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
packet_.seqNum = 0x0004;
|
packet_.seqNum = 0x0004;
|
||||||
packet_.is_first_packet_in_frame = false;
|
packet_.is_first_packet_in_frame = false;
|
||||||
packet_.markerBit = false;
|
packet_.markerBit = false;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(-3, session_.InsertPacket(packet_, frame_buffer_, frame_data));
|
||||||
-3, session_.InsertPacket(packet_, frame_buffer_, kNoErrors, frame_data));
|
|
||||||
packet_.seqNum = 0x0010;
|
packet_.seqNum = 0x0010;
|
||||||
packet_.is_first_packet_in_frame = false;
|
packet_.is_first_packet_in_frame = false;
|
||||||
packet_.markerBit = false;
|
packet_.markerBit = false;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
packet_.seqNum = 0x0008;
|
packet_.seqNum = 0x0008;
|
||||||
packet_.is_first_packet_in_frame = false;
|
packet_.is_first_packet_in_frame = false;
|
||||||
packet_.markerBit = true;
|
packet_.markerBit = true;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
|
|
||||||
packet_.seqNum = 0x0009;
|
packet_.seqNum = 0x0009;
|
||||||
packet_.is_first_packet_in_frame = false;
|
packet_.is_first_packet_in_frame = false;
|
||||||
packet_.markerBit = false;
|
packet_.markerBit = false;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(-3, session_.InsertPacket(packet_, frame_buffer_, frame_data));
|
||||||
-3, session_.InsertPacket(packet_, frame_buffer_, kNoErrors, frame_data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestNalUnits, OnlyReceivedEmptyPacket) {
|
TEST_F(TestNalUnits, OnlyReceivedEmptyPacket) {
|
||||||
@ -389,8 +313,7 @@ TEST_F(TestNalUnits, OnlyReceivedEmptyPacket) {
|
|||||||
packet_.sizeBytes = 0;
|
packet_.sizeBytes = 0;
|
||||||
packet_.seqNum = 0;
|
packet_.seqNum = 0;
|
||||||
packet_.markerBit = false;
|
packet_.markerBit = false;
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(0, session_.InsertPacket(packet_, frame_buffer_, frame_data));
|
||||||
0, session_.InsertPacket(packet_, frame_buffer_, kNoErrors, frame_data));
|
|
||||||
|
|
||||||
EXPECT_EQ(0U, session_.MakeDecodable());
|
EXPECT_EQ(0U, session_.MakeDecodable());
|
||||||
EXPECT_EQ(0U, session_.SessionLength());
|
EXPECT_EQ(0U, session_.SessionLength());
|
||||||
@ -402,18 +325,16 @@ TEST_F(TestNalUnits, OneIsolatedNaluLoss) {
|
|||||||
packet_.seqNum = 0;
|
packet_.seqNum = 0;
|
||||||
packet_.markerBit = false;
|
packet_.markerBit = false;
|
||||||
FillPacket(0);
|
FillPacket(0);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
|
|
||||||
packet_.is_first_packet_in_frame = false;
|
packet_.is_first_packet_in_frame = false;
|
||||||
packet_.completeNALU = kNaluComplete;
|
packet_.completeNALU = kNaluComplete;
|
||||||
packet_.seqNum += 2;
|
packet_.seqNum += 2;
|
||||||
packet_.markerBit = true;
|
packet_.markerBit = true;
|
||||||
FillPacket(2);
|
FillPacket(2);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
|
|
||||||
EXPECT_EQ(0U, session_.MakeDecodable());
|
EXPECT_EQ(0U, session_.MakeDecodable());
|
||||||
EXPECT_EQ(2 * packet_buffer_size(), session_.SessionLength());
|
EXPECT_EQ(2 * packet_buffer_size(), session_.SessionLength());
|
||||||
@ -429,18 +350,16 @@ TEST_F(TestNalUnits, LossInMiddleOfNalu) {
|
|||||||
packet_.seqNum = 0;
|
packet_.seqNum = 0;
|
||||||
packet_.markerBit = false;
|
packet_.markerBit = false;
|
||||||
FillPacket(0);
|
FillPacket(0);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
|
|
||||||
packet_.is_first_packet_in_frame = false;
|
packet_.is_first_packet_in_frame = false;
|
||||||
packet_.completeNALU = kNaluEnd;
|
packet_.completeNALU = kNaluEnd;
|
||||||
packet_.seqNum += 2;
|
packet_.seqNum += 2;
|
||||||
packet_.markerBit = true;
|
packet_.markerBit = true;
|
||||||
FillPacket(2);
|
FillPacket(2);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
|
|
||||||
EXPECT_EQ(packet_buffer_size(), session_.MakeDecodable());
|
EXPECT_EQ(packet_buffer_size(), session_.MakeDecodable());
|
||||||
EXPECT_EQ(packet_buffer_size(), session_.SessionLength());
|
EXPECT_EQ(packet_buffer_size(), session_.SessionLength());
|
||||||
@ -454,18 +373,16 @@ TEST_F(TestNalUnits, StartAndEndOfLastNalUnitLost) {
|
|||||||
packet_.seqNum = 0;
|
packet_.seqNum = 0;
|
||||||
packet_.markerBit = false;
|
packet_.markerBit = false;
|
||||||
FillPacket(0);
|
FillPacket(0);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
|
|
||||||
packet_.is_first_packet_in_frame = false;
|
packet_.is_first_packet_in_frame = false;
|
||||||
packet_.completeNALU = kNaluIncomplete;
|
packet_.completeNALU = kNaluIncomplete;
|
||||||
packet_.seqNum += 2;
|
packet_.seqNum += 2;
|
||||||
packet_.markerBit = false;
|
packet_.markerBit = false;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
|
|
||||||
EXPECT_EQ(packet_buffer_size(), session_.MakeDecodable());
|
EXPECT_EQ(packet_buffer_size(), session_.MakeDecodable());
|
||||||
EXPECT_EQ(packet_buffer_size(), session_.SessionLength());
|
EXPECT_EQ(packet_buffer_size(), session_.SessionLength());
|
||||||
@ -480,27 +397,24 @@ TEST_F(TestNalUnits, ReorderWrapNoLoss) {
|
|||||||
packet_.seqNum += 1;
|
packet_.seqNum += 1;
|
||||||
packet_.markerBit = false;
|
packet_.markerBit = false;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
|
|
||||||
packet_.is_first_packet_in_frame = true;
|
packet_.is_first_packet_in_frame = true;
|
||||||
packet_.completeNALU = kNaluComplete;
|
packet_.completeNALU = kNaluComplete;
|
||||||
packet_.seqNum -= 1;
|
packet_.seqNum -= 1;
|
||||||
packet_.markerBit = false;
|
packet_.markerBit = false;
|
||||||
FillPacket(0);
|
FillPacket(0);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
|
|
||||||
packet_.is_first_packet_in_frame = false;
|
packet_.is_first_packet_in_frame = false;
|
||||||
packet_.completeNALU = kNaluEnd;
|
packet_.completeNALU = kNaluEnd;
|
||||||
packet_.seqNum += 2;
|
packet_.seqNum += 2;
|
||||||
packet_.markerBit = true;
|
packet_.markerBit = true;
|
||||||
FillPacket(2);
|
FillPacket(2);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
|
|
||||||
EXPECT_EQ(0U, session_.MakeDecodable());
|
EXPECT_EQ(0U, session_.MakeDecodable());
|
||||||
EXPECT_EQ(3 * packet_buffer_size(), session_.SessionLength());
|
EXPECT_EQ(3 * packet_buffer_size(), session_.SessionLength());
|
||||||
@ -514,18 +428,16 @@ TEST_F(TestNalUnits, WrapLosses) {
|
|||||||
packet_.completeNALU = kNaluIncomplete;
|
packet_.completeNALU = kNaluIncomplete;
|
||||||
packet_.markerBit = false;
|
packet_.markerBit = false;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
|
|
||||||
packet_.is_first_packet_in_frame = false;
|
packet_.is_first_packet_in_frame = false;
|
||||||
packet_.completeNALU = kNaluEnd;
|
packet_.completeNALU = kNaluEnd;
|
||||||
packet_.seqNum += 2;
|
packet_.seqNum += 2;
|
||||||
packet_.markerBit = true;
|
packet_.markerBit = true;
|
||||||
FillPacket(2);
|
FillPacket(2);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
|
|
||||||
EXPECT_EQ(2 * packet_buffer_size(), session_.MakeDecodable());
|
EXPECT_EQ(2 * packet_buffer_size(), session_.MakeDecodable());
|
||||||
EXPECT_EQ(0U, session_.SessionLength());
|
EXPECT_EQ(0U, session_.SessionLength());
|
||||||
@ -539,18 +451,16 @@ TEST_F(TestNalUnits, ReorderWrapLosses) {
|
|||||||
packet_.seqNum += 2;
|
packet_.seqNum += 2;
|
||||||
packet_.markerBit = true;
|
packet_.markerBit = true;
|
||||||
FillPacket(2);
|
FillPacket(2);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
|
|
||||||
packet_.seqNum -= 2;
|
packet_.seqNum -= 2;
|
||||||
packet_.is_first_packet_in_frame = false;
|
packet_.is_first_packet_in_frame = false;
|
||||||
packet_.completeNALU = kNaluIncomplete;
|
packet_.completeNALU = kNaluIncomplete;
|
||||||
packet_.markerBit = false;
|
packet_.markerBit = false;
|
||||||
FillPacket(1);
|
FillPacket(1);
|
||||||
EXPECT_EQ(packet_buffer_size(),
|
EXPECT_EQ(packet_buffer_size(), static_cast<size_t>(session_.InsertPacket(
|
||||||
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
|
packet_, frame_buffer_, frame_data)));
|
||||||
kNoErrors, frame_data)));
|
|
||||||
|
|
||||||
EXPECT_EQ(2 * packet_buffer_size(), session_.MakeDecodable());
|
EXPECT_EQ(2 * packet_buffer_size(), session_.MakeDecodable());
|
||||||
EXPECT_EQ(0U, session_.SessionLength());
|
EXPECT_EQ(0U, session_.SessionLength());
|
||||||
|
|||||||
@ -99,9 +99,8 @@ class VideoCodingModuleImpl : public VideoCodingModule {
|
|||||||
return receiver_.IncomingPacket(incomingPayload, payloadLength, rtpInfo);
|
return receiver_.IncomingPacket(incomingPayload, payloadLength, rtpInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SetReceiverRobustnessMode(ReceiverRobustness robustnessMode,
|
int SetReceiverRobustnessMode(ReceiverRobustness robustnessMode) override {
|
||||||
VCMDecodeErrorMode errorMode) override {
|
return receiver_.SetReceiverRobustnessMode(robustnessMode);
|
||||||
return receiver_.SetReceiverRobustnessMode(robustnessMode, errorMode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetNackSettings(size_t max_nack_list_size,
|
void SetNackSettings(size_t max_nack_list_size,
|
||||||
|
|||||||
@ -131,15 +131,12 @@ class VideoReceiver : public Module {
|
|||||||
|
|
||||||
// DEPRECATED.
|
// DEPRECATED.
|
||||||
int SetReceiverRobustnessMode(
|
int SetReceiverRobustnessMode(
|
||||||
VideoCodingModule::ReceiverRobustness robustnessMode,
|
VideoCodingModule::ReceiverRobustness robustnessMode);
|
||||||
VCMDecodeErrorMode errorMode);
|
|
||||||
|
|
||||||
void SetNackSettings(size_t max_nack_list_size,
|
void SetNackSettings(size_t max_nack_list_size,
|
||||||
int max_packet_age_to_nack,
|
int max_packet_age_to_nack,
|
||||||
int max_incomplete_time_ms);
|
int max_incomplete_time_ms);
|
||||||
|
|
||||||
void SetDecodeErrorMode(VCMDecodeErrorMode decode_error_mode);
|
|
||||||
|
|
||||||
int32_t SetReceiveChannelParameters(int64_t rtt);
|
int32_t SetReceiveChannelParameters(int64_t rtt);
|
||||||
int32_t SetVideoProtection(VCMVideoProtection videoProtection, bool enable);
|
int32_t SetVideoProtection(VCMVideoProtection videoProtection, bool enable);
|
||||||
|
|
||||||
|
|||||||
@ -158,8 +158,6 @@ int32_t VideoReceiver::SetReceiveChannelParameters(int64_t rtt) {
|
|||||||
// between the protection method and decoding with or without errors.
|
// between the protection method and decoding with or without errors.
|
||||||
int32_t VideoReceiver::SetVideoProtection(VCMVideoProtection videoProtection,
|
int32_t VideoReceiver::SetVideoProtection(VCMVideoProtection videoProtection,
|
||||||
bool enable) {
|
bool enable) {
|
||||||
// By default, do not decode with errors.
|
|
||||||
_receiver.SetDecodeErrorMode(kNoErrors);
|
|
||||||
switch (videoProtection) {
|
switch (videoProtection) {
|
||||||
case kProtectionNack: {
|
case kProtectionNack: {
|
||||||
RTC_DCHECK(enable);
|
RTC_DCHECK(enable);
|
||||||
@ -171,7 +169,6 @@ int32_t VideoReceiver::SetVideoProtection(VCMVideoProtection videoProtection,
|
|||||||
RTC_DCHECK(enable);
|
RTC_DCHECK(enable);
|
||||||
_receiver.SetNackMode(kNack, media_optimization::kLowRttNackMs,
|
_receiver.SetNackMode(kNack, media_optimization::kLowRttNackMs,
|
||||||
media_optimization::kMaxRttDelayThreshold);
|
media_optimization::kMaxRttDelayThreshold);
|
||||||
_receiver.SetDecodeErrorMode(kNoErrors);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case kProtectionFEC:
|
case kProtectionFEC:
|
||||||
@ -179,7 +176,6 @@ int32_t VideoReceiver::SetVideoProtection(VCMVideoProtection videoProtection,
|
|||||||
// No receiver-side protection.
|
// No receiver-side protection.
|
||||||
RTC_DCHECK(enable);
|
RTC_DCHECK(enable);
|
||||||
_receiver.SetNackMode(kNoNack, -1, -1);
|
_receiver.SetNackMode(kNoNack, -1, -1);
|
||||||
_receiver.SetDecodeErrorMode(kWithErrors);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return VCM_OK;
|
return VCM_OK;
|
||||||
@ -439,10 +435,8 @@ int32_t VideoReceiver::Delay() const {
|
|||||||
return _timing->TargetVideoDelay();
|
return _timing->TargetVideoDelay();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only used by VCMRobustnessTest.
|
|
||||||
int VideoReceiver::SetReceiverRobustnessMode(
|
int VideoReceiver::SetReceiverRobustnessMode(
|
||||||
VideoCodingModule::ReceiverRobustness robustnessMode,
|
VideoCodingModule::ReceiverRobustness robustnessMode) {
|
||||||
VCMDecodeErrorMode decode_error_mode) {
|
|
||||||
RTC_DCHECK_RUN_ON(&construction_thread_checker_);
|
RTC_DCHECK_RUN_ON(&construction_thread_checker_);
|
||||||
RTC_DCHECK(!IsDecoderThreadRunning());
|
RTC_DCHECK(!IsDecoderThreadRunning());
|
||||||
switch (robustnessMode) {
|
switch (robustnessMode) {
|
||||||
@ -457,16 +451,9 @@ int VideoReceiver::SetReceiverRobustnessMode(
|
|||||||
RTC_NOTREACHED();
|
RTC_NOTREACHED();
|
||||||
return VCM_PARAMETER_ERROR;
|
return VCM_PARAMETER_ERROR;
|
||||||
}
|
}
|
||||||
_receiver.SetDecodeErrorMode(decode_error_mode);
|
|
||||||
return VCM_OK;
|
return VCM_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoReceiver::SetDecodeErrorMode(VCMDecodeErrorMode decode_error_mode) {
|
|
||||||
RTC_DCHECK_RUN_ON(&construction_thread_checker_);
|
|
||||||
RTC_DCHECK(!IsDecoderThreadRunning());
|
|
||||||
_receiver.SetDecodeErrorMode(decode_error_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VideoReceiver::SetNackSettings(size_t max_nack_list_size,
|
void VideoReceiver::SetNackSettings(size_t max_nack_list_size,
|
||||||
int max_packet_age_to_nack,
|
int max_packet_age_to_nack,
|
||||||
int max_incomplete_time_ms) {
|
int max_incomplete_time_ms) {
|
||||||
|
|||||||
@ -41,9 +41,7 @@ VideoStreamDecoder::VideoStreamDecoder(
|
|||||||
enable_nack ? (enable_fec ? kProtectionNackFEC : kProtectionNack)
|
enable_nack ? (enable_fec ? kProtectionNackFEC : kProtectionNack)
|
||||||
: kProtectionNone;
|
: kProtectionNone;
|
||||||
|
|
||||||
VCMDecodeErrorMode decode_error_mode = enable_nack ? kNoErrors : kWithErrors;
|
|
||||||
video_receiver_->SetVideoProtection(video_protection, true);
|
video_receiver_->SetVideoProtection(video_protection, true);
|
||||||
video_receiver_->SetDecodeErrorMode(decode_error_mode);
|
|
||||||
VCMPacketRequestCallback* packet_request_callback =
|
VCMPacketRequestCallback* packet_request_callback =
|
||||||
enable_nack ? vcm_packet_request_callback : nullptr;
|
enable_nack ? vcm_packet_request_callback : nullptr;
|
||||||
video_receiver_->RegisterPacketRequestCallback(packet_request_callback);
|
video_receiver_->RegisterPacketRequestCallback(packet_request_callback);
|
||||||
|
|||||||
Reference in New Issue
Block a user