Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(58)

Unified Diff: webrtc/ortc/ortcfactory_integrationtest.cc

Issue 2675173003: Adding "adapter" ORTC objects on top of ChannelManager/BaseChannel/etc. (Closed)
Patch Set: Rebase onto split-off RtcError CL Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/ortc/ortcfactory.cc ('k') | webrtc/ortc/rtpreceivershim.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/ortc/ortcfactory_integrationtest.cc
diff --git a/webrtc/ortc/ortcfactory_integrationtest.cc b/webrtc/ortc/ortcfactory_integrationtest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6b377765f6ac4ea2859eaf81824d1d0b75dd6768
--- /dev/null
+++ b/webrtc/ortc/ortcfactory_integrationtest.cc
@@ -0,0 +1,448 @@
+/*
+ * 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 <memory>
+
+#include "webrtc/api/ortc/ortcfactoryinterface.h"
+#include "webrtc/base/criticalsection.h"
+#include "webrtc/base/fakenetwork.h"
+#include "webrtc/base/gunit.h"
+#include "webrtc/base/physicalsocketserver.h"
+#include "webrtc/base/virtualsocketserver.h"
+#include "webrtc/p2p/base/udptransport.h"
+#include "webrtc/pc/test/fakeaudiocapturemodule.h"
+#include "webrtc/pc/test/fakeperiodicvideocapturer.h"
+#include "webrtc/pc/test/fakevideotrackrenderer.h"
+
+namespace {
+
+const int kDefaultTimeout = 10000; // 10 seconds.
+// Default number of audio/video frames to wait for before considering a test a
+// success.
+const int kDefaultNumFrames = 3;
+static const rtc::IPAddress kIPv4LocalHostAddress =
+ rtc::IPAddress(0x7F000001); // 127.0.0.1
+
+class PacketReceiver : public sigslot::has_slots<> {
+ public:
+ explicit PacketReceiver(rtc::PacketTransportInternal* transport) {
+ transport->SignalReadPacket.connect(this, &PacketReceiver::OnReadPacket);
+ }
+ int packets_read() const {
+ rtc::CritScope cs(&critsec_);
+ return packets_read_;
+ }
+
+ private:
+ void OnReadPacket(rtc::PacketTransportInternal*,
+ const char*,
+ size_t,
+ const rtc::PacketTime&,
+ int) {
+ rtc::CritScope cs(&critsec_);
+ ++packets_read_;
+ }
+
+ int packets_read_ = 0;
+ rtc::CriticalSection critsec_;
+};
+
+webrtc::RtpParameters MakeMinimalOpusParametersWithSsrc(uint32_t ssrc) {
+ webrtc::RtpParameters parameters;
+ webrtc::RtpCodecParameters opus_codec;
+ opus_codec.name = "opus";
+ opus_codec.kind = cricket::MEDIA_TYPE_AUDIO;
+ opus_codec.payload_type = 111;
+ opus_codec.clock_rate.emplace(48000);
+ opus_codec.num_channels.emplace(2);
+ parameters.codecs.push_back(std::move(opus_codec));
+ webrtc::RtpEncodingParameters encoding;
+ encoding.ssrc.emplace(ssrc);
+ encoding.codec_payload_type.emplace(111);
+ parameters.encodings.push_back(std::move(encoding));
+ return parameters;
+}
+
+webrtc::RtpParameters MakeMinimalOpusParameters() {
+ return MakeMinimalOpusParametersWithSsrc(0xdeadbeef);
+}
+
+webrtc::RtpParameters MakeMinimalVp8ParametersWithSsrc(uint32_t ssrc) {
+ webrtc::RtpParameters parameters;
+ webrtc::RtpCodecParameters vp8_codec;
+ vp8_codec.name = "VP8";
+ vp8_codec.kind = cricket::MEDIA_TYPE_VIDEO;
+ vp8_codec.payload_type = 111;
+ parameters.codecs.push_back(std::move(vp8_codec));
+ webrtc::RtpEncodingParameters encoding;
+ encoding.ssrc.emplace(ssrc);
+ encoding.codec_payload_type.emplace(111);
+ parameters.encodings.push_back(std::move(encoding));
+ return parameters;
+}
+
+webrtc::RtpParameters MakeMinimalVp8Parameters() {
+ return MakeMinimalVp8ParametersWithSsrc(0xdeadbeef);
+}
+
+} // namespace
+
+namespace webrtc {
+
+// Used to test that things work end-to-end when using the default
+// implementations of threads/etc. provided by OrtcFactory, with the exception
+// of using a virtual network.
+//
+// By default, the virtual network manager doesn't enumerate any networks, but
+// sockets can still be created in this state.
+class OrtcFactoryTest : public testing::Test {
+ public:
+ OrtcFactoryTest()
+ : virtual_socket_server_(&physical_socket_server_),
+ network_thread_(&virtual_socket_server_),
+ fake_audio_capture_module1_(FakeAudioCaptureModule::Create()),
+ fake_audio_capture_module2_(FakeAudioCaptureModule::Create()) {
+ // Sockets are bound to the ANY address, so this is needed to tell the
+ // virtual network which address to use in this case.
+ virtual_socket_server_.SetDefaultRoute(kIPv4LocalHostAddress);
+ network_thread_.Start();
+ // Need to create after network thread is started.
+ ortc_factory1_ = OrtcFactoryInterface::Create(
+ &network_thread_, nullptr, &fake_network_manager_,
+ nullptr, fake_audio_capture_module1_)
+ .MoveValue();
+ ortc_factory2_ = OrtcFactoryInterface::Create(
+ &network_thread_, nullptr, &fake_network_manager_,
+ nullptr, fake_audio_capture_module2_)
+ .MoveValue();
+ }
+
+ protected:
+ // Ends up using fake audio capture module, which was passed into OrtcFactory
+ // on creation.
+ rtc::scoped_refptr<webrtc::AudioTrackInterface> CreateLocalAudioTrack(
+ const std::string& id,
+ OrtcFactoryInterface* ortc_factory) {
+ // Disable echo cancellation to make test more efficient.
+ cricket::AudioOptions options;
+ options.echo_cancellation.emplace(true);
+ rtc::scoped_refptr<webrtc::AudioSourceInterface> source =
+ ortc_factory->CreateAudioSource(options);
+ return ortc_factory->CreateAudioTrack(id, source);
+ }
+
+ // Stores created capturer in |fake_video_capturers_|.
+ rtc::scoped_refptr<webrtc::VideoTrackInterface>
+ CreateLocalVideoTrackAndFakeCapturer(const std::string& id,
+ OrtcFactoryInterface* ortc_factory) {
+ cricket::FakeVideoCapturer* fake_capturer =
+ new webrtc::FakePeriodicVideoCapturer();
+ fake_video_capturers_.push_back(fake_capturer);
+ rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> source =
+ ortc_factory->CreateVideoSource(
+ std::unique_ptr<cricket::VideoCapturer>(fake_capturer));
+ return rtc::scoped_refptr<webrtc::VideoTrackInterface>(
+ ortc_factory->CreateVideoTrack(id, source));
+ }
+
+ rtc::PhysicalSocketServer physical_socket_server_;
+ rtc::VirtualSocketServer virtual_socket_server_;
+ rtc::Thread network_thread_;
+ rtc::FakeNetworkManager fake_network_manager_;
+ rtc::scoped_refptr<FakeAudioCaptureModule> fake_audio_capture_module1_;
+ rtc::scoped_refptr<FakeAudioCaptureModule> fake_audio_capture_module2_;
+ std::unique_ptr<OrtcFactoryInterface> ortc_factory1_;
+ std::unique_ptr<OrtcFactoryInterface> ortc_factory2_;
+ // Actually owned by video tracks.
+ std::vector<cricket::FakeVideoCapturer*> fake_video_capturers_;
+};
+
+TEST_F(OrtcFactoryTest, EndToEndUdpTransport) {
+ std::unique_ptr<UdpTransportInterface> transport1 =
+ ortc_factory1_->CreateUdpTransport(AF_INET).MoveValue();
+ std::unique_ptr<UdpTransportInterface> transport2 =
+ ortc_factory2_->CreateUdpTransport(AF_INET).MoveValue();
+ // Sockets are bound to the ANY address, so we need to provide the IP address
+ // explicitly.
+ transport1->SetRemoteAddress(
+ rtc::SocketAddress(virtual_socket_server_.GetDefaultRoute(AF_INET),
+ transport2->GetLocalAddress().port()));
+ transport2->SetRemoteAddress(
+ rtc::SocketAddress(virtual_socket_server_.GetDefaultRoute(AF_INET),
+ transport1->GetLocalAddress().port()));
+
+ // TODO(deadbeef): Once there's something (RTP senders/receivers) that can
+ // use UdpTransport end-to-end, use that for this end-to-end test instead of
+ // making assumptions about the implementation.
+ //
+ // For now, this assumes the returned object is a UdpTransportProxy that wraps
+ // a UdpTransport.
+ cricket::UdpTransport* internal_transport1 =
+ static_cast<cricket::UdpTransport*>(transport1->GetInternal());
+ cricket::UdpTransport* internal_transport2 =
+ static_cast<cricket::UdpTransport*>(transport2->GetInternal());
+ PacketReceiver receiver1(internal_transport1);
+ PacketReceiver receiver2(internal_transport2);
+ // Need to call internal "SendPacket" method on network thread.
+ network_thread_.Invoke<void>(
+ RTC_FROM_HERE, [internal_transport1, internal_transport2]() {
+ internal_transport1->SendPacket("foo", sizeof("foo"),
+ rtc::PacketOptions(), 0);
+ internal_transport2->SendPacket("foo", sizeof("foo"),
+ rtc::PacketOptions(), 0);
+ });
+ EXPECT_EQ_WAIT(1, receiver1.packets_read(), kDefaultTimeout);
+ EXPECT_EQ_WAIT(1, receiver2.packets_read(), kDefaultTimeout);
+}
+
+// Very basic end-to-end test with a single pair of audio RTP sender and
+// receiver.
+//
+// Uses muxed RTCP, and minimal parameters with a hard-coded config that's
+// known to work.
+TEST_F(OrtcFactoryTest, UnidirectionalAudioRtpSenderAndReceiver) {
+ // Start by creating underlying UDP transports.
+ std::unique_ptr<UdpTransportInterface> sender_udp_transport =
+ ortc_factory1_->CreateUdpTransport(AF_INET).MoveValue();
+ std::unique_ptr<UdpTransportInterface> receiver_udp_transport =
+ ortc_factory2_->CreateUdpTransport(AF_INET).MoveValue();
+ // Sockets are bound to the ANY address, so we need to provide the IP address
+ // explicitly.
+ sender_udp_transport->SetRemoteAddress(
+ rtc::SocketAddress(virtual_socket_server_.GetDefaultRoute(AF_INET),
+ receiver_udp_transport->GetLocalAddress().port()));
+ receiver_udp_transport->SetRemoteAddress(
+ rtc::SocketAddress(virtual_socket_server_.GetDefaultRoute(AF_INET),
+ sender_udp_transport->GetLocalAddress().port()));
+
+ // Create RTP transports.
+ RtcpParameters rtcp_parameters;
+ rtcp_parameters.mux = true;
+ std::unique_ptr<RtpTransportInterface> sender_rtp_transport =
+ ortc_factory1_
+ ->CreateRtpTransport(rtcp_parameters, sender_udp_transport.get(),
+ nullptr, nullptr)
+ .MoveValue();
+ std::unique_ptr<RtpTransportInterface> receiver_rtp_transport =
+ ortc_factory2_
+ ->CreateRtpTransport(rtcp_parameters, receiver_udp_transport.get(),
+ nullptr, nullptr)
+ .MoveValue();
+
+ auto sender_result = ortc_factory1_->CreateRtpSender(
+ cricket::MEDIA_TYPE_AUDIO, sender_rtp_transport.get());
+ auto receiver_result = ortc_factory2_->CreateRtpReceiver(
+ cricket::MEDIA_TYPE_AUDIO, receiver_rtp_transport.get());
+ ASSERT_TRUE(sender_result.ok());
+ ASSERT_TRUE(receiver_result.ok());
+ auto sender = sender_result.MoveValue();
+ auto receiver = receiver_result.MoveValue();
+
+ RtpParameters opus_parameters = MakeMinimalOpusParameters();
+ EXPECT_TRUE(receiver->Receive(opus_parameters).ok());
+ EXPECT_TRUE(
+ sender->SetTrack(CreateLocalAudioTrack("audio", ortc_factory1_.get()))
+ .ok());
+ EXPECT_TRUE(sender->Send(opus_parameters).ok());
+ // Sender and receiver are connected and configured; audio frames should be
+ // able to flow at this point.
+ EXPECT_TRUE_WAIT(
+ fake_audio_capture_module2_->frames_received() > kDefaultNumFrames,
+ kDefaultTimeout);
+}
+
+// Very basic end-to-end test with a single pair of video RTP sender and
+// receiver.
+//
+// Uses muxed RTCP, and minimal parameters with a hard-coded config that's
+// known to work.
+TEST_F(OrtcFactoryTest, UnidirectionalVideoRtpSenderAndReceiver) {
+ // Start by creating underlying UDP transports.
+ std::unique_ptr<UdpTransportInterface> sender_udp_transport =
+ ortc_factory1_->CreateUdpTransport(AF_INET).MoveValue();
+ std::unique_ptr<UdpTransportInterface> receiver_udp_transport =
+ ortc_factory2_->CreateUdpTransport(AF_INET).MoveValue();
+ // Sockets are bound to the ANY address, so we need to provide the IP address
+ // explicitly.
+ sender_udp_transport->SetRemoteAddress(
+ rtc::SocketAddress(virtual_socket_server_.GetDefaultRoute(AF_INET),
+ receiver_udp_transport->GetLocalAddress().port()));
+ receiver_udp_transport->SetRemoteAddress(
+ rtc::SocketAddress(virtual_socket_server_.GetDefaultRoute(AF_INET),
+ sender_udp_transport->GetLocalAddress().port()));
+
+ // Create RTP transports.
+ RtcpParameters rtcp_parameters;
+ rtcp_parameters.mux = true;
+ std::unique_ptr<RtpTransportInterface> sender_rtp_transport =
+ ortc_factory1_
+ ->CreateRtpTransport(rtcp_parameters, sender_udp_transport.get(),
+ nullptr, nullptr)
+ .MoveValue();
+ std::unique_ptr<RtpTransportInterface> receiver_rtp_transport =
+ ortc_factory2_
+ ->CreateRtpTransport(rtcp_parameters, receiver_udp_transport.get(),
+ nullptr, nullptr)
+ .MoveValue();
+
+ auto sender_result = ortc_factory1_->CreateRtpSender(
+ cricket::MEDIA_TYPE_VIDEO, sender_rtp_transport.get());
+ auto receiver_result = ortc_factory2_->CreateRtpReceiver(
+ cricket::MEDIA_TYPE_VIDEO, receiver_rtp_transport.get());
+ ASSERT_TRUE(sender_result.ok());
+ ASSERT_TRUE(receiver_result.ok());
+ auto sender = sender_result.MoveValue();
+ auto receiver = receiver_result.MoveValue();
+
+ RtpParameters vp8_parameters = MakeMinimalVp8Parameters();
+ EXPECT_TRUE(receiver->Receive(vp8_parameters).ok());
+ FakeVideoTrackRenderer fake_renderer(
+ static_cast<VideoTrackInterface*>(receiver->GetTrack().get()));
+ EXPECT_TRUE(sender
+ ->SetTrack(CreateLocalVideoTrackAndFakeCapturer(
+ "video", ortc_factory1_.get()))
+ .ok());
+ EXPECT_TRUE(sender->Send(vp8_parameters).ok());
+ // Sender and receiver are connected and configured; video frames should be
+ // able to flow at this point.
+ EXPECT_TRUE_WAIT(fake_renderer.num_rendered_frames() > kDefaultNumFrames,
+ kDefaultTimeout);
+}
+
+// End-to-end test with two pairs of RTP senders and receivers, for audio and
+// video.
+//
+// Uses muxed RTCP, and minimal parameters with hard-coded configs that are
+// known to work.
+TEST_F(OrtcFactoryTest, BidirectionalAudioVideoRtpSendersAndReceivers) {
+ // Start by creating underlying UDP transports.
+ std::unique_ptr<UdpTransportInterface> udp_transport1 =
+ ortc_factory1_->CreateUdpTransport(AF_INET).MoveValue();
+ std::unique_ptr<UdpTransportInterface> udp_transport2 =
+ ortc_factory2_->CreateUdpTransport(AF_INET).MoveValue();
+ // Sockets are bound to the ANY address, so we need to provide the IP address
+ // explicitly.
+ udp_transport1->SetRemoteAddress(
+ rtc::SocketAddress(virtual_socket_server_.GetDefaultRoute(AF_INET),
+ udp_transport2->GetLocalAddress().port()));
+ udp_transport2->SetRemoteAddress(
+ rtc::SocketAddress(virtual_socket_server_.GetDefaultRoute(AF_INET),
+ udp_transport1->GetLocalAddress().port()));
+
+ // Create RTP transports.
+ RtcpParameters rtcp_parameters;
+ rtcp_parameters.mux = true;
+ std::unique_ptr<RtpTransportInterface> rtp_transport1 =
+ ortc_factory1_
+ ->CreateRtpTransport(rtcp_parameters, udp_transport1.get(), nullptr,
+ nullptr)
+ .MoveValue();
+ std::unique_ptr<RtpTransportInterface> rtp_transport2 =
+ ortc_factory2_
+ ->CreateRtpTransport(rtcp_parameters, udp_transport2.get(), nullptr,
+ nullptr)
+ .MoveValue();
+
+ // Create all the senders and receivers (four per endpoint).
+ auto audio_sender_result1 = ortc_factory1_->CreateRtpSender(
+ cricket::MEDIA_TYPE_AUDIO, rtp_transport1.get());
+ auto video_sender_result1 = ortc_factory1_->CreateRtpSender(
+ cricket::MEDIA_TYPE_VIDEO, rtp_transport1.get());
+ auto audio_receiver_result1 = ortc_factory1_->CreateRtpReceiver(
+ cricket::MEDIA_TYPE_AUDIO, rtp_transport1.get());
+ auto video_receiver_result1 = ortc_factory1_->CreateRtpReceiver(
+ cricket::MEDIA_TYPE_VIDEO, rtp_transport1.get());
+ ASSERT_TRUE(audio_sender_result1.ok());
+ ASSERT_TRUE(video_sender_result1.ok());
+ ASSERT_TRUE(audio_receiver_result1.ok());
+ ASSERT_TRUE(video_receiver_result1.ok());
+ auto audio_sender1 = audio_sender_result1.MoveValue();
+ auto video_sender1 = video_sender_result1.MoveValue();
+ auto audio_receiver1 = audio_receiver_result1.MoveValue();
+ auto video_receiver1 = video_receiver_result1.MoveValue();
+
+ auto audio_sender_result2 = ortc_factory2_->CreateRtpSender(
+ cricket::MEDIA_TYPE_AUDIO, rtp_transport2.get());
+ auto video_sender_result2 = ortc_factory2_->CreateRtpSender(
+ cricket::MEDIA_TYPE_VIDEO, rtp_transport2.get());
+ auto audio_receiver_result2 = ortc_factory2_->CreateRtpReceiver(
+ cricket::MEDIA_TYPE_AUDIO, rtp_transport2.get());
+ auto video_receiver_result2 = ortc_factory2_->CreateRtpReceiver(
+ cricket::MEDIA_TYPE_VIDEO, rtp_transport2.get());
+ ASSERT_TRUE(audio_sender_result2.ok());
+ ASSERT_TRUE(video_sender_result2.ok());
+ ASSERT_TRUE(audio_receiver_result2.ok());
+ ASSERT_TRUE(video_receiver_result2.ok());
+ auto audio_sender2 = audio_sender_result2.MoveValue();
+ auto video_sender2 = video_sender_result2.MoveValue();
+ auto audio_receiver2 = audio_receiver_result2.MoveValue();
+ auto video_receiver2 = video_receiver_result2.MoveValue();
+
+ // "sent_X_parameters1" are the parameters that endpoint 1 sends with and
+ // endpoint 2 receives with.
+ RtpParameters sent_opus_parameters1 =
+ MakeMinimalOpusParametersWithSsrc(0xdeadbeef);
+ RtpParameters sent_vp8_parameters1 =
+ MakeMinimalVp8ParametersWithSsrc(0xbaadfeed);
+ RtpParameters sent_opus_parameters2 =
+ MakeMinimalOpusParametersWithSsrc(0x13333337);
+ RtpParameters sent_vp8_parameters2 =
+ MakeMinimalVp8ParametersWithSsrc(0x12345678);
+
+ // Configure the receivers' parameters.
+ EXPECT_TRUE(audio_receiver1->Receive(sent_opus_parameters2).ok());
+ EXPECT_TRUE(video_receiver1->Receive(sent_vp8_parameters2).ok());
+ EXPECT_TRUE(audio_receiver2->Receive(sent_opus_parameters1).ok());
+ EXPECT_TRUE(video_receiver2->Receive(sent_vp8_parameters1).ok());
+ FakeVideoTrackRenderer fake_video_renderer1(
+ static_cast<VideoTrackInterface*>(video_receiver1->GetTrack().get()));
+ FakeVideoTrackRenderer fake_video_renderer2(
+ static_cast<VideoTrackInterface*>(video_receiver2->GetTrack().get()));
+
+ // Configure the senders' parameters.
+ EXPECT_TRUE(
+ audio_sender1
+ ->SetTrack(CreateLocalAudioTrack("audio", ortc_factory1_.get()))
+ .ok());
+ EXPECT_TRUE(video_sender1
+ ->SetTrack(CreateLocalVideoTrackAndFakeCapturer(
+ "video", ortc_factory1_.get()))
+ .ok());
+ EXPECT_TRUE(
+ audio_sender2
+ ->SetTrack(CreateLocalAudioTrack("audio", ortc_factory2_.get()))
+ .ok());
+ EXPECT_TRUE(video_sender2
+ ->SetTrack(CreateLocalVideoTrackAndFakeCapturer(
+ "video", ortc_factory2_.get()))
+ .ok());
+ EXPECT_TRUE(audio_sender1->Send(sent_opus_parameters1).ok());
+ EXPECT_TRUE(video_sender1->Send(sent_vp8_parameters1).ok());
+ EXPECT_TRUE(audio_sender2->Send(sent_opus_parameters2).ok());
+ EXPECT_TRUE(video_sender2->Send(sent_vp8_parameters2).ok());
+ // Senders and receivers are connected and configured; audio and frames
+ // should be able to flow at this point.
+ EXPECT_TRUE_WAIT(
+ fake_audio_capture_module1_->frames_received() > kDefaultNumFrames &&
+ fake_video_renderer1.num_rendered_frames() > kDefaultNumFrames &&
+ fake_audio_capture_module2_->frames_received() > kDefaultNumFrames &&
+ fake_video_renderer2.num_rendered_frames() > kDefaultNumFrames,
+ kDefaultTimeout);
+}
+
+// TODO(deadbeef): End-to-end test for multiple senders/receivers of the same
+// media type, once that's supported. Currently, it is not because the
+// implementation relies on there being a single VoiceChannel and VideoChannel,
+// and these only support a single set of codecs per send/receive direction.
+
+// TODO(deadbeef): End-to-end test for simulcast, once that's supported by this
+// API.
+
+} // namespace webrtc
« no previous file with comments | « webrtc/ortc/ortcfactory.cc ('k') | webrtc/ortc/rtpreceivershim.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698