blob: b6d049ef7efd5a9b669d1c671a71d399ace7271f [file] [log] [blame]
johan62d02c32017-01-24 04:38:27 -08001/*
2 * Copyright 2017 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "test/gmock.h"
Yves Gerey665174f2018-06-19 15:03:05 +020012#include "test/gtest.h"
johan62d02c32017-01-24 04:38:27 -080013
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#include "common_video/h264/h264_common.h"
15#include "media/base/mediaconstants.h"
16#include "modules/pacing/packet_router.h"
17#include "modules/rtp_rtcp/source/rtp_packet_received.h"
18#include "modules/utility/include/process_thread.h"
19#include "modules/video_coding/frame_object.h"
20#include "modules/video_coding/include/video_coding_defines.h"
21#include "modules/video_coding/packet.h"
22#include "modules/video_coding/rtp_frame_reference_finder.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "rtc_base/bytebuffer.h"
24#include "rtc_base/logging.h"
25#include "rtc_base/ptr_util.h"
26#include "system_wrappers/include/clock.h"
27#include "system_wrappers/include/field_trial_default.h"
28#include "test/field_trial.h"
29#include "video/rtp_video_stream_receiver.h"
johan62d02c32017-01-24 04:38:27 -080030
31using testing::_;
32
33namespace webrtc {
34
35namespace {
36
johan62d02c32017-01-24 04:38:27 -080037const uint8_t kH264StartCode[] = {0x00, 0x00, 0x00, 0x01};
38
39class MockTransport : public Transport {
40 public:
41 MOCK_METHOD3(SendRtp,
42 bool(const uint8_t* packet,
43 size_t length,
44 const PacketOptions& options));
45 MOCK_METHOD2(SendRtcp, bool(const uint8_t* packet, size_t length));
46};
47
48class MockNackSender : public NackSender {
49 public:
50 MOCK_METHOD1(SendNack, void(const std::vector<uint16_t>& sequence_numbers));
51};
52
53class MockKeyFrameRequestSender : public KeyFrameRequestSender {
54 public:
55 MOCK_METHOD0(RequestKeyFrame, void());
56};
57
58class MockOnCompleteFrameCallback
59 : public video_coding::OnCompleteFrameCallback {
60 public:
61 MockOnCompleteFrameCallback() : buffer_(rtc::ByteBuffer::ORDER_NETWORK) {}
62
philipele7c891f2018-02-22 14:35:06 +010063 MOCK_METHOD1(DoOnCompleteFrame, void(video_coding::EncodedFrame* frame));
johan62d02c32017-01-24 04:38:27 -080064 MOCK_METHOD1(DoOnCompleteFrameFailNullptr,
philipele7c891f2018-02-22 14:35:06 +010065 void(video_coding::EncodedFrame* frame));
johan62d02c32017-01-24 04:38:27 -080066 MOCK_METHOD1(DoOnCompleteFrameFailLength,
philipele7c891f2018-02-22 14:35:06 +010067 void(video_coding::EncodedFrame* frame));
johan62d02c32017-01-24 04:38:27 -080068 MOCK_METHOD1(DoOnCompleteFrameFailBitstream,
philipele7c891f2018-02-22 14:35:06 +010069 void(video_coding::EncodedFrame* frame));
70 void OnCompleteFrame(std::unique_ptr<video_coding::EncodedFrame> frame) {
johan62d02c32017-01-24 04:38:27 -080071 if (!frame) {
72 DoOnCompleteFrameFailNullptr(nullptr);
73 return;
74 }
75 EXPECT_EQ(buffer_.Length(), frame->size());
76 if (buffer_.Length() != frame->size()) {
77 DoOnCompleteFrameFailLength(frame.get());
78 return;
79 }
80 std::vector<uint8_t> actual_data(frame->size());
81 frame->GetBitstream(actual_data.data());
82 if (memcmp(buffer_.Data(), actual_data.data(), buffer_.Length()) != 0) {
83 DoOnCompleteFrameFailBitstream(frame.get());
84 return;
85 }
86 DoOnCompleteFrame(frame.get());
87 }
88 void AppendExpectedBitstream(const uint8_t data[], size_t size_in_bytes) {
89 // TODO(Johan): Let rtc::ByteBuffer handle uint8_t* instead of char*.
90 buffer_.WriteBytes(reinterpret_cast<const char*>(data), size_in_bytes);
91 }
92 rtc::ByteBufferWriter buffer_;
93};
94
eladalonc0d481a2017-08-02 07:39:07 -070095class MockRtpPacketSink : public RtpPacketSinkInterface {
96 public:
97 MOCK_METHOD1(OnRtpPacket, void(const RtpPacketReceived&));
98};
99
100constexpr uint32_t kSsrc = 111;
101constexpr uint16_t kSequenceNumber = 222;
102std::unique_ptr<RtpPacketReceived> CreateRtpPacketReceived(
103 uint32_t ssrc = kSsrc,
104 uint16_t sequence_number = kSequenceNumber) {
105 auto packet = rtc::MakeUnique<RtpPacketReceived>();
106 packet->SetSsrc(ssrc);
107 packet->SetSequenceNumber(sequence_number);
108 return packet;
109}
110
111MATCHER_P(SamePacketAs, other, "") {
112 return arg.Ssrc() == other.Ssrc() &&
113 arg.SequenceNumber() == other.SequenceNumber();
114}
115
johan62d02c32017-01-24 04:38:27 -0800116} // namespace
117
nisseb1f2ff92017-06-09 04:01:55 -0700118class RtpVideoStreamReceiverTest : public testing::Test {
johan62d02c32017-01-24 04:38:27 -0800119 public:
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100120 RtpVideoStreamReceiverTest() : RtpVideoStreamReceiverTest("") {}
121 explicit RtpVideoStreamReceiverTest(std::string field_trials)
122 : override_field_trials_(field_trials),
123 config_(CreateConfig()),
johan62d02c32017-01-24 04:38:27 -0800124 process_thread_(ProcessThread::Create("TestThread")) {}
125
126 void SetUp() {
nisseca5706d2017-09-11 02:32:16 -0700127 rtp_receive_statistics_ =
128 rtc::WrapUnique(ReceiveStatistics::Create(Clock::GetRealTimeClock()));
129 rtp_video_stream_receiver_ = rtc::MakeUnique<RtpVideoStreamReceiver>(
nisse05843312017-04-18 23:38:35 -0700130 &mock_transport_, nullptr, &packet_router_, &config_,
nisseca5706d2017-09-11 02:32:16 -0700131 rtp_receive_statistics_.get(), nullptr, process_thread_.get(),
Yves Gerey665174f2018-06-19 15:03:05 +0200132 &mock_nack_sender_, &mock_key_frame_request_sender_,
133 &mock_on_complete_frame_callback_);
johan62d02c32017-01-24 04:38:27 -0800134 }
135
136 WebRtcRTPHeader GetDefaultPacket() {
137 WebRtcRTPHeader packet;
138 memset(&packet, 0, sizeof(packet));
philipelcb96ad82018-07-02 14:41:58 +0200139 packet.video_header().codec = kVideoCodecH264;
johan62d02c32017-01-24 04:38:27 -0800140 return packet;
141 }
142
143 // TODO(Johan): refactor h264_sps_pps_tracker_unittests.cc to avoid duplicate
144 // code.
philipel83c97da2017-06-21 07:22:40 -0700145 void AddSps(WebRtcRTPHeader* packet,
146 uint8_t sps_id,
147 std::vector<uint8_t>* data) {
johan62d02c32017-01-24 04:38:27 -0800148 NaluInfo info;
149 info.type = H264::NaluType::kSps;
150 info.sps_id = sps_id;
151 info.pps_id = -1;
johan62d02c32017-01-24 04:38:27 -0800152 data->push_back(H264::NaluType::kSps);
153 data->push_back(sps_id);
philipelcb96ad82018-07-02 14:41:58 +0200154 packet->video_header()
155 .codecHeader.H264
156 .nalus[packet->video_header().codecHeader.H264.nalus_length++] = info;
johan62d02c32017-01-24 04:38:27 -0800157 }
158
159 void AddPps(WebRtcRTPHeader* packet,
philipel83c97da2017-06-21 07:22:40 -0700160 uint8_t sps_id,
161 uint8_t pps_id,
johan62d02c32017-01-24 04:38:27 -0800162 std::vector<uint8_t>* data) {
163 NaluInfo info;
164 info.type = H264::NaluType::kPps;
165 info.sps_id = sps_id;
166 info.pps_id = pps_id;
johan62d02c32017-01-24 04:38:27 -0800167 data->push_back(H264::NaluType::kPps);
168 data->push_back(pps_id);
philipelcb96ad82018-07-02 14:41:58 +0200169 packet->video_header()
170 .codecHeader.H264
171 .nalus[packet->video_header().codecHeader.H264.nalus_length++] = info;
johan62d02c32017-01-24 04:38:27 -0800172 }
173
174 void AddIdr(WebRtcRTPHeader* packet, int pps_id) {
175 NaluInfo info;
176 info.type = H264::NaluType::kIdr;
177 info.sps_id = -1;
178 info.pps_id = pps_id;
philipelcb96ad82018-07-02 14:41:58 +0200179 packet->video_header()
180 .codecHeader.H264
181 .nalus[packet->video_header().codecHeader.H264.nalus_length++] = info;
johan62d02c32017-01-24 04:38:27 -0800182 }
183
184 protected:
185 static VideoReceiveStream::Config CreateConfig() {
186 VideoReceiveStream::Config config(nullptr);
187 config.rtp.remote_ssrc = 1111;
188 config.rtp.local_ssrc = 2222;
189 return config;
190 }
191
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100192 const webrtc::test::ScopedFieldTrials override_field_trials_;
johan62d02c32017-01-24 04:38:27 -0800193 VideoReceiveStream::Config config_;
194 MockNackSender mock_nack_sender_;
195 MockKeyFrameRequestSender mock_key_frame_request_sender_;
196 MockTransport mock_transport_;
197 MockOnCompleteFrameCallback mock_on_complete_frame_callback_;
198 PacketRouter packet_router_;
johan62d02c32017-01-24 04:38:27 -0800199 std::unique_ptr<ProcessThread> process_thread_;
nisseca5706d2017-09-11 02:32:16 -0700200 std::unique_ptr<ReceiveStatistics> rtp_receive_statistics_;
nisseb1f2ff92017-06-09 04:01:55 -0700201 std::unique_ptr<RtpVideoStreamReceiver> rtp_video_stream_receiver_;
johan62d02c32017-01-24 04:38:27 -0800202};
203
nisseb1f2ff92017-06-09 04:01:55 -0700204TEST_F(RtpVideoStreamReceiverTest, GenericKeyFrame) {
johan62d02c32017-01-24 04:38:27 -0800205 WebRtcRTPHeader rtp_header;
206 const std::vector<uint8_t> data({1, 2, 3, 4});
207 memset(&rtp_header, 0, sizeof(rtp_header));
208 rtp_header.header.sequenceNumber = 1;
209 rtp_header.header.markerBit = 1;
philipelcb96ad82018-07-02 14:41:58 +0200210 rtp_header.video_header().is_first_packet_in_frame = true;
johan62d02c32017-01-24 04:38:27 -0800211 rtp_header.frameType = kVideoFrameKey;
philipelcb96ad82018-07-02 14:41:58 +0200212 rtp_header.video_header().codec = kVideoCodecGeneric;
johan62d02c32017-01-24 04:38:27 -0800213 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
214 data.size());
215 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
nisseb1f2ff92017-06-09 04:01:55 -0700216 rtp_video_stream_receiver_->OnReceivedPayloadData(data.data(), data.size(),
217 &rtp_header);
johan62d02c32017-01-24 04:38:27 -0800218}
219
philipeld8f6c162018-01-19 14:41:41 +0100220TEST_F(RtpVideoStreamReceiverTest, NoInfiniteRecursionOnEncapsulatedRedPacket) {
221 const uint8_t kRedPayloadType = 125;
222 VideoCodec codec;
223 codec.plType = kRedPayloadType;
philipeld8f6c162018-01-19 14:41:41 +0100224 rtp_video_stream_receiver_->AddReceiveCodec(codec, {});
Yves Gerey665174f2018-06-19 15:03:05 +0200225 const std::vector<uint8_t> data({
226 0x80, // RTP version.
227 kRedPayloadType, // Payload type.
228 0, 0, 0, 0, 0, 0, // Don't care.
229 0, 0, 0x4, 0x57, // SSRC
230 kRedPayloadType, // RED header.
231 0, 0, 0, 0, 0 // Don't care.
232 });
philipeld8f6c162018-01-19 14:41:41 +0100233 RtpPacketReceived packet;
234 EXPECT_TRUE(packet.Parse(data.data(), data.size()));
235 rtp_video_stream_receiver_->StartReceive();
236 rtp_video_stream_receiver_->OnRtpPacket(packet);
237}
238
nisseb1f2ff92017-06-09 04:01:55 -0700239TEST_F(RtpVideoStreamReceiverTest, GenericKeyFrameBitstreamError) {
johan62d02c32017-01-24 04:38:27 -0800240 WebRtcRTPHeader rtp_header;
241 const std::vector<uint8_t> data({1, 2, 3, 4});
242 memset(&rtp_header, 0, sizeof(rtp_header));
243 rtp_header.header.sequenceNumber = 1;
244 rtp_header.header.markerBit = 1;
philipelcb96ad82018-07-02 14:41:58 +0200245 rtp_header.video_header().is_first_packet_in_frame = true;
johan62d02c32017-01-24 04:38:27 -0800246 rtp_header.frameType = kVideoFrameKey;
philipelcb96ad82018-07-02 14:41:58 +0200247 rtp_header.video_header().codec = kVideoCodecGeneric;
johan62d02c32017-01-24 04:38:27 -0800248 constexpr uint8_t expected_bitsteam[] = {1, 2, 3, 0xff};
249 mock_on_complete_frame_callback_.AppendExpectedBitstream(
250 expected_bitsteam, sizeof(expected_bitsteam));
251 EXPECT_CALL(mock_on_complete_frame_callback_,
252 DoOnCompleteFrameFailBitstream(_));
nisseb1f2ff92017-06-09 04:01:55 -0700253 rtp_video_stream_receiver_->OnReceivedPayloadData(data.data(), data.size(),
254 &rtp_header);
johan62d02c32017-01-24 04:38:27 -0800255}
256
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100257class RtpVideoStreamReceiverTestH264
258 : public RtpVideoStreamReceiverTest,
259 public testing::WithParamInterface<std::string> {
260 protected:
261 RtpVideoStreamReceiverTestH264() : RtpVideoStreamReceiverTest(GetParam()) {}
262};
263
264INSTANTIATE_TEST_CASE_P(
265 SpsPpsIdrIsKeyframe,
266 RtpVideoStreamReceiverTestH264,
267 ::testing::Values("", "WebRTC-SpsPpsIdrIsH264Keyframe/Enabled/"));
268
269TEST_P(RtpVideoStreamReceiverTestH264, InBandSpsPps) {
johan62d02c32017-01-24 04:38:27 -0800270 std::vector<uint8_t> sps_data;
271 WebRtcRTPHeader sps_packet = GetDefaultPacket();
272 AddSps(&sps_packet, 0, &sps_data);
273 sps_packet.header.sequenceNumber = 0;
philipelcb96ad82018-07-02 14:41:58 +0200274 sps_packet.video_header().is_first_packet_in_frame = true;
johan62d02c32017-01-24 04:38:27 -0800275 mock_on_complete_frame_callback_.AppendExpectedBitstream(
276 kH264StartCode, sizeof(kH264StartCode));
277 mock_on_complete_frame_callback_.AppendExpectedBitstream(sps_data.data(),
278 sps_data.size());
nisseb1f2ff92017-06-09 04:01:55 -0700279 rtp_video_stream_receiver_->OnReceivedPayloadData(
280 sps_data.data(), sps_data.size(), &sps_packet);
johan62d02c32017-01-24 04:38:27 -0800281
282 std::vector<uint8_t> pps_data;
283 WebRtcRTPHeader pps_packet = GetDefaultPacket();
284 AddPps(&pps_packet, 0, 1, &pps_data);
285 pps_packet.header.sequenceNumber = 1;
philipelcb96ad82018-07-02 14:41:58 +0200286 pps_packet.video_header().is_first_packet_in_frame = true;
johan62d02c32017-01-24 04:38:27 -0800287 mock_on_complete_frame_callback_.AppendExpectedBitstream(
288 kH264StartCode, sizeof(kH264StartCode));
289 mock_on_complete_frame_callback_.AppendExpectedBitstream(pps_data.data(),
290 pps_data.size());
nisseb1f2ff92017-06-09 04:01:55 -0700291 rtp_video_stream_receiver_->OnReceivedPayloadData(
292 pps_data.data(), pps_data.size(), &pps_packet);
johan62d02c32017-01-24 04:38:27 -0800293
294 std::vector<uint8_t> idr_data;
295 WebRtcRTPHeader idr_packet = GetDefaultPacket();
296 AddIdr(&idr_packet, 1);
philipelcb96ad82018-07-02 14:41:58 +0200297 idr_packet.video_header().is_first_packet_in_frame = true;
johan62d02c32017-01-24 04:38:27 -0800298 idr_packet.header.sequenceNumber = 2;
299 idr_packet.header.markerBit = 1;
johan62d02c32017-01-24 04:38:27 -0800300 idr_packet.frameType = kVideoFrameKey;
johan62d02c32017-01-24 04:38:27 -0800301 idr_data.insert(idr_data.end(), {0x65, 1, 2, 3});
302 mock_on_complete_frame_callback_.AppendExpectedBitstream(
303 kH264StartCode, sizeof(kH264StartCode));
304 mock_on_complete_frame_callback_.AppendExpectedBitstream(idr_data.data(),
305 idr_data.size());
306 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
nisseb1f2ff92017-06-09 04:01:55 -0700307 rtp_video_stream_receiver_->OnReceivedPayloadData(
308 idr_data.data(), idr_data.size(), &idr_packet);
johan62d02c32017-01-24 04:38:27 -0800309}
310
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100311TEST_P(RtpVideoStreamReceiverTestH264, OutOfBandFmtpSpsPps) {
johan62d02c32017-01-24 04:38:27 -0800312 constexpr int kPayloadType = 99;
313 VideoCodec codec;
314 codec.plType = kPayloadType;
315 std::map<std::string, std::string> codec_params;
316 // Example parameter sets from https://tools.ietf.org/html/rfc3984#section-8.2
317 // .
318 codec_params.insert(
319 {cricket::kH264FmtpSpropParameterSets, "Z0IACpZTBYmI,aMljiA=="});
nisseb1f2ff92017-06-09 04:01:55 -0700320 rtp_video_stream_receiver_->AddReceiveCodec(codec, codec_params);
johan62d02c32017-01-24 04:38:27 -0800321 const uint8_t binary_sps[] = {0x67, 0x42, 0x00, 0x0a, 0x96,
322 0x53, 0x05, 0x89, 0x88};
323 mock_on_complete_frame_callback_.AppendExpectedBitstream(
324 kH264StartCode, sizeof(kH264StartCode));
325 mock_on_complete_frame_callback_.AppendExpectedBitstream(binary_sps,
326 sizeof(binary_sps));
327 const uint8_t binary_pps[] = {0x68, 0xc9, 0x63, 0x88};
328 mock_on_complete_frame_callback_.AppendExpectedBitstream(
329 kH264StartCode, sizeof(kH264StartCode));
330 mock_on_complete_frame_callback_.AppendExpectedBitstream(binary_pps,
331 sizeof(binary_pps));
332
333 std::vector<uint8_t> data;
334 WebRtcRTPHeader idr_packet = GetDefaultPacket();
335 AddIdr(&idr_packet, 0);
336 idr_packet.header.payloadType = kPayloadType;
philipelcb96ad82018-07-02 14:41:58 +0200337 idr_packet.video_header().is_first_packet_in_frame = true;
johan62d02c32017-01-24 04:38:27 -0800338 idr_packet.header.sequenceNumber = 2;
339 idr_packet.header.markerBit = 1;
philipelcb96ad82018-07-02 14:41:58 +0200340 idr_packet.video_header().is_first_packet_in_frame = true;
johan62d02c32017-01-24 04:38:27 -0800341 idr_packet.frameType = kVideoFrameKey;
philipelcb96ad82018-07-02 14:41:58 +0200342 idr_packet.video_header().codec = kVideoCodecH264;
johan62d02c32017-01-24 04:38:27 -0800343 data.insert(data.end(), {1, 2, 3});
344 mock_on_complete_frame_callback_.AppendExpectedBitstream(
345 kH264StartCode, sizeof(kH264StartCode));
346 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
347 data.size());
348 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
nisseb1f2ff92017-06-09 04:01:55 -0700349 rtp_video_stream_receiver_->OnReceivedPayloadData(data.data(), data.size(),
350 &idr_packet);
johan62d02c32017-01-24 04:38:27 -0800351}
352
nisseb1f2ff92017-06-09 04:01:55 -0700353TEST_F(RtpVideoStreamReceiverTest, PaddingInMediaStream) {
philipel54ca9192017-03-21 05:45:18 -0700354 WebRtcRTPHeader header = GetDefaultPacket();
355 std::vector<uint8_t> data;
356 data.insert(data.end(), {1, 2, 3});
357 header.header.payloadType = 99;
philipelcb96ad82018-07-02 14:41:58 +0200358 header.video_header().is_first_packet_in_frame = true;
philipel54ca9192017-03-21 05:45:18 -0700359 header.header.sequenceNumber = 2;
360 header.header.markerBit = true;
361 header.frameType = kVideoFrameKey;
philipelcb96ad82018-07-02 14:41:58 +0200362 header.video_header().codec = kVideoCodecGeneric;
philipel54ca9192017-03-21 05:45:18 -0700363 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
364 data.size());
365
366 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
nisseb1f2ff92017-06-09 04:01:55 -0700367 rtp_video_stream_receiver_->OnReceivedPayloadData(data.data(), data.size(),
368 &header);
philipel54ca9192017-03-21 05:45:18 -0700369
370 header.header.sequenceNumber = 3;
nisseb1f2ff92017-06-09 04:01:55 -0700371 rtp_video_stream_receiver_->OnReceivedPayloadData(nullptr, 0, &header);
philipel54ca9192017-03-21 05:45:18 -0700372
373 header.frameType = kVideoFrameDelta;
374 header.header.sequenceNumber = 4;
375 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
nisseb1f2ff92017-06-09 04:01:55 -0700376 rtp_video_stream_receiver_->OnReceivedPayloadData(data.data(), data.size(),
377 &header);
philipel54ca9192017-03-21 05:45:18 -0700378
379 header.header.sequenceNumber = 6;
nisseb1f2ff92017-06-09 04:01:55 -0700380 rtp_video_stream_receiver_->OnReceivedPayloadData(data.data(), data.size(),
381 &header);
philipel54ca9192017-03-21 05:45:18 -0700382
383 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
384 header.header.sequenceNumber = 5;
nisseb1f2ff92017-06-09 04:01:55 -0700385 rtp_video_stream_receiver_->OnReceivedPayloadData(nullptr, 0, &header);
philipel54ca9192017-03-21 05:45:18 -0700386}
387
nisseb1f2ff92017-06-09 04:01:55 -0700388TEST_F(RtpVideoStreamReceiverTest, RequestKeyframeIfFirstFrameIsDelta) {
philipel2c53b132017-05-16 08:06:30 -0700389 WebRtcRTPHeader rtp_header;
390 const std::vector<uint8_t> data({1, 2, 3, 4});
391 memset(&rtp_header, 0, sizeof(rtp_header));
392 rtp_header.header.sequenceNumber = 1;
393 rtp_header.header.markerBit = 1;
philipelcb96ad82018-07-02 14:41:58 +0200394 rtp_header.video_header().is_first_packet_in_frame = true;
philipel2c53b132017-05-16 08:06:30 -0700395 rtp_header.frameType = kVideoFrameDelta;
philipelcb96ad82018-07-02 14:41:58 +0200396 rtp_header.video_header().codec = kVideoCodecGeneric;
philipel2c53b132017-05-16 08:06:30 -0700397
398 EXPECT_CALL(mock_key_frame_request_sender_, RequestKeyFrame());
nisseb1f2ff92017-06-09 04:01:55 -0700399 rtp_video_stream_receiver_->OnReceivedPayloadData(data.data(), data.size(),
400 &rtp_header);
philipel2c53b132017-05-16 08:06:30 -0700401}
402
eladalonc0d481a2017-08-02 07:39:07 -0700403TEST_F(RtpVideoStreamReceiverTest, SecondarySinksGetRtpNotifications) {
404 rtp_video_stream_receiver_->StartReceive();
405
406 MockRtpPacketSink secondary_sink_1;
407 MockRtpPacketSink secondary_sink_2;
408
409 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink_1);
410 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink_2);
411
412 auto rtp_packet = CreateRtpPacketReceived();
413 EXPECT_CALL(secondary_sink_1, OnRtpPacket(SamePacketAs(*rtp_packet)));
414 EXPECT_CALL(secondary_sink_2, OnRtpPacket(SamePacketAs(*rtp_packet)));
415
416 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
417
418 // Test tear-down.
419 rtp_video_stream_receiver_->StopReceive();
420 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink_1);
421 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink_2);
422}
423
424TEST_F(RtpVideoStreamReceiverTest, RemovedSecondarySinksGetNoRtpNotifications) {
425 rtp_video_stream_receiver_->StartReceive();
426
427 MockRtpPacketSink secondary_sink;
428
429 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
430 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
431
432 auto rtp_packet = CreateRtpPacketReceived();
433
434 EXPECT_CALL(secondary_sink, OnRtpPacket(_)).Times(0);
435
436 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
437
438 // Test tear-down.
439 rtp_video_stream_receiver_->StopReceive();
440}
441
442TEST_F(RtpVideoStreamReceiverTest,
443 OnlyRemovedSecondarySinksExcludedFromNotifications) {
444 rtp_video_stream_receiver_->StartReceive();
445
446 MockRtpPacketSink kept_secondary_sink;
447 MockRtpPacketSink removed_secondary_sink;
448
449 rtp_video_stream_receiver_->AddSecondarySink(&kept_secondary_sink);
450 rtp_video_stream_receiver_->AddSecondarySink(&removed_secondary_sink);
451 rtp_video_stream_receiver_->RemoveSecondarySink(&removed_secondary_sink);
452
453 auto rtp_packet = CreateRtpPacketReceived();
454 EXPECT_CALL(kept_secondary_sink, OnRtpPacket(SamePacketAs(*rtp_packet)));
455
456 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
457
458 // Test tear-down.
459 rtp_video_stream_receiver_->StopReceive();
460 rtp_video_stream_receiver_->RemoveSecondarySink(&kept_secondary_sink);
461}
462
463TEST_F(RtpVideoStreamReceiverTest,
464 SecondariesOfNonStartedStreamGetNoNotifications) {
465 // Explicitly showing that the stream is not in the |started| state,
466 // regardless of whether streams start out |started| or |stopped|.
467 rtp_video_stream_receiver_->StopReceive();
468
469 MockRtpPacketSink secondary_sink;
470 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
471
472 auto rtp_packet = CreateRtpPacketReceived();
473 EXPECT_CALL(secondary_sink, OnRtpPacket(_)).Times(0);
474
475 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
476
477 // Test tear-down.
478 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
479}
480
481#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
482TEST_F(RtpVideoStreamReceiverTest, RepeatedSecondarySinkDisallowed) {
483 MockRtpPacketSink secondary_sink;
484
485 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
486 EXPECT_DEATH(rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink),
487 "");
488
489 // Test tear-down.
490 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
491}
492#endif
493
johan62d02c32017-01-24 04:38:27 -0800494} // namespace webrtc