blob: 297218205f2ccaaa25ee6423ae0da1bd30e78a9f [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/gtest.h"
12#include "test/gmock.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"
23#include "modules/video_coding/timing.h"
24#include "rtc_base/bytebuffer.h"
25#include "rtc_base/logging.h"
26#include "rtc_base/ptr_util.h"
27#include "system_wrappers/include/clock.h"
28#include "system_wrappers/include/field_trial_default.h"
29#include "test/field_trial.h"
30#include "video/rtp_video_stream_receiver.h"
johan62d02c32017-01-24 04:38:27 -080031
32using testing::_;
33
34namespace webrtc {
35
36namespace {
37
johan62d02c32017-01-24 04:38:27 -080038const uint8_t kH264StartCode[] = {0x00, 0x00, 0x00, 0x01};
39
40class MockTransport : public Transport {
41 public:
42 MOCK_METHOD3(SendRtp,
43 bool(const uint8_t* packet,
44 size_t length,
45 const PacketOptions& options));
46 MOCK_METHOD2(SendRtcp, bool(const uint8_t* packet, size_t length));
47};
48
49class MockNackSender : public NackSender {
50 public:
51 MOCK_METHOD1(SendNack, void(const std::vector<uint16_t>& sequence_numbers));
52};
53
54class MockKeyFrameRequestSender : public KeyFrameRequestSender {
55 public:
56 MOCK_METHOD0(RequestKeyFrame, void());
57};
58
59class MockOnCompleteFrameCallback
60 : public video_coding::OnCompleteFrameCallback {
61 public:
62 MockOnCompleteFrameCallback() : buffer_(rtc::ByteBuffer::ORDER_NETWORK) {}
63
64 MOCK_METHOD1(DoOnCompleteFrame, void(video_coding::FrameObject* frame));
65 MOCK_METHOD1(DoOnCompleteFrameFailNullptr,
66 void(video_coding::FrameObject* frame));
67 MOCK_METHOD1(DoOnCompleteFrameFailLength,
68 void(video_coding::FrameObject* frame));
69 MOCK_METHOD1(DoOnCompleteFrameFailBitstream,
70 void(video_coding::FrameObject* frame));
71 void OnCompleteFrame(std::unique_ptr<video_coding::FrameObject> frame) {
72 if (!frame) {
73 DoOnCompleteFrameFailNullptr(nullptr);
74 return;
75 }
76 EXPECT_EQ(buffer_.Length(), frame->size());
77 if (buffer_.Length() != frame->size()) {
78 DoOnCompleteFrameFailLength(frame.get());
79 return;
80 }
81 std::vector<uint8_t> actual_data(frame->size());
82 frame->GetBitstream(actual_data.data());
83 if (memcmp(buffer_.Data(), actual_data.data(), buffer_.Length()) != 0) {
84 DoOnCompleteFrameFailBitstream(frame.get());
85 return;
86 }
87 DoOnCompleteFrame(frame.get());
88 }
89 void AppendExpectedBitstream(const uint8_t data[], size_t size_in_bytes) {
90 // TODO(Johan): Let rtc::ByteBuffer handle uint8_t* instead of char*.
91 buffer_.WriteBytes(reinterpret_cast<const char*>(data), size_in_bytes);
92 }
93 rtc::ByteBufferWriter buffer_;
94};
95
eladalonc0d481a2017-08-02 07:39:07 -070096class MockRtpPacketSink : public RtpPacketSinkInterface {
97 public:
98 MOCK_METHOD1(OnRtpPacket, void(const RtpPacketReceived&));
99};
100
101constexpr uint32_t kSsrc = 111;
102constexpr uint16_t kSequenceNumber = 222;
103std::unique_ptr<RtpPacketReceived> CreateRtpPacketReceived(
104 uint32_t ssrc = kSsrc,
105 uint16_t sequence_number = kSequenceNumber) {
106 auto packet = rtc::MakeUnique<RtpPacketReceived>();
107 packet->SetSsrc(ssrc);
108 packet->SetSequenceNumber(sequence_number);
109 return packet;
110}
111
112MATCHER_P(SamePacketAs, other, "") {
113 return arg.Ssrc() == other.Ssrc() &&
114 arg.SequenceNumber() == other.SequenceNumber();
115}
116
johan62d02c32017-01-24 04:38:27 -0800117} // namespace
118
nisseb1f2ff92017-06-09 04:01:55 -0700119class RtpVideoStreamReceiverTest : public testing::Test {
johan62d02c32017-01-24 04:38:27 -0800120 public:
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100121 RtpVideoStreamReceiverTest() : RtpVideoStreamReceiverTest("") {}
122 explicit RtpVideoStreamReceiverTest(std::string field_trials)
123 : override_field_trials_(field_trials),
124 config_(CreateConfig()),
johan62d02c32017-01-24 04:38:27 -0800125 timing_(Clock::GetRealTimeClock()),
126 process_thread_(ProcessThread::Create("TestThread")) {}
127
128 void SetUp() {
nisseca5706d2017-09-11 02:32:16 -0700129 rtp_receive_statistics_ =
130 rtc::WrapUnique(ReceiveStatistics::Create(Clock::GetRealTimeClock()));
131 rtp_video_stream_receiver_ = rtc::MakeUnique<RtpVideoStreamReceiver>(
nisse05843312017-04-18 23:38:35 -0700132 &mock_transport_, nullptr, &packet_router_, &config_,
nisseca5706d2017-09-11 02:32:16 -0700133 rtp_receive_statistics_.get(), nullptr, process_thread_.get(),
134 &mock_nack_sender_,
philipela45102f2017-02-22 05:30:39 -0800135 &mock_key_frame_request_sender_, &mock_on_complete_frame_callback_,
nisseca5706d2017-09-11 02:32:16 -0700136 &timing_);
johan62d02c32017-01-24 04:38:27 -0800137 }
138
139 WebRtcRTPHeader GetDefaultPacket() {
140 WebRtcRTPHeader packet;
141 memset(&packet, 0, sizeof(packet));
142 packet.type.Video.codec = kRtpVideoH264;
143 return packet;
144 }
145
146 // TODO(Johan): refactor h264_sps_pps_tracker_unittests.cc to avoid duplicate
147 // code.
philipel83c97da2017-06-21 07:22:40 -0700148 void AddSps(WebRtcRTPHeader* packet,
149 uint8_t sps_id,
150 std::vector<uint8_t>* data) {
johan62d02c32017-01-24 04:38:27 -0800151 NaluInfo info;
152 info.type = H264::NaluType::kSps;
153 info.sps_id = sps_id;
154 info.pps_id = -1;
johan62d02c32017-01-24 04:38:27 -0800155 data->push_back(H264::NaluType::kSps);
156 data->push_back(sps_id);
157 packet->type.Video.codecHeader.H264
158 .nalus[packet->type.Video.codecHeader.H264.nalus_length++] = info;
159 }
160
161 void AddPps(WebRtcRTPHeader* packet,
philipel83c97da2017-06-21 07:22:40 -0700162 uint8_t sps_id,
163 uint8_t pps_id,
johan62d02c32017-01-24 04:38:27 -0800164 std::vector<uint8_t>* data) {
165 NaluInfo info;
166 info.type = H264::NaluType::kPps;
167 info.sps_id = sps_id;
168 info.pps_id = pps_id;
johan62d02c32017-01-24 04:38:27 -0800169 data->push_back(H264::NaluType::kPps);
170 data->push_back(pps_id);
171 packet->type.Video.codecHeader.H264
172 .nalus[packet->type.Video.codecHeader.H264.nalus_length++] = info;
173 }
174
175 void AddIdr(WebRtcRTPHeader* packet, int pps_id) {
176 NaluInfo info;
177 info.type = H264::NaluType::kIdr;
178 info.sps_id = -1;
179 info.pps_id = pps_id;
180 packet->type.Video.codecHeader.H264
181 .nalus[packet->type.Video.codecHeader.H264.nalus_length++] = info;
182 }
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_;
199 VCMTiming timing_;
200 std::unique_ptr<ProcessThread> process_thread_;
nisseca5706d2017-09-11 02:32:16 -0700201 std::unique_ptr<ReceiveStatistics> rtp_receive_statistics_;
nisseb1f2ff92017-06-09 04:01:55 -0700202 std::unique_ptr<RtpVideoStreamReceiver> rtp_video_stream_receiver_;
johan62d02c32017-01-24 04:38:27 -0800203};
204
nisseb1f2ff92017-06-09 04:01:55 -0700205TEST_F(RtpVideoStreamReceiverTest, GenericKeyFrame) {
johan62d02c32017-01-24 04:38:27 -0800206 WebRtcRTPHeader rtp_header;
207 const std::vector<uint8_t> data({1, 2, 3, 4});
208 memset(&rtp_header, 0, sizeof(rtp_header));
209 rtp_header.header.sequenceNumber = 1;
210 rtp_header.header.markerBit = 1;
211 rtp_header.type.Video.is_first_packet_in_frame = true;
212 rtp_header.frameType = kVideoFrameKey;
213 rtp_header.type.Video.codec = kRtpVideoGeneric;
214 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
215 data.size());
216 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
nisseb1f2ff92017-06-09 04:01:55 -0700217 rtp_video_stream_receiver_->OnReceivedPayloadData(data.data(), data.size(),
218 &rtp_header);
johan62d02c32017-01-24 04:38:27 -0800219}
220
nisseb1f2ff92017-06-09 04:01:55 -0700221TEST_F(RtpVideoStreamReceiverTest, GenericKeyFrameBitstreamError) {
johan62d02c32017-01-24 04:38:27 -0800222 WebRtcRTPHeader rtp_header;
223 const std::vector<uint8_t> data({1, 2, 3, 4});
224 memset(&rtp_header, 0, sizeof(rtp_header));
225 rtp_header.header.sequenceNumber = 1;
226 rtp_header.header.markerBit = 1;
227 rtp_header.type.Video.is_first_packet_in_frame = true;
228 rtp_header.frameType = kVideoFrameKey;
229 rtp_header.type.Video.codec = kRtpVideoGeneric;
230 constexpr uint8_t expected_bitsteam[] = {1, 2, 3, 0xff};
231 mock_on_complete_frame_callback_.AppendExpectedBitstream(
232 expected_bitsteam, sizeof(expected_bitsteam));
233 EXPECT_CALL(mock_on_complete_frame_callback_,
234 DoOnCompleteFrameFailBitstream(_));
nisseb1f2ff92017-06-09 04:01:55 -0700235 rtp_video_stream_receiver_->OnReceivedPayloadData(data.data(), data.size(),
236 &rtp_header);
johan62d02c32017-01-24 04:38:27 -0800237}
238
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100239class RtpVideoStreamReceiverTestH264
240 : public RtpVideoStreamReceiverTest,
241 public testing::WithParamInterface<std::string> {
242 protected:
243 RtpVideoStreamReceiverTestH264() : RtpVideoStreamReceiverTest(GetParam()) {}
244};
245
246INSTANTIATE_TEST_CASE_P(
247 SpsPpsIdrIsKeyframe,
248 RtpVideoStreamReceiverTestH264,
249 ::testing::Values("", "WebRTC-SpsPpsIdrIsH264Keyframe/Enabled/"));
250
251TEST_P(RtpVideoStreamReceiverTestH264, InBandSpsPps) {
johan62d02c32017-01-24 04:38:27 -0800252 std::vector<uint8_t> sps_data;
253 WebRtcRTPHeader sps_packet = GetDefaultPacket();
254 AddSps(&sps_packet, 0, &sps_data);
255 sps_packet.header.sequenceNumber = 0;
philipel83c97da2017-06-21 07:22:40 -0700256 sps_packet.type.Video.is_first_packet_in_frame = true;
johan62d02c32017-01-24 04:38:27 -0800257 mock_on_complete_frame_callback_.AppendExpectedBitstream(
258 kH264StartCode, sizeof(kH264StartCode));
259 mock_on_complete_frame_callback_.AppendExpectedBitstream(sps_data.data(),
260 sps_data.size());
nisseb1f2ff92017-06-09 04:01:55 -0700261 rtp_video_stream_receiver_->OnReceivedPayloadData(
262 sps_data.data(), sps_data.size(), &sps_packet);
johan62d02c32017-01-24 04:38:27 -0800263
264 std::vector<uint8_t> pps_data;
265 WebRtcRTPHeader pps_packet = GetDefaultPacket();
266 AddPps(&pps_packet, 0, 1, &pps_data);
267 pps_packet.header.sequenceNumber = 1;
philipel83c97da2017-06-21 07:22:40 -0700268 pps_packet.type.Video.is_first_packet_in_frame = true;
johan62d02c32017-01-24 04:38:27 -0800269 mock_on_complete_frame_callback_.AppendExpectedBitstream(
270 kH264StartCode, sizeof(kH264StartCode));
271 mock_on_complete_frame_callback_.AppendExpectedBitstream(pps_data.data(),
272 pps_data.size());
nisseb1f2ff92017-06-09 04:01:55 -0700273 rtp_video_stream_receiver_->OnReceivedPayloadData(
274 pps_data.data(), pps_data.size(), &pps_packet);
johan62d02c32017-01-24 04:38:27 -0800275
276 std::vector<uint8_t> idr_data;
277 WebRtcRTPHeader idr_packet = GetDefaultPacket();
278 AddIdr(&idr_packet, 1);
279 idr_packet.type.Video.is_first_packet_in_frame = true;
280 idr_packet.header.sequenceNumber = 2;
281 idr_packet.header.markerBit = 1;
johan62d02c32017-01-24 04:38:27 -0800282 idr_packet.frameType = kVideoFrameKey;
johan62d02c32017-01-24 04:38:27 -0800283 idr_data.insert(idr_data.end(), {0x65, 1, 2, 3});
284 mock_on_complete_frame_callback_.AppendExpectedBitstream(
285 kH264StartCode, sizeof(kH264StartCode));
286 mock_on_complete_frame_callback_.AppendExpectedBitstream(idr_data.data(),
287 idr_data.size());
288 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
nisseb1f2ff92017-06-09 04:01:55 -0700289 rtp_video_stream_receiver_->OnReceivedPayloadData(
290 idr_data.data(), idr_data.size(), &idr_packet);
johan62d02c32017-01-24 04:38:27 -0800291}
292
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100293TEST_P(RtpVideoStreamReceiverTestH264, OutOfBandFmtpSpsPps) {
johan62d02c32017-01-24 04:38:27 -0800294 constexpr int kPayloadType = 99;
295 VideoCodec codec;
296 codec.plType = kPayloadType;
297 std::map<std::string, std::string> codec_params;
298 // Example parameter sets from https://tools.ietf.org/html/rfc3984#section-8.2
299 // .
300 codec_params.insert(
301 {cricket::kH264FmtpSpropParameterSets, "Z0IACpZTBYmI,aMljiA=="});
nisseb1f2ff92017-06-09 04:01:55 -0700302 rtp_video_stream_receiver_->AddReceiveCodec(codec, codec_params);
johan62d02c32017-01-24 04:38:27 -0800303 const uint8_t binary_sps[] = {0x67, 0x42, 0x00, 0x0a, 0x96,
304 0x53, 0x05, 0x89, 0x88};
305 mock_on_complete_frame_callback_.AppendExpectedBitstream(
306 kH264StartCode, sizeof(kH264StartCode));
307 mock_on_complete_frame_callback_.AppendExpectedBitstream(binary_sps,
308 sizeof(binary_sps));
309 const uint8_t binary_pps[] = {0x68, 0xc9, 0x63, 0x88};
310 mock_on_complete_frame_callback_.AppendExpectedBitstream(
311 kH264StartCode, sizeof(kH264StartCode));
312 mock_on_complete_frame_callback_.AppendExpectedBitstream(binary_pps,
313 sizeof(binary_pps));
314
315 std::vector<uint8_t> data;
316 WebRtcRTPHeader idr_packet = GetDefaultPacket();
317 AddIdr(&idr_packet, 0);
318 idr_packet.header.payloadType = kPayloadType;
319 idr_packet.type.Video.is_first_packet_in_frame = true;
320 idr_packet.header.sequenceNumber = 2;
321 idr_packet.header.markerBit = 1;
322 idr_packet.type.Video.is_first_packet_in_frame = true;
323 idr_packet.frameType = kVideoFrameKey;
324 idr_packet.type.Video.codec = kRtpVideoH264;
325 data.insert(data.end(), {1, 2, 3});
326 mock_on_complete_frame_callback_.AppendExpectedBitstream(
327 kH264StartCode, sizeof(kH264StartCode));
328 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
329 data.size());
330 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
nisseb1f2ff92017-06-09 04:01:55 -0700331 rtp_video_stream_receiver_->OnReceivedPayloadData(data.data(), data.size(),
332 &idr_packet);
johan62d02c32017-01-24 04:38:27 -0800333}
334
nisseb1f2ff92017-06-09 04:01:55 -0700335TEST_F(RtpVideoStreamReceiverTest, PaddingInMediaStream) {
philipel54ca9192017-03-21 05:45:18 -0700336 WebRtcRTPHeader header = GetDefaultPacket();
337 std::vector<uint8_t> data;
338 data.insert(data.end(), {1, 2, 3});
339 header.header.payloadType = 99;
340 header.type.Video.is_first_packet_in_frame = true;
341 header.header.sequenceNumber = 2;
342 header.header.markerBit = true;
343 header.frameType = kVideoFrameKey;
344 header.type.Video.codec = kRtpVideoGeneric;
345 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
346 data.size());
347
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 &header);
philipel54ca9192017-03-21 05:45:18 -0700351
352 header.header.sequenceNumber = 3;
nisseb1f2ff92017-06-09 04:01:55 -0700353 rtp_video_stream_receiver_->OnReceivedPayloadData(nullptr, 0, &header);
philipel54ca9192017-03-21 05:45:18 -0700354
355 header.frameType = kVideoFrameDelta;
356 header.header.sequenceNumber = 4;
357 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
nisseb1f2ff92017-06-09 04:01:55 -0700358 rtp_video_stream_receiver_->OnReceivedPayloadData(data.data(), data.size(),
359 &header);
philipel54ca9192017-03-21 05:45:18 -0700360
361 header.header.sequenceNumber = 6;
nisseb1f2ff92017-06-09 04:01:55 -0700362 rtp_video_stream_receiver_->OnReceivedPayloadData(data.data(), data.size(),
363 &header);
philipel54ca9192017-03-21 05:45:18 -0700364
365 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
366 header.header.sequenceNumber = 5;
nisseb1f2ff92017-06-09 04:01:55 -0700367 rtp_video_stream_receiver_->OnReceivedPayloadData(nullptr, 0, &header);
philipel54ca9192017-03-21 05:45:18 -0700368}
369
nisseb1f2ff92017-06-09 04:01:55 -0700370TEST_F(RtpVideoStreamReceiverTest, RequestKeyframeIfFirstFrameIsDelta) {
philipel2c53b132017-05-16 08:06:30 -0700371 WebRtcRTPHeader rtp_header;
372 const std::vector<uint8_t> data({1, 2, 3, 4});
373 memset(&rtp_header, 0, sizeof(rtp_header));
374 rtp_header.header.sequenceNumber = 1;
375 rtp_header.header.markerBit = 1;
376 rtp_header.type.Video.is_first_packet_in_frame = true;
377 rtp_header.frameType = kVideoFrameDelta;
378 rtp_header.type.Video.codec = kRtpVideoGeneric;
379
380 EXPECT_CALL(mock_key_frame_request_sender_, RequestKeyFrame());
nisseb1f2ff92017-06-09 04:01:55 -0700381 rtp_video_stream_receiver_->OnReceivedPayloadData(data.data(), data.size(),
382 &rtp_header);
philipel2c53b132017-05-16 08:06:30 -0700383}
384
eladalonc0d481a2017-08-02 07:39:07 -0700385TEST_F(RtpVideoStreamReceiverTest, SecondarySinksGetRtpNotifications) {
386 rtp_video_stream_receiver_->StartReceive();
387
388 MockRtpPacketSink secondary_sink_1;
389 MockRtpPacketSink secondary_sink_2;
390
391 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink_1);
392 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink_2);
393
394 auto rtp_packet = CreateRtpPacketReceived();
395 EXPECT_CALL(secondary_sink_1, OnRtpPacket(SamePacketAs(*rtp_packet)));
396 EXPECT_CALL(secondary_sink_2, OnRtpPacket(SamePacketAs(*rtp_packet)));
397
398 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
399
400 // Test tear-down.
401 rtp_video_stream_receiver_->StopReceive();
402 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink_1);
403 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink_2);
404}
405
406TEST_F(RtpVideoStreamReceiverTest, RemovedSecondarySinksGetNoRtpNotifications) {
407 rtp_video_stream_receiver_->StartReceive();
408
409 MockRtpPacketSink secondary_sink;
410
411 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
412 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
413
414 auto rtp_packet = CreateRtpPacketReceived();
415
416 EXPECT_CALL(secondary_sink, OnRtpPacket(_)).Times(0);
417
418 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
419
420 // Test tear-down.
421 rtp_video_stream_receiver_->StopReceive();
422}
423
424TEST_F(RtpVideoStreamReceiverTest,
425 OnlyRemovedSecondarySinksExcludedFromNotifications) {
426 rtp_video_stream_receiver_->StartReceive();
427
428 MockRtpPacketSink kept_secondary_sink;
429 MockRtpPacketSink removed_secondary_sink;
430
431 rtp_video_stream_receiver_->AddSecondarySink(&kept_secondary_sink);
432 rtp_video_stream_receiver_->AddSecondarySink(&removed_secondary_sink);
433 rtp_video_stream_receiver_->RemoveSecondarySink(&removed_secondary_sink);
434
435 auto rtp_packet = CreateRtpPacketReceived();
436 EXPECT_CALL(kept_secondary_sink, OnRtpPacket(SamePacketAs(*rtp_packet)));
437
438 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
439
440 // Test tear-down.
441 rtp_video_stream_receiver_->StopReceive();
442 rtp_video_stream_receiver_->RemoveSecondarySink(&kept_secondary_sink);
443}
444
445TEST_F(RtpVideoStreamReceiverTest,
446 SecondariesOfNonStartedStreamGetNoNotifications) {
447 // Explicitly showing that the stream is not in the |started| state,
448 // regardless of whether streams start out |started| or |stopped|.
449 rtp_video_stream_receiver_->StopReceive();
450
451 MockRtpPacketSink secondary_sink;
452 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
453
454 auto rtp_packet = CreateRtpPacketReceived();
455 EXPECT_CALL(secondary_sink, OnRtpPacket(_)).Times(0);
456
457 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
458
459 // Test tear-down.
460 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
461}
462
463#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
464TEST_F(RtpVideoStreamReceiverTest, RepeatedSecondarySinkDisallowed) {
465 MockRtpPacketSink secondary_sink;
466
467 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
468 EXPECT_DEATH(rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink),
469 "");
470
471 // Test tear-down.
472 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
473}
474#endif
475
johan62d02c32017-01-24 04:38:27 -0800476} // namespace webrtc