blob: 8ca827c94bd78d3e242d8d04c53ffa389eab7246 [file] [log] [blame]
eladalon760a0762017-05-31 09:12:25 -07001/*
2 * Copyright (c) 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
11#include "webrtc/call/rtp_demuxer.h"
12
13#include <memory>
eladalond0244c22017-06-08 04:19:13 -070014#include <string>
eladalon760a0762017-05-31 09:12:25 -070015
16#include "webrtc/base/arraysize.h"
17#include "webrtc/base/checks.h"
18#include "webrtc/base/ptr_util.h"
nissed76b7b22017-06-01 04:02:35 -070019#include "webrtc/call/rtp_packet_sink_interface.h"
eladalond0244c22017-06-08 04:19:13 -070020#include "webrtc/modules/rtp_rtcp/include/rtp_header_extension_map.h"
21#include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h"
eladalon760a0762017-05-31 09:12:25 -070022#include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h"
23#include "webrtc/test/gmock.h"
24#include "webrtc/test/gtest.h"
25
26namespace webrtc {
27
28namespace {
29
30using ::testing::_;
eladalond0244c22017-06-08 04:19:13 -070031using ::testing::AtLeast;
32using ::testing::InSequence;
33using ::testing::NiceMock;
eladalon760a0762017-05-31 09:12:25 -070034
35class MockRtpPacketSink : public RtpPacketSinkInterface {
36 public:
37 MOCK_METHOD1(OnRtpPacket, void(const RtpPacketReceived&));
38};
39
eladalond0244c22017-06-08 04:19:13 -070040MATCHER_P(SamePacketAs, other, "") {
41 return arg.Ssrc() == other.Ssrc() &&
42 arg.SequenceNumber() == other.SequenceNumber();
eladalon760a0762017-05-31 09:12:25 -070043}
44
eladalond0244c22017-06-08 04:19:13 -070045std::unique_ptr<RtpPacketReceived> CreateRtpPacketReceived(
46 uint32_t ssrc,
47 size_t sequence_number = 0) {
48 // |sequence_number| is declared |size_t| to prevent ugly casts when calling
49 // the function, but should in reality always be a |uint16_t|.
50 EXPECT_LT(sequence_number, 1u << 16);
51
eladalon760a0762017-05-31 09:12:25 -070052 auto packet = rtc::MakeUnique<RtpPacketReceived>();
53 packet->SetSsrc(ssrc);
eladalond0244c22017-06-08 04:19:13 -070054 packet->SetSequenceNumber(static_cast<uint16_t>(sequence_number));
eladalon760a0762017-05-31 09:12:25 -070055 return packet;
56}
57
eladalond0244c22017-06-08 04:19:13 -070058std::unique_ptr<RtpPacketReceived> CreateRtpPacketReceivedWithRsid(
59 const std::string& rsid,
60 uint32_t ssrc,
61 size_t sequence_number = 0) {
62 // |sequence_number| is declared |size_t| to prevent ugly casts when calling
63 // the function, but should in reality always be a |uint16_t|.
64 EXPECT_LT(sequence_number, 1u << 16);
eladalon760a0762017-05-31 09:12:25 -070065
eladalond0244c22017-06-08 04:19:13 -070066 const int rsid_extension_id = 6;
67 RtpPacketReceived::ExtensionManager extension_manager;
68 extension_manager.Register<RtpStreamId>(rsid_extension_id);
69 auto packet = rtc::MakeUnique<RtpPacketReceived>(&extension_manager);
70 packet->SetExtension<RtpStreamId>(rsid);
71 packet->SetSsrc(ssrc);
72 packet->SetSequenceNumber(static_cast<uint16_t>(sequence_number));
73 return packet;
74}
eladalon760a0762017-05-31 09:12:25 -070075
eladalond0244c22017-06-08 04:19:13 -070076TEST(RtpDemuxerTest, OnRtpPacketCalledOnCorrectSinkBySsrc) {
eladalon760a0762017-05-31 09:12:25 -070077 RtpDemuxer demuxer;
eladalon760a0762017-05-31 09:12:25 -070078
eladalond0244c22017-06-08 04:19:13 -070079 constexpr uint32_t ssrcs[] = {101, 202, 303};
80 MockRtpPacketSink sinks[arraysize(ssrcs)];
81 for (size_t i = 0; i < arraysize(ssrcs); i++) {
82 demuxer.AddSink(ssrcs[i], &sinks[i]);
83 }
84
85 for (size_t i = 0; i < arraysize(ssrcs); i++) {
86 auto packet = CreateRtpPacketReceived(ssrcs[i]);
87 EXPECT_CALL(sinks[i], OnRtpPacket(SamePacketAs(*packet))).Times(1);
88 EXPECT_TRUE(demuxer.OnRtpPacket(*packet));
89 }
90
91 // Test tear-down
92 for (const auto& sink : sinks) {
93 demuxer.RemoveSink(&sink);
eladalon760a0762017-05-31 09:12:25 -070094 }
95}
96
eladalond0244c22017-06-08 04:19:13 -070097TEST(RtpDemuxerTest, OnRtpPacketCalledOnCorrectSinkByRsid) {
98 RtpDemuxer demuxer;
99
100 const std::string rsids[] = {"a", "b", "c"};
101 MockRtpPacketSink sinks[arraysize(rsids)];
102 for (size_t i = 0; i < arraysize(rsids); i++) {
103 demuxer.AddSink(rsids[i], &sinks[i]);
104 }
105
106 for (size_t i = 0; i < arraysize(rsids); i++) {
107 auto packet =
108 CreateRtpPacketReceivedWithRsid(rsids[i], static_cast<uint32_t>(i), i);
109 EXPECT_CALL(sinks[i], OnRtpPacket(SamePacketAs(*packet))).Times(1);
110 EXPECT_TRUE(demuxer.OnRtpPacket(*packet));
111 }
112
113 // Test tear-down
114 for (const auto& sink : sinks) {
115 demuxer.RemoveSink(&sink);
116 }
117}
118
119TEST(RtpDemuxerTest, PacketsDeliveredInRightOrder) {
120 RtpDemuxer demuxer;
121
122 constexpr uint32_t ssrcs[] = {101, 202, 303};
123 MockRtpPacketSink sinks[arraysize(ssrcs)];
124 for (size_t i = 0; i < arraysize(ssrcs); i++) {
125 demuxer.AddSink(ssrcs[i], &sinks[i]);
126 }
127
128 std::unique_ptr<RtpPacketReceived> packets[5];
129 for (size_t i = 0; i < arraysize(packets); i++) {
130 packets[i] = CreateRtpPacketReceived(ssrcs[0], i);
131 }
132
133 InSequence sequence;
134 for (const auto& packet : packets) {
135 EXPECT_CALL(sinks[0], OnRtpPacket(SamePacketAs(*packet))).Times(1);
136 }
137
138 for (const auto& packet : packets) {
139 EXPECT_TRUE(demuxer.OnRtpPacket(*packet));
140 }
141
142 // Test tear-down
143 for (const auto& sink : sinks) {
144 demuxer.RemoveSink(&sink);
145 }
146}
147
148TEST(RtpDemuxerTest, MultipleSinksMappedToSameSsrc) {
149 RtpDemuxer demuxer;
150
151 MockRtpPacketSink sinks[3];
152 constexpr uint32_t ssrc = 404;
153 for (auto& sink : sinks) {
154 demuxer.AddSink(ssrc, &sink);
eladalon760a0762017-05-31 09:12:25 -0700155 }
156
157 // Reception of an RTP packet associated with the shared SSRC triggers the
eladalond0244c22017-06-08 04:19:13 -0700158 // callback on all of the sinks associated with it.
159 auto packet = CreateRtpPacketReceived(ssrc);
160 for (auto& sink : sinks) {
161 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet)));
eladalon760a0762017-05-31 09:12:25 -0700162 }
eladalond0244c22017-06-08 04:19:13 -0700163 EXPECT_TRUE(demuxer.OnRtpPacket(*packet));
eladalon760a0762017-05-31 09:12:25 -0700164
eladalond0244c22017-06-08 04:19:13 -0700165 // Test tear-down
166 for (const auto& sink : sinks) {
167 demuxer.RemoveSink(&sink);
eladalon760a0762017-05-31 09:12:25 -0700168 }
169}
170
eladalond0244c22017-06-08 04:19:13 -0700171TEST(RtpDemuxerTest, SinkMappedToMultipleSsrcs) {
172 RtpDemuxer demuxer;
173
174 constexpr uint32_t ssrcs[] = {404, 505, 606};
175 MockRtpPacketSink sink;
176 for (uint32_t ssrc : ssrcs) {
177 demuxer.AddSink(ssrc, &sink);
eladalon760a0762017-05-31 09:12:25 -0700178 }
179
180 // The sink which is associated with multiple SSRCs gets the callback
181 // triggered for each of those SSRCs.
eladalond0244c22017-06-08 04:19:13 -0700182 for (uint32_t ssrc : ssrcs) {
eladalon760a0762017-05-31 09:12:25 -0700183 auto packet = CreateRtpPacketReceived(ssrc);
eladalond0244c22017-06-08 04:19:13 -0700184 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet)));
185 EXPECT_TRUE(demuxer.OnRtpPacket(*packet));
eladalon760a0762017-05-31 09:12:25 -0700186 }
187
eladalond0244c22017-06-08 04:19:13 -0700188 // Test tear-down
189 demuxer.RemoveSink(&sink);
eladalon760a0762017-05-31 09:12:25 -0700190}
191
eladalond0244c22017-06-08 04:19:13 -0700192TEST(RtpDemuxerTest, NoCallbackOnSsrcSinkRemovedBeforeFirstPacket) {
193 RtpDemuxer demuxer;
194
195 constexpr uint32_t ssrc = 404;
196 MockRtpPacketSink sink;
197 demuxer.AddSink(ssrc, &sink);
198
199 ASSERT_TRUE(demuxer.RemoveSink(&sink));
200
201 // The removed sink does not get callbacks.
202 auto packet = CreateRtpPacketReceived(ssrc);
203 EXPECT_CALL(sink, OnRtpPacket(_)).Times(0); // Not called.
204 EXPECT_FALSE(demuxer.OnRtpPacket(*packet));
205}
206
207TEST(RtpDemuxerTest, NoCallbackOnSsrcSinkRemovedAfterFirstPacket) {
208 RtpDemuxer demuxer;
209
210 constexpr uint32_t ssrc = 404;
211 NiceMock<MockRtpPacketSink> sink;
212 demuxer.AddSink(ssrc, &sink);
213
214 InSequence sequence;
215 uint16_t seq_num;
216 for (seq_num = 0; seq_num < 10; seq_num++) {
217 ASSERT_TRUE(demuxer.OnRtpPacket(*CreateRtpPacketReceived(ssrc, seq_num)));
eladalon760a0762017-05-31 09:12:25 -0700218 }
219
eladalond0244c22017-06-08 04:19:13 -0700220 ASSERT_TRUE(demuxer.RemoveSink(&sink));
eladalon760a0762017-05-31 09:12:25 -0700221
eladalond0244c22017-06-08 04:19:13 -0700222 // The removed sink does not get callbacks.
223 auto packet = CreateRtpPacketReceived(ssrc, seq_num);
224 EXPECT_CALL(sink, OnRtpPacket(_)).Times(0); // Not called.
225 EXPECT_FALSE(demuxer.OnRtpPacket(*packet));
226}
227
228TEST(RtpDemuxerTest, RepeatedSsrcAssociationsDoNotTriggerRepeatedCallbacks) {
229 RtpDemuxer demuxer;
230
231 constexpr uint32_t ssrc = 111;
232 MockRtpPacketSink sink;
233
234 demuxer.AddSink(ssrc, &sink);
235 demuxer.AddSink(ssrc, &sink);
236
237 auto packet = CreateRtpPacketReceived(ssrc);
238 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1);
239 EXPECT_TRUE(demuxer.OnRtpPacket(*packet));
240
241 // Test tear-down
242 demuxer.RemoveSink(&sink);
243}
244
245TEST(RtpDemuxerTest, RemoveSinkReturnsFalseForNeverAddedSink) {
246 RtpDemuxer demuxer;
247 MockRtpPacketSink sink;
248
249 EXPECT_FALSE(demuxer.RemoveSink(&sink));
250}
251
252TEST(RtpDemuxerTest, RemoveSinkReturnsTrueForPreviouslyAddedSsrcSink) {
253 RtpDemuxer demuxer;
254
255 constexpr uint32_t ssrc = 101;
256 MockRtpPacketSink sink;
257 demuxer.AddSink(ssrc, &sink);
258
259 EXPECT_TRUE(demuxer.RemoveSink(&sink));
260}
261
262TEST(RtpDemuxerTest,
263 RemoveSinkReturnsTrueForUnresolvedPreviouslyAddedRsidSink) {
264 RtpDemuxer demuxer;
265
266 const std::string rsid = "a";
267 MockRtpPacketSink sink;
268 demuxer.AddSink(rsid, &sink);
269
270 EXPECT_TRUE(demuxer.RemoveSink(&sink));
271}
272
273TEST(RtpDemuxerTest, RemoveSinkReturnsTrueForResolvedPreviouslyAddedRsidSink) {
274 RtpDemuxer demuxer;
275
276 const std::string rsid = "a";
277 constexpr uint32_t ssrc = 101;
278 NiceMock<MockRtpPacketSink> sink;
279 demuxer.AddSink(rsid, &sink);
280 ASSERT_TRUE(
281 demuxer.OnRtpPacket(*CreateRtpPacketReceivedWithRsid(rsid, ssrc)));
282
283 EXPECT_TRUE(demuxer.RemoveSink(&sink));
284}
285
286TEST(RtpDemuxerTest, OnRtpPacketCalledForRsidSink) {
287 RtpDemuxer demuxer;
288
289 MockRtpPacketSink sink;
290 const std::string rsid = "a";
291 demuxer.AddSink(rsid, &sink);
292
293 // Create a sequence of RTP packets, where only the first one actually
294 // mentions the RSID.
295 std::unique_ptr<RtpPacketReceived> packets[5];
296 constexpr uint32_t rsid_ssrc = 111;
297 packets[0] = CreateRtpPacketReceivedWithRsid(rsid, rsid_ssrc);
298 for (size_t i = 1; i < arraysize(packets); i++) {
299 packets[i] = CreateRtpPacketReceived(rsid_ssrc, i);
eladalon760a0762017-05-31 09:12:25 -0700300 }
eladalond0244c22017-06-08 04:19:13 -0700301
302 // The first packet associates the RSID with the SSRC, thereby allowing the
303 // demuxer to correctly demux all of the packets.
304 InSequence sequence;
305 for (const auto& packet : packets) {
306 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1);
307 }
308 for (const auto& packet : packets) {
309 EXPECT_TRUE(demuxer.OnRtpPacket(*packet));
310 }
311
312 // Test tear-down
313 demuxer.RemoveSink(&sink);
314}
315
316TEST(RtpDemuxerTest, NoCallbackOnRsidSinkRemovedBeforeFirstPacket) {
317 RtpDemuxer demuxer;
318
319 MockRtpPacketSink sink;
320 const std::string rsid = "a";
321 demuxer.AddSink(rsid, &sink);
322
323 // Sink removed - it won't get triggers even if packets with its RSID arrive.
324 ASSERT_TRUE(demuxer.RemoveSink(&sink));
325
326 constexpr uint32_t ssrc = 111;
327 auto packet = CreateRtpPacketReceivedWithRsid(rsid, ssrc);
328 EXPECT_CALL(sink, OnRtpPacket(_)).Times(0); // Not called.
329 EXPECT_FALSE(demuxer.OnRtpPacket(*packet));
330}
331
332TEST(RtpDemuxerTest, NoCallbackOnRsidSinkRemovedAfterFirstPacket) {
333 RtpDemuxer demuxer;
334
335 NiceMock<MockRtpPacketSink> sink;
336 const std::string rsid = "a";
337 demuxer.AddSink(rsid, &sink);
338
339 InSequence sequence;
340 constexpr uint32_t ssrc = 111;
341 uint16_t seq_num;
342 for (seq_num = 0; seq_num < 10; seq_num++) {
343 auto packet = CreateRtpPacketReceivedWithRsid(rsid, ssrc, seq_num);
344 ASSERT_TRUE(demuxer.OnRtpPacket(*packet));
345 }
346
347 // Sink removed - it won't get triggers even if packets with its RSID arrive.
348 ASSERT_TRUE(demuxer.RemoveSink(&sink));
349
350 auto packet = CreateRtpPacketReceivedWithRsid(rsid, ssrc, seq_num);
351 EXPECT_CALL(sink, OnRtpPacket(_)).Times(0); // Not called.
352 EXPECT_FALSE(demuxer.OnRtpPacket(*packet));
353}
354
355// The RSID to SSRC mapping should be one-to-one. If we end up receiving
356// two (or more) packets with the same SSRC, but different RSIDs, we guarantee
357// remembering the first one; no guarantees are made about further associations.
358TEST(RtpDemuxerTest, FirstSsrcAssociatedWithAnRsidIsNotForgotten) {
359 RtpDemuxer demuxer;
360
361 // Each sink has a distinct RSID.
362 MockRtpPacketSink sink_a;
363 const std::string rsid_a = "a";
364 demuxer.AddSink(rsid_a, &sink_a);
365
366 MockRtpPacketSink sink_b;
367 const std::string rsid_b = "b";
368 demuxer.AddSink(rsid_b, &sink_b);
369
370 InSequence sequence; // Verify that the order of delivery is unchanged.
371
372 constexpr uint32_t shared_ssrc = 100;
373
374 // First a packet with |rsid_a| is received, and |sink_a| is associated with
375 // its SSRC.
376 auto packet_a = CreateRtpPacketReceivedWithRsid(rsid_a, shared_ssrc, 10);
377 EXPECT_CALL(sink_a, OnRtpPacket(SamePacketAs(*packet_a))).Times(1);
378 EXPECT_TRUE(demuxer.OnRtpPacket(*packet_a));
379
380 // Second, a packet with |rsid_b| is received. Its RSID is ignored.
381 auto packet_b = CreateRtpPacketReceivedWithRsid(rsid_b, shared_ssrc, 20);
382 EXPECT_CALL(sink_a, OnRtpPacket(SamePacketAs(*packet_b))).Times(1);
383 EXPECT_TRUE(demuxer.OnRtpPacket(*packet_b));
384
385 // Known edge-case; adding a new RSID association makes us re-examine all
386 // SSRCs. |sink_b| may or may not be associated with the SSRC now; we make
387 // no promises on that. We do however still guarantee that |sink_a| still
388 // receives the new packets.
389 MockRtpPacketSink sink_ignored;
390 demuxer.AddSink("ignored", &sink_ignored);
391 auto packet_c = CreateRtpPacketReceivedWithRsid(rsid_b, shared_ssrc, 30);
392 EXPECT_CALL(sink_a, OnRtpPacket(SamePacketAs(*packet_c))).Times(1);
393 EXPECT_CALL(sink_b, OnRtpPacket(SamePacketAs(*packet_c))).Times(AtLeast(0));
394 EXPECT_TRUE(demuxer.OnRtpPacket(*packet_c));
395
396 // Test tear-down
397 demuxer.RemoveSink(&sink_a);
398 demuxer.RemoveSink(&sink_b);
399 demuxer.RemoveSink(&sink_ignored);
400}
401
402TEST(RtpDemuxerTest, MultipleRsidsOnSameSink) {
403 RtpDemuxer demuxer;
404
405 MockRtpPacketSink sink;
406 const std::string rsids[] = {"a", "b", "c"};
407
408 for (const std::string& rsid : rsids) {
409 demuxer.AddSink(rsid, &sink);
410 }
411
412 InSequence sequence;
413 for (size_t i = 0; i < arraysize(rsids); i++) {
414 // Assign different SSRCs and sequence numbers to all packets.
415 const uint32_t ssrc = 1000 + static_cast<uint32_t>(i);
416 const uint16_t sequence_number = 50 + static_cast<uint16_t>(i);
417 auto packet =
418 CreateRtpPacketReceivedWithRsid(rsids[i], ssrc, sequence_number);
419 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1);
420 EXPECT_TRUE(demuxer.OnRtpPacket(*packet));
421 }
422
423 // Test tear-down
424 demuxer.RemoveSink(&sink);
425}
426
427TEST(RtpDemuxerTest, SinkWithBothRsidAndSsrcAssociations) {
428 RtpDemuxer demuxer;
429
430 MockRtpPacketSink sink;
431 constexpr uint32_t standalone_ssrc = 10101;
432 constexpr uint32_t rsid_ssrc = 20202;
433 const std::string rsid = "a";
434
435 demuxer.AddSink(standalone_ssrc, &sink);
436 demuxer.AddSink(rsid, &sink);
437
438 InSequence sequence;
439
440 auto ssrc_packet = CreateRtpPacketReceived(standalone_ssrc, 11);
441 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*ssrc_packet))).Times(1);
442 EXPECT_TRUE(demuxer.OnRtpPacket(*ssrc_packet));
443
444 auto rsid_packet = CreateRtpPacketReceivedWithRsid(rsid, rsid_ssrc, 22);
445 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*rsid_packet))).Times(1);
446 EXPECT_TRUE(demuxer.OnRtpPacket(*rsid_packet));
447
448 // Test tear-down
449 demuxer.RemoveSink(&sink);
450}
451
452TEST(RtpDemuxerTest, AssociatingByRsidAndBySsrcCannotTriggerDoubleCall) {
453 RtpDemuxer demuxer;
454 MockRtpPacketSink sink;
455
456 constexpr uint32_t ssrc = 10101;
457 demuxer.AddSink(ssrc, &sink);
458
459 const std::string rsid = "a";
460 demuxer.AddSink(rsid, &sink);
461
462 constexpr uint16_t seq_num = 999;
463 auto packet = CreateRtpPacketReceivedWithRsid(rsid, ssrc, seq_num);
464 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1);
465 EXPECT_TRUE(demuxer.OnRtpPacket(*packet));
466
467 // Test tear-down
468 demuxer.RemoveSink(&sink);
eladalon760a0762017-05-31 09:12:25 -0700469}
470
471#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
eladalond0244c22017-06-08 04:19:13 -0700472TEST(RtpDemuxerTest, RsidMustBeNonEmpty) {
473 RtpDemuxer demuxer;
474 MockRtpPacketSink sink;
475 EXPECT_DEATH(demuxer.AddSink("", &sink), "");
476}
477
478TEST(RtpDemuxerTest, RsidMustBeAlphaNumeric) {
479 RtpDemuxer demuxer;
480 MockRtpPacketSink sink;
481 EXPECT_DEATH(demuxer.AddSink("a_3", &sink), "");
482}
483
484TEST(RtpDemuxerTest, RsidMustNotExceedMaximumLength) {
485 RtpDemuxer demuxer;
486 MockRtpPacketSink sink;
487 std::string rsid(StreamId::kMaxSize + 1, 'a');
488 EXPECT_DEATH(demuxer.AddSink(rsid, &sink), "");
489}
490
491TEST(RtpDemuxerTest, RepeatedRsidAssociationsDisallowed) {
492 RtpDemuxer demuxer;
493 MockRtpPacketSink sink;
494 demuxer.AddSink("a", &sink);
495 EXPECT_DEATH(demuxer.AddSink("a", &sink), "");
eladalon760a0762017-05-31 09:12:25 -0700496}
497#endif
498
499} // namespace
500} // namespace webrtc