Chromium Code Reviews| Index: webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc |
| diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc |
| index 14bbff781c50bfc3fc4ebff9b43da808043298ac..8cbab24003a330c94924dd6a5bf5abda59a19a6a 100644 |
| --- a/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc |
| +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc |
| @@ -19,13 +19,16 @@ |
| #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" |
| #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" |
| #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h" |
| +#include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h" |
|
danilchap
2017/09/04 09:03:04
where is it used?
sprang_webrtc
2017/09/04 11:09:28
It's not in this revision. Removed.
|
| #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h" |
| #include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h" |
| #include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" |
| #include "webrtc/modules/rtp_rtcp/source/rtp_sender.h" |
| #include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h" |
| #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" |
| +#include "webrtc/rtc_base/arraysize.h" |
| #include "webrtc/rtc_base/buffer.h" |
| +#include "webrtc/rtc_base/ptr_util.h" |
| #include "webrtc/rtc_base/rate_limiter.h" |
| #include "webrtc/test/field_trial.h" |
| #include "webrtc/test/gmock.h" |
| @@ -55,6 +58,7 @@ const size_t kMaxPaddingSize = 224u; |
| const int kVideoRotationExtensionId = 5; |
| const size_t kGenericHeaderLength = 1; |
| const uint8_t kPayloadData[] = {47, 11, 32, 93, 89}; |
| +const int64_t kDefaultExpectedRetransmissionTimeMs = 125; |
| using ::testing::_; |
| using ::testing::ElementsAreArray; |
| @@ -238,7 +242,8 @@ class RtpSenderTest : public ::testing::TestWithParam<bool> { |
| EXPECT_TRUE(rtp_sender_->SendOutgoingData( |
| kVideoFrameKey, kPayloadType, kTimestamp, kCaptureTimeMs, kPayloadData, |
| - sizeof(kPayloadData), nullptr, nullptr, nullptr)); |
| + sizeof(kPayloadData), nullptr, nullptr, nullptr, |
| + kDefaultExpectedRetransmissionTimeMs)); |
| } |
| }; |
| @@ -249,15 +254,36 @@ class RtpSenderTestWithoutPacer : public RtpSenderTest { |
| void SetUp() override { SetUpRtpSender(false); } |
| }; |
| +class TestRtpSenderVideo : public RTPSenderVideo { |
| + public: |
| + TestRtpSenderVideo(Clock* clock, |
| + RTPSender* rtp_sender, |
| + FlexfecSender* flexfec_sender) |
| + : RTPSenderVideo(clock, rtp_sender, flexfec_sender) {} |
| + ~TestRtpSenderVideo() override {} |
| + |
| + StorageType GetStorageType(const RTPVideoHeader& header, |
| + int32_t retransmission_settings, |
| + int64_t expected_retransmission_time, |
| + FrameType frame_type) { |
| + auto packetizer = rtc::WrapUnique(RtpPacketizer::Create( |
|
danilchap
2017/09/04 09:03:04
since packetizer is no longer needed, it might cle
sprang_webrtc
2017/09/04 11:09:28
It's still needed in order to access the protected
danilchap
2017/09/04 11:19:10
missed that reason. Yep, keep it then, or make Sto
|
| + header.codec, kMaxPacketLength, 0, &header.codecHeader, frame_type)); |
| + |
| + return RTPSenderVideo::GetStorageType( |
| + GetTemporalId(header), retransmission_settings, packetizer.get(), |
| + expected_retransmission_time); |
| + } |
| +}; |
| + |
| class RtpSenderVideoTest : public RtpSenderTest { |
| protected: |
| void SetUp() override { |
| // TODO(pbos): Set up to use pacer. |
| SetUpRtpSender(false); |
| rtp_sender_video_.reset( |
| - new RTPSenderVideo(&fake_clock_, rtp_sender_.get(), nullptr)); |
| + new TestRtpSenderVideo(&fake_clock_, rtp_sender_.get(), nullptr)); |
| } |
| - std::unique_ptr<RTPSenderVideo> rtp_sender_video_; |
| + std::unique_ptr<TestRtpSenderVideo> rtp_sender_video_; |
| }; |
| TEST_P(RtpSenderTestWithoutPacer, AllocatePacketSetCsrc) { |
| @@ -861,9 +887,9 @@ TEST_P(RtpSenderTestWithoutPacer, SendGenericVideo) { |
| uint8_t payload[] = {47, 11, 32, 93, 89}; |
| // Send keyframe |
| - ASSERT_TRUE(rtp_sender_->SendOutgoingData(kVideoFrameKey, payload_type, 1234, |
| - 4321, payload, sizeof(payload), |
| - nullptr, nullptr, nullptr)); |
| + ASSERT_TRUE(rtp_sender_->SendOutgoingData( |
| + kVideoFrameKey, payload_type, 1234, 4321, payload, sizeof(payload), |
| + nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs)); |
| auto sent_payload = transport_.last_sent_packet().payload(); |
| uint8_t generic_header = sent_payload[0]; |
| @@ -878,7 +904,7 @@ TEST_P(RtpSenderTestWithoutPacer, SendGenericVideo) { |
| ASSERT_TRUE(rtp_sender_->SendOutgoingData( |
| kVideoFrameDelta, payload_type, 1234, 4321, payload, sizeof(payload), |
| - nullptr, nullptr, nullptr)); |
| + nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs)); |
| sent_payload = transport_.last_sent_packet().payload(); |
| generic_header = sent_payload[0]; |
| @@ -998,7 +1024,8 @@ TEST_P(RtpSenderTest, NoFlexfecForTimingFrames) { |
| video_header.video_timing.flags = TimingFrameFlags::kTriggeredByTimer; |
| EXPECT_TRUE(rtp_sender_->SendOutgoingData( |
| kVideoFrameKey, kPayloadType, kTimestamp, kCaptureTimeMs, kPayloadData, |
| - sizeof(kPayloadData), nullptr, &video_header, nullptr)); |
| + sizeof(kPayloadData), nullptr, &video_header, nullptr, |
| + kDefaultExpectedRetransmissionTimeMs)); |
| EXPECT_CALL(mock_rtc_event_log_, |
| LogRtpHeader(PacketDirection::kOutgoingPacket, _, _, _)) |
| @@ -1023,7 +1050,8 @@ TEST_P(RtpSenderTest, NoFlexfecForTimingFrames) { |
| video_header.video_timing.flags = TimingFrameFlags::kInvalid; |
| EXPECT_TRUE(rtp_sender_->SendOutgoingData( |
| kVideoFrameKey, kPayloadType, kTimestamp + 1, kCaptureTimeMs + 1, |
| - kPayloadData, sizeof(kPayloadData), nullptr, &video_header, nullptr)); |
| + kPayloadData, sizeof(kPayloadData), nullptr, &video_header, nullptr, |
| + kDefaultExpectedRetransmissionTimeMs)); |
| EXPECT_CALL(mock_rtc_event_log_, |
| LogRtpHeader(PacketDirection::kOutgoingPacket, _, _, _)) |
| @@ -1168,9 +1196,9 @@ TEST_P(RtpSenderTest, FrameCountCallbacks) { |
| EXPECT_CALL(mock_paced_sender_, InsertPacket(_, _, _, _, _, _)) |
| .Times(::testing::AtLeast(2)); |
| - ASSERT_TRUE(rtp_sender_->SendOutgoingData(kVideoFrameKey, payload_type, 1234, |
| - 4321, payload, sizeof(payload), |
| - nullptr, nullptr, nullptr)); |
| + ASSERT_TRUE(rtp_sender_->SendOutgoingData( |
| + kVideoFrameKey, payload_type, 1234, 4321, payload, sizeof(payload), |
| + nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs)); |
| EXPECT_EQ(1U, callback.num_calls_); |
| EXPECT_EQ(ssrc, callback.ssrc_); |
| @@ -1179,7 +1207,7 @@ TEST_P(RtpSenderTest, FrameCountCallbacks) { |
| ASSERT_TRUE(rtp_sender_->SendOutgoingData( |
| kVideoFrameDelta, payload_type, 1234, 4321, payload, sizeof(payload), |
| - nullptr, nullptr, nullptr)); |
| + nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs)); |
| EXPECT_EQ(2U, callback.num_calls_); |
| EXPECT_EQ(ssrc, callback.ssrc_); |
| @@ -1245,7 +1273,7 @@ TEST_P(RtpSenderTest, BitrateCallbacks) { |
| for (uint32_t i = 0; i < kNumPackets; ++i) { |
| ASSERT_TRUE(rtp_sender_->SendOutgoingData( |
| kVideoFrameKey, payload_type, 1234, 4321, payload, sizeof(payload), |
| - nullptr, nullptr, nullptr)); |
| + nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs)); |
| fake_clock_.AdvanceTimeMilliseconds(kPacketInterval); |
| } |
| @@ -1327,8 +1355,8 @@ TEST_P(RtpSenderTestWithoutPacer, StreamDataCountersCallbacks) { |
| // Send a frame. |
| ASSERT_TRUE(rtp_sender_->SendOutgoingData( |
| - kVideoFrameKey, payload_type, 1234, 4321, payload, |
| - sizeof(payload), nullptr, nullptr, nullptr)); |
| + kVideoFrameKey, payload_type, 1234, 4321, payload, sizeof(payload), |
| + nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs)); |
| StreamDataCounters expected; |
| expected.transmitted.payload_bytes = 6; |
| expected.transmitted.header_bytes = 12; |
| @@ -1369,8 +1397,8 @@ TEST_P(RtpSenderTestWithoutPacer, StreamDataCountersCallbacks) { |
| fec_params.max_fec_frames = 1; |
| rtp_sender_->SetFecParameters(fec_params, fec_params); |
| ASSERT_TRUE(rtp_sender_->SendOutgoingData( |
| - kVideoFrameDelta, payload_type, 1234, 4321, payload, |
| - sizeof(payload), nullptr, nullptr, nullptr)); |
| + kVideoFrameDelta, payload_type, 1234, 4321, payload, sizeof(payload), |
| + nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs)); |
| expected.transmitted.payload_bytes = 40; |
| expected.transmitted.header_bytes = 60; |
| expected.transmitted.packets = 5; |
| @@ -1388,8 +1416,8 @@ TEST_P(RtpSenderAudioTest, SendAudio) { |
| uint8_t payload[] = {47, 11, 32, 93, 89}; |
| ASSERT_TRUE(rtp_sender_->SendOutgoingData( |
| - kAudioFrameCN, payload_type, 1234, 4321, payload, |
| - sizeof(payload), nullptr, nullptr, nullptr)); |
| + kAudioFrameCN, payload_type, 1234, 4321, payload, sizeof(payload), |
| + nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs)); |
| auto sent_payload = transport_.last_sent_packet().payload(); |
| EXPECT_THAT(sent_payload, ElementsAreArray(payload)); |
| @@ -1407,8 +1435,8 @@ TEST_P(RtpSenderAudioTest, SendAudioWithAudioLevelExtension) { |
| uint8_t payload[] = {47, 11, 32, 93, 89}; |
| ASSERT_TRUE(rtp_sender_->SendOutgoingData( |
| - kAudioFrameCN, payload_type, 1234, 4321, payload, |
| - sizeof(payload), nullptr, nullptr, nullptr)); |
| + kAudioFrameCN, payload_type, 1234, 4321, payload, sizeof(payload), |
| + nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs)); |
| auto sent_payload = transport_.last_sent_packet().payload(); |
| EXPECT_THAT(sent_payload, ElementsAreArray(payload)); |
| @@ -1445,22 +1473,22 @@ TEST_P(RtpSenderAudioTest, CheckMarkerBitForTelephoneEvents) { |
| // During start, it takes the starting timestamp as last sent timestamp. |
| // The duration is calculated as the difference of current and last sent |
| // timestamp. So for first call it will skip since the duration is zero. |
| - ASSERT_TRUE(rtp_sender_->SendOutgoingData(kEmptyFrame, kPayloadType, |
| - capture_time_ms, 0, nullptr, 0, |
| - nullptr, nullptr, nullptr)); |
| + ASSERT_TRUE(rtp_sender_->SendOutgoingData( |
| + kEmptyFrame, kPayloadType, capture_time_ms, 0, nullptr, 0, nullptr, |
| + nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs)); |
| // DTMF Sample Length is (Frequency/1000) * Duration. |
| // So in this case, it is (8000/1000) * 500 = 4000. |
| // Sending it as two packets. |
| ASSERT_TRUE(rtp_sender_->SendOutgoingData( |
| - kEmptyFrame, kPayloadType, capture_time_ms + 2000, 0, |
| - nullptr, 0, nullptr, nullptr, nullptr)); |
| + kEmptyFrame, kPayloadType, capture_time_ms + 2000, 0, nullptr, 0, nullptr, |
| + nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs)); |
| // Marker Bit should be set to 1 for first packet. |
| EXPECT_TRUE(transport_.last_sent_packet().Marker()); |
| ASSERT_TRUE(rtp_sender_->SendOutgoingData( |
| - kEmptyFrame, kPayloadType, capture_time_ms + 4000, 0, |
| - nullptr, 0, nullptr, nullptr, nullptr)); |
| + kEmptyFrame, kPayloadType, capture_time_ms + 4000, 0, nullptr, 0, nullptr, |
| + nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs)); |
| // Marker Bit should be set to 0 for rest of the packets. |
| EXPECT_FALSE(transport_.last_sent_packet().Marker()); |
| } |
| @@ -1478,8 +1506,8 @@ TEST_P(RtpSenderTestWithoutPacer, BytesReportedCorrectly) { |
| uint8_t payload[] = {47, 11, 32, 93, 89}; |
| ASSERT_TRUE(rtp_sender_->SendOutgoingData( |
| - kVideoFrameKey, kPayloadType, 1234, 4321, payload, |
| - sizeof(payload), nullptr, nullptr, nullptr)); |
| + kVideoFrameKey, kPayloadType, 1234, 4321, payload, sizeof(payload), |
| + nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs)); |
| // Will send 2 full-size padding packets. |
| rtp_sender_->TimeToSendPadding(1, PacedPacketInfo()); |
| @@ -1553,7 +1581,7 @@ TEST_P(RtpSenderVideoTest, KeyFrameHasCVO) { |
| hdr.rotation = kVideoRotation_0; |
| rtp_sender_video_->SendVideo(kRtpVideoGeneric, kVideoFrameKey, kPayload, |
| kTimestamp, 0, kFrame, sizeof(kFrame), nullptr, |
| - &hdr); |
| + &hdr, kDefaultExpectedRetransmissionTimeMs); |
| VideoRotation rotation; |
| EXPECT_TRUE( |
| @@ -1579,7 +1607,8 @@ TEST_P(RtpSenderVideoTest, TimingFrameHasPacketizationTimstampSet) { |
| fake_clock_.AdvanceTimeMilliseconds(kPacketizationTimeMs); |
| rtp_sender_video_->SendVideo(kRtpVideoGeneric, kVideoFrameKey, kPayload, |
| kTimestamp, kCaptureTimestamp, kFrame, |
| - sizeof(kFrame), nullptr, &hdr); |
| + sizeof(kFrame), nullptr, &hdr, |
| + kDefaultExpectedRetransmissionTimeMs); |
| VideoSendTiming timing; |
| EXPECT_TRUE(transport_.last_sent_packet().GetExtension<VideoTimingExtension>( |
| &timing)); |
| @@ -1595,14 +1624,14 @@ TEST_P(RtpSenderVideoTest, DeltaFrameHasCVOWhenChanged) { |
| RTPVideoHeader hdr = {0}; |
| hdr.rotation = kVideoRotation_90; |
| - EXPECT_TRUE(rtp_sender_video_->SendVideo(kRtpVideoGeneric, kVideoFrameKey, |
| - kPayload, kTimestamp, 0, kFrame, |
| - sizeof(kFrame), nullptr, &hdr)); |
| + EXPECT_TRUE(rtp_sender_video_->SendVideo( |
| + kRtpVideoGeneric, kVideoFrameKey, kPayload, kTimestamp, 0, kFrame, |
| + sizeof(kFrame), nullptr, &hdr, kDefaultExpectedRetransmissionTimeMs)); |
| hdr.rotation = kVideoRotation_0; |
| - EXPECT_TRUE(rtp_sender_video_->SendVideo(kRtpVideoGeneric, kVideoFrameDelta, |
| - kPayload, kTimestamp + 1, 0, kFrame, |
| - sizeof(kFrame), nullptr, &hdr)); |
| + EXPECT_TRUE(rtp_sender_video_->SendVideo( |
| + kRtpVideoGeneric, kVideoFrameDelta, kPayload, kTimestamp + 1, 0, kFrame, |
| + sizeof(kFrame), nullptr, &hdr, kDefaultExpectedRetransmissionTimeMs)); |
| VideoRotation rotation; |
| EXPECT_TRUE( |
| @@ -1617,13 +1646,13 @@ TEST_P(RtpSenderVideoTest, DeltaFrameHasCVOWhenNonZero) { |
| RTPVideoHeader hdr = {0}; |
| hdr.rotation = kVideoRotation_90; |
| - EXPECT_TRUE(rtp_sender_video_->SendVideo(kRtpVideoGeneric, kVideoFrameKey, |
| - kPayload, kTimestamp, 0, kFrame, |
| - sizeof(kFrame), nullptr, &hdr)); |
| + EXPECT_TRUE(rtp_sender_video_->SendVideo( |
| + kRtpVideoGeneric, kVideoFrameKey, kPayload, kTimestamp, 0, kFrame, |
| + sizeof(kFrame), nullptr, &hdr, kDefaultExpectedRetransmissionTimeMs)); |
| - EXPECT_TRUE(rtp_sender_video_->SendVideo(kRtpVideoGeneric, kVideoFrameDelta, |
| - kPayload, kTimestamp + 1, 0, kFrame, |
| - sizeof(kFrame), nullptr, &hdr)); |
| + EXPECT_TRUE(rtp_sender_video_->SendVideo( |
| + kRtpVideoGeneric, kVideoFrameDelta, kPayload, kTimestamp + 1, 0, kFrame, |
| + sizeof(kFrame), nullptr, &hdr, kDefaultExpectedRetransmissionTimeMs)); |
| VideoRotation rotation; |
| EXPECT_TRUE( |
| @@ -1652,6 +1681,254 @@ TEST_P(RtpSenderVideoTest, SendVideoWithCameraAndFlipCVO) { |
| ConvertCVOByteToVideoRotation(flip_bit | camera_bit | 3)); |
| } |
| +TEST_P(RtpSenderVideoTest, RetransmissionTypesGeneric) { |
| + RTPVideoHeader header; |
| + header.codec = kRtpVideoGeneric; |
| + |
| + EXPECT_EQ(kDontRetransmit, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitOff, kDefaultExpectedRetransmissionTimeMs, |
| + kVideoFrameDelta)); |
| + EXPECT_EQ(kAllowRetransmission, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitBaseLayer, |
| + kDefaultExpectedRetransmissionTimeMs, kVideoFrameDelta)); |
| + EXPECT_EQ(kAllowRetransmission, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitHigherLayers, |
| + kDefaultExpectedRetransmissionTimeMs, kVideoFrameDelta)); |
| + EXPECT_EQ(kAllowRetransmission, |
| + rtp_sender_video_->GetStorageType( |
| + header, kConditionallyRetransmitHigherLayers, |
| + kDefaultExpectedRetransmissionTimeMs, kVideoFrameDelta)); |
| + EXPECT_EQ(kAllowRetransmission, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitAllPackets, |
| + kDefaultExpectedRetransmissionTimeMs, kVideoFrameDelta)); |
| +} |
| + |
| +TEST_P(RtpSenderVideoTest, RetransmissionTypesH264) { |
| + RTPVideoHeader header; |
| + header.codec = kRtpVideoH264; |
| + header.codecHeader.H264.packetization_mode = |
| + H264PacketizationMode::NonInterleaved; |
| + |
| + EXPECT_EQ(kDontRetransmit, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitOff, kDefaultExpectedRetransmissionTimeMs, |
| + kVideoFrameDelta)); |
| + EXPECT_EQ(kAllowRetransmission, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitBaseLayer, |
| + kDefaultExpectedRetransmissionTimeMs, kVideoFrameDelta)); |
| + EXPECT_EQ(kAllowRetransmission, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitHigherLayers, |
| + kDefaultExpectedRetransmissionTimeMs, kVideoFrameDelta)); |
| + EXPECT_EQ(kAllowRetransmission, |
| + rtp_sender_video_->GetStorageType( |
| + header, kConditionallyRetransmitHigherLayers, |
| + kDefaultExpectedRetransmissionTimeMs, kVideoFrameDelta)); |
| + EXPECT_EQ(kAllowRetransmission, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitAllPackets, |
| + kDefaultExpectedRetransmissionTimeMs, kVideoFrameDelta)); |
| +} |
| + |
| +TEST_P(RtpSenderVideoTest, RetransmissionTypesVP8BaseLayer) { |
| + RTPVideoHeader header; |
| + header.codec = kRtpVideoVp8; |
| + header.codecHeader.VP8.temporalIdx = 0; |
| + |
| + EXPECT_EQ(kDontRetransmit, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitOff, kDefaultExpectedRetransmissionTimeMs, |
| + kVideoFrameDelta)); |
| + EXPECT_EQ(kAllowRetransmission, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitBaseLayer, |
| + kDefaultExpectedRetransmissionTimeMs, kVideoFrameDelta)); |
| + EXPECT_EQ(kDontRetransmit, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitHigherLayers, |
| + kDefaultExpectedRetransmissionTimeMs, kVideoFrameDelta)); |
| + EXPECT_EQ(kAllowRetransmission, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitHigherLayers | kRetransmitBaseLayer, |
| + kDefaultExpectedRetransmissionTimeMs, kVideoFrameDelta)); |
| + EXPECT_EQ(kDontRetransmit, |
| + rtp_sender_video_->GetStorageType( |
| + header, kConditionallyRetransmitHigherLayers, |
| + kDefaultExpectedRetransmissionTimeMs, kVideoFrameDelta)); |
| + EXPECT_EQ( |
| + kAllowRetransmission, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitBaseLayer | kConditionallyRetransmitHigherLayers, |
| + kDefaultExpectedRetransmissionTimeMs, kVideoFrameDelta)); |
| + EXPECT_EQ(kAllowRetransmission, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitAllPackets, |
| + kDefaultExpectedRetransmissionTimeMs, kVideoFrameDelta)); |
| +} |
| + |
| +TEST_P(RtpSenderVideoTest, RetransmissionTypesVP8HigherLayers) { |
| + RTPVideoHeader header; |
| + header.codec = kRtpVideoVp8; |
| + |
| + for (int tid = 1; tid <= kMaxTemporalStreams; ++tid) { |
| + header.codecHeader.VP8.temporalIdx = tid; |
| + |
| + EXPECT_EQ(kDontRetransmit, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitOff, kDefaultExpectedRetransmissionTimeMs, |
| + kVideoFrameDelta)); |
| + EXPECT_EQ(kDontRetransmit, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitBaseLayer, |
| + kDefaultExpectedRetransmissionTimeMs, kVideoFrameDelta)); |
| + EXPECT_EQ(kAllowRetransmission, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitHigherLayers, |
| + kDefaultExpectedRetransmissionTimeMs, kVideoFrameDelta)); |
| + EXPECT_EQ(kAllowRetransmission, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitHigherLayers | kRetransmitBaseLayer, |
| + kDefaultExpectedRetransmissionTimeMs, kVideoFrameDelta)); |
| + EXPECT_EQ(kAllowRetransmission, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitAllPackets, |
| + kDefaultExpectedRetransmissionTimeMs, kVideoFrameDelta)); |
| + } |
| +} |
| + |
| +TEST_P(RtpSenderVideoTest, RetransmissionTypesVP9) { |
| + RTPVideoHeader header; |
| + header.codec = kRtpVideoVp9; |
| + |
| + for (int tid = 1; tid <= kMaxTemporalStreams; ++tid) { |
| + header.codecHeader.VP9.temporal_idx = tid; |
| + |
| + EXPECT_EQ(kDontRetransmit, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitOff, kDefaultExpectedRetransmissionTimeMs, |
| + kVideoFrameDelta)); |
| + EXPECT_EQ(kDontRetransmit, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitBaseLayer, |
| + kDefaultExpectedRetransmissionTimeMs, kVideoFrameDelta)); |
| + EXPECT_EQ(kAllowRetransmission, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitHigherLayers, |
| + kDefaultExpectedRetransmissionTimeMs, kVideoFrameDelta)); |
| + EXPECT_EQ(kAllowRetransmission, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitHigherLayers | kRetransmitBaseLayer, |
| + kDefaultExpectedRetransmissionTimeMs, kVideoFrameDelta)); |
| + EXPECT_EQ(kAllowRetransmission, |
| + rtp_sender_video_->GetStorageType( |
| + header, kRetransmitAllPackets, |
| + kDefaultExpectedRetransmissionTimeMs, kVideoFrameDelta)); |
| + } |
| +} |
| + |
| +TEST_P(RtpSenderVideoTest, ConditionalRetransmit) { |
| + const int64_t kFrameIntervalMs = 33; |
| + const int64_t kRttMs = (kFrameIntervalMs * 3) / 2; |
| + const uint8_t kSettings = |
| + kRetransmitBaseLayer | kConditionallyRetransmitHigherLayers; |
| + |
| + // Insert VP8 frames for all temporal layers, but stop before the final index. |
| + RTPVideoHeader header; |
| + header.codec = kRtpVideoVp8; |
| + |
| + // Fill averaging window to prevent rounding errors. |
| + constexpr int kNumRepetitions = |
| + (RTPSenderVideo::kTLRateWindowSizeMs + (kFrameIntervalMs / 2)) / |
| + kFrameIntervalMs; |
| + constexpr int kPattern[] = {0, 2, 1, 2}; |
| + for (size_t i = 0; i < arraysize(kPattern) * kNumRepetitions; ++i) { |
| + header.codecHeader.VP8.temporalIdx = kPattern[i % arraysize(kPattern)]; |
| + rtp_sender_video_->GetStorageType( |
| + header, kSettings, kRttMs, i == 0 ? kVideoFrameKey : kVideoFrameDelta); |
| + fake_clock_.AdvanceTimeMilliseconds(kFrameIntervalMs); |
| + } |
| + |
| + // Since we're at the start of the pattern, the next expected frame in TL0 is |
| + // right now. We will wait at most one expected retransmission time before |
| + // acknowledging that it did not arrive, which means this frame and the next |
| + // will not be retransmitted. |
| + header.codecHeader.VP8.temporalIdx = 1; |
| + EXPECT_EQ(StorageType::kDontRetransmit, |
| + rtp_sender_video_->GetStorageType(header, kSettings, kRttMs, |
| + kVideoFrameDelta)); |
| + fake_clock_.AdvanceTimeMilliseconds(kFrameIntervalMs); |
| + EXPECT_EQ(StorageType::kDontRetransmit, |
| + rtp_sender_video_->GetStorageType(header, kSettings, kRttMs, |
| + kVideoFrameDelta)); |
| + fake_clock_.AdvanceTimeMilliseconds(kFrameIntervalMs); |
| + |
| + // The TL0 frame did not arrive. So allow retransmission. |
| + EXPECT_EQ(StorageType::kAllowRetransmission, |
| + rtp_sender_video_->GetStorageType(header, kSettings, kRttMs, |
| + kVideoFrameDelta)); |
| + fake_clock_.AdvanceTimeMilliseconds(kFrameIntervalMs); |
| + |
| + // Insert a frame for TL2. We just had frame in TL1, so the next one there is |
| + // in three frames away. TL0 is still too far in the past. So, allow |
| + // retransmission. |
| + header.codecHeader.VP8.temporalIdx = 2; |
| + EXPECT_EQ(StorageType::kAllowRetransmission, |
| + rtp_sender_video_->GetStorageType(header, kSettings, kRttMs, |
| + kVideoFrameDelta)); |
| + fake_clock_.AdvanceTimeMilliseconds(kFrameIntervalMs); |
| + |
| + // Another TL2, next in TL1 is two frames away. Allow again. |
| + EXPECT_EQ(StorageType::kAllowRetransmission, |
| + rtp_sender_video_->GetStorageType(header, kSettings, kRttMs, |
| + kVideoFrameDelta)); |
| + fake_clock_.AdvanceTimeMilliseconds(kFrameIntervalMs); |
| + |
| + // Yet another TL2, next in TL1 is now only one frame away, so don't store |
| + // for retransmission. |
| + EXPECT_EQ(StorageType::kDontRetransmit, |
| + rtp_sender_video_->GetStorageType(header, kSettings, kRttMs, |
| + kVideoFrameDelta)); |
| +} |
| + |
| +TEST_P(RtpSenderVideoTest, ConditionalRetransmitLimit) { |
| + const int64_t kFrameIntervalMs = 200; |
| + const int64_t kRttMs = (kFrameIntervalMs * 3) / 2; |
| + const int32_t kSettings = |
| + kRetransmitBaseLayer | kConditionallyRetransmitHigherLayers; |
| + |
| + // Insert VP8 frames for all temporal layers, but stop before the final index. |
| + RTPVideoHeader header; |
| + header.codec = kRtpVideoVp8; |
| + |
| + // Fill averaging window to prevent rounding errors. |
| + constexpr int kNumRepetitions = |
| + (RTPSenderVideo::kTLRateWindowSizeMs + (kFrameIntervalMs / 2)) / |
| + kFrameIntervalMs; |
| + constexpr int kPattern[] = {0, 2, 2, 2}; |
| + for (size_t i = 0; i < arraysize(kPattern) * kNumRepetitions; ++i) { |
| + header.codecHeader.VP8.temporalIdx = kPattern[i % arraysize(kPattern)]; |
| + |
| + rtp_sender_video_->GetStorageType( |
| + header, kSettings, kRttMs, i == 0 ? kVideoFrameKey : kVideoFrameDelta); |
| + fake_clock_.AdvanceTimeMilliseconds(kFrameIntervalMs); |
| + } |
| + |
| + // Since we're at the start of the pattern, the next expected frame will be |
| + // right now in TL0. Put it in TL1 instead. Regular rules would dictate that |
| + // we don't store for retransmission because we expect a frame in a lower |
| + // layer, but that last frame in TL1 was a long time ago in absolute terms, |
| + // so allow retransmission anyway. |
| + header.codecHeader.VP8.temporalIdx = 1; |
| + EXPECT_EQ(StorageType::kAllowRetransmission, |
| + rtp_sender_video_->GetStorageType(header, kSettings, kRttMs, |
| + kVideoFrameDelta)); |
| +} |
| + |
| TEST_P(RtpSenderTest, OnOverheadChanged) { |
| MockOverheadObserver mock_overhead_observer; |
| rtp_sender_.reset( |