1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "call/flexfec_receive_stream.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <cstdint>
14*d9f75844SAndroid Build Coastguard Worker #include <memory>
15*d9f75844SAndroid Build Coastguard Worker #include <vector>
16*d9f75844SAndroid Build Coastguard Worker
17*d9f75844SAndroid Build Coastguard Worker #include "api/array_view.h"
18*d9f75844SAndroid Build Coastguard Worker #include "api/call/transport.h"
19*d9f75844SAndroid Build Coastguard Worker #include "api/rtp_headers.h"
20*d9f75844SAndroid Build Coastguard Worker #include "api/rtp_parameters.h"
21*d9f75844SAndroid Build Coastguard Worker #include "call/flexfec_receive_stream_impl.h"
22*d9f75844SAndroid Build Coastguard Worker #include "call/rtp_stream_receiver_controller.h"
23*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
24*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/mocks/mock_recovered_packet_receiver.h"
25*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/mocks/mock_rtcp_rtt_stats.h"
26*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/byte_io.h"
27*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
28*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/rtp_packet_received.h"
29*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/thread.h"
30*d9f75844SAndroid Build Coastguard Worker #include "test/gmock.h"
31*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
32*d9f75844SAndroid Build Coastguard Worker #include "test/mock_transport.h"
33*d9f75844SAndroid Build Coastguard Worker
34*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
35*d9f75844SAndroid Build Coastguard Worker
36*d9f75844SAndroid Build Coastguard Worker namespace {
37*d9f75844SAndroid Build Coastguard Worker
38*d9f75844SAndroid Build Coastguard Worker using ::testing::_;
39*d9f75844SAndroid Build Coastguard Worker
40*d9f75844SAndroid Build Coastguard Worker constexpr uint8_t kFlexfecPlType = 118;
41*d9f75844SAndroid Build Coastguard Worker constexpr uint8_t kFlexfecSsrc[] = {0x00, 0x00, 0x00, 0x01};
42*d9f75844SAndroid Build Coastguard Worker constexpr uint8_t kMediaSsrc[] = {0x00, 0x00, 0x00, 0x02};
43*d9f75844SAndroid Build Coastguard Worker
CreateDefaultConfig(Transport * rtcp_send_transport)44*d9f75844SAndroid Build Coastguard Worker FlexfecReceiveStream::Config CreateDefaultConfig(
45*d9f75844SAndroid Build Coastguard Worker Transport* rtcp_send_transport) {
46*d9f75844SAndroid Build Coastguard Worker FlexfecReceiveStream::Config config(rtcp_send_transport);
47*d9f75844SAndroid Build Coastguard Worker config.payload_type = kFlexfecPlType;
48*d9f75844SAndroid Build Coastguard Worker config.rtp.remote_ssrc = ByteReader<uint32_t>::ReadBigEndian(kFlexfecSsrc);
49*d9f75844SAndroid Build Coastguard Worker config.protected_media_ssrcs = {
50*d9f75844SAndroid Build Coastguard Worker ByteReader<uint32_t>::ReadBigEndian(kMediaSsrc)};
51*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(config.IsCompleteAndEnabled());
52*d9f75844SAndroid Build Coastguard Worker return config;
53*d9f75844SAndroid Build Coastguard Worker }
54*d9f75844SAndroid Build Coastguard Worker
ParsePacket(rtc::ArrayView<const uint8_t> packet)55*d9f75844SAndroid Build Coastguard Worker RtpPacketReceived ParsePacket(rtc::ArrayView<const uint8_t> packet) {
56*d9f75844SAndroid Build Coastguard Worker RtpPacketReceived parsed_packet(nullptr);
57*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(parsed_packet.Parse(packet));
58*d9f75844SAndroid Build Coastguard Worker return parsed_packet;
59*d9f75844SAndroid Build Coastguard Worker }
60*d9f75844SAndroid Build Coastguard Worker
61*d9f75844SAndroid Build Coastguard Worker } // namespace
62*d9f75844SAndroid Build Coastguard Worker
TEST(FlexfecReceiveStreamConfigTest,IsCompleteAndEnabled)63*d9f75844SAndroid Build Coastguard Worker TEST(FlexfecReceiveStreamConfigTest, IsCompleteAndEnabled) {
64*d9f75844SAndroid Build Coastguard Worker MockTransport rtcp_send_transport;
65*d9f75844SAndroid Build Coastguard Worker FlexfecReceiveStream::Config config(&rtcp_send_transport);
66*d9f75844SAndroid Build Coastguard Worker
67*d9f75844SAndroid Build Coastguard Worker config.rtp.local_ssrc = 18374743;
68*d9f75844SAndroid Build Coastguard Worker config.rtcp_mode = RtcpMode::kCompound;
69*d9f75844SAndroid Build Coastguard Worker config.rtp.transport_cc = true;
70*d9f75844SAndroid Build Coastguard Worker config.rtp.extensions.emplace_back(TransportSequenceNumber::Uri(), 7);
71*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(config.IsCompleteAndEnabled());
72*d9f75844SAndroid Build Coastguard Worker
73*d9f75844SAndroid Build Coastguard Worker config.payload_type = 123;
74*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(config.IsCompleteAndEnabled());
75*d9f75844SAndroid Build Coastguard Worker
76*d9f75844SAndroid Build Coastguard Worker config.rtp.remote_ssrc = 238423838;
77*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(config.IsCompleteAndEnabled());
78*d9f75844SAndroid Build Coastguard Worker
79*d9f75844SAndroid Build Coastguard Worker config.protected_media_ssrcs.push_back(138989393);
80*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(config.IsCompleteAndEnabled());
81*d9f75844SAndroid Build Coastguard Worker
82*d9f75844SAndroid Build Coastguard Worker config.protected_media_ssrcs.push_back(33423423);
83*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(config.IsCompleteAndEnabled());
84*d9f75844SAndroid Build Coastguard Worker }
85*d9f75844SAndroid Build Coastguard Worker
86*d9f75844SAndroid Build Coastguard Worker class FlexfecReceiveStreamTest : public ::testing::Test {
87*d9f75844SAndroid Build Coastguard Worker protected:
FlexfecReceiveStreamTest()88*d9f75844SAndroid Build Coastguard Worker FlexfecReceiveStreamTest()
89*d9f75844SAndroid Build Coastguard Worker : config_(CreateDefaultConfig(&rtcp_send_transport_)) {
90*d9f75844SAndroid Build Coastguard Worker receive_stream_ = std::make_unique<FlexfecReceiveStreamImpl>(
91*d9f75844SAndroid Build Coastguard Worker Clock::GetRealTimeClock(), config_, &recovered_packet_receiver_,
92*d9f75844SAndroid Build Coastguard Worker &rtt_stats_);
93*d9f75844SAndroid Build Coastguard Worker receive_stream_->RegisterWithTransport(&rtp_stream_receiver_controller_);
94*d9f75844SAndroid Build Coastguard Worker }
95*d9f75844SAndroid Build Coastguard Worker
~FlexfecReceiveStreamTest()96*d9f75844SAndroid Build Coastguard Worker ~FlexfecReceiveStreamTest() {
97*d9f75844SAndroid Build Coastguard Worker receive_stream_->UnregisterFromTransport();
98*d9f75844SAndroid Build Coastguard Worker }
99*d9f75844SAndroid Build Coastguard Worker
100*d9f75844SAndroid Build Coastguard Worker rtc::AutoThread main_thread_;
101*d9f75844SAndroid Build Coastguard Worker MockTransport rtcp_send_transport_;
102*d9f75844SAndroid Build Coastguard Worker FlexfecReceiveStream::Config config_;
103*d9f75844SAndroid Build Coastguard Worker MockRecoveredPacketReceiver recovered_packet_receiver_;
104*d9f75844SAndroid Build Coastguard Worker MockRtcpRttStats rtt_stats_;
105*d9f75844SAndroid Build Coastguard Worker RtpStreamReceiverController rtp_stream_receiver_controller_;
106*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<FlexfecReceiveStreamImpl> receive_stream_;
107*d9f75844SAndroid Build Coastguard Worker };
108*d9f75844SAndroid Build Coastguard Worker
TEST_F(FlexfecReceiveStreamTest,ConstructDestruct)109*d9f75844SAndroid Build Coastguard Worker TEST_F(FlexfecReceiveStreamTest, ConstructDestruct) {}
110*d9f75844SAndroid Build Coastguard Worker
111*d9f75844SAndroid Build Coastguard Worker // Create a FlexFEC packet that protects a single media packet and ensure
112*d9f75844SAndroid Build Coastguard Worker // that the callback is called. Correctness of recovery is checked in the
113*d9f75844SAndroid Build Coastguard Worker // FlexfecReceiver unit tests.
TEST_F(FlexfecReceiveStreamTest,RecoversPacket)114*d9f75844SAndroid Build Coastguard Worker TEST_F(FlexfecReceiveStreamTest, RecoversPacket) {
115*d9f75844SAndroid Build Coastguard Worker constexpr uint8_t kFlexfecSeqNum[] = {0x00, 0x01};
116*d9f75844SAndroid Build Coastguard Worker constexpr uint8_t kFlexfecTs[] = {0x00, 0x11, 0x22, 0x33};
117*d9f75844SAndroid Build Coastguard Worker constexpr uint8_t kMediaPlType = 107;
118*d9f75844SAndroid Build Coastguard Worker constexpr uint8_t kMediaSeqNum[] = {0x00, 0x02};
119*d9f75844SAndroid Build Coastguard Worker constexpr uint8_t kMediaTs[] = {0xaa, 0xbb, 0xcc, 0xdd};
120*d9f75844SAndroid Build Coastguard Worker
121*d9f75844SAndroid Build Coastguard Worker // This packet mask protects a single media packet, i.e., the FlexFEC payload
122*d9f75844SAndroid Build Coastguard Worker // is a copy of that media packet. When inserted in the FlexFEC pipeline,
123*d9f75844SAndroid Build Coastguard Worker // it will thus trivially recover the lost media packet.
124*d9f75844SAndroid Build Coastguard Worker constexpr uint8_t kKBit0 = 1 << 7;
125*d9f75844SAndroid Build Coastguard Worker constexpr uint8_t kFlexfecPktMask[] = {kKBit0 | 0x00, 0x01};
126*d9f75844SAndroid Build Coastguard Worker constexpr uint8_t kPayloadLength[] = {0x00, 0x04};
127*d9f75844SAndroid Build Coastguard Worker constexpr uint8_t kSsrcCount = 1;
128*d9f75844SAndroid Build Coastguard Worker constexpr uint8_t kReservedBits = 0x00;
129*d9f75844SAndroid Build Coastguard Worker constexpr uint8_t kPayloadBits = 0x00;
130*d9f75844SAndroid Build Coastguard Worker // clang-format off
131*d9f75844SAndroid Build Coastguard Worker constexpr uint8_t kFlexfecPacket[] = {
132*d9f75844SAndroid Build Coastguard Worker // RTP header.
133*d9f75844SAndroid Build Coastguard Worker 0x80, kFlexfecPlType, kFlexfecSeqNum[0], kFlexfecSeqNum[1],
134*d9f75844SAndroid Build Coastguard Worker kFlexfecTs[0], kFlexfecTs[1], kFlexfecTs[2], kFlexfecTs[3],
135*d9f75844SAndroid Build Coastguard Worker kFlexfecSsrc[0], kFlexfecSsrc[1], kFlexfecSsrc[2], kFlexfecSsrc[3],
136*d9f75844SAndroid Build Coastguard Worker // FlexFEC header.
137*d9f75844SAndroid Build Coastguard Worker 0x00, kMediaPlType, kPayloadLength[0], kPayloadLength[1],
138*d9f75844SAndroid Build Coastguard Worker kMediaTs[0], kMediaTs[1], kMediaTs[2], kMediaTs[3],
139*d9f75844SAndroid Build Coastguard Worker kSsrcCount, kReservedBits, kReservedBits, kReservedBits,
140*d9f75844SAndroid Build Coastguard Worker kMediaSsrc[0], kMediaSsrc[1], kMediaSsrc[2], kMediaSsrc[3],
141*d9f75844SAndroid Build Coastguard Worker kMediaSeqNum[0], kMediaSeqNum[1], kFlexfecPktMask[0], kFlexfecPktMask[1],
142*d9f75844SAndroid Build Coastguard Worker // FEC payload.
143*d9f75844SAndroid Build Coastguard Worker kPayloadBits, kPayloadBits, kPayloadBits, kPayloadBits};
144*d9f75844SAndroid Build Coastguard Worker // clang-format on
145*d9f75844SAndroid Build Coastguard Worker
146*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(recovered_packet_receiver_,
147*d9f75844SAndroid Build Coastguard Worker OnRecoveredPacket(_, kRtpHeaderSize + kPayloadLength[1]));
148*d9f75844SAndroid Build Coastguard Worker
149*d9f75844SAndroid Build Coastguard Worker receive_stream_->OnRtpPacket(ParsePacket(kFlexfecPacket));
150*d9f75844SAndroid Build Coastguard Worker
151*d9f75844SAndroid Build Coastguard Worker // Tear-down
152*d9f75844SAndroid Build Coastguard Worker receive_stream_->UnregisterFromTransport();
153*d9f75844SAndroid Build Coastguard Worker }
154*d9f75844SAndroid Build Coastguard Worker
155*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
156