blob: c8bd8f93934538b51ac8f062fe0907e40031052d [file] [log] [blame]
deadbeefe814a0d2017-02-26 02:15:091/*
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
11#include <memory>
12
Karl Wiberg3e9e5b32017-11-06 04:01:5613#include "api/audio_codecs/builtin_audio_decoder_factory.h"
14#include "api/audio_codecs/builtin_audio_encoder_factory.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3115#include "media/base/fakemediaengine.h"
16#include "ortc/ortcfactory.h"
17#include "ortc/testrtpparameters.h"
18#include "p2p/base/fakepackettransport.h"
19#include "pc/test/fakevideotracksource.h"
20#include "rtc_base/gunit.h"
deadbeefe814a0d2017-02-26 02:15:0921
22namespace webrtc {
23
24// This test uses an individual RtpSender using only the public interface, and
25// verifies that its behaves as designed at an API level. Also tests that
26// parameters are applied to the audio/video engines as expected. Network and
27// media interfaces are faked to isolate what's being tested.
28//
29// This test shouldn't result any any actual media being sent. That sort of
30// test should go in ortcfactory_integrationtest.cc.
31class OrtcRtpSenderTest : public testing::Test {
32 public:
33 OrtcRtpSenderTest() : fake_packet_transport_("fake") {
34 // Need to set the fake packet transport to writable, in order to test that
35 // the "send" flag is applied to the media engine based on the encoding
36 // |active| flag.
37 fake_packet_transport_.SetWritable(true);
38 fake_media_engine_ = new cricket::FakeMediaEngine();
39 // Note: This doesn't need to use fake network classes, since we already
40 // use FakePacketTransport.
41 auto ortc_factory_result = OrtcFactory::Create(
42 nullptr, nullptr, nullptr, nullptr, nullptr,
Karl Wiberg3e9e5b32017-11-06 04:01:5643 std::unique_ptr<cricket::MediaEngineInterface>(fake_media_engine_),
44 CreateBuiltinAudioEncoderFactory(), CreateBuiltinAudioDecoderFactory());
deadbeefe814a0d2017-02-26 02:15:0945 ortc_factory_ = ortc_factory_result.MoveValue();
sprangdb2a9fc2017-08-09 13:42:3246 RtpTransportParameters parameters;
47 parameters.rtcp.mux = true;
deadbeefe814a0d2017-02-26 02:15:0948 auto rtp_transport_result = ortc_factory_->CreateRtpTransport(
sprangdb2a9fc2017-08-09 13:42:3249 parameters, &fake_packet_transport_, nullptr, nullptr);
deadbeefe814a0d2017-02-26 02:15:0950 rtp_transport_ = rtp_transport_result.MoveValue();
51 }
52
53 protected:
54 rtc::scoped_refptr<AudioTrackInterface> CreateAudioTrack(
55 const std::string& id) {
56 return ortc_factory_->CreateAudioTrack(id, nullptr);
57 }
58
59 rtc::scoped_refptr<VideoTrackInterface> CreateVideoTrack(
60 const std::string& id) {
61 return rtc::scoped_refptr<webrtc::VideoTrackInterface>(
62 ortc_factory_->CreateVideoTrack(id, FakeVideoTrackSource::Create()));
63 }
64
65 // Owned by |ortc_factory_|.
66 cricket::FakeMediaEngine* fake_media_engine_;
67 rtc::FakePacketTransport fake_packet_transport_;
68 std::unique_ptr<OrtcFactoryInterface> ortc_factory_;
69 std::unique_ptr<RtpTransportInterface> rtp_transport_;
70};
71
72TEST_F(OrtcRtpSenderTest, GetAndSetTrack) {
73 // Test GetTrack with a sender constructed with a track.
74 auto audio_track = CreateAudioTrack("audio");
75 auto audio_sender_result =
76 ortc_factory_->CreateRtpSender(audio_track, rtp_transport_.get());
77 auto audio_sender = audio_sender_result.MoveValue();
78 EXPECT_EQ(audio_track, audio_sender->GetTrack());
79
80 // Test GetTrack after SetTrack.
81 auto video_sender_result = ortc_factory_->CreateRtpSender(
82 cricket::MEDIA_TYPE_VIDEO, rtp_transport_.get());
83 auto video_sender = video_sender_result.MoveValue();
84 auto video_track = CreateVideoTrack("video1");
85 EXPECT_TRUE(video_sender->SetTrack(video_track).ok());
86 EXPECT_EQ(video_track, video_sender->GetTrack());
87 video_track = CreateVideoTrack("video2");
88 EXPECT_TRUE(video_sender->SetTrack(video_track).ok());
89 EXPECT_EQ(video_track, video_sender->GetTrack());
90}
91
92// Test that track can be set when previously unset, even after Send has been
93// called.
94TEST_F(OrtcRtpSenderTest, SetTrackWhileSending) {
95 auto audio_sender_result = ortc_factory_->CreateRtpSender(
96 cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get());
97 auto audio_sender = audio_sender_result.MoveValue();
98 EXPECT_TRUE(audio_sender->Send(MakeMinimalOpusParameters()).ok());
99 EXPECT_TRUE(audio_sender->SetTrack(CreateAudioTrack("audio")).ok());
100
101 auto video_sender_result = ortc_factory_->CreateRtpSender(
102 cricket::MEDIA_TYPE_VIDEO, rtp_transport_.get());
103 auto video_sender = video_sender_result.MoveValue();
104 EXPECT_TRUE(video_sender->Send(MakeMinimalVp8Parameters()).ok());
105 EXPECT_TRUE(video_sender->SetTrack(CreateVideoTrack("video")).ok());
106}
107
108// Test that track can be changed mid-sending. Differs from the above test in
109// that the track is set and being changed, rather than unset and being set for
110// the first time.
111TEST_F(OrtcRtpSenderTest, ChangeTrackWhileSending) {
112 auto audio_sender_result = ortc_factory_->CreateRtpSender(
113 CreateAudioTrack("audio1"), rtp_transport_.get());
114 auto audio_sender = audio_sender_result.MoveValue();
115 EXPECT_TRUE(audio_sender->Send(MakeMinimalOpusParameters()).ok());
116 EXPECT_TRUE(audio_sender->SetTrack(CreateAudioTrack("audio2")).ok());
117
118 auto video_sender_result = ortc_factory_->CreateRtpSender(
119 CreateVideoTrack("video1"), rtp_transport_.get());
120 auto video_sender = video_sender_result.MoveValue();
121 EXPECT_TRUE(video_sender->Send(MakeMinimalVp8Parameters()).ok());
122 EXPECT_TRUE(video_sender->SetTrack(CreateVideoTrack("video2")).ok());
123}
124
125// Test that track can be set to null while sending.
126TEST_F(OrtcRtpSenderTest, UnsetTrackWhileSending) {
127 auto audio_sender_result = ortc_factory_->CreateRtpSender(
128 CreateAudioTrack("audio"), rtp_transport_.get());
129 auto audio_sender = audio_sender_result.MoveValue();
130 EXPECT_TRUE(audio_sender->Send(MakeMinimalOpusParameters()).ok());
131 EXPECT_TRUE(audio_sender->SetTrack(nullptr).ok());
132
133 auto video_sender_result = ortc_factory_->CreateRtpSender(
134 CreateVideoTrack("video"), rtp_transport_.get());
135 auto video_sender = video_sender_result.MoveValue();
136 EXPECT_TRUE(video_sender->Send(MakeMinimalVp8Parameters()).ok());
137 EXPECT_TRUE(video_sender->SetTrack(nullptr).ok());
138}
139
140// Shouldn't be able to set an audio track on a video sender or vice versa.
141TEST_F(OrtcRtpSenderTest, SetTrackOfWrongKindFails) {
142 auto audio_sender_result = ortc_factory_->CreateRtpSender(
143 cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get());
144 auto audio_sender = audio_sender_result.MoveValue();
145 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER,
146 audio_sender->SetTrack(CreateVideoTrack("video")).type());
147
148 auto video_sender_result = ortc_factory_->CreateRtpSender(
149 cricket::MEDIA_TYPE_VIDEO, rtp_transport_.get());
150 auto video_sender = video_sender_result.MoveValue();
151 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER,
152 video_sender->SetTrack(CreateAudioTrack("audio")).type());
153}
154
155// Currently SetTransport isn't supported. When it is, replace this test with a
156// test/tests for it.
157TEST_F(OrtcRtpSenderTest, SetTransportFails) {
158 rtc::FakePacketTransport fake_packet_transport("another_transport");
sprangdb2a9fc2017-08-09 13:42:32159 RtpTransportParameters parameters;
160 parameters.rtcp.mux = true;
deadbeefe814a0d2017-02-26 02:15:09161 auto rtp_transport_result = ortc_factory_->CreateRtpTransport(
sprangdb2a9fc2017-08-09 13:42:32162 parameters, &fake_packet_transport, nullptr, nullptr);
deadbeefe814a0d2017-02-26 02:15:09163 auto rtp_transport = rtp_transport_result.MoveValue();
164
165 auto sender_result = ortc_factory_->CreateRtpSender(cricket::MEDIA_TYPE_AUDIO,
166 rtp_transport_.get());
167 auto sender = sender_result.MoveValue();
168 EXPECT_EQ(RTCErrorType::UNSUPPORTED_OPERATION,
169 sender->SetTransport(rtp_transport.get()).type());
170}
171
172TEST_F(OrtcRtpSenderTest, GetTransport) {
173 auto result = ortc_factory_->CreateRtpSender(cricket::MEDIA_TYPE_AUDIO,
174 rtp_transport_.get());
175 EXPECT_EQ(rtp_transport_.get(), result.value()->GetTransport());
176}
177
178// Test that "Send" causes the expected parameters to be applied to the media
179// engine level, for an audio sender.
180TEST_F(OrtcRtpSenderTest, SendAppliesAudioParametersToMediaEngine) {
181 auto audio_sender_result = ortc_factory_->CreateRtpSender(
182 cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get());
183 auto audio_sender = audio_sender_result.MoveValue();
184
185 // First, create parameters with all the bells and whistles.
186 RtpParameters parameters;
187
188 RtpCodecParameters opus_codec;
189 opus_codec.name = "opus";
190 opus_codec.kind = cricket::MEDIA_TYPE_AUDIO;
191 opus_codec.payload_type = 120;
192 opus_codec.clock_rate.emplace(48000);
193 opus_codec.num_channels.emplace(2);
194 opus_codec.parameters["minptime"] = "10";
195 opus_codec.rtcp_feedback.emplace_back(RtcpFeedbackType::TRANSPORT_CC);
196 parameters.codecs.push_back(std::move(opus_codec));
197
198 // Add two codecs, expecting the first to be used.
199 // TODO(deadbeef): Once "codec_payload_type" is supported, use it to select a
200 // codec that's not at the top of the list.
201 RtpCodecParameters isac_codec;
202 isac_codec.name = "ISAC";
203 isac_codec.kind = cricket::MEDIA_TYPE_AUDIO;
204 isac_codec.payload_type = 110;
205 isac_codec.clock_rate.emplace(16000);
206 parameters.codecs.push_back(std::move(isac_codec));
207
208 RtpEncodingParameters encoding;
209 encoding.ssrc.emplace(0xdeadbeef);
210 encoding.max_bitrate_bps.emplace(20000);
211 parameters.encodings.push_back(std::move(encoding));
212
213 parameters.header_extensions.emplace_back(
214 "urn:ietf:params:rtp-hdrext:ssrc-audio-level", 3);
215
216 EXPECT_TRUE(audio_sender->Send(parameters).ok());
217
218 // Now verify that the parameters were applied to the fake media engine layer
219 // that exists below BaseChannel.
220 cricket::FakeVoiceMediaChannel* fake_voice_channel =
221 fake_media_engine_->GetVoiceChannel(0);
222 ASSERT_NE(nullptr, fake_voice_channel);
223 EXPECT_TRUE(fake_voice_channel->sending());
224
225 // Verify codec parameters.
226 ASSERT_GT(fake_voice_channel->send_codecs().size(), 0u);
227 const cricket::AudioCodec& top_codec = fake_voice_channel->send_codecs()[0];
228 EXPECT_EQ("opus", top_codec.name);
229 EXPECT_EQ(120, top_codec.id);
230 EXPECT_EQ(48000, top_codec.clockrate);
231 EXPECT_EQ(2u, top_codec.channels);
232 ASSERT_NE(top_codec.params.end(), top_codec.params.find("minptime"));
233 EXPECT_EQ("10", top_codec.params.at("minptime"));
234
235 // Verify encoding parameters.
236 EXPECT_EQ(20000, fake_voice_channel->max_bps());
237 ASSERT_EQ(1u, fake_voice_channel->send_streams().size());
238 const cricket::StreamParams& send_stream =
239 fake_voice_channel->send_streams()[0];
240 EXPECT_EQ(1u, send_stream.ssrcs.size());
241 EXPECT_EQ(0xdeadbeef, send_stream.first_ssrc());
242
243 // Verify header extensions.
244 ASSERT_EQ(1u, fake_voice_channel->send_extensions().size());
245 const RtpExtension& extension = fake_voice_channel->send_extensions()[0];
246 EXPECT_EQ("urn:ietf:params:rtp-hdrext:ssrc-audio-level", extension.uri);
247 EXPECT_EQ(3, extension.id);
248}
249
250// Test that "Send" causes the expected parameters to be applied to the media
251// engine level, for a video sender.
252TEST_F(OrtcRtpSenderTest, SendAppliesVideoParametersToMediaEngine) {
253 auto video_sender_result = ortc_factory_->CreateRtpSender(
254 cricket::MEDIA_TYPE_VIDEO, rtp_transport_.get());
255 auto video_sender = video_sender_result.MoveValue();
256
257 // First, create parameters with all the bells and whistles.
258 RtpParameters parameters;
259
260 RtpCodecParameters vp8_codec;
261 vp8_codec.name = "VP8";
262 vp8_codec.kind = cricket::MEDIA_TYPE_VIDEO;
263 vp8_codec.payload_type = 99;
264 // Try a couple types of feedback params. "Generic NACK" is a bit of a
265 // special case, so test it here.
266 vp8_codec.rtcp_feedback.emplace_back(RtcpFeedbackType::CCM,
267 RtcpFeedbackMessageType::FIR);
268 vp8_codec.rtcp_feedback.emplace_back(RtcpFeedbackType::NACK,
269 RtcpFeedbackMessageType::GENERIC_NACK);
270 parameters.codecs.push_back(std::move(vp8_codec));
271
272 RtpCodecParameters vp8_rtx_codec;
273 vp8_rtx_codec.name = "rtx";
274 vp8_rtx_codec.kind = cricket::MEDIA_TYPE_VIDEO;
275 vp8_rtx_codec.payload_type = 100;
276 vp8_rtx_codec.parameters["apt"] = "99";
277 parameters.codecs.push_back(std::move(vp8_rtx_codec));
278
279 // Add two codecs, expecting the first to be used.
280 // TODO(deadbeef): Once "codec_payload_type" is supported, use it to select a
281 // codec that's not at the top of the list.
282 RtpCodecParameters vp9_codec;
283 vp9_codec.name = "VP9";
284 vp9_codec.kind = cricket::MEDIA_TYPE_VIDEO;
285 vp9_codec.payload_type = 102;
286 parameters.codecs.push_back(std::move(vp9_codec));
287
288 RtpCodecParameters vp9_rtx_codec;
289 vp9_rtx_codec.name = "rtx";
290 vp9_rtx_codec.kind = cricket::MEDIA_TYPE_VIDEO;
291 vp9_rtx_codec.payload_type = 103;
292 vp9_rtx_codec.parameters["apt"] = "102";
293 parameters.codecs.push_back(std::move(vp9_rtx_codec));
294
295 RtpEncodingParameters encoding;
296 encoding.ssrc.emplace(0xdeadbeef);
297 encoding.rtx.emplace(0xbaadfeed);
298 encoding.max_bitrate_bps.emplace(99999);
299 parameters.encodings.push_back(std::move(encoding));
300
301 parameters.header_extensions.emplace_back("urn:3gpp:video-orientation", 4);
302 parameters.header_extensions.emplace_back(
303 "http://www.webrtc.org/experiments/rtp-hdrext/playout-delay", 6);
304
305 EXPECT_TRUE(video_sender->Send(parameters).ok());
306
307 // Now verify that the parameters were applied to the fake media engine layer
308 // that exists below BaseChannel.
309 cricket::FakeVideoMediaChannel* fake_video_channel =
310 fake_media_engine_->GetVideoChannel(0);
311 ASSERT_NE(nullptr, fake_video_channel);
312 EXPECT_TRUE(fake_video_channel->sending());
313
314 // Verify codec parameters.
315 ASSERT_GE(fake_video_channel->send_codecs().size(), 2u);
316 const cricket::VideoCodec& top_codec = fake_video_channel->send_codecs()[0];
317 EXPECT_EQ("VP8", top_codec.name);
318 EXPECT_EQ(99, top_codec.id);
319 EXPECT_TRUE(top_codec.feedback_params.Has({"ccm", "fir"}));
320 EXPECT_TRUE(top_codec.feedback_params.Has(cricket::FeedbackParam("nack")));
321
322 const cricket::VideoCodec& rtx_codec = fake_video_channel->send_codecs()[1];
323 EXPECT_EQ("rtx", rtx_codec.name);
324 EXPECT_EQ(100, rtx_codec.id);
325 ASSERT_NE(rtx_codec.params.end(), rtx_codec.params.find("apt"));
326 EXPECT_EQ("99", rtx_codec.params.at("apt"));
327
328 // Verify encoding parameters.
329 EXPECT_EQ(99999, fake_video_channel->max_bps());
330 ASSERT_EQ(1u, fake_video_channel->send_streams().size());
331 const cricket::StreamParams& send_stream =
332 fake_video_channel->send_streams()[0];
333 EXPECT_EQ(2u, send_stream.ssrcs.size());
334 EXPECT_EQ(0xdeadbeef, send_stream.first_ssrc());
335 uint32_t rtx_ssrc = 0u;
336 EXPECT_TRUE(send_stream.GetFidSsrc(send_stream.first_ssrc(), &rtx_ssrc));
337 EXPECT_EQ(0xbaadfeed, rtx_ssrc);
338
339 // Verify header extensions.
340 ASSERT_EQ(2u, fake_video_channel->send_extensions().size());
341 const RtpExtension& extension1 = fake_video_channel->send_extensions()[0];
342 EXPECT_EQ("urn:3gpp:video-orientation", extension1.uri);
343 EXPECT_EQ(4, extension1.id);
344 const RtpExtension& extension2 = fake_video_channel->send_extensions()[1];
345 EXPECT_EQ("http://www.webrtc.org/experiments/rtp-hdrext/playout-delay",
346 extension2.uri);
347 EXPECT_EQ(6, extension2.id);
348}
349
350// Ensure that when primary or RTX SSRCs are left unset, they're generated
351// automatically.
352TEST_F(OrtcRtpSenderTest, SendGeneratesSsrcsWhenEmpty) {
353 auto audio_sender_result = ortc_factory_->CreateRtpSender(
354 cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get());
355 auto audio_sender = audio_sender_result.MoveValue();
356 RtpParameters parameters = MakeMinimalOpusParametersWithNoSsrc();
357 // Default RTX parameters, with no SSRC.
358 parameters.encodings[0].rtx.emplace();
359 EXPECT_TRUE(audio_sender->Send(parameters).ok());
360
361 cricket::FakeVoiceMediaChannel* fake_voice_channel =
362 fake_media_engine_->GetVoiceChannel(0);
363 ASSERT_NE(nullptr, fake_voice_channel);
364 ASSERT_EQ(1u, fake_voice_channel->send_streams().size());
365 const cricket::StreamParams& audio_send_stream =
366 fake_voice_channel->send_streams()[0];
367 EXPECT_NE(0u, audio_send_stream.first_ssrc());
368 uint32_t rtx_ssrc = 0u;
369 EXPECT_TRUE(
370 audio_send_stream.GetFidSsrc(audio_send_stream.first_ssrc(), &rtx_ssrc));
371 EXPECT_NE(0u, rtx_ssrc);
372 EXPECT_NE(audio_send_stream.first_ssrc(), rtx_ssrc);
373
374 auto video_sender_result = ortc_factory_->CreateRtpSender(
375 cricket::MEDIA_TYPE_VIDEO, rtp_transport_.get());
376 auto video_sender = video_sender_result.MoveValue();
377 parameters = MakeMinimalVp8ParametersWithNoSsrc();
378 // Default RTX parameters, with no SSRC.
379 parameters.encodings[0].rtx.emplace();
380 EXPECT_TRUE(video_sender->Send(parameters).ok());
381
382 cricket::FakeVideoMediaChannel* fake_video_channel =
383 fake_media_engine_->GetVideoChannel(0);
384 ASSERT_NE(nullptr, fake_video_channel);
385 ASSERT_EQ(1u, fake_video_channel->send_streams().size());
386 const cricket::StreamParams& video_send_stream =
387 fake_video_channel->send_streams()[0];
388 EXPECT_NE(0u, video_send_stream.first_ssrc());
389 rtx_ssrc = 0u;
390 EXPECT_TRUE(
391 video_send_stream.GetFidSsrc(video_send_stream.first_ssrc(), &rtx_ssrc));
392 EXPECT_NE(0u, rtx_ssrc);
393 EXPECT_NE(video_send_stream.first_ssrc(), rtx_ssrc);
394 EXPECT_NE(video_send_stream.first_ssrc(), audio_send_stream.first_ssrc());
395}
396
397// Test changing both the send codec and SSRC at the same time, and verify that
398// the new parameters are applied to the media engine level.
399TEST_F(OrtcRtpSenderTest, CallingSendTwiceChangesParameters) {
400 auto audio_sender_result = ortc_factory_->CreateRtpSender(
401 cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get());
402 auto audio_sender = audio_sender_result.MoveValue();
403 EXPECT_TRUE(
404 audio_sender->Send(MakeMinimalOpusParametersWithSsrc(0x11111111)).ok());
405 EXPECT_TRUE(
406 audio_sender->Send(MakeMinimalIsacParametersWithSsrc(0x22222222)).ok());
407
408 cricket::FakeVoiceMediaChannel* fake_voice_channel =
409 fake_media_engine_->GetVoiceChannel(0);
410 ASSERT_NE(nullptr, fake_voice_channel);
411 ASSERT_GT(fake_voice_channel->send_codecs().size(), 0u);
412 EXPECT_EQ("ISAC", fake_voice_channel->send_codecs()[0].name);
413 ASSERT_EQ(1u, fake_voice_channel->send_streams().size());
414 EXPECT_EQ(0x22222222u, fake_voice_channel->send_streams()[0].first_ssrc());
415
416 auto video_sender_result = ortc_factory_->CreateRtpSender(
417 cricket::MEDIA_TYPE_VIDEO, rtp_transport_.get());
418 auto video_sender = video_sender_result.MoveValue();
419 EXPECT_TRUE(
420 video_sender->Send(MakeMinimalVp8ParametersWithSsrc(0x33333333)).ok());
421 EXPECT_TRUE(
422 video_sender->Send(MakeMinimalVp9ParametersWithSsrc(0x44444444)).ok());
423
424 cricket::FakeVideoMediaChannel* fake_video_channel =
425 fake_media_engine_->GetVideoChannel(0);
426 ASSERT_NE(nullptr, fake_video_channel);
427 ASSERT_GT(fake_video_channel->send_codecs().size(), 0u);
428 EXPECT_EQ("VP9", fake_video_channel->send_codecs()[0].name);
429 ASSERT_EQ(1u, fake_video_channel->send_streams().size());
430 EXPECT_EQ(0x44444444u, fake_video_channel->send_streams()[0].first_ssrc());
431}
432
433// Ensure that if the |active| flag of RtpEncodingParameters is set to false,
434// sending stops at the media engine level.
435TEST_F(OrtcRtpSenderTest, DeactivatingEncodingStopsSending) {
436 auto audio_sender_result = ortc_factory_->CreateRtpSender(
437 cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get());
438 auto audio_sender = audio_sender_result.MoveValue();
439 RtpParameters parameters = MakeMinimalOpusParameters();
440 EXPECT_TRUE(audio_sender->Send(parameters).ok());
441
442 // Expect "sending" flag to initially be true.
443 cricket::FakeVoiceMediaChannel* fake_voice_channel =
444 fake_media_engine_->GetVoiceChannel(0);
445 ASSERT_NE(nullptr, fake_voice_channel);
446 EXPECT_TRUE(fake_voice_channel->sending());
447
448 // Deactivate encoding and expect it to change to false.
449 parameters.encodings[0].active = false;
450 EXPECT_TRUE(audio_sender->Send(parameters).ok());
451 EXPECT_FALSE(fake_voice_channel->sending());
452
453 // Try the same thing for video now.
454 auto video_sender_result = ortc_factory_->CreateRtpSender(
455 cricket::MEDIA_TYPE_VIDEO, rtp_transport_.get());
456 auto video_sender = video_sender_result.MoveValue();
457 parameters = MakeMinimalVp8Parameters();
458 EXPECT_TRUE(video_sender->Send(parameters).ok());
459
460 cricket::FakeVideoMediaChannel* fake_video_channel =
461 fake_media_engine_->GetVideoChannel(0);
462 ASSERT_NE(nullptr, fake_video_channel);
463 EXPECT_TRUE(fake_video_channel->sending());
464
465 parameters.encodings[0].active = false;
466 EXPECT_TRUE(video_sender->Send(parameters).ok());
467 EXPECT_FALSE(fake_video_channel->sending());
468}
469
470// Ensure that calling Send with an empty list of encodings causes send streams
471// at the media engine level to be cleared.
472TEST_F(OrtcRtpSenderTest, CallingSendWithEmptyEncodingsClearsSendStreams) {
473 auto audio_sender_result = ortc_factory_->CreateRtpSender(
474 cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get());
475 auto audio_sender = audio_sender_result.MoveValue();
476 RtpParameters parameters = MakeMinimalOpusParameters();
477 EXPECT_TRUE(audio_sender->Send(parameters).ok());
478 parameters.encodings.clear();
479 EXPECT_TRUE(audio_sender->Send(parameters).ok());
480
481 cricket::FakeVoiceMediaChannel* fake_voice_channel =
482 fake_media_engine_->GetVoiceChannel(0);
483 ASSERT_NE(nullptr, fake_voice_channel);
484 EXPECT_TRUE(fake_voice_channel->send_streams().empty());
485
486 auto video_sender_result = ortc_factory_->CreateRtpSender(
487 cricket::MEDIA_TYPE_VIDEO, rtp_transport_.get());
488 auto video_sender = video_sender_result.MoveValue();
489 parameters = MakeMinimalVp8Parameters();
490 EXPECT_TRUE(video_sender->Send(parameters).ok());
491 parameters.encodings.clear();
492 EXPECT_TRUE(video_sender->Send(parameters).ok());
493
494 cricket::FakeVideoMediaChannel* fake_video_channel =
495 fake_media_engine_->GetVideoChannel(0);
496 ASSERT_NE(nullptr, fake_video_channel);
497 EXPECT_TRUE(fake_video_channel->send_streams().empty());
498}
499
500// These errors should be covered by rtpparametersconversion_unittest.cc, but
501// we should at least test that those errors are propogated from calls to Send,
502// with a few examples.
503TEST_F(OrtcRtpSenderTest, SendReturnsErrorOnInvalidParameters) {
504 auto result = ortc_factory_->CreateRtpSender(cricket::MEDIA_TYPE_VIDEO,
505 rtp_transport_.get());
506 auto sender = result.MoveValue();
507 // NACK feedback missing message type.
508 RtpParameters invalid_feedback = MakeMinimalVp8Parameters();
509 invalid_feedback.codecs[0].rtcp_feedback.emplace_back(RtcpFeedbackType::NACK);
510 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER,
511 sender->Send(invalid_feedback).type());
512 // Negative payload type.
513 RtpParameters invalid_pt = MakeMinimalVp8Parameters();
514 invalid_pt.codecs[0].payload_type = -1;
515 EXPECT_EQ(RTCErrorType::INVALID_RANGE, sender->Send(invalid_pt).type());
516 // Duplicate codec payload types.
517 RtpParameters duplicate_payload_types = MakeMinimalVp8Parameters();
518 duplicate_payload_types.codecs.push_back(duplicate_payload_types.codecs[0]);
519 duplicate_payload_types.codecs.back().name = "VP9";
520 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER,
521 sender->Send(duplicate_payload_types).type());
522}
523
524// Two senders using the same transport shouldn't be able to use the same
525// payload type to refer to different codecs, same header extension IDs to
526// refer to different extensions, or same SSRC.
527TEST_F(OrtcRtpSenderTest, SendReturnsErrorOnIdConflicts) {
528 auto audio_sender_result = ortc_factory_->CreateRtpSender(
529 cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get());
530 auto video_sender_result = ortc_factory_->CreateRtpSender(
531 cricket::MEDIA_TYPE_VIDEO, rtp_transport_.get());
532 auto audio_sender = audio_sender_result.MoveValue();
533 auto video_sender = video_sender_result.MoveValue();
534
535 // First test payload type conflict.
536 RtpParameters audio_parameters = MakeMinimalOpusParameters();
537 RtpParameters video_parameters = MakeMinimalVp8Parameters();
538 audio_parameters.codecs[0].payload_type = 100;
539 video_parameters.codecs[0].payload_type = 100;
540 EXPECT_TRUE(audio_sender->Send(audio_parameters).ok());
541 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER,
542 video_sender->Send(video_parameters).type());
543
544 // Test header extension ID conflict.
545 video_parameters.codecs[0].payload_type = 110;
546 audio_parameters.header_extensions.emplace_back("foo", 4);
547 video_parameters.header_extensions.emplace_back("bar", 4);
548 EXPECT_TRUE(audio_sender->Send(audio_parameters).ok());
549 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER,
550 video_sender->Send(video_parameters).type());
551
552 // Test SSRC conflict. Have an RTX SSRC that conflicts with a primary SSRC
553 // for extra challenge.
554 video_parameters.header_extensions[0].uri = "foo";
555 audio_parameters.encodings[0].ssrc.emplace(0xdeadbeef);
556 video_parameters.encodings[0].ssrc.emplace(0xabbaabba);
557 video_parameters.encodings[0].rtx.emplace(0xdeadbeef);
558 EXPECT_TRUE(audio_sender->Send(audio_parameters).ok());
559 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER,
560 video_sender->Send(video_parameters).type());
561
562 // Sanity check that parameters can be set if the conflicts are all resolved.
563 video_parameters.encodings[0].rtx->ssrc.emplace(0xbaadf00d);
564 EXPECT_TRUE(video_sender->Send(video_parameters).ok());
565}
566
567// Ensure that deleting a sender causes send streams at the media engine level
568// to be cleared.
569TEST_F(OrtcRtpSenderTest, DeletingSenderClearsSendStreams) {
570 auto audio_sender_result = ortc_factory_->CreateRtpSender(
571 cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get());
572 auto audio_sender = audio_sender_result.MoveValue();
573 EXPECT_TRUE(audio_sender->Send(MakeMinimalOpusParameters()).ok());
574
575 // Also create an audio receiver, to prevent the voice channel from being
576 // completely deleted.
577 auto audio_receiver_result = ortc_factory_->CreateRtpReceiver(
578 cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get());
579 auto audio_receiver = audio_receiver_result.MoveValue();
580 EXPECT_TRUE(audio_receiver->Receive(MakeMinimalOpusParameters()).ok());
581
582 audio_sender.reset(nullptr);
583 cricket::FakeVoiceMediaChannel* fake_voice_channel =
584 fake_media_engine_->GetVoiceChannel(0);
585 ASSERT_NE(nullptr, fake_voice_channel);
586 EXPECT_TRUE(fake_voice_channel->send_streams().empty());
587
588 auto video_sender_result = ortc_factory_->CreateRtpSender(
589 cricket::MEDIA_TYPE_VIDEO, rtp_transport_.get());
590 auto video_sender = video_sender_result.MoveValue();
591 EXPECT_TRUE(video_sender->Send(MakeMinimalVp8Parameters()).ok());
592
593 // Also create an video receiver, to prevent the video channel from being
594 // completely deleted.
595 auto video_receiver_result = ortc_factory_->CreateRtpReceiver(
596 cricket::MEDIA_TYPE_VIDEO, rtp_transport_.get());
597 auto video_receiver = video_receiver_result.MoveValue();
598 EXPECT_TRUE(video_receiver->Receive(MakeMinimalVp8Parameters()).ok());
599
600 video_sender.reset(nullptr);
601 cricket::FakeVideoMediaChannel* fake_video_channel =
602 fake_media_engine_->GetVideoChannel(0);
603 ASSERT_NE(nullptr, fake_video_channel);
604 EXPECT_TRUE(fake_video_channel->send_streams().empty());
605}
606
607// If Send hasn't been called, GetParameters should return empty parameters.
608TEST_F(OrtcRtpSenderTest, GetDefaultParameters) {
609 auto result = ortc_factory_->CreateRtpSender(cricket::MEDIA_TYPE_AUDIO,
610 rtp_transport_.get());
611 EXPECT_EQ(RtpParameters(), result.value()->GetParameters());
612 result = ortc_factory_->CreateRtpSender(cricket::MEDIA_TYPE_VIDEO,
613 rtp_transport_.get());
614 EXPECT_EQ(RtpParameters(), result.value()->GetParameters());
615}
616
617// Test that GetParameters returns the last parameters passed into Send, along
618// with the implementation-default values filled in where they were left unset.
619TEST_F(OrtcRtpSenderTest,
620 GetParametersReturnsLastSetParametersWithDefaultsFilled) {
621 auto audio_sender_result = ortc_factory_->CreateRtpSender(
622 CreateAudioTrack("audio"), rtp_transport_.get());
623 auto audio_sender = audio_sender_result.MoveValue();
624
625 RtpParameters opus_parameters = MakeMinimalOpusParameters();
626 EXPECT_TRUE(audio_sender->Send(opus_parameters).ok());
627 EXPECT_EQ(opus_parameters, audio_sender->GetParameters());
628
629 RtpParameters isac_parameters = MakeMinimalIsacParameters();
630 // Sanity check that num_channels actually is left unset.
631 ASSERT_FALSE(isac_parameters.codecs[0].num_channels);
632 EXPECT_TRUE(audio_sender->Send(isac_parameters).ok());
633 // Should be filled with a default "num channels" of 1.
634 // TODO(deadbeef): This should actually default to 2 for some codecs. Update
635 // this test once that's implemented.
636 isac_parameters.codecs[0].num_channels.emplace(1);
637 EXPECT_EQ(isac_parameters, audio_sender->GetParameters());
638
639 auto video_sender_result = ortc_factory_->CreateRtpSender(
640 CreateVideoTrack("video"), rtp_transport_.get());
641 auto video_sender = video_sender_result.MoveValue();
642
643 RtpParameters vp8_parameters = MakeMinimalVp8Parameters();
644 // Sanity check that clock_rate actually is left unset.
645 EXPECT_TRUE(video_sender->Send(vp8_parameters).ok());
646 // Should be filled with a default clock rate of 90000.
647 vp8_parameters.codecs[0].clock_rate.emplace(90000);
648 EXPECT_EQ(vp8_parameters, video_sender->GetParameters());
649
650 RtpParameters vp9_parameters = MakeMinimalVp9Parameters();
651 // Sanity check that clock_rate actually is left unset.
652 EXPECT_TRUE(video_sender->Send(vp9_parameters).ok());
653 // Should be filled with a default clock rate of 90000.
654 vp9_parameters.codecs[0].clock_rate.emplace(90000);
655 EXPECT_EQ(vp9_parameters, video_sender->GetParameters());
656}
657
658TEST_F(OrtcRtpSenderTest, GetKind) {
659 // Construct one sender from the "kind" enum and another from a track.
660 auto audio_sender_result = ortc_factory_->CreateRtpSender(
661 cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get());
662 auto video_sender_result = ortc_factory_->CreateRtpSender(
663 CreateVideoTrack("video"), rtp_transport_.get());
664 auto audio_sender = audio_sender_result.MoveValue();
665 auto video_sender = video_sender_result.MoveValue();
666 EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, audio_sender->GetKind());
667 EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, video_sender->GetKind());
668}
669
670} // namespace webrtc