From 97c96238396ded77ecd91ab0f84647e89b070d80 Mon Sep 17 00:00:00 2001 From: Harald Alvestrand Date: Tue, 30 May 2023 04:04:07 +0000 Subject: [PATCH] Make a shim object implementing the VideoMediaChannel interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The intent is that this object can be used instead of VideoMediaChannel, clearing the way for decomposing VideoMediaChannel into send and receive classes. This CL uses it for the "both" role of WebRtcVideoEngine::CreateMediaChannel; a later CL will use it for all roles on all engines. Bug: webrtc:13931 Change-Id: Ibd0ca2c3c45b5e3bfcced8f7e30a1edd63cf7654 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/306720 Commit-Queue: Harald Alvestrand Reviewed-by: Henrik Boström Cr-Commit-Position: refs/heads/main@{#40173} --- media/BUILD.gn | 46 ++- media/base/media_channel.h | 3 + media/base/media_channel_impl.h | 31 +- media/base/media_channel_shim.cc | 38 +++ media/base/media_channel_shim.h | 333 +++++++++++++++++++ media/engine/webrtc_video_engine.cc | 16 +- media/engine/webrtc_video_engine.h | 1 + media/engine/webrtc_video_engine_unittest.cc | 95 +++--- 8 files changed, 510 insertions(+), 53 deletions(-) create mode 100644 media/base/media_channel_shim.cc create mode 100644 media/base/media_channel_shim.h diff --git a/media/BUILD.gn b/media/BUILD.gn index 37d07c1404..80b39e6fd0 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn @@ -141,6 +141,40 @@ rtc_library("rtc_media_base") { ] } +rtc_library("media_channel_shim") { + sources = [ + "base/media_channel_shim.cc", + "base/media_channel_shim.h", + ] + deps = [ + ":codec", + ":media_channel", + ":media_channel_impl", + ":stream_params", + "../api:frame_transformer_interface", + "../api:rtc_error", + "../api:rtp_headers", + "../api:rtp_parameters", + "../api:rtp_sender_interface", + "../api:scoped_refptr", + "../api/crypto:frame_decryptor_interface", + "../api/crypto:frame_encryptor_interface", + "../api/transport/rtp:rtp_source", + "../api/video:recordable_encoded_frame", + "../api/video:video_frame", + "../api/video_codecs:video_codecs_api", + "../modules/rtp_rtcp:rtp_rtcp_format", + "../rtc_base:checks", + "../rtc_base:network_route", + "../rtc_base/network:sent_packet", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/functional:any_invocable", + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + rtc_library("media_channel_impl") { sources = [ "base/media_channel_impl.cc", @@ -205,8 +239,10 @@ rtc_source_set("media_channel") { "../api:frame_transformer_interface", "../api:media_stream_interface", "../api:rtc_error", + "../api:rtp_headers", "../api:rtp_parameters", "../api:rtp_sender_interface", + "../api:scoped_refptr", "../api/audio_codecs:audio_codecs_api", "../api/crypto:frame_decryptor_interface", "../api/crypto:frame_encryptor_interface", @@ -214,6 +250,7 @@ rtc_source_set("media_channel") { "../api/transport:datagram_transport_interface", "../api/transport/rtp:rtp_source", "../api/units:time_delta", + "../api/video:recordable_encoded_frame", "../api/video:video_frame", "../api/video:video_rtp_headers", "../api/video_codecs:scalability_mode", @@ -224,15 +261,21 @@ rtc_source_set("media_channel") { "../modules/rtp_rtcp:rtp_rtcp_format", "../rtc_base:async_packet_socket", "../rtc_base:buffer", + "../rtc_base:checks", "../rtc_base:copy_on_write_buffer", "../rtc_base:dscp", "../rtc_base:logging", "../rtc_base:network_route", "../rtc_base:socket", "../rtc_base:stringutils", + "../rtc_base/network:sent_packet", "../video/config:encoder_config", ] - absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] + absl_deps = [ + "//third_party/abseil-cpp/absl/functional:any_invocable", + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] } rtc_source_set("delayable") { @@ -429,6 +472,7 @@ rtc_library("rtc_audio_video") { ":codec", ":media_channel", ":media_channel_impl", + ":media_channel_shim", ":media_constants", ":rid_description", ":rtc_media_base", diff --git a/media/base/media_channel.h b/media/base/media_channel.h index 02dc693e86..de7024e1b9 100644 --- a/media/base/media_channel.h +++ b/media/base/media_channel.h @@ -954,6 +954,9 @@ class VideoMediaSendChannelInterface : public MediaSendChannelInterface { virtual bool SendCodecHasLntf() const = 0; virtual bool SendCodecHasNack() const = 0; virtual absl::optional SendCodecRtxTime() const = 0; + // TODO(bugs.webrtc.org/13931): Remove when configuration is more sensible + virtual void SetSendCodecChangedCallback( + absl::AnyInvocable callback) = 0; }; class VideoMediaReceiveChannelInterface : public MediaReceiveChannelInterface { diff --git a/media/base/media_channel_impl.h b/media/base/media_channel_impl.h index 35e01240fa..e3c8cc183c 100644 --- a/media/base/media_channel_impl.h +++ b/media/base/media_channel_impl.h @@ -244,6 +244,9 @@ class VideoMediaChannel : public MediaChannel, 0; bool AddRecvStream(const StreamParams& sp) override = 0; void OnPacketReceived(const webrtc::RtpPacketReceived& packet) override = 0; + void SetEncoderSelector(uint32_t ssrc, + webrtc::VideoEncoderFactory::EncoderSelectorInterface* + encoder_selector) override {} // This fills the "bitrate parts" (rtx, video bitrate) of the // BandwidthEstimationInfo, since that part that isn't possible to get @@ -257,27 +260,25 @@ class VideoMediaChannel : public MediaChannel, // Gets quality stats for the channel. virtual bool GetSendStats(VideoMediaSendInfo* info) = 0; virtual bool GetReceiveStats(VideoMediaReceiveInfo* info) = 0; + bool GetStats(VideoMediaSendInfo* info) override { + return GetSendStats(info); + } + bool GetStats(VideoMediaReceiveInfo* info) override { + return GetReceiveStats(info); + } // TODO(bugs.webrtc.org/13931): Remove when configuration is more sensible - virtual void SetSendCodecChangedCallback( - absl::AnyInvocable callback) = 0; + void SetSendCodecChangedCallback( + absl::AnyInvocable callback) override = 0; + // Enable network condition based codec switching. + // Note: should have been pure virtual. + void SetVideoCodecSwitchingEnabled(bool enabled) override; private: // Functions not implemented on this interface - bool GetStats(VideoMediaSendInfo* info) override { - RTC_CHECK_NOTREACHED(); - return false; - } - bool GetStats(VideoMediaReceiveInfo* info) override { - RTC_CHECK_NOTREACHED(); - return false; - } bool HasNetworkInterface() const override { return MediaChannel::HasNetworkInterface(); } - // Enable network condition based codec switching. - void SetVideoCodecSwitchingEnabled(bool enabled) override; - MediaChannel* ImplForTesting() override { // This class and its subclasses are not interface classes. RTC_CHECK_NOTREACHED(); @@ -666,6 +667,10 @@ class VideoMediaSendChannel : public VideoMediaSendChannelInterface { absl::AnyInvocable&)> callback) override { impl()->SetSsrcListChangedCallback(std::move(callback)); } + void SetSendCodecChangedCallback( + absl::AnyInvocable callback) override { + impl()->SetSendCodecChangedCallback(std::move(callback)); + } MediaChannel* ImplForTesting() override { return impl_; } diff --git a/media/base/media_channel_shim.cc b/media/base/media_channel_shim.cc new file mode 100644 index 0000000000..432ea1ccf3 --- /dev/null +++ b/media/base/media_channel_shim.cc @@ -0,0 +1,38 @@ +/* + * Copyright 2023 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 "media/base/media_channel_shim.h" + +namespace cricket { + +// Note: The VideoMediaChannel default implementations are not used here, and +// should be removed from that interface. +// TODO(bugs.webrtc.org/13931): Remove them. +VideoMediaShimChannel::VideoMediaShimChannel( + std::unique_ptr send_impl, + std::unique_ptr receive_impl) + : VideoMediaChannel(MediaChannel::Role::kBoth, nullptr, false), + send_impl_(std::move(send_impl)), + receive_impl_(std::move(receive_impl)) { + if (send_impl_ && receive_impl_) { + send_impl_->SetSendCodecChangedCallback([this]() { + // Adjust receive streams based on send codec. + receive_impl_->SetReceiverFeedbackParameters( + send_impl_->SendCodecHasLntf(), send_impl_->SendCodecHasNack(), + send_impl_->SendCodecRtcpMode(), send_impl_->SendCodecRtxTime()); + }); + send_impl_->SetSsrcListChangedCallback( + [this](const std::set& choices) { + receive_impl_->ChooseReceiverReportSsrc(choices); + }); + } +} + +} // namespace cricket diff --git a/media/base/media_channel_shim.h b/media/base/media_channel_shim.h new file mode 100644 index 0000000000..458d2a0811 --- /dev/null +++ b/media/base/media_channel_shim.h @@ -0,0 +1,333 @@ +/* + * Copyright 2023 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. + */ + +#ifndef MEDIA_BASE_MEDIA_CHANNEL_SHIM_H_ +#define MEDIA_BASE_MEDIA_CHANNEL_SHIM_H_ + +#include + +#include +#include +#include +#include +#include +#include + +#include "absl/functional/any_invocable.h" +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "api/crypto/frame_decryptor_interface.h" +#include "api/crypto/frame_encryptor_interface.h" +#include "api/frame_transformer_interface.h" +#include "api/media_types.h" +#include "api/rtc_error.h" +#include "api/rtp_headers.h" +#include "api/rtp_parameters.h" +#include "api/rtp_sender_interface.h" +#include "api/scoped_refptr.h" +#include "api/transport/rtp/rtp_source.h" +#include "api/video/recordable_encoded_frame.h" +#include "api/video/video_frame.h" +#include "api/video/video_sink_interface.h" +#include "api/video/video_source_interface.h" +#include "api/video_codecs/video_encoder_factory.h" +#include "media/base/codec.h" +#include "media/base/media_channel.h" +#include "media/base/media_channel_impl.h" +#include "media/base/stream_params.h" +#include "modules/rtp_rtcp/source/rtp_packet_received.h" +#include "rtc_base/checks.h" +#include "rtc_base/network/sent_packet.h" +#include "rtc_base/network_route.h" + +// The VideoMediaShimChannel is replacing the VideoMediaChannel +// interface. +// If called with both send_impl and receive_impl, it operates in kBoth +// mode; if called with only one, it will shim that one and DCHECK if one +// tries to do functions belonging to the other. + +namespace cricket { +class VideoMediaShimChannel : public VideoMediaChannel { + public: + VideoMediaShimChannel( + std::unique_ptr send_impl, + std::unique_ptr receive_impl); + + VideoMediaSendChannelInterface* AsVideoSendChannel() override { return this; } + VideoMediaReceiveChannelInterface* AsVideoReceiveChannel() override { + return this; + } + VoiceMediaSendChannelInterface* AsVoiceSendChannel() override { + RTC_CHECK_NOTREACHED(); + return nullptr; + } + VoiceMediaReceiveChannelInterface* AsVoiceReceiveChannel() override { + RTC_CHECK_NOTREACHED(); + return nullptr; + } + + // SetInterface needs to run on both send and receive channels. + void SetInterface(MediaChannelNetworkInterface* iface) override { + if (send_impl_) { + send_impl()->SetInterface(iface); + } + if (receive_impl_) { + receive_impl()->SetInterface(iface); + } + } + + // Not really valid for this mode + MediaChannel* ImplForTesting() override { + RTC_CHECK_NOTREACHED(); + return nullptr; + } + + // Implementation of MediaBaseChannelInterface + cricket::MediaType media_type() const override { return MEDIA_TYPE_VIDEO; } + + // Implementation of MediaSendChannelInterface + void OnPacketSent(const rtc::SentPacket& sent_packet) override { + send_impl()->OnPacketSent(sent_packet); + } + void OnReadyToSend(bool ready) override { send_impl()->OnReadyToSend(ready); } + void OnNetworkRouteChanged(absl::string_view transport_name, + const rtc::NetworkRoute& network_route) override { + send_impl()->OnNetworkRouteChanged(transport_name, network_route); + } + void SetExtmapAllowMixed(bool extmap_allow_mixed) override { + send_impl()->SetExtmapAllowMixed(extmap_allow_mixed); + } + bool HasNetworkInterface() const override { + return send_impl()->HasNetworkInterface(); + } + bool ExtmapAllowMixed() const override { + return send_impl()->ExtmapAllowMixed(); + } + + bool AddSendStream(const StreamParams& sp) override { + return send_impl()->AddSendStream(sp); + } + bool RemoveSendStream(uint32_t ssrc) override { + return send_impl()->RemoveSendStream(ssrc); + } + void SetFrameEncryptor(uint32_t ssrc, + rtc::scoped_refptr + frame_encryptor) override { + send_impl()->SetFrameEncryptor(ssrc, frame_encryptor); + } + webrtc::RTCError SetRtpSendParameters( + uint32_t ssrc, + const webrtc::RtpParameters& parameters, + webrtc::SetParametersCallback callback = nullptr) override { + return send_impl()->SetRtpSendParameters(ssrc, parameters, + std::move(callback)); + } + + void SetEncoderToPacketizerFrameTransformer( + uint32_t ssrc, + rtc::scoped_refptr frame_transformer) + override { + return send_impl()->SetEncoderToPacketizerFrameTransformer( + ssrc, frame_transformer); + } + void SetEncoderSelector(uint32_t ssrc, + webrtc::VideoEncoderFactory::EncoderSelectorInterface* + encoder_selector) override { + send_impl()->SetEncoderSelector(ssrc, encoder_selector); + } + webrtc::RtpParameters GetRtpSendParameters(uint32_t ssrc) const override { + return send_impl()->GetRtpSendParameters(ssrc); + } + // Send_Implementation of VideoMediaSendChannelInterface + bool SetSendParameters(const VideoSendParameters& params) override { + return send_impl()->SetSendParameters(params); + } + bool GetSendCodec(VideoCodec* send_codec) override { + return send_impl()->GetSendCodec(send_codec); + } + bool SetSend(bool send) override { return send_impl()->SetSend(send); } + bool SetVideoSend( + uint32_t ssrc, + const VideoOptions* options, + rtc::VideoSourceInterface* source) override { + return send_impl()->SetVideoSend(ssrc, options, source); + } + void GenerateSendKeyFrame(uint32_t ssrc, + const std::vector& rids) override { + return send_impl()->GenerateSendKeyFrame(ssrc, rids); + } + void SetVideoCodecSwitchingEnabled(bool enabled) override { + return send_impl()->SetVideoCodecSwitchingEnabled(enabled); + } + bool GetStats(VideoMediaSendInfo* info) override { + return send_impl_->GetStats(info); + } + bool GetSendStats(VideoMediaSendInfo* info) override { + return send_impl_->GetStats(info); + } + void FillBitrateInfo(BandwidthEstimationInfo* bwe_info) override { + return send_impl_->FillBitrateInfo(bwe_info); + } + // Information queries to support SetReceiverFeedbackParameters + webrtc::RtcpMode SendCodecRtcpMode() const override { + return send_impl()->SendCodecRtcpMode(); + } + bool SendCodecHasLntf() const override { + return send_impl()->SendCodecHasLntf(); + } + bool SendCodecHasNack() const override { + return send_impl()->SendCodecHasNack(); + } + absl::optional SendCodecRtxTime() const override { + return send_impl()->SendCodecRtxTime(); + } + void SetSsrcListChangedCallback( + absl::AnyInvocable&)> callback) override { + send_impl()->SetSsrcListChangedCallback(std::move(callback)); + } + void SetSendCodecChangedCallback( + absl::AnyInvocable callback) override { + // This callback is used internally by the shim, so should not be called by + // users. + RTC_CHECK_NOTREACHED(); + } + + // Implementation of Delayable + bool SetBaseMinimumPlayoutDelayMs(uint32_t ssrc, int delay_ms) override { + return receive_impl()->SetBaseMinimumPlayoutDelayMs(ssrc, delay_ms); + } + absl::optional GetBaseMinimumPlayoutDelayMs( + uint32_t ssrc) const override { + return receive_impl()->GetBaseMinimumPlayoutDelayMs(ssrc); + } + // Implementation of MediaReceiveChannelInterface + void OnPacketReceived(const webrtc::RtpPacketReceived& packet) override { + receive_impl()->OnPacketReceived(packet); + } + bool AddRecvStream(const StreamParams& sp) override { + return receive_impl()->AddRecvStream(sp); + } + bool RemoveRecvStream(uint32_t ssrc) override { + return receive_impl()->RemoveRecvStream(ssrc); + } + void ResetUnsignaledRecvStream() override { + return receive_impl()->ResetUnsignaledRecvStream(); + } + absl::optional GetUnsignaledSsrc() const override { + return receive_impl()->GetUnsignaledSsrc(); + } + void ChooseReceiverReportSsrc(const std::set& choices) override { + return receive_impl()->ChooseReceiverReportSsrc(choices); + } + void OnDemuxerCriteriaUpdatePending() override { + receive_impl()->OnDemuxerCriteriaUpdatePending(); + } + void OnDemuxerCriteriaUpdateComplete() override { + receive_impl()->OnDemuxerCriteriaUpdateComplete(); + } + void SetFrameDecryptor(uint32_t ssrc, + rtc::scoped_refptr + frame_decryptor) override { + receive_impl()->SetFrameDecryptor(ssrc, frame_decryptor); + } + void SetDepacketizerToDecoderFrameTransformer( + uint32_t ssrc, + rtc::scoped_refptr frame_transformer) + override { + receive_impl()->SetDepacketizerToDecoderFrameTransformer(ssrc, + frame_transformer); + } + // Implementation of VideoMediaReceiveChannelInterface + bool SetRecvParameters(const VideoRecvParameters& params) override { + return receive_impl()->SetRecvParameters(params); + } + webrtc::RtpParameters GetRtpReceiveParameters(uint32_t ssrc) const override { + return receive_impl()->GetRtpReceiveParameters(ssrc); + } + webrtc::RtpParameters GetDefaultRtpReceiveParameters() const override { + return receive_impl()->GetDefaultRtpReceiveParameters(); + } + bool SetSink(uint32_t ssrc, + rtc::VideoSinkInterface* sink) override { + return receive_impl()->SetSink(ssrc, sink); + } + void SetDefaultSink( + rtc::VideoSinkInterface* sink) override { + return receive_impl()->SetDefaultSink(sink); + } + void RequestRecvKeyFrame(uint32_t ssrc) override { + return receive_impl()->RequestRecvKeyFrame(ssrc); + } + std::vector GetSources(uint32_t ssrc) const override { + return receive_impl()->GetSources(ssrc); + } + // Set recordable encoded frame callback for `ssrc` + void SetRecordableEncodedFrameCallback( + uint32_t ssrc, + std::function callback) + override { + return receive_impl()->SetRecordableEncodedFrameCallback( + ssrc, std::move(callback)); + } + // Clear recordable encoded frame callback for `ssrc` + void ClearRecordableEncodedFrameCallback(uint32_t ssrc) override { + receive_impl()->ClearRecordableEncodedFrameCallback(ssrc); + } + bool GetStats(VideoMediaReceiveInfo* info) override { + return receive_impl()->GetStats(info); + } + bool GetReceiveStats(VideoMediaReceiveInfo* info) override { + return receive_impl()->GetStats(info); + } + void SetReceiverFeedbackParameters(bool lntf_enabled, + bool nack_enabled, + webrtc::RtcpMode rtcp_mode, + absl::optional rtx_time) override { + receive_impl()->SetReceiverFeedbackParameters(lntf_enabled, nack_enabled, + rtcp_mode, rtx_time); + } + void SetReceive(bool receive) override { + receive_impl()->SetReceive(receive); + } + bool AddDefaultRecvStreamForTesting(const StreamParams& sp) override { + return receive_impl()->AddDefaultRecvStreamForTesting(sp); + } + + // Only for testing of implementations - these will be used to static_cast the + // pointers to the implementations, so can only be safely used in conjunction + // with the corresponding create functions. + VideoMediaSendChannelInterface* SendImplForTesting() { + return send_impl_.get(); + } + VideoMediaReceiveChannelInterface* ReceiveImplForTesting() { + return receive_impl_.get(); + } + + private: + VideoMediaSendChannelInterface* send_impl() { return send_impl_.get(); } + VideoMediaReceiveChannelInterface* receive_impl() { + RTC_DCHECK(receive_impl_); + return receive_impl_.get(); + } + const VideoMediaSendChannelInterface* send_impl() const { + RTC_DCHECK(send_impl_); + return send_impl_.get(); + } + const VideoMediaReceiveChannelInterface* receive_impl() const { + return receive_impl_.get(); + } + + std::unique_ptr send_impl_; + std::unique_ptr receive_impl_; +}; + +} // namespace cricket + +#endif // MEDIA_BASE_MEDIA_CHANNEL_SHIM_H_ diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc index 3828f0092d..bf547b788d 100644 --- a/media/engine/webrtc_video_engine.cc +++ b/media/engine/webrtc_video_engine.cc @@ -627,6 +627,18 @@ VideoMediaChannel* WebRtcVideoEngine::CreateMediaChannel( const webrtc::CryptoOptions& crypto_options, webrtc::VideoBitrateAllocatorFactory* video_bitrate_allocator_factory) { RTC_LOG(LS_INFO) << "CreateMediaChannel. Options: " << options.ToString(); + if (role == MediaChannel::Role::kBoth) { + auto send_channel = std::make_unique( + MediaChannel::Role::kSend, call, config, options, crypto_options, + encoder_factory_.get(), decoder_factory_.get(), + video_bitrate_allocator_factory); + auto receive_channel = std::make_unique( + MediaChannel::Role::kReceive, call, config, options, crypto_options, + encoder_factory_.get(), decoder_factory_.get(), + video_bitrate_allocator_factory); + return new VideoMediaShimChannel(std::move(send_channel), + std::move(receive_channel)); + } return new WebRtcVideoChannel(role, call, config, options, crypto_options, encoder_factory_.get(), decoder_factory_.get(), video_bitrate_allocator_factory); @@ -1014,7 +1026,9 @@ bool WebRtcVideoChannel::ApplyChangedParams( } } else { if (changed_params.send_codec || changed_params.rtcp_mode) { - send_codec_changed_callback_(); + if (send_codec_changed_callback_) { + send_codec_changed_callback_(); + } } } return true; diff --git a/media/engine/webrtc_video_engine.h b/media/engine/webrtc_video_engine.h index 2013e6979c..5a5dd9451b 100644 --- a/media/engine/webrtc_video_engine.h +++ b/media/engine/webrtc_video_engine.h @@ -59,6 +59,7 @@ #include "media/base/codec.h" #include "media/base/media_channel.h" #include "media/base/media_channel_impl.h" +#include "media/base/media_channel_shim.h" #include "media/base/media_config.h" #include "media/base/media_engine.h" #include "media/base/stream_params.h" diff --git a/media/engine/webrtc_video_engine_unittest.cc b/media/engine/webrtc_video_engine_unittest.cc index 1c613a0ad1..66535caa05 100644 --- a/media/engine/webrtc_video_engine_unittest.cc +++ b/media/engine/webrtc_video_engine_unittest.cc @@ -1797,11 +1797,10 @@ class WebRtcVideoChannelBaseTest : public ::testing::Test { // needs to be disabled, otherwise, tests which check the size of received // frames become flaky. media_config.video.enable_cpu_adaptation = false; - channel_.reset( - static_cast(engine_.CreateMediaChannel( - cricket::MediaChannel::Role::kBoth, call_.get(), media_config, - cricket::VideoOptions(), webrtc::CryptoOptions(), - video_bitrate_allocator_factory_.get()))); + channel_.reset(engine_.CreateMediaChannel( + cricket::MediaChannel::Role::kBoth, call_.get(), media_config, + cricket::VideoOptions(), webrtc::CryptoOptions(), + video_bitrate_allocator_factory_.get())); send_channel_ = std::make_unique(channel_.get()); receive_channel_ = std::make_unique(channel_.get()); @@ -1820,6 +1819,15 @@ class WebRtcVideoChannelBaseTest : public ::testing::Test { EXPECT_TRUE(channel_->SetVideoSend(kSsrc, nullptr, frame_forwarder_.get())); } + // Returns pointer to implementation of the send channel. + WebRtcVideoChannel* SendImpl() { + // Note that this function requires intimate knowledge of how the channel + // was created. + return static_cast( + static_cast(channel_.get()) + ->SendImplForTesting()); + } + // Utility method to setup an additional stream to send and receive video. // Used to test send and recv between two streams. void SetUpSecondStream() { @@ -1866,7 +1874,7 @@ class WebRtcVideoChannelBaseTest : public ::testing::Test { frame_source_ = std::make_unique( kVideoWidth, kVideoHeight, rtc::kNumMicrosecsPerSec / kFramerate); - bool sending = channel_->sending(); + bool sending = SendImpl()->sending(); bool success = SetSend(false); if (success) { cricket::VideoSendParameters parameters; @@ -1992,7 +2000,7 @@ class WebRtcVideoChannelBaseTest : public ::testing::Test { std::unique_ptr frame_forwarder_; std::unique_ptr frame_forwarder_2_; - std::unique_ptr channel_; + std::unique_ptr channel_; std::unique_ptr send_channel_; std::unique_ptr receive_channel_; cricket::FakeNetworkInterface network_interface_; @@ -2004,23 +2012,23 @@ class WebRtcVideoChannelBaseTest : public ::testing::Test { // Test that SetSend works. TEST_F(WebRtcVideoChannelBaseTest, SetSend) { - EXPECT_FALSE(channel_->sending()); + EXPECT_FALSE(SendImpl()->sending()); EXPECT_TRUE(channel_->SetVideoSend(kSsrc, nullptr, frame_forwarder_.get())); EXPECT_TRUE(SetOneCodec(DefaultCodec())); - EXPECT_FALSE(channel_->sending()); + EXPECT_FALSE(SendImpl()->sending()); EXPECT_TRUE(SetSend(true)); - EXPECT_TRUE(channel_->sending()); + EXPECT_TRUE(SendImpl()->sending()); SendFrame(); EXPECT_GT(NumRtpPackets(), 0); EXPECT_TRUE(SetSend(false)); - EXPECT_FALSE(channel_->sending()); + EXPECT_FALSE(SendImpl()->sending()); } // Test that SetSend fails without codecs being set. TEST_F(WebRtcVideoChannelBaseTest, SetSendWithoutCodecs) { - EXPECT_FALSE(channel_->sending()); + EXPECT_FALSE(SendImpl()->sending()); EXPECT_FALSE(SetSend(true)); - EXPECT_FALSE(channel_->sending()); + EXPECT_FALSE(SendImpl()->sending()); } // Test that we properly set the send and recv buffer sizes by the time @@ -2544,13 +2552,13 @@ TEST_F(WebRtcVideoChannelBaseTest, RequestEncoderFallback) { // RequestEncoderFallback will post a task to the worker thread (which is also // the current thread), hence the ProcessMessages call. - channel_->RequestEncoderFallback(); + SendImpl()->RequestEncoderFallback(); time_controller_.AdvanceTime(kFrameDuration); ASSERT_TRUE(channel_->GetSendCodec(&codec)); EXPECT_EQ("VP8", codec.name); // No other codec to fall back to, keep using VP8. - channel_->RequestEncoderFallback(); + SendImpl()->RequestEncoderFallback(); time_controller_.AdvanceTime(kFrameDuration); ASSERT_TRUE(channel_->GetSendCodec(&codec)); EXPECT_EQ("VP8", codec.name); @@ -2568,8 +2576,8 @@ TEST_F(WebRtcVideoChannelBaseTest, RequestEncoderSwitchDefaultFallback) { // RequestEncoderSwitch will post a task to the worker thread (which is also // the current thread), hence the ProcessMessages call. - channel_->RequestEncoderSwitch(webrtc::SdpVideoFormat("UnavailableCodec"), - /*allow_default_fallback=*/true); + SendImpl()->RequestEncoderSwitch(webrtc::SdpVideoFormat("UnavailableCodec"), + /*allow_default_fallback=*/true); time_controller_.AdvanceTime(kFrameDuration); // Requested encoder is not available. Default fallback is allowed. Switch to @@ -2591,7 +2599,7 @@ TEST_F(WebRtcVideoChannelBaseTest, RequestEncoderSwitchStrictPreference) { ASSERT_TRUE(channel_->GetSendCodec(&codec)); EXPECT_EQ("VP8", codec.name); - channel_->RequestEncoderSwitch( + SendImpl()->RequestEncoderSwitch( webrtc::SdpVideoFormat("VP9", {{"profile-id", "1"}}), /*allow_default_fallback=*/false); time_controller_.AdvanceTime(kFrameDuration); @@ -2601,7 +2609,7 @@ TEST_F(WebRtcVideoChannelBaseTest, RequestEncoderSwitchStrictPreference) { ASSERT_TRUE(channel_->GetSendCodec(&codec)); EXPECT_EQ("VP8", codec.name); - channel_->RequestEncoderSwitch( + SendImpl()->RequestEncoderSwitch( webrtc::SdpVideoFormat("VP9", {{"profile-id", "0"}}), /*allow_default_fallback=*/false); time_controller_.AdvanceTime(kFrameDuration); @@ -2624,7 +2632,7 @@ TEST_F(WebRtcVideoChannelBaseTest, SendCodecIsMovedToFrontInRtpParameters) { // RequestEncoderFallback will post a task to the worker thread (which is also // the current thread), hence the ProcessMessages call. - channel_->RequestEncoderFallback(); + SendImpl()->RequestEncoderFallback(); time_controller_.AdvanceTime(kFrameDuration); send_codecs = send_channel_->GetRtpSendParameters(kSsrc).codecs; @@ -2676,6 +2684,23 @@ class WebRtcVideoChannelTest : public WebRtcVideoEngineTest { SetUp(); } + // Returns pointer to implementation of the send channel. + WebRtcVideoChannel* SendImpl() { + // Note that this function requires intimate knowledge of how the channel + // was created. + return static_cast( + static_cast(channel_.get()) + ->SendImplForTesting()); + } + + // Casts a shim channel to a webrtc::Transport. Used once. + webrtc::Transport* ChannelImplAsTransport(VideoMediaChannel* channel) { + return static_cast( + static_cast( + static_cast(channel) + ->SendImplForTesting())); + } + cricket::VideoCodec GetEngineCodec(const std::string& name) { for (const cricket::VideoCodec& engine_codec : engine_.send_codecs()) { if (absl::EqualsIgnoreCase(name, engine_codec.name)) @@ -5511,15 +5536,13 @@ TEST_F(WebRtcVideoChannelTest, TestSetDscpOptions) { std::unique_ptr network_interface( new cricket::FakeNetworkInterface); MediaConfig config; - std::unique_ptr channel; + std::unique_ptr channel; std::unique_ptr send_channel; webrtc::RtpParameters parameters; - channel.reset( - static_cast(engine_.CreateMediaChannel( - cricket::MediaChannel::Role::kBoth, call_.get(), config, - VideoOptions(), webrtc::CryptoOptions(), - video_bitrate_allocator_factory_.get()))); + channel.reset(engine_.CreateMediaChannel( + cricket::MediaChannel::Role::kBoth, call_.get(), config, VideoOptions(), + webrtc::CryptoOptions(), video_bitrate_allocator_factory_.get())); send_channel.reset(new VideoMediaSendChannel(channel_.get())); channel->SetInterface(network_interface.get()); @@ -5530,11 +5553,9 @@ TEST_F(WebRtcVideoChannelTest, TestSetDscpOptions) { // Default value when DSCP is enabled is also DSCP_DEFAULT, until it is set // through rtp parameters. config.enable_dscp = true; - channel.reset( - static_cast(engine_.CreateMediaChannel( - cricket::MediaChannel::Role::kBoth, call_.get(), config, - VideoOptions(), webrtc::CryptoOptions(), - video_bitrate_allocator_factory_.get()))); + channel.reset(engine_.CreateMediaChannel( + cricket::MediaChannel::Role::kBoth, call_.get(), config, VideoOptions(), + webrtc::CryptoOptions(), video_bitrate_allocator_factory_.get())); send_channel.reset(new VideoMediaSendChannel(channel.get())); channel->SetInterface(network_interface.get()); EXPECT_EQ(rtc::DSCP_DEFAULT, network_interface->dscp()); @@ -5556,19 +5577,17 @@ TEST_F(WebRtcVideoChannelTest, TestSetDscpOptions) { // Packets should also self-identify their dscp in PacketOptions. const uint8_t kData[10] = {0}; - EXPECT_TRUE(static_cast(channel.get()) - ->SendRtcp(kData, sizeof(kData))); + EXPECT_TRUE( + ChannelImplAsTransport(channel.get())->SendRtcp(kData, sizeof(kData))); EXPECT_EQ(rtc::DSCP_CS1, network_interface->options().dscp); channel->SetInterface(nullptr); // Verify that setting the option to false resets the // DiffServCodePoint. config.enable_dscp = false; - channel.reset( - static_cast(engine_.CreateMediaChannel( - cricket::MediaChannel::Role::kBoth, call_.get(), config, - VideoOptions(), webrtc::CryptoOptions(), - video_bitrate_allocator_factory_.get()))); + channel.reset(engine_.CreateMediaChannel( + cricket::MediaChannel::Role::kBoth, call_.get(), config, VideoOptions(), + webrtc::CryptoOptions(), video_bitrate_allocator_factory_.get())); channel->SetInterface(network_interface.get()); EXPECT_EQ(rtc::DSCP_DEFAULT, network_interface->dscp()); channel->SetInterface(nullptr);