OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/call/rtp_demuxer.h" | 11 #include "webrtc/call/rtp_demuxer.h" |
12 | 12 |
13 #include <memory> | 13 #include <memory> |
14 #include <string> | |
14 | 15 |
15 #include "webrtc/base/arraysize.h" | 16 #include "webrtc/base/arraysize.h" |
16 #include "webrtc/base/checks.h" | 17 #include "webrtc/base/checks.h" |
17 #include "webrtc/base/ptr_util.h" | 18 #include "webrtc/base/ptr_util.h" |
19 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h" | |
20 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h" | |
18 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h" | 21 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h" |
19 #include "webrtc/test/gmock.h" | 22 #include "webrtc/test/gmock.h" |
20 #include "webrtc/test/gtest.h" | 23 #include "webrtc/test/gtest.h" |
21 | 24 |
22 namespace webrtc { | 25 namespace webrtc { |
23 | 26 |
24 namespace { | 27 namespace { |
25 | 28 |
26 using ::testing::_; | 29 using ::testing::_; |
30 using ::testing::AtLeast; | |
31 using ::testing::InSequence; | |
27 | 32 |
28 class MockRtpPacketSink : public RtpPacketSinkInterface { | 33 class MockRtpPacketSink : public RtpPacketSinkInterface { |
29 public: | 34 public: |
30 MOCK_METHOD1(OnRtpPacket, void(const RtpPacketReceived&)); | 35 MOCK_METHOD1(OnRtpPacket, void(const RtpPacketReceived&)); |
31 }; | 36 }; |
32 | 37 |
33 constexpr uint32_t kSsrcs[] = {101, 202, 303}; | 38 MATCHER_P(SamePacketAs, other, "") { |
34 | 39 return arg.Ssrc() == other.Ssrc() && |
35 MATCHER_P(SsrcSameAsIn, other, "") { | 40 arg.SequenceNumber() == other.SequenceNumber(); |
36 return arg.Ssrc() == other.Ssrc(); | 41 } |
37 } | 42 |
38 | 43 std::unique_ptr<RtpPacketReceived> CreateRtpPacketReceived( |
39 std::unique_ptr<RtpPacketReceived> CreateRtpPacketReceived(uint32_t ssrc) { | 44 uint32_t ssrc, |
40 auto packet = rtc::MakeUnique<RtpPacketReceived>(); | 45 uint16_t sequence_number = 0, |
46 const std::string* rsid = nullptr) { | |
47 std::unique_ptr<RtpPacketReceived> packet; | |
48 if (rsid == nullptr) { | |
49 packet = rtc::MakeUnique<RtpPacketReceived>(); | |
50 } else { | |
51 const int kRsidExtensionId = 6; | |
52 webrtc::RtpHeaderExtensionMap extensions; | |
53 extensions.Register<webrtc::RtpStreamId>(kRsidExtensionId); | |
54 rtp::Packet::ExtensionManager extensions_manager(extensions); | |
danilchap
2017/06/02 17:42:19
why not just
RtpPacketReceieved::ExtensionManager
eladalon
2017/06/02 19:44:04
1. I'd like to make it very clear when the packet
danilchap
2017/06/07 13:45:41
Good reason!
Did you consider two functions to mak
eladalon
2017/06/07 19:30:00
Done.
| |
55 packet = rtc::MakeUnique<RtpPacketReceived>(&extensions_manager); | |
56 packet->SetExtension<webrtc::RtpStreamId>(*rsid); | |
57 } | |
41 packet->SetSsrc(ssrc); | 58 packet->SetSsrc(ssrc); |
59 packet->SetSequenceNumber(sequence_number); | |
42 return packet; | 60 return packet; |
43 } | 61 } |
44 | 62 |
45 class RtpDemuxerTest : public ::testing::Test { | 63 class RtpDemuxerTest : public ::testing::Test { |
46 protected: | 64 protected: |
47 RtpDemuxerTest() { | 65 RtpDemuxerTest() = default; |
danilchap
2017/06/02 17:42:19
feel free to omit default constructor/destructor f
eladalon
2017/06/02 19:44:04
Done.
| |
48 for (size_t i = 0; i < arraysize(sinks); i++) { | 66 ~RtpDemuxerTest() override = default; |
49 demuxer.AddSink(kSsrcs[i], &sinks[i]); | |
50 } | |
51 } | |
52 | |
53 ~RtpDemuxerTest() override { | |
54 for (auto& sink : sinks) { | |
55 EXPECT_EQ(demuxer.RemoveSink(&sink), 1u); | |
56 } | |
57 } | |
58 | 67 |
59 RtpDemuxer demuxer; | 68 RtpDemuxer demuxer; |
danilchap
2017/06/02 17:42:20
fixture that small easy not to use at all:
just an
eladalon
2017/06/02 19:44:04
Done.
| |
60 MockRtpPacketSink sinks[arraysize(kSsrcs)]; | |
61 }; | 69 }; |
62 | 70 |
63 TEST_F(RtpDemuxerTest, OnRtpPacketCalledOnCorrectSink) { | 71 TEST_F(RtpDemuxerTest, OnRtpPacketCalledOnCorrectSink) { |
72 constexpr uint32_t ssrcs[] = {101, 202, 303}; | |
73 MockRtpPacketSink sinks[arraysize(ssrcs)]; | |
74 for (size_t i = 0; i < arraysize(ssrcs); i++) { | |
75 demuxer.AddSink(ssrcs[i], &sinks[i]); | |
76 } | |
77 | |
64 for (size_t i = 0; i < arraysize(sinks); i++) { | 78 for (size_t i = 0; i < arraysize(sinks); i++) { |
65 auto packet = CreateRtpPacketReceived(kSsrcs[i]); | 79 auto packet = CreateRtpPacketReceived(ssrcs[i]); |
66 EXPECT_CALL(sinks[i], OnRtpPacket(SsrcSameAsIn(*packet))); | 80 EXPECT_CALL(sinks[i], OnRtpPacket(SamePacketAs(*packet))).Times(1); |
danilchap
2017/06/02 17:42:19
.Times(1) can by omitted if you wish
https://githu
eladalon
2017/06/02 19:44:04
Some people see it as self-documentation. I am sti
| |
67 demuxer.OnRtpPacket(*packet); | 81 EXPECT_EQ(demuxer.OnRtpPacket(*packet), true); |
danilchap
2017/06/02 17:42:19
EXPECT_TRUE
eladalon
2017/06/02 19:44:04
Yes, that does look silly.Almost like "if (x == tr
| |
82 } | |
83 | |
84 // Test tear-down | |
danilchap
2017/06/02 17:42:19
end comments with a '.'
eladalon
2017/06/02 19:44:04
I believe full stops belong at the end of a senten
| |
85 for (size_t i = 0; i < arraysize(ssrcs); i++) { | |
86 EXPECT_EQ(demuxer.RemoveSink(&sinks[i]), 1u); | |
87 } | |
88 } | |
89 | |
90 TEST_F(RtpDemuxerTest, PacketsDeliveredInRightOrder) { | |
91 constexpr uint32_t ssrcs[] = {101, 202, 303}; | |
92 MockRtpPacketSink sinks[arraysize(ssrcs)]; | |
93 for (size_t i = 0; i < arraysize(ssrcs); i++) { | |
94 demuxer.AddSink(ssrcs[i], &sinks[i]); | |
95 } | |
96 | |
97 std::unique_ptr<RtpPacketReceived> packets[5]; | |
98 for (size_t i = 0; i < arraysize(packets); i++) { | |
99 packets[i] = CreateRtpPacketReceived(ssrcs[0], static_cast<uint16_t>(i)); | |
danilchap
2017/06/02 17:42:20
if you wish to be more explicit, then beeing expli
eladalon
2017/06/02 19:44:04
I'm actually doing this to avoid compiler errors.
| |
100 } | |
101 | |
102 InSequence sequence; | |
103 for (auto& packet : packets) { | |
danilchap
2017/06/02 17:42:19
may by const auto& since you do not change the val
eladalon
2017/06/02 19:44:04
Done.
| |
104 EXPECT_CALL(sinks[0], OnRtpPacket(SamePacketAs(*packet))).Times(1); | |
105 } | |
106 | |
107 for (auto& packet : packets) { | |
108 EXPECT_EQ(demuxer.OnRtpPacket(*packet), true); | |
109 } | |
110 | |
111 // Test tear-down | |
112 for (size_t i = 0; i < arraysize(ssrcs); i++) { | |
113 EXPECT_EQ(demuxer.RemoveSink(&sinks[i]), 1u); | |
68 } | 114 } |
69 } | 115 } |
70 | 116 |
71 TEST_F(RtpDemuxerTest, MultipleSinksMappedToSameSsrc) { | 117 TEST_F(RtpDemuxerTest, MultipleSinksMappedToSameSsrc) { |
72 // |sinks| associated with different SSRCs each. Add a few additional sinks | 118 MockRtpPacketSink sinks[3]; |
73 // that are all associated with one new, distinct SSRC. | 119 constexpr uint32_t ssrc = 404; |
74 MockRtpPacketSink same_ssrc_sinks[arraysize(sinks)]; | 120 for (auto& sink : sinks) { |
75 constexpr uint32_t kSharedSsrc = 404; | 121 demuxer.AddSink(ssrc, &sink); |
76 for (auto& sink : same_ssrc_sinks) { | |
77 demuxer.AddSink(kSharedSsrc, &sink); | |
78 } | 122 } |
79 | 123 |
80 // Reception of an RTP packet associated with the shared SSRC triggers the | 124 // Reception of an RTP packet associated with the shared SSRC triggers the |
81 // callback on all of the interfaces associated with it. | 125 // callback on all of the sinks associated with it. |
82 auto packet = CreateRtpPacketReceived(kSharedSsrc); | 126 auto packet = CreateRtpPacketReceived(ssrc); |
83 for (auto& sink : same_ssrc_sinks) { | 127 for (auto& sink : sinks) { |
84 EXPECT_CALL(sink, OnRtpPacket(SsrcSameAsIn(*packet))); | 128 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))); |
85 } | 129 } |
86 demuxer.OnRtpPacket(*packet); | 130 EXPECT_EQ(demuxer.OnRtpPacket(*packet), true); |
87 | 131 |
88 // Test-specific tear-down | 132 // Test tear-down |
89 for (auto& sink : same_ssrc_sinks) { | 133 for (auto& sink : sinks) { |
danilchap
2017/06/02 17:42:20
may be const auto&
eladalon
2017/06/02 19:44:04
Done.
| |
90 EXPECT_EQ(demuxer.RemoveSink(&sink), 1u); | 134 EXPECT_EQ(demuxer.RemoveSink(&sink), 1u); |
91 } | 135 } |
92 } | 136 } |
93 | 137 |
94 TEST_F(RtpDemuxerTest, SinkMappedToMultipleSsrcs) { | 138 TEST_F(RtpDemuxerTest, SinkMappedToMultipleSsrcs) { |
95 // |sinks| associated with different SSRCs each. We set one of them to also | 139 constexpr uint32_t ssrcs[] = {404, 505, 606}; |
96 // be mapped to additional SSRCs. | 140 MockRtpPacketSink sink; |
97 constexpr uint32_t kSsrcsOfMultiSsrcSink[] = {404, 505, 606}; | 141 for (uint32_t ssrc : ssrcs) { |
98 MockRtpPacketSink multi_ssrc_sink; | 142 demuxer.AddSink(ssrc, &sink); |
99 for (uint32_t ssrc : kSsrcsOfMultiSsrcSink) { | |
100 demuxer.AddSink(ssrc, &multi_ssrc_sink); | |
101 } | 143 } |
102 | 144 |
103 // The sink which is associated with multiple SSRCs gets the callback | 145 // The sink which is associated with multiple SSRCs gets the callback |
104 // triggered for each of those SSRCs. | 146 // triggered for each of those SSRCs. |
105 for (uint32_t ssrc : kSsrcsOfMultiSsrcSink) { | 147 for (uint32_t ssrc : ssrcs) { |
106 auto packet = CreateRtpPacketReceived(ssrc); | 148 auto packet = CreateRtpPacketReceived(ssrc); |
107 EXPECT_CALL(multi_ssrc_sink, OnRtpPacket(SsrcSameAsIn(*packet))); | 149 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))); |
108 demuxer.OnRtpPacket(*packet); | 150 EXPECT_EQ(demuxer.OnRtpPacket(*packet), true); |
109 } | 151 } |
110 | 152 |
111 // Test-specific tear-down | 153 // Test tear-down |
112 EXPECT_EQ(demuxer.RemoveSink(&multi_ssrc_sink), | 154 EXPECT_EQ(demuxer.RemoveSink(&sink), arraysize(ssrcs)); |
113 arraysize(kSsrcsOfMultiSsrcSink)); | 155 } |
114 } | 156 |
115 | 157 TEST_F(RtpDemuxerTest, NoCallbackOnSsrcSinkRemovedBeforeFirstPacket) { |
116 TEST_F(RtpDemuxerTest, OnRtpPacketNotCalledOnRemovedSinks) { | 158 constexpr uint32_t ssrc = 404; |
danilchap
2017/06/02 17:42:19
404 is very good number for test where ssrc will n
eladalon
2017/06/02 19:44:04
:-)
| |
117 // |sinks| associated with different SSRCs each. We set one of them to also | 159 MockRtpPacketSink sink; |
118 // be mapped to additional SSRCs. | 160 demuxer.AddSink(ssrc, &sink); |
119 constexpr uint32_t kSsrcsOfMultiSsrcSink[] = {404, 505, 606}; | 161 |
120 MockRtpPacketSink multi_ssrc_sink; | 162 EXPECT_EQ(demuxer.RemoveSink(&sink), 1u); |
121 for (uint32_t ssrc : kSsrcsOfMultiSsrcSink) { | 163 |
122 demuxer.AddSink(ssrc, &multi_ssrc_sink); | 164 // The removed sink does not get callbacks. |
123 } | 165 auto packet = CreateRtpPacketReceived(ssrc); |
124 | 166 EXPECT_CALL(sink, OnRtpPacket(_)).Times(0); |
125 // Remove the sink. | 167 EXPECT_EQ(demuxer.OnRtpPacket(*packet), false); |
danilchap
2017/06/02 17:42:19
EXPECT_FALSE
eladalon
2017/06/02 19:44:04
Done.
| |
126 EXPECT_EQ(demuxer.RemoveSink(&multi_ssrc_sink), | 168 } |
127 arraysize(kSsrcsOfMultiSsrcSink)); | 169 |
128 | 170 TEST_F(RtpDemuxerTest, NoCallbackOnSsrcSinkRemovedAfterFirstPacket) { |
129 // The removed sink does not get callbacks triggered for any of the SSRCs | 171 constexpr uint32_t ssrc = 404; |
130 // with which it was previously associated. | 172 MockRtpPacketSink sink; |
131 EXPECT_CALL(multi_ssrc_sink, OnRtpPacket(_)).Times(0); | 173 demuxer.AddSink(ssrc, &sink); |
132 for (uint32_t ssrc : kSsrcsOfMultiSsrcSink) { | 174 |
133 auto packet = CreateRtpPacketReceived(ssrc); | 175 InSequence sequence; |
134 demuxer.OnRtpPacket(*packet); | 176 uint16_t seq_num; |
danilchap
2017/06/02 17:42:19
do you use the variable outside the for loop?
eladalon
2017/06/02 19:44:04
Actually, I'd meant to do it for the last packet (
| |
135 } | 177 for (seq_num = 0; seq_num < 10; seq_num++) { |
178 auto packet = CreateRtpPacketReceived(ssrc, seq_num); | |
179 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); | |
180 EXPECT_EQ(demuxer.OnRtpPacket(*packet), true); | |
181 } | |
182 | |
183 EXPECT_EQ(demuxer.RemoveSink(&sink), 1u); | |
184 | |
185 // The removed sink does not get callbacks. | |
186 auto packet = CreateRtpPacketReceived(ssrc); | |
187 EXPECT_CALL(sink, OnRtpPacket(_)).Times(0); | |
188 EXPECT_EQ(demuxer.OnRtpPacket(*packet), false); | |
189 } | |
190 | |
191 TEST_F(RtpDemuxerTest, RepeatedSsrcAssociationsDoNotTriggerRepeatedCallbacks) { | |
192 constexpr uint32_t ssrc = 111; | |
193 MockRtpPacketSink sink; | |
194 | |
195 demuxer.AddSink(ssrc, &sink); | |
196 demuxer.AddSink(ssrc, &sink); | |
197 | |
198 auto packet = CreateRtpPacketReceived(ssrc); | |
199 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); | |
200 EXPECT_EQ(demuxer.OnRtpPacket(*packet), true); | |
201 | |
202 // Test tear-down | |
203 EXPECT_EQ(demuxer.RemoveSink(&sink), 1u); | |
204 } | |
205 | |
206 TEST_F(RtpDemuxerTest, OnRtpPacketCalledForRsidSink) { | |
207 MockRtpPacketSink sink; | |
208 const std::string rsid = "a"; | |
209 demuxer.AddSink(rsid, &sink); | |
210 | |
211 // Create a sequence of RTP packets, where only the first one actually | |
212 // mentions the RSID. | |
213 std::unique_ptr<RtpPacketReceived> packets[5]; | |
214 constexpr uint32_t rsid_ssrc = 111; | |
215 packets[0] = | |
216 CreateRtpPacketReceived(rsid_ssrc, static_cast<uint16_t>(0), &rsid); | |
217 for (size_t i = 1; i < arraysize(packets); i++) { | |
218 packets[i] = CreateRtpPacketReceived(rsid_ssrc, static_cast<uint16_t>(i)); | |
219 } | |
220 | |
221 // The first packet associates the RSID with the SSRC, thereby allowing the | |
222 // demuxer to correctly demux all of the packets. | |
223 InSequence sequence; | |
224 for (auto& packet : packets) { | |
225 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); | |
226 } | |
227 for (auto& packet : packets) { | |
228 EXPECT_EQ(demuxer.OnRtpPacket(*packet), true); | |
229 } | |
230 | |
231 // Test tear-down | |
232 EXPECT_EQ(demuxer.RemoveSink(&sink), 1u); | |
233 } | |
234 | |
235 TEST_F(RtpDemuxerTest, NoCallbackOnRsidSinkRemovedBeforeFirstPacket) { | |
236 MockRtpPacketSink sink; | |
237 const std::string rsid = "a"; | |
238 demuxer.AddSink(rsid, &sink); | |
239 | |
240 // Sink removed - it won't get triggers even if packets with its RSID arrive. | |
241 EXPECT_EQ(demuxer.RemoveSink(&sink), 1u); | |
242 | |
243 constexpr uint32_t ssrc = 111; | |
244 constexpr uint16_t seq_num = 222; | |
245 auto packet = CreateRtpPacketReceived(ssrc, seq_num, &rsid); | |
246 EXPECT_CALL(sink, OnRtpPacket(_)).Times(0); // Not called. | |
247 EXPECT_EQ(demuxer.OnRtpPacket(*packet), false); | |
248 } | |
249 | |
250 TEST_F(RtpDemuxerTest, NoCallbackOnRsidSinkRemovedAfterFirstPacket) { | |
251 MockRtpPacketSink sink; | |
252 const std::string rsid = "a"; | |
253 demuxer.AddSink(rsid, &sink); | |
254 | |
255 InSequence sequence; | |
256 constexpr uint32_t ssrc = 111; | |
257 uint16_t seq_num; | |
258 for (seq_num = 0; seq_num < 10; seq_num++) { | |
259 auto packet = CreateRtpPacketReceived(ssrc, seq_num, &rsid); | |
260 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); | |
261 EXPECT_EQ(demuxer.OnRtpPacket(*packet), true); | |
262 } | |
263 | |
264 // Sink removed - it won't get triggers even if packets with its RSID arrive. | |
265 EXPECT_EQ(demuxer.RemoveSink(&sink), 1u); | |
266 | |
267 auto packet = CreateRtpPacketReceived(ssrc, seq_num, &rsid); | |
268 EXPECT_CALL(sink, OnRtpPacket(_)).Times(0); // Not called. | |
269 EXPECT_EQ(demuxer.OnRtpPacket(*packet), false); | |
270 } | |
271 | |
272 // The RSID to SSRC mapping should be one-to-one. If we end up receiving | |
273 // two (or more) packets with the same SSRC, but different RSIDs, we guarantee | |
274 // remembering the first one; no guarantees are made about further associations. | |
275 TEST_F(RtpDemuxerTest, FirstSsrcAssociatedWithAnRsidIsNotForgotten) { | |
276 // Each sink has a distinct RSID. | |
277 MockRtpPacketSink sink_a; | |
278 const std::string rsid_a = "a"; | |
279 demuxer.AddSink(rsid_a, &sink_a); | |
280 | |
281 MockRtpPacketSink sink_b; | |
282 const std::string rsid_b = "b"; | |
283 demuxer.AddSink(rsid_b, &sink_b); | |
284 | |
285 InSequence sequence; // Verify that the order of delivery is unchanged. | |
286 | |
287 constexpr uint32_t kSharedSsrc = 100; | |
288 | |
289 // First a packet with |rsid_a| is received, and |sink_a| is associated with | |
290 // its SSRC. | |
291 auto packet_a = | |
292 CreateRtpPacketReceived(kSharedSsrc, static_cast<uint16_t>(10), &rsid_a); | |
293 EXPECT_CALL(sink_a, OnRtpPacket(SamePacketAs(*packet_a))).Times(1); | |
294 EXPECT_EQ(demuxer.OnRtpPacket(*packet_a), true); | |
295 | |
296 // Second, a packet with |rsid_b| is received. Its RSID is ignored. | |
297 auto packet_b = | |
298 CreateRtpPacketReceived(kSharedSsrc, static_cast<uint16_t>(20), &rsid_b); | |
299 EXPECT_CALL(sink_a, OnRtpPacket(SamePacketAs(*packet_b))).Times(1); | |
300 EXPECT_EQ(demuxer.OnRtpPacket(*packet_b), true); | |
301 | |
302 // Known edge-case; adding a new RSID association makes us re-examine all | |
303 // SSRCs. |sink_b| may or may not be associated with the SSRC now; we make | |
304 // no promises on that. We do however still guarantee that |sink_a| still | |
305 // receives the new packets. | |
306 MockRtpPacketSink sink_ignored; | |
307 demuxer.AddSink("ignored", &sink_ignored); | |
308 auto packet_c = | |
309 CreateRtpPacketReceived(kSharedSsrc, static_cast<uint16_t>(30), &rsid_b); | |
310 EXPECT_CALL(sink_a, OnRtpPacket(SamePacketAs(*packet_c))).Times(1); | |
311 EXPECT_CALL(sink_b, OnRtpPacket(SamePacketAs(*packet_c))).Times(AtLeast(0)); | |
312 EXPECT_EQ(demuxer.OnRtpPacket(*packet_c), true); | |
313 | |
314 // Test tear-down | |
315 EXPECT_EQ(demuxer.RemoveSink(&sink_a), 1u); | |
316 EXPECT_EQ(demuxer.RemoveSink(&sink_b), 1u); | |
317 EXPECT_EQ(demuxer.RemoveSink(&sink_ignored), 1u); | |
318 } | |
319 | |
320 TEST_F(RtpDemuxerTest, MultipleRsidsOnSameSink) { | |
321 MockRtpPacketSink sink; | |
322 const std::string rsids[] = {"a", "b", "c"}; | |
323 | |
324 for (const std::string& rsid : rsids) { | |
325 demuxer.AddSink(rsid, &sink); | |
326 } | |
327 | |
328 InSequence sequence; | |
329 for (size_t i = 0; i < arraysize(rsids); i++) { | |
330 // Assign different SSRCs and sequence numbers to all packets. | |
331 const uint32_t ssrc = 1000 + static_cast<uint32_t>(i); | |
danilchap
2017/06/02 17:42:19
static_cast is probably an overkill here.
Do you t
eladalon
2017/06/02 19:44:04
Not readability; trying to keep the trybots' vario
| |
332 const uint16_t sequence_number = 50 + static_cast<uint32_t>(i); | |
333 auto packet = CreateRtpPacketReceived(ssrc, sequence_number, &rsids[i]); | |
334 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); | |
335 EXPECT_EQ(demuxer.OnRtpPacket(*packet), true); | |
336 } | |
337 | |
338 // Test tear-down | |
339 EXPECT_EQ(demuxer.RemoveSink(&sink), arraysize(rsids)); | |
340 } | |
341 | |
342 TEST_F(RtpDemuxerTest, SinkWithBothRsidAndSsrcAssociations) { | |
343 MockRtpPacketSink sink; | |
344 constexpr uint32_t standalone_ssrc = 10101; | |
345 constexpr uint32_t rsid_ssrc = 20202; | |
346 const std::string rsid = "a"; | |
347 | |
348 demuxer.AddSink(standalone_ssrc, &sink); | |
349 demuxer.AddSink(rsid, &sink); | |
350 | |
351 InSequence sequence; | |
352 | |
353 auto ssrc_packet = CreateRtpPacketReceived(standalone_ssrc, 11); | |
354 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*ssrc_packet))).Times(1); | |
355 EXPECT_EQ(demuxer.OnRtpPacket(*ssrc_packet), true); | |
356 | |
357 auto rsid_packet = CreateRtpPacketReceived(rsid_ssrc, 22, &rsid); | |
358 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*rsid_packet))).Times(1); | |
359 EXPECT_EQ(demuxer.OnRtpPacket(*rsid_packet), true); | |
360 | |
361 // Test tear-down | |
362 EXPECT_EQ(demuxer.RemoveSink(&sink), 2u); | |
363 } | |
364 | |
365 TEST_F(RtpDemuxerTest, AssociatingByRsidAndBySsrcCannotTriggerDoubleCall) { | |
366 MockRtpPacketSink sink; | |
367 | |
368 constexpr uint32_t ssrc = 10101; | |
369 demuxer.AddSink(ssrc, &sink); | |
370 | |
371 const std::string rsid = "a"; | |
372 demuxer.AddSink(rsid, &sink); | |
373 | |
374 constexpr uint16_t seq_num = 999; | |
375 auto packet = CreateRtpPacketReceived(ssrc, seq_num, &rsid); | |
376 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); | |
377 EXPECT_EQ(demuxer.OnRtpPacket(*packet), true); | |
378 | |
379 // Test tear-down | |
380 | |
381 // The RSID and the SSRC associations above have merged into one. | |
382 EXPECT_EQ(demuxer.RemoveSink(&sink), 1u); | |
136 } | 383 } |
137 | 384 |
138 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) | 385 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) |
139 TEST_F(RtpDemuxerTest, RepeatedAssociationsForbidden) { | 386 TEST_F(RtpDemuxerTest, RsidMustBeNonEmpty) { |
140 // Set-up already associated sinks[0] with kSsrcs[0]. Repeating the | 387 MockRtpPacketSink sink; |
141 // association is an error. | 388 EXPECT_DEATH(demuxer.AddSink("", &sink), ""); |
142 EXPECT_DEATH(demuxer.AddSink(kSsrcs[0], &sinks[0]), ""); | 389 } |
390 | |
391 TEST_F(RtpDemuxerTest, RsidMustBeAlphaNumeric) { | |
392 MockRtpPacketSink sink; | |
393 EXPECT_DEATH(demuxer.AddSink("a_3", &sink), ""); | |
394 } | |
395 | |
396 TEST_F(RtpDemuxerTest, RsidMustNotExceedMaximumLength) { | |
397 std::stringstream ss; | |
398 for (size_t i = 0; i < StreamId::kMaxSize + 1; i++) { | |
399 ss << "a"; | |
400 } | |
danilchap
2017/06/02 17:42:19
std::string long_rsid(StreamId::kMaxSize + 1, 'a')
eladalon
2017/06/02 19:44:04
Done.
| |
401 MockRtpPacketSink sink; | |
402 EXPECT_DEATH(demuxer.AddSink(ss.str(), &sink), ""); | |
403 } | |
404 | |
405 TEST_F(RtpDemuxerTest, RepeatedRsidAssociationsDisallowed) { | |
406 MockRtpPacketSink sink; | |
407 demuxer.AddSink("a", &sink); | |
408 EXPECT_DEATH(demuxer.AddSink("a", &sink), ""); | |
143 } | 409 } |
144 #endif | 410 #endif |
145 | 411 |
146 } // namespace | 412 } // namespace |
147 } // namespace webrtc | 413 } // namespace webrtc |
OLD | NEW |