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);