Make CreateSendChannel and CreateReceiveChannel methods pure virtual

These methods previously had a default implementation that triggered
a crash. All implementations must now return a valid object, which
simplifies the code that calls them.

Bug: webrtc:13931
Change-Id: I877fbc929b58c6b83767c6ac5a81c8aa942e3fef
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/369021
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#43453}
This commit is contained in:
Tommi 2024-11-26 08:36:15 +01:00 committed by WebRTC LUCI CQ
parent d171832b6c
commit 98b3588974
6 changed files with 15 additions and 83 deletions

View File

@ -534,7 +534,7 @@ bool FakeVideoMediaReceiveChannel::GetStats(VideoMediaReceiveInfo* /* info */) {
return false; return false;
} }
FakeVoiceEngine::FakeVoiceEngine() : fail_create_channel_(false) { FakeVoiceEngine::FakeVoiceEngine() {
// Add a fake audio codec. Note that the name must not be "" as there are // Add a fake audio codec. Note that the name must not be "" as there are
// sanity checks against that. // sanity checks against that.
SetCodecs({cricket::CreateAudioCodec(101, "fake_audio_codec", 8000, 1)}); SetCodecs({cricket::CreateAudioCodec(101, "fake_audio_codec", 8000, 1)});
@ -606,8 +606,7 @@ void FakeVoiceEngine::SetRtpHeaderExtensions(
header_extensions_ = std::move(header_extensions); header_extensions_ = std::move(header_extensions);
} }
FakeVideoEngine::FakeVideoEngine() FakeVideoEngine::FakeVideoEngine() : capture_(false) {
: capture_(false), fail_create_channel_(false) {
// Add a fake video codec. Note that the name must not be "" as there are // Add a fake video codec. Note that the name must not be "" as there are
// sanity checks against that. // sanity checks against that.
send_codecs_.push_back(cricket::CreateVideoCodec(111, "fake_video_codec")); send_codecs_.push_back(cricket::CreateVideoCodec(111, "fake_video_codec"));
@ -625,10 +624,6 @@ FakeVideoEngine::CreateSendChannel(
const webrtc::CryptoOptions& /* crypto_options */, const webrtc::CryptoOptions& /* crypto_options */,
webrtc:: webrtc::
VideoBitrateAllocatorFactory* /* video_bitrate_allocator_factory */) { VideoBitrateAllocatorFactory* /* video_bitrate_allocator_factory */) {
if (fail_create_channel_) {
return nullptr;
}
std::unique_ptr<FakeVideoMediaSendChannel> ch = std::unique_ptr<FakeVideoMediaSendChannel> ch =
std::make_unique<FakeVideoMediaSendChannel>(options, std::make_unique<FakeVideoMediaSendChannel>(options,
call->network_thread()); call->network_thread());
@ -640,10 +635,6 @@ FakeVideoEngine::CreateReceiveChannel(
const MediaConfig& /* config */, const MediaConfig& /* config */,
const VideoOptions& options, const VideoOptions& options,
const webrtc::CryptoOptions& /* crypto_options */) { const webrtc::CryptoOptions& /* crypto_options */) {
if (fail_create_channel_) {
return nullptr;
}
std::unique_ptr<FakeVideoMediaReceiveChannel> ch = std::unique_ptr<FakeVideoMediaReceiveChannel> ch =
std::make_unique<FakeVideoMediaReceiveChannel>(options, std::make_unique<FakeVideoMediaReceiveChannel>(options,
call->network_thread()); call->network_thread());
@ -697,9 +688,5 @@ void FakeMediaEngine::SetVideoCodecs(const std::vector<Codec>& codecs) {
video_->SetSendCodecs(codecs); video_->SetSendCodecs(codecs);
video_->SetRecvCodecs(codecs); video_->SetRecvCodecs(codecs);
} }
void FakeMediaEngine::set_fail_create_channel(bool fail) {
voice_->fail_create_channel_ = fail;
video_->fail_create_channel_ = fail;
}
} // namespace cricket } // namespace cricket

View File

@ -805,7 +805,6 @@ class FakeVoiceEngine : public VoiceEngineInterface {
private: private:
std::vector<Codec> recv_codecs_; std::vector<Codec> recv_codecs_;
std::vector<Codec> send_codecs_; std::vector<Codec> send_codecs_;
bool fail_create_channel_;
std::vector<webrtc::RtpHeaderExtensionCapability> header_extensions_; std::vector<webrtc::RtpHeaderExtensionCapability> header_extensions_;
friend class FakeMediaEngine; friend class FakeMediaEngine;
@ -847,7 +846,6 @@ class FakeVideoEngine : public VideoEngineInterface {
std::vector<Codec> recv_codecs_; std::vector<Codec> recv_codecs_;
bool capture_; bool capture_;
VideoOptions options_; VideoOptions options_;
bool fail_create_channel_;
std::vector<webrtc::RtpHeaderExtensionCapability> header_extensions_; std::vector<webrtc::RtpHeaderExtensionCapability> header_extensions_;
friend class FakeMediaEngine; friend class FakeMediaEngine;
@ -864,8 +862,6 @@ class FakeMediaEngine : public CompositeMediaEngine {
void SetAudioSendCodecs(const std::vector<Codec>& codecs); void SetAudioSendCodecs(const std::vector<Codec>& codecs);
void SetVideoCodecs(const std::vector<Codec>& codecs); void SetVideoCodecs(const std::vector<Codec>& codecs);
void set_fail_create_channel(bool fail);
FakeVoiceEngine* fake_voice_engine() { return voice_; } FakeVoiceEngine* fake_voice_engine() { return voice_; }
FakeVideoEngine* fake_video_engine() { return video_; } FakeVideoEngine* fake_video_engine() { return video_; }

View File

@ -109,22 +109,14 @@ class VoiceEngineInterface : public RtpHeaderExtensionQueryInterface {
const MediaConfig& /* config */, const MediaConfig& /* config */,
const AudioOptions& /* options */, const AudioOptions& /* options */,
const webrtc::CryptoOptions& /* crypto_options */, const webrtc::CryptoOptions& /* crypto_options */,
webrtc::AudioCodecPairId /* codec_pair_id */) { webrtc::AudioCodecPairId /* codec_pair_id */) = 0;
// TODO(hta): Make pure virtual when all downstream has updated
RTC_CHECK_NOTREACHED();
return nullptr;
}
virtual std::unique_ptr<VoiceMediaReceiveChannelInterface> virtual std::unique_ptr<VoiceMediaReceiveChannelInterface>
CreateReceiveChannel(webrtc::Call* /* call */, CreateReceiveChannel(webrtc::Call* /* call */,
const MediaConfig& /* config */, const MediaConfig& /* config */,
const AudioOptions& /* options */, const AudioOptions& /* options */,
const webrtc::CryptoOptions& /* crypto_options */, const webrtc::CryptoOptions& /* crypto_options */,
webrtc::AudioCodecPairId /* codec_pair_id */) { webrtc::AudioCodecPairId /* codec_pair_id */) = 0;
// TODO(hta): Make pure virtual when all downstream has updated
RTC_CHECK_NOTREACHED();
return nullptr;
}
// Legacy: Retrieve list of supported codecs. // Legacy: Retrieve list of supported codecs.
// + protection codecs, and assigns PT numbers that may have to be // + protection codecs, and assigns PT numbers that may have to be
@ -159,22 +151,14 @@ class VideoEngineInterface : public RtpHeaderExtensionQueryInterface {
const MediaConfig& /* config */, const MediaConfig& /* config */,
const VideoOptions& /* options */, const VideoOptions& /* options */,
const webrtc::CryptoOptions& /* crypto_options */, const webrtc::CryptoOptions& /* crypto_options */,
webrtc:: webrtc::VideoBitrateAllocatorFactory*
VideoBitrateAllocatorFactory* /* video_bitrate_allocator_factory */) { /* video_bitrate_allocator_factory */) = 0;
// Default implementation, delete when all is updated
RTC_CHECK_NOTREACHED();
return nullptr;
}
virtual std::unique_ptr<VideoMediaReceiveChannelInterface> virtual std::unique_ptr<VideoMediaReceiveChannelInterface>
CreateReceiveChannel(webrtc::Call* /* call */, CreateReceiveChannel(webrtc::Call* /* call */,
const MediaConfig& /* config */, const MediaConfig& /* config */,
const VideoOptions& /* options */, const VideoOptions& /* options */,
const webrtc::CryptoOptions& /* crypto_options */) { const webrtc::CryptoOptions& /* crypto_options */) = 0;
// Default implementation, delete when all is updated
RTC_CHECK_NOTREACHED();
return nullptr;
}
// Legacy: Retrieve list of supported codecs. // Legacy: Retrieve list of supported codecs.
// + protection codecs, and assigns PT numbers that may have to be // + protection codecs, and assigns PT numbers that may have to be

View File

@ -278,29 +278,6 @@ class PeerConnectionMediaTestPlanB : public PeerConnectionMediaBaseTest {
: PeerConnectionMediaBaseTest(SdpSemantics::kPlanB_DEPRECATED) {} : PeerConnectionMediaBaseTest(SdpSemantics::kPlanB_DEPRECATED) {}
}; };
TEST_P(PeerConnectionMediaTest,
FailToSetRemoteDescriptionIfCreateMediaChannelFails) {
auto caller = CreatePeerConnectionWithAudioVideo();
auto callee = CreatePeerConnectionWithAudioVideo();
callee->media_engine()->set_fail_create_channel(true);
std::string error;
ASSERT_FALSE(callee->SetRemoteDescription(caller->CreateOffer(), &error));
EXPECT_THAT(error,
HasSubstr("Failed to set remote offer sdp: Failed to create"));
}
TEST_P(PeerConnectionMediaTest,
FailToSetLocalDescriptionIfCreateMediaChannelFails) {
auto caller = CreatePeerConnectionWithAudioVideo();
caller->media_engine()->set_fail_create_channel(true);
std::string error;
ASSERT_FALSE(caller->SetLocalDescription(caller->CreateOffer(), &error));
EXPECT_THAT(error,
HasSubstr("Failed to set local offer sdp: Failed to create"));
}
std::vector<std::string> GetIds( std::vector<std::string> GetIds(
const std::vector<cricket::StreamParams>& streams) { const std::vector<cricket::StreamParams>& streams) {
std::vector<std::string> ids; std::vector<std::string> ids;

View File

@ -135,6 +135,7 @@ RtpTransceiver::RtpTransceiver(cricket::MediaType media_type,
context_(context) { context_(context) {
RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO || RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
media_type == cricket::MEDIA_TYPE_VIDEO); media_type == cricket::MEDIA_TYPE_VIDEO);
RTC_DCHECK(context_);
} }
RtpTransceiver::RtpTransceiver( RtpTransceiver::RtpTransceiver(
@ -151,6 +152,7 @@ RtpTransceiver::RtpTransceiver(
header_extensions_to_negotiate_( header_extensions_to_negotiate_(
std::move(header_extensions_to_negotiate)), std::move(header_extensions_to_negotiate)),
on_negotiation_needed_(std::move(on_negotiation_needed)) { on_negotiation_needed_(std::move(on_negotiation_needed)) {
RTC_DCHECK(context_);
RTC_DCHECK(media_type_ == cricket::MEDIA_TYPE_AUDIO || RTC_DCHECK(media_type_ == cricket::MEDIA_TYPE_AUDIO ||
media_type_ == cricket::MEDIA_TYPE_VIDEO); media_type_ == cricket::MEDIA_TYPE_VIDEO);
RTC_DCHECK_EQ(sender->media_type(), receiver->media_type()); RTC_DCHECK_EQ(sender->media_type(), receiver->media_type());
@ -214,18 +216,20 @@ RTCError RtpTransceiver::CreateChannel(
VideoBitrateAllocatorFactory* video_bitrate_allocator_factory, VideoBitrateAllocatorFactory* video_bitrate_allocator_factory,
std::function<RtpTransportInternal*(absl::string_view)> transport_lookup) { std::function<RtpTransportInternal*(absl::string_view)> transport_lookup) {
RTC_DCHECK_RUN_ON(thread_); RTC_DCHECK_RUN_ON(thread_);
RTC_DCHECK(!channel());
if (!media_engine()) { if (!media_engine()) {
// TODO(hta): Must be a better way // TODO(hta): Must be a better way
return RTCError(RTCErrorType::INTERNAL_ERROR, return RTCError(RTCErrorType::INTERNAL_ERROR,
"No media engine for mid=" + std::string(mid)); "No media engine for mid=" + std::string(mid));
} }
std::unique_ptr<cricket::ChannelInterface> new_channel; std::unique_ptr<cricket::ChannelInterface> new_channel;
if (media_type() == cricket::MEDIA_TYPE_AUDIO) { if (media_type() == cricket::MEDIA_TYPE_AUDIO) {
// TODO(bugs.webrtc.org/11992): CreateVideoChannel internally switches to // TODO(bugs.webrtc.org/11992): CreateVideoChannel internally switches to
// the worker thread. We shouldn't be using the `call_ptr_` hack here but // the worker thread. We shouldn't be using the `call_ptr_` hack here but
// simply be on the worker thread and use `call_` (update upstream code). // simply be on the worker thread and use `call_` (update upstream code).
RTC_DCHECK(call_ptr); RTC_DCHECK(call_ptr);
RTC_DCHECK(media_engine());
// TODO(bugs.webrtc.org/11992): Remove this workaround after updates in // TODO(bugs.webrtc.org/11992): Remove this workaround after updates in
// PeerConnection and add the expectation that we're already on the right // PeerConnection and add the expectation that we're already on the right
// thread. // thread.
@ -238,17 +242,10 @@ RTCError RtpTransceiver::CreateChannel(
media_send_channel = media_engine()->voice().CreateSendChannel( media_send_channel = media_engine()->voice().CreateSendChannel(
call_ptr, media_config, audio_options, crypto_options, call_ptr, media_config, audio_options, crypto_options,
codec_pair_id); codec_pair_id);
if (!media_send_channel) {
// TODO(bugs.webrtc.org/14912): Consider CHECK or reporting failure
return;
}
std::unique_ptr<cricket::VoiceMediaReceiveChannelInterface> std::unique_ptr<cricket::VoiceMediaReceiveChannelInterface>
media_receive_channel = media_engine()->voice().CreateReceiveChannel( media_receive_channel = media_engine()->voice().CreateReceiveChannel(
call_ptr, media_config, audio_options, crypto_options, call_ptr, media_config, audio_options, crypto_options,
codec_pair_id); codec_pair_id);
if (!media_receive_channel) {
return;
}
// Note that this is safe because both sending and // Note that this is safe because both sending and
// receiving channels will be deleted at the same time. // receiving channels will be deleted at the same time.
media_send_channel->SetSsrcListChangedCallback( media_send_channel->SetSsrcListChangedCallback(
@ -276,16 +273,9 @@ RTCError RtpTransceiver::CreateChannel(
media_send_channel = media_engine()->video().CreateSendChannel( media_send_channel = media_engine()->video().CreateSendChannel(
call_ptr, media_config, video_options, crypto_options, call_ptr, media_config, video_options, crypto_options,
video_bitrate_allocator_factory); video_bitrate_allocator_factory);
if (!media_send_channel) {
return;
}
std::unique_ptr<cricket::VideoMediaReceiveChannelInterface> std::unique_ptr<cricket::VideoMediaReceiveChannelInterface>
media_receive_channel = media_engine()->video().CreateReceiveChannel( media_receive_channel = media_engine()->video().CreateReceiveChannel(
call_ptr, media_config, video_options, crypto_options); call_ptr, media_config, video_options, crypto_options);
if (!media_receive_channel) {
return;
}
// Note that this is safe because both sending and // Note that this is safe because both sending and
// receiving channels will be deleted at the same time. // receiving channels will be deleted at the same time.
media_send_channel->SetSsrcListChangedCallback( media_send_channel->SetSsrcListChangedCallback(
@ -301,11 +291,6 @@ RTCError RtpTransceiver::CreateChannel(
context()->ssrc_generator()); context()->ssrc_generator());
}); });
} }
if (!new_channel) {
// TODO(hta): Must be a better way
return RTCError(RTCErrorType::INTERNAL_ERROR,
"Failed to create channel for mid=" + std::string(mid));
}
SetChannel(std::move(new_channel), transport_lookup); SetChannel(std::move(new_channel), transport_lookup);
return RTCError::OK(); return RTCError::OK();
} }
@ -339,6 +324,8 @@ void RtpTransceiver::SetChannel(
// helps with keeping the channel implementation requirements being met and // helps with keeping the channel implementation requirements being met and
// avoids synchronization for accessing the pointer or network related state. // avoids synchronization for accessing the pointer or network related state.
context()->network_thread()->BlockingCall([&]() { context()->network_thread()->BlockingCall([&]() {
// TODO(tommi): Isn't `channel_` guaranteed to be nullptr here? (i.e.
// remove this block).
if (channel_) { if (channel_) {
channel_->SetFirstPacketReceivedCallback(nullptr); channel_->SetFirstPacketReceivedCallback(nullptr);
channel_->SetFirstPacketSentCallback(nullptr); channel_->SetFirstPacketSentCallback(nullptr);

View File

@ -99,6 +99,7 @@ TEST_F(RtpTransceiverTest, CannotSetChannelOnStoppedTransceiver) {
// Clear the current channel - required to allow SetChannel() // Clear the current channel - required to allow SetChannel()
EXPECT_CALL(*channel1_ptr, SetFirstPacketReceivedCallback(_)); EXPECT_CALL(*channel1_ptr, SetFirstPacketReceivedCallback(_));
transceiver->ClearChannel(); transceiver->ClearChannel();
ASSERT_EQ(nullptr, transceiver->channel());
// Channel can no longer be set, so this call should be a no-op. // Channel can no longer be set, so this call should be a no-op.
transceiver->SetChannel(std::move(channel2), transceiver->SetChannel(std::move(channel2),
[](const std::string&) { return nullptr; }); [](const std::string&) { return nullptr; });