/* * Copyright 2017 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include #include "api/audio_codecs/builtin_audio_decoder_factory.h" #include "api/audio_codecs/builtin_audio_encoder_factory.h" #include "media/base/fakemediaengine.h" #include "ortc/ortcfactory.h" #include "ortc/testrtpparameters.h" #include "p2p/base/fakepackettransport.h" #include "pc/test/fakevideotracksource.h" #include "rtc_base/gunit.h" namespace webrtc { // This test uses an individual RtpReceiver using only the public interface, // and verifies that it behaves as designed at an API level. Also tests that // parameters are applied to the audio/video engines as expected. Network and // media interfaces are faked to isolate what's being tested. // // This test shouldn't result any any actual media being sent. That sort of // test should go in ortcfactory_integrationtest.cc. class OrtcRtpReceiverTest : public testing::Test { public: OrtcRtpReceiverTest() : fake_packet_transport_("fake") { fake_media_engine_ = new cricket::FakeMediaEngine(); // Note: This doesn't need to use fake network classes, since we already // use FakePacketTransport. auto ortc_factory_result = OrtcFactory::Create( nullptr, nullptr, nullptr, nullptr, nullptr, std::unique_ptr(fake_media_engine_), CreateBuiltinAudioEncoderFactory(), CreateBuiltinAudioDecoderFactory()); ortc_factory_ = ortc_factory_result.MoveValue(); RtpTransportParameters parameters; parameters.rtcp.mux = true; auto rtp_transport_result = ortc_factory_->CreateRtpTransport( parameters, &fake_packet_transport_, nullptr, nullptr); rtp_transport_ = rtp_transport_result.MoveValue(); } protected: // Owned by |ortc_factory_|. cricket::FakeMediaEngine* fake_media_engine_; rtc::FakePacketTransport fake_packet_transport_; std::unique_ptr ortc_factory_; std::unique_ptr rtp_transport_; }; // See ortcrtpreceiverinterface.h for the current expectations of what GetTrack // will return after calls to Receive. // TODO(deadbeef): Replace this test when the non-standard behavior is fixed // and GetTrack starts returning the same track for the lifetime of the // receiver. TEST_F(OrtcRtpReceiverTest, GetTrack) { auto receiver_result = ortc_factory_->CreateRtpReceiver( cricket::MEDIA_TYPE_VIDEO, rtp_transport_.get()); ASSERT_TRUE(receiver_result.ok()); auto receiver = receiver_result.MoveValue(); // Track initially expected to be null. EXPECT_EQ(nullptr, receiver_result.value().get()); EXPECT_TRUE(receiver->Receive(MakeMinimalVp8ParametersWithNoSsrc()).ok()); auto initial_track = receiver->GetTrack(); EXPECT_NE(nullptr, initial_track); // Codec changing but SSRC (or lack thereof) isn't; shouldn't create new track EXPECT_TRUE(receiver->Receive(MakeMinimalVp9ParametersWithNoSsrc()).ok()); EXPECT_EQ(initial_track, receiver->GetTrack()); // Explicitly set SSRC and expect a different track. EXPECT_TRUE( receiver->Receive(MakeMinimalVp9ParametersWithSsrc(0xdeadbeef)).ok()); auto next_track = receiver->GetTrack(); EXPECT_NE(next_track, initial_track); // Deactivating the encoding shouldn't change the track. RtpParameters inactive_encoding = MakeMinimalVp9ParametersWithSsrc(0xdeadbeef); inactive_encoding.encodings[0].active = false; EXPECT_TRUE(receiver->Receive(inactive_encoding).ok()); EXPECT_EQ(next_track, receiver->GetTrack()); // Removing all encodings *is* expected to clear the track. RtpParameters no_encodings = MakeMinimalVp9ParametersWithSsrc(0xdeadbeef); no_encodings.encodings.clear(); EXPECT_TRUE(receiver->Receive(no_encodings).ok()); EXPECT_EQ(nullptr, receiver->GetTrack()); } // Currently SetTransport isn't supported. When it is, replace this test with a // test/tests for it. TEST_F(OrtcRtpReceiverTest, SetTransportFails) { rtc::FakePacketTransport fake_packet_transport("another_transport"); RtpTransportParameters parameters; parameters.rtcp.mux = true; auto rtp_transport_result = ortc_factory_->CreateRtpTransport( parameters, &fake_packet_transport, nullptr, nullptr); auto rtp_transport = rtp_transport_result.MoveValue(); auto receiver_result = ortc_factory_->CreateRtpReceiver( cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get()); auto receiver = receiver_result.MoveValue(); EXPECT_EQ(RTCErrorType::UNSUPPORTED_OPERATION, receiver->SetTransport(rtp_transport.get()).type()); } TEST_F(OrtcRtpReceiverTest, GetTransport) { auto result = ortc_factory_->CreateRtpReceiver(cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get()); EXPECT_EQ(rtp_transport_.get(), result.value()->GetTransport()); } // Test that "Receive" causes the expected parameters to be applied to the media // engine level, for an audio receiver. TEST_F(OrtcRtpReceiverTest, ReceiveAppliesAudioParametersToMediaEngine) { auto audio_receiver_result = ortc_factory_->CreateRtpReceiver( cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get()); auto audio_receiver = audio_receiver_result.MoveValue(); // First, create parameters with all the bells and whistles. RtpParameters parameters; RtpCodecParameters opus_codec; opus_codec.name = "opus"; opus_codec.kind = cricket::MEDIA_TYPE_AUDIO; opus_codec.payload_type = 120; opus_codec.clock_rate.emplace(48000); opus_codec.num_channels.emplace(2); opus_codec.parameters["minptime"] = "10"; opus_codec.rtcp_feedback.emplace_back(RtcpFeedbackType::TRANSPORT_CC); parameters.codecs.push_back(std::move(opus_codec)); // Add two codecs, expecting the first to be used. // TODO(deadbeef): Once "codec_payload_type" is supported, use it to select a // codec that's not at the top of the list. RtpCodecParameters isac_codec; isac_codec.name = "ISAC"; isac_codec.kind = cricket::MEDIA_TYPE_AUDIO; isac_codec.payload_type = 110; isac_codec.clock_rate.emplace(16000); parameters.codecs.push_back(std::move(isac_codec)); RtpEncodingParameters encoding; encoding.ssrc.emplace(0xdeadbeef); parameters.encodings.push_back(std::move(encoding)); parameters.header_extensions.emplace_back( "urn:ietf:params:rtp-hdrext:ssrc-audio-level", 3); EXPECT_TRUE(audio_receiver->Receive(parameters).ok()); // Now verify that the parameters were applied to the fake media engine layer // that exists below BaseChannel. cricket::FakeVoiceMediaChannel* fake_voice_channel = fake_media_engine_->GetVoiceChannel(0); ASSERT_NE(nullptr, fake_voice_channel); EXPECT_TRUE(fake_voice_channel->playout()); // Verify codec parameters. ASSERT_GT(fake_voice_channel->recv_codecs().size(), 0u); const cricket::AudioCodec& top_codec = fake_voice_channel->recv_codecs()[0]; EXPECT_EQ("opus", top_codec.name); EXPECT_EQ(120, top_codec.id); EXPECT_EQ(48000, top_codec.clockrate); EXPECT_EQ(2u, top_codec.channels); ASSERT_NE(top_codec.params.end(), top_codec.params.find("minptime")); EXPECT_EQ("10", top_codec.params.at("minptime")); // Verify encoding parameters. ASSERT_EQ(1u, fake_voice_channel->recv_streams().size()); const cricket::StreamParams& recv_stream = fake_voice_channel->recv_streams()[0]; EXPECT_EQ(1u, recv_stream.ssrcs.size()); EXPECT_EQ(0xdeadbeef, recv_stream.first_ssrc()); // Verify header extensions. ASSERT_EQ(1u, fake_voice_channel->recv_extensions().size()); const RtpExtension& extension = fake_voice_channel->recv_extensions()[0]; EXPECT_EQ("urn:ietf:params:rtp-hdrext:ssrc-audio-level", extension.uri); EXPECT_EQ(3, extension.id); } // Test that "Receive" causes the expected parameters to be applied to the media // engine level, for a video receiver. TEST_F(OrtcRtpReceiverTest, ReceiveAppliesVideoParametersToMediaEngine) { auto video_receiver_result = ortc_factory_->CreateRtpReceiver( cricket::MEDIA_TYPE_VIDEO, rtp_transport_.get()); auto video_receiver = video_receiver_result.MoveValue(); // First, create parameters with all the bells and whistles. RtpParameters parameters; RtpCodecParameters vp8_codec; vp8_codec.name = "VP8"; vp8_codec.kind = cricket::MEDIA_TYPE_VIDEO; vp8_codec.payload_type = 99; // Try a couple types of feedback params. "Generic NACK" is a bit of a // special case, so test it here. vp8_codec.rtcp_feedback.emplace_back(RtcpFeedbackType::CCM, RtcpFeedbackMessageType::FIR); vp8_codec.rtcp_feedback.emplace_back(RtcpFeedbackType::NACK, RtcpFeedbackMessageType::GENERIC_NACK); parameters.codecs.push_back(std::move(vp8_codec)); RtpCodecParameters vp8_rtx_codec; vp8_rtx_codec.name = "rtx"; vp8_rtx_codec.kind = cricket::MEDIA_TYPE_VIDEO; vp8_rtx_codec.payload_type = 100; vp8_rtx_codec.parameters["apt"] = "99"; parameters.codecs.push_back(std::move(vp8_rtx_codec)); // Add two codecs, expecting the first to be used. // TODO(deadbeef): Once "codec_payload_type" is supported, use it to select a // codec that's not at the top of the list. RtpCodecParameters vp9_codec; vp9_codec.name = "VP9"; vp9_codec.kind = cricket::MEDIA_TYPE_VIDEO; vp9_codec.payload_type = 102; parameters.codecs.push_back(std::move(vp9_codec)); RtpCodecParameters vp9_rtx_codec; vp9_rtx_codec.name = "rtx"; vp9_rtx_codec.kind = cricket::MEDIA_TYPE_VIDEO; vp9_rtx_codec.payload_type = 103; vp9_rtx_codec.parameters["apt"] = "102"; parameters.codecs.push_back(std::move(vp9_rtx_codec)); RtpEncodingParameters encoding; encoding.ssrc.emplace(0xdeadbeef); encoding.rtx.emplace(0xbaadfeed); parameters.encodings.push_back(std::move(encoding)); parameters.header_extensions.emplace_back("urn:3gpp:video-orientation", 4); parameters.header_extensions.emplace_back( "http://www.webrtc.org/experiments/rtp-hdrext/playout-delay", 6); EXPECT_TRUE(video_receiver->Receive(parameters).ok()); // Now verify that the parameters were applied to the fake media engine layer // that exists below BaseChannel. cricket::FakeVideoMediaChannel* fake_video_channel = fake_media_engine_->GetVideoChannel(0); ASSERT_NE(nullptr, fake_video_channel); // Verify codec parameters. ASSERT_GE(fake_video_channel->recv_codecs().size(), 2u); const cricket::VideoCodec& top_codec = fake_video_channel->recv_codecs()[0]; EXPECT_EQ("VP8", top_codec.name); EXPECT_EQ(99, top_codec.id); EXPECT_TRUE(top_codec.feedback_params.Has({"ccm", "fir"})); EXPECT_TRUE(top_codec.feedback_params.Has(cricket::FeedbackParam("nack"))); const cricket::VideoCodec& rtx_codec = fake_video_channel->recv_codecs()[1]; EXPECT_EQ("rtx", rtx_codec.name); EXPECT_EQ(100, rtx_codec.id); ASSERT_NE(rtx_codec.params.end(), rtx_codec.params.find("apt")); EXPECT_EQ("99", rtx_codec.params.at("apt")); // Verify encoding parameters. ASSERT_EQ(1u, fake_video_channel->recv_streams().size()); const cricket::StreamParams& recv_stream = fake_video_channel->recv_streams()[0]; EXPECT_EQ(2u, recv_stream.ssrcs.size()); EXPECT_EQ(0xdeadbeef, recv_stream.first_ssrc()); uint32_t rtx_ssrc = 0u; EXPECT_TRUE(recv_stream.GetFidSsrc(recv_stream.first_ssrc(), &rtx_ssrc)); EXPECT_EQ(0xbaadfeed, rtx_ssrc); // Verify header extensions. ASSERT_EQ(2u, fake_video_channel->recv_extensions().size()); const RtpExtension& extension1 = fake_video_channel->recv_extensions()[0]; EXPECT_EQ("urn:3gpp:video-orientation", extension1.uri); EXPECT_EQ(4, extension1.id); const RtpExtension& extension2 = fake_video_channel->recv_extensions()[1]; EXPECT_EQ("http://www.webrtc.org/experiments/rtp-hdrext/playout-delay", extension2.uri); EXPECT_EQ(6, extension2.id); } // Test changing both the receive codec and SSRC at the same time, and verify // that the new parameters are applied to the media engine level. TEST_F(OrtcRtpReceiverTest, CallingReceiveTwiceChangesParameters) { auto audio_receiver_result = ortc_factory_->CreateRtpReceiver( cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get()); auto audio_receiver = audio_receiver_result.MoveValue(); RTCError error = audio_receiver->Receive(MakeMinimalOpusParametersWithSsrc(0x11111111)); EXPECT_TRUE(error.ok()); error = audio_receiver->Receive(MakeMinimalIsacParametersWithSsrc(0x22222222)); EXPECT_TRUE(error.ok()); cricket::FakeVoiceMediaChannel* fake_voice_channel = fake_media_engine_->GetVoiceChannel(0); ASSERT_NE(nullptr, fake_voice_channel); ASSERT_GT(fake_voice_channel->recv_codecs().size(), 0u); EXPECT_EQ("ISAC", fake_voice_channel->recv_codecs()[0].name); ASSERT_EQ(1u, fake_voice_channel->recv_streams().size()); EXPECT_EQ(0x22222222u, fake_voice_channel->recv_streams()[0].first_ssrc()); auto video_receiver_result = ortc_factory_->CreateRtpReceiver( cricket::MEDIA_TYPE_VIDEO, rtp_transport_.get()); auto video_receiver = video_receiver_result.MoveValue(); error = video_receiver->Receive(MakeMinimalVp8ParametersWithSsrc(0x33333333)); EXPECT_TRUE(error.ok()); error = video_receiver->Receive(MakeMinimalVp9ParametersWithSsrc(0x44444444)); EXPECT_TRUE(error.ok()); cricket::FakeVideoMediaChannel* fake_video_channel = fake_media_engine_->GetVideoChannel(0); ASSERT_NE(nullptr, fake_video_channel); ASSERT_GT(fake_video_channel->recv_codecs().size(), 0u); EXPECT_EQ("VP9", fake_video_channel->recv_codecs()[0].name); ASSERT_EQ(1u, fake_video_channel->recv_streams().size()); EXPECT_EQ(0x44444444u, fake_video_channel->recv_streams()[0].first_ssrc()); } // Ensure that if the |active| flag of RtpEncodingParameters is set to false, // playout stops at the media engine level. Note that this is only applicable // to audio (at least currently). TEST_F(OrtcRtpReceiverTest, DeactivatingEncodingStopsPlayout) { auto audio_receiver_result = ortc_factory_->CreateRtpReceiver( cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get()); auto audio_receiver = audio_receiver_result.MoveValue(); RtpParameters parameters = MakeMinimalOpusParameters(); EXPECT_TRUE(audio_receiver->Receive(parameters).ok()); // Expect "playout" flag to initially be true. cricket::FakeVoiceMediaChannel* fake_voice_channel = fake_media_engine_->GetVoiceChannel(0); ASSERT_NE(nullptr, fake_voice_channel); EXPECT_TRUE(fake_voice_channel->playout()); // Deactivate encoding and expect it to change to false. parameters.encodings[0].active = false; EXPECT_TRUE(audio_receiver->Receive(parameters).ok()); EXPECT_FALSE(fake_voice_channel->playout()); } // Ensure that calling Receive with an empty list of encodings causes receive // streams at the media engine level to be cleared. TEST_F(OrtcRtpReceiverTest, CallingReceiveWithEmptyEncodingsClearsReceiveStreams) { auto audio_receiver_result = ortc_factory_->CreateRtpReceiver( cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get()); auto audio_receiver = audio_receiver_result.MoveValue(); RtpParameters parameters = MakeMinimalOpusParameters(); EXPECT_TRUE(audio_receiver->Receive(parameters).ok()); parameters.encodings.clear(); EXPECT_TRUE(audio_receiver->Receive(parameters).ok()); cricket::FakeVoiceMediaChannel* fake_voice_channel = fake_media_engine_->GetVoiceChannel(0); ASSERT_NE(nullptr, fake_voice_channel); EXPECT_TRUE(fake_voice_channel->recv_streams().empty()); auto video_receiver_result = ortc_factory_->CreateRtpReceiver( cricket::MEDIA_TYPE_VIDEO, rtp_transport_.get()); auto video_receiver = video_receiver_result.MoveValue(); parameters = MakeMinimalVp8Parameters(); EXPECT_TRUE(video_receiver->Receive(parameters).ok()); parameters.encodings.clear(); EXPECT_TRUE(video_receiver->Receive(parameters).ok()); cricket::FakeVideoMediaChannel* fake_video_channel = fake_media_engine_->GetVideoChannel(0); ASSERT_NE(nullptr, fake_video_channel); EXPECT_TRUE(fake_video_channel->recv_streams().empty()); } // These errors should be covered by rtpparametersconversion_unittest.cc, but // we should at least test that those errors are propogated from calls to // Receive, with a few examples. TEST_F(OrtcRtpReceiverTest, ReceiveReturnsErrorOnInvalidParameters) { auto result = ortc_factory_->CreateRtpReceiver(cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get()); auto receiver = result.MoveValue(); // CCM feedback missing message type. RtpParameters invalid_feedback = MakeMinimalOpusParameters(); invalid_feedback.codecs[0].rtcp_feedback.emplace_back(RtcpFeedbackType::CCM); EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, receiver->Receive(invalid_feedback).type()); // Payload type greater than 127. RtpParameters invalid_pt = MakeMinimalOpusParameters(); invalid_pt.codecs[0].payload_type = 128; EXPECT_EQ(RTCErrorType::INVALID_RANGE, receiver->Receive(invalid_pt).type()); // Duplicate header extension IDs. RtpParameters duplicate_ids = MakeMinimalOpusParameters(); duplicate_ids.header_extensions.emplace_back("foo", 5); duplicate_ids.header_extensions.emplace_back("bar", 5); EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, receiver->Receive(duplicate_ids).type()); } // Two receivers using the same transport shouldn't be able to use the same // payload type to refer to different codecs, same header extension IDs to // refer to different extensions, or same SSRC. TEST_F(OrtcRtpReceiverTest, ReceiveReturnsErrorOnIdConflicts) { auto audio_receiver_result = ortc_factory_->CreateRtpReceiver( cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get()); auto video_receiver_result = ortc_factory_->CreateRtpReceiver( cricket::MEDIA_TYPE_VIDEO, rtp_transport_.get()); auto audio_receiver = audio_receiver_result.MoveValue(); auto video_receiver = video_receiver_result.MoveValue(); // First test payload type conflict. RtpParameters audio_parameters = MakeMinimalOpusParameters(); RtpParameters video_parameters = MakeMinimalVp8Parameters(); audio_parameters.codecs[0].payload_type = 100; video_parameters.codecs[0].payload_type = 100; EXPECT_TRUE(audio_receiver->Receive(audio_parameters).ok()); EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, video_receiver->Receive(video_parameters).type()); // Test header extension ID conflict. video_parameters.codecs[0].payload_type = 110; audio_parameters.header_extensions.emplace_back("foo", 4); video_parameters.header_extensions.emplace_back("bar", 4); EXPECT_TRUE(audio_receiver->Receive(audio_parameters).ok()); EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, video_receiver->Receive(video_parameters).type()); // Test SSRC conflict. Have an RTX SSRC that conflicts with a primary SSRC // for extra challenge. video_parameters.header_extensions[0].uri = "foo"; audio_parameters.encodings[0].ssrc.emplace(0xabbaabba); audio_parameters.encodings[0].rtx.emplace(0xdeadbeef); video_parameters.encodings[0].ssrc.emplace(0xdeadbeef); EXPECT_TRUE(audio_receiver->Receive(audio_parameters).ok()); EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, video_receiver->Receive(video_parameters).type()); // Sanity check that parameters can be set if the conflicts are all resolved. video_parameters.encodings[0].ssrc.emplace(0xbaadf00d); EXPECT_TRUE(video_receiver->Receive(video_parameters).ok()); } // Ensure that deleting a receiver causes receive streams at the media engine // level to be cleared. TEST_F(OrtcRtpReceiverTest, DeletingReceiverClearsReceiveStreams) { auto audio_receiver_result = ortc_factory_->CreateRtpReceiver( cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get()); auto audio_receiver = audio_receiver_result.MoveValue(); EXPECT_TRUE(audio_receiver->Receive(MakeMinimalOpusParameters()).ok()); // Also create an audio sender, to prevent the voice channel from being // completely deleted. auto audio_sender_result = ortc_factory_->CreateRtpSender( cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get()); auto audio_sender = audio_sender_result.MoveValue(); EXPECT_TRUE(audio_sender->Send(MakeMinimalOpusParameters()).ok()); audio_receiver.reset(nullptr); cricket::FakeVoiceMediaChannel* fake_voice_channel = fake_media_engine_->GetVoiceChannel(0); ASSERT_NE(nullptr, fake_voice_channel); EXPECT_TRUE(fake_voice_channel->recv_streams().empty()); auto video_receiver_result = ortc_factory_->CreateRtpReceiver( cricket::MEDIA_TYPE_VIDEO, rtp_transport_.get()); auto video_receiver = video_receiver_result.MoveValue(); EXPECT_TRUE(video_receiver->Receive(MakeMinimalVp8Parameters()).ok()); // Also create an video sender, to prevent the video channel from being // completely deleted. auto video_sender_result = ortc_factory_->CreateRtpSender( cricket::MEDIA_TYPE_VIDEO, rtp_transport_.get()); auto video_sender = video_sender_result.MoveValue(); EXPECT_TRUE(video_sender->Send(MakeMinimalVp8Parameters()).ok()); video_receiver.reset(nullptr); cricket::FakeVideoMediaChannel* fake_video_channel = fake_media_engine_->GetVideoChannel(0); ASSERT_NE(nullptr, fake_video_channel); EXPECT_TRUE(fake_video_channel->recv_streams().empty()); } // If Receive hasn't been called, GetParameters should return empty parameters. TEST_F(OrtcRtpReceiverTest, GetDefaultParameters) { auto result = ortc_factory_->CreateRtpReceiver(cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get()); EXPECT_EQ(RtpParameters(), result.value()->GetParameters()); result = ortc_factory_->CreateRtpReceiver(cricket::MEDIA_TYPE_VIDEO, rtp_transport_.get()); EXPECT_EQ(RtpParameters(), result.value()->GetParameters()); } // Test that GetParameters returns the last parameters passed into Receive, // along with the implementation-default values filled in where they were left // unset. TEST_F(OrtcRtpReceiverTest, GetParametersReturnsLastSetParametersWithDefaultsFilled) { auto audio_receiver_result = ortc_factory_->CreateRtpReceiver( cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get()); auto audio_receiver = audio_receiver_result.MoveValue(); RtpParameters opus_parameters = MakeMinimalOpusParameters(); EXPECT_TRUE(audio_receiver->Receive(opus_parameters).ok()); EXPECT_EQ(opus_parameters, audio_receiver->GetParameters()); RtpParameters isac_parameters = MakeMinimalIsacParameters(); // Sanity check that num_channels actually is left unset. ASSERT_FALSE(isac_parameters.codecs[0].num_channels); EXPECT_TRUE(audio_receiver->Receive(isac_parameters).ok()); // Should be filled with a default "num channels" of 1. // TODO(deadbeef): This should actually default to 2 for some codecs. Update // this test once that's implemented. isac_parameters.codecs[0].num_channels.emplace(1); EXPECT_EQ(isac_parameters, audio_receiver->GetParameters()); auto video_receiver_result = ortc_factory_->CreateRtpReceiver( cricket::MEDIA_TYPE_VIDEO, rtp_transport_.get()); auto video_receiver = video_receiver_result.MoveValue(); RtpParameters vp8_parameters = MakeMinimalVp8Parameters(); // Sanity check that clock_rate actually is left unset. EXPECT_TRUE(video_receiver->Receive(vp8_parameters).ok()); // Should be filled with a default clock rate of 90000. vp8_parameters.codecs[0].clock_rate.emplace(90000); EXPECT_EQ(vp8_parameters, video_receiver->GetParameters()); RtpParameters vp9_parameters = MakeMinimalVp9Parameters(); // Sanity check that clock_rate actually is left unset. EXPECT_TRUE(video_receiver->Receive(vp9_parameters).ok()); // Should be filled with a default clock rate of 90000. vp9_parameters.codecs[0].clock_rate.emplace(90000); EXPECT_EQ(vp9_parameters, video_receiver->GetParameters()); } TEST_F(OrtcRtpReceiverTest, GetKind) { auto audio_receiver_result = ortc_factory_->CreateRtpReceiver( cricket::MEDIA_TYPE_AUDIO, rtp_transport_.get()); auto video_receiver_result = ortc_factory_->CreateRtpReceiver( cricket::MEDIA_TYPE_VIDEO, rtp_transport_.get()); auto audio_receiver = audio_receiver_result.MoveValue(); auto video_receiver = video_receiver_result.MoveValue(); EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, audio_receiver->GetKind()); EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, video_receiver->GetKind()); } } // namespace webrtc