/* * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include #include "webrtc/base/array_view.h" #include "webrtc/call/flexfec_receive_stream_impl.h" #include "webrtc/modules/pacing/packet_router.h" #include "webrtc/modules/rtp_rtcp/include/flexfec_receiver.h" #include "webrtc/modules/rtp_rtcp/mocks/mock_recovered_packet_receiver.h" #include "webrtc/modules/rtp_rtcp/mocks/mock_rtcp_rtt_stats.h" #include "webrtc/modules/rtp_rtcp/source/byte_io.h" #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h" #include "webrtc/modules/utility/include/mock/mock_process_thread.h" #include "webrtc/test/gmock.h" #include "webrtc/test/gtest.h" #include "webrtc/test/mock_transport.h" namespace webrtc { namespace { constexpr uint8_t kFlexfecPlType = 118; constexpr uint8_t kFlexfecSsrc[] = {0x00, 0x00, 0x00, 0x01}; constexpr uint8_t kMediaSsrc[] = {0x00, 0x00, 0x00, 0x02}; FlexfecReceiveStream::Config CreateDefaultConfig( Transport* rtcp_send_transport) { FlexfecReceiveStream::Config config(rtcp_send_transport); config.payload_type = kFlexfecPlType; config.remote_ssrc = ByteReader::ReadBigEndian(kFlexfecSsrc); config.protected_media_ssrcs = { ByteReader::ReadBigEndian(kMediaSsrc)}; EXPECT_TRUE(config.IsCompleteAndEnabled()); return config; } RtpPacketReceived ParsePacket(rtc::ArrayView packet) { RtpPacketReceived parsed_packet(nullptr); EXPECT_TRUE(parsed_packet.Parse(packet)); return parsed_packet; } } // namespace TEST(FlexfecReceiveStreamConfigTest, IsCompleteAndEnabled) { MockTransport rtcp_send_transport; FlexfecReceiveStream::Config config(&rtcp_send_transport); config.local_ssrc = 18374743; config.rtcp_mode = RtcpMode::kCompound; config.transport_cc = true; config.rtp_header_extensions.emplace_back(TransportSequenceNumber::kUri, 7); EXPECT_FALSE(config.IsCompleteAndEnabled()); config.payload_type = 123; EXPECT_FALSE(config.IsCompleteAndEnabled()); config.remote_ssrc = 238423838; EXPECT_FALSE(config.IsCompleteAndEnabled()); config.protected_media_ssrcs.push_back(138989393); EXPECT_TRUE(config.IsCompleteAndEnabled()); config.protected_media_ssrcs.push_back(33423423); EXPECT_FALSE(config.IsCompleteAndEnabled()); } class FlexfecReceiveStreamTest : public ::testing::Test { protected: FlexfecReceiveStreamTest() : config_(CreateDefaultConfig(&rtcp_send_transport_)), receive_stream_(config_, &recovered_packet_receiver_, &rtt_stats_, &process_thread_) {} MockTransport rtcp_send_transport_; FlexfecReceiveStream::Config config_; MockRecoveredPacketReceiver recovered_packet_receiver_; MockRtcpRttStats rtt_stats_; MockProcessThread process_thread_; FlexfecReceiveStreamImpl receive_stream_; }; TEST_F(FlexfecReceiveStreamTest, ConstructDestruct) {} TEST_F(FlexfecReceiveStreamTest, StartStop) { receive_stream_.Start(); receive_stream_.Stop(); } // Create a FlexFEC packet that protects a single media packet and ensure // that the callback is called. Correctness of recovery is checked in the // FlexfecReceiver unit tests. TEST_F(FlexfecReceiveStreamTest, RecoversPacketWhenStarted) { constexpr uint8_t kFlexfecSeqNum[] = {0x00, 0x01}; constexpr uint8_t kFlexfecTs[] = {0x00, 0x11, 0x22, 0x33}; constexpr uint8_t kMediaPlType = 107; constexpr uint8_t kMediaSeqNum[] = {0x00, 0x02}; constexpr uint8_t kMediaTs[] = {0xaa, 0xbb, 0xcc, 0xdd}; // This packet mask protects a single media packet, i.e., the FlexFEC payload // is a copy of that media packet. When inserted in the FlexFEC pipeline, // it will thus trivially recover the lost media packet. constexpr uint8_t kKBit0 = 1 << 7; constexpr uint8_t kFlexfecPktMask[] = {kKBit0 | 0x00, 0x01}; constexpr uint8_t kPayloadLength[] = {0x00, 0x04}; constexpr uint8_t kSsrcCount = 1; constexpr uint8_t kReservedBits = 0x00; constexpr uint8_t kPayloadBits = 0x00; // clang-format off constexpr uint8_t kFlexfecPacket[] = { // RTP header. 0x80, kFlexfecPlType, kFlexfecSeqNum[0], kFlexfecSeqNum[1], kFlexfecTs[0], kFlexfecTs[1], kFlexfecTs[2], kFlexfecTs[3], kFlexfecSsrc[0], kFlexfecSsrc[1], kFlexfecSsrc[2], kFlexfecSsrc[3], // FlexFEC header. 0x00, kMediaPlType, kPayloadLength[0], kPayloadLength[1], kMediaTs[0], kMediaTs[1], kMediaTs[2], kMediaTs[3], kSsrcCount, kReservedBits, kReservedBits, kReservedBits, kMediaSsrc[0], kMediaSsrc[1], kMediaSsrc[2], kMediaSsrc[3], kMediaSeqNum[0], kMediaSeqNum[1], kFlexfecPktMask[0], kFlexfecPktMask[1], // FEC payload. kPayloadBits, kPayloadBits, kPayloadBits, kPayloadBits}; // clang-format on testing::StrictMock recovered_packet_receiver; FlexfecReceiveStreamImpl receive_stream(config_, &recovered_packet_receiver, &rtt_stats_, &process_thread_); // Do not call back before being started. receive_stream.OnRtpPacket(ParsePacket(kFlexfecPacket)); // Call back after being started. receive_stream.Start(); EXPECT_CALL( recovered_packet_receiver, OnRecoveredPacket(::testing::_, kRtpHeaderSize + kPayloadLength[1])); receive_stream.OnRtpPacket(ParsePacket(kFlexfecPacket)); } } // namespace webrtc