Improve test outcomes for WebRTC-PayloadTypesInTransport
Previous CL left tests that did not succeed when field trial
"WebRTC-PayloadTypesInTransport" was enabled.
This fixes most of them.
The changes involve rewriting the fake media engine and letting a peer connection factory have its own CodecVendor member.
Bug: webrtc:360058654
Change-Id: Idb722fb6da52e8b2af2786a9c5331c19ecd52b3d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/380841
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#44103}
diff --git a/media/base/codec_list.cc b/media/base/codec_list.cc
index da1d1d0..9fa1b3c 100644
--- a/media/base/codec_list.cc
+++ b/media/base/codec_list.cc
@@ -63,6 +63,15 @@
// TODO: https://issues.webrtc.org/384756622 - reject codec earlier and
// enable check. RTC_DCHECK(apt_it != codec.params.end()); Until that is
// fixed:
+ if (codec.id == Codec::kIdNotSet) {
+ // Should not have an apt parameter.
+ if (apt_it != codec.params.end()) {
+ RTC_LOG(LS_WARNING) << "Surprising condition: RTX codec without "
+ << "PT has an apt parameter";
+ }
+ // Stop checking the associated PT.
+ break;
+ }
if (apt_it == codec.params.end()) {
RTC_LOG(LS_WARNING) << "Surprising condition: RTX codec without"
<< " apt parameter: " << codec;
@@ -70,6 +79,8 @@
}
int associated_pt;
if (!(rtc::FromString(apt_it->second, &associated_pt))) {
+ RTC_LOG(LS_ERROR) << "Non-numeric argument to rtx apt: " << codec
+ << " apt=" << apt_it->second;
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
"Non-numeric argument to rtx apt parameter");
}
diff --git a/media/base/codec_list_unittest.cc b/media/base/codec_list_unittest.cc
index e7303f0..6dea0cd 100644
--- a/media/base/codec_list_unittest.cc
+++ b/media/base/codec_list_unittest.cc
@@ -33,6 +33,7 @@
std::vector<Codec> apt_without_number{
CreateVideoCodec({webrtc::SdpVideoFormat{
"rtx", webrtc::CodecParameterMap{{"apt", "not-a-number"}}}})};
+ apt_without_number[0].id = 96;
RTCErrorOr<CodecList> checked_codec_list =
CodecList::Create(apt_without_number);
EXPECT_FALSE(checked_codec_list.ok());
@@ -51,6 +52,7 @@
std::vector<Codec> apt_without_number{
CreateVideoCodec({webrtc::SdpVideoFormat{
"rtx", webrtc::CodecParameterMap{{"apt", "not-a-number"}}}})};
+ apt_without_number[0].id = 96;
#if RTC_DCHECK_IS_ON
EXPECT_DEATH(
CodecList bad = CodecList::CreateFromTrustedData(apt_without_number),
diff --git a/media/base/fake_media_engine.cc b/media/base/fake_media_engine.cc
index 298efd6..a2d56d0 100644
--- a/media/base/fake_media_engine.cc
+++ b/media/base/fake_media_engine.cc
@@ -559,7 +559,10 @@
return false;
}
-FakeVoiceEngine::FakeVoiceEngine() {
+FakeVoiceEngine::FakeVoiceEngine()
+ : encoder_factory_(webrtc::make_ref_counted<FakeVoiceEncoderFactory>(this)),
+ decoder_factory_(
+ webrtc::make_ref_counted<FakeVoiceDecoderFactory>(this)) {
// Add a fake audio codec. Note that the name must not be "" as there are
// sanity checks against that.
SetCodecs({cricket::CreateAudioCodec(101, "fake_audio_codec", 8000, 1)});
diff --git a/media/base/fake_media_engine.h b/media/base/fake_media_engine.h
index 36c0d81..1f92789 100644
--- a/media/base/fake_media_engine.h
+++ b/media/base/fake_media_engine.h
@@ -818,10 +818,10 @@
const std::vector<Codec>& LegacySendCodecs() const override;
const std::vector<Codec>& LegacyRecvCodecs() const override;
webrtc::AudioEncoderFactory* encoder_factory() const override {
- return nullptr;
+ return encoder_factory_.get();
}
webrtc::AudioDecoderFactory* decoder_factory() const override {
- return nullptr;
+ return decoder_factory_.get();
}
void SetCodecs(const std::vector<Codec>& codecs);
void SetRecvCodecs(const std::vector<Codec>& codecs);
@@ -837,8 +837,66 @@
std::vector<webrtc::RtpHeaderExtensionCapability> header_extensions);
private:
+ class FakeVoiceEncoderFactory : public webrtc::AudioEncoderFactory {
+ public:
+ explicit FakeVoiceEncoderFactory(FakeVoiceEngine* owner) : owner_(owner) {}
+ std::vector<webrtc::AudioCodecSpec> GetSupportedEncoders() override {
+ // The reason for this convoluted mapping is because there are
+ // too many tests that expect to push codecs into the fake voice
+ // engine's "send_codecs/recv_codecs" and have them show up later.
+ std::vector<webrtc::AudioCodecSpec> specs;
+ for (const auto& codec : owner_->send_codecs_) {
+ specs.push_back(webrtc::AudioCodecSpec{
+ {codec.name, codec.clockrate, codec.channels},
+ {codec.clockrate, codec.channels, codec.bitrate}});
+ }
+ return specs;
+ }
+ std::optional<webrtc::AudioCodecInfo> QueryAudioEncoder(
+ const webrtc::SdpAudioFormat& format) override {
+ return std::nullopt;
+ }
+ absl::Nullable<std::unique_ptr<webrtc::AudioEncoder>> Create(
+ const webrtc::Environment& env,
+ const webrtc::SdpAudioFormat& format,
+ Options options) override {
+ return nullptr;
+ }
+ FakeVoiceEngine* owner_;
+ };
+ class FakeVoiceDecoderFactory : public webrtc::AudioDecoderFactory {
+ public:
+ explicit FakeVoiceDecoderFactory(FakeVoiceEngine* owner) : owner_(owner) {}
+ std::vector<webrtc::AudioCodecSpec> GetSupportedDecoders() override {
+ // The reason for this convoluted mapping is because there are
+ // too many tests that expect to push codecs into the fake voice
+ // engine's "send_codecs/recv_codecs" and have them show up later.
+ std::vector<webrtc::AudioCodecSpec> specs;
+ for (const auto& codec : owner_->recv_codecs_) {
+ specs.push_back(webrtc::AudioCodecSpec{
+ {codec.name, codec.clockrate, codec.channels},
+ {codec.clockrate, codec.channels, codec.bitrate}});
+ }
+ return specs;
+ }
+ bool IsSupportedDecoder(const webrtc::SdpAudioFormat& format) override {
+ return false;
+ }
+ absl::Nullable<std::unique_ptr<webrtc::AudioDecoder>> Create(
+ const webrtc::Environment& env,
+ const webrtc::SdpAudioFormat& format,
+ std::optional<webrtc::AudioCodecPairId> codec_pair_id) override {
+ return nullptr;
+ }
+
+ private:
+ FakeVoiceEngine* owner_;
+ };
+
std::vector<Codec> recv_codecs_;
std::vector<Codec> send_codecs_;
+ webrtc::scoped_refptr<FakeVoiceEncoderFactory> encoder_factory_;
+ webrtc::scoped_refptr<FakeVoiceDecoderFactory> decoder_factory_;
std::vector<webrtc::RtpHeaderExtensionCapability> header_extensions_;
friend class FakeMediaEngine;
diff --git a/pc/BUILD.gn b/pc/BUILD.gn
index a07b5d6..f147c49 100644
--- a/pc/BUILD.gn
+++ b/pc/BUILD.gn
@@ -2420,6 +2420,7 @@
":pc_test_utils",
":peer_connection",
":peer_connection_factory",
+ ":peer_connection_factory_proxy",
":peer_connection_internal",
":peer_connection_proxy",
":peerconnection_wrapper",
diff --git a/pc/peer_connection_factory.cc b/pc/peer_connection_factory.cc
index cb6a581..bc07ab3 100644
--- a/pc/peer_connection_factory.cc
+++ b/pc/peer_connection_factory.cc
@@ -107,6 +107,10 @@
rtc::scoped_refptr<ConnectionContext> context,
PeerConnectionFactoryDependencies* dependencies)
: context_(context),
+ codec_vendor_(context_->media_engine(),
+ context_->use_rtx(),
+ context_->env().field_trials()),
+
event_log_factory_(std::move(dependencies->event_log_factory)),
fec_controller_factory_(std::move(dependencies->fec_controller_factory)),
network_state_predictor_factory_(
@@ -147,19 +151,17 @@
RtpCapabilities PeerConnectionFactory::GetRtpSenderCapabilities(
cricket::MediaType kind) const {
RTC_DCHECK_RUN_ON(signaling_thread());
- cricket::CodecVendor codec_vendor(media_engine(), context_->use_rtx(),
- context_->env().field_trials());
switch (kind) {
case cricket::MEDIA_TYPE_AUDIO: {
cricket::Codecs cricket_codecs;
- cricket_codecs = codec_vendor.audio_send_codecs().codecs();
+ cricket_codecs = codec_vendor_.audio_send_codecs().codecs();
auto extensions =
GetDefaultEnabledRtpHeaderExtensions(media_engine()->voice());
return ToRtpCapabilities(cricket_codecs, extensions);
}
case cricket::MEDIA_TYPE_VIDEO: {
cricket::Codecs cricket_codecs;
- cricket_codecs = codec_vendor.video_send_codecs().codecs();
+ cricket_codecs = codec_vendor_.video_send_codecs().codecs();
auto extensions =
GetDefaultEnabledRtpHeaderExtensions(media_engine()->video());
return ToRtpCapabilities(cricket_codecs, extensions);
@@ -176,19 +178,17 @@
RtpCapabilities PeerConnectionFactory::GetRtpReceiverCapabilities(
cricket::MediaType kind) const {
RTC_DCHECK_RUN_ON(signaling_thread());
- cricket::CodecVendor codec_vendor(media_engine(), context_->use_rtx(),
- context_->env().field_trials());
switch (kind) {
case cricket::MEDIA_TYPE_AUDIO: {
cricket::Codecs cricket_codecs;
- cricket_codecs = codec_vendor.audio_recv_codecs().codecs();
+ cricket_codecs = codec_vendor_.audio_recv_codecs().codecs();
auto extensions =
GetDefaultEnabledRtpHeaderExtensions(media_engine()->voice());
return ToRtpCapabilities(cricket_codecs, extensions);
}
case cricket::MEDIA_TYPE_VIDEO: {
cricket::Codecs cricket_codecs =
- codec_vendor.video_recv_codecs().codecs();
+ codec_vendor_.video_recv_codecs().codecs();
auto extensions =
GetDefaultEnabledRtpHeaderExtensions(media_engine()->video());
return ToRtpCapabilities(cricket_codecs, extensions);
diff --git a/pc/peer_connection_factory.h b/pc/peer_connection_factory.h
index 3d99c13..0b1e167 100644
--- a/pc/peer_connection_factory.h
+++ b/pc/peer_connection_factory.h
@@ -39,6 +39,8 @@
#include "call/call.h"
#include "call/rtp_transport_controller_send_factory_interface.h"
#include "media/base/media_engine.h"
+#include "p2p/base/port_allocator.h"
+#include "pc/codec_vendor.h"
#include "pc/connection_context.h"
#include "rtc_base/thread.h"
#include "rtc_base/thread_annotations.h"
@@ -107,6 +109,7 @@
}
cricket::MediaEngineInterface* media_engine() const;
+ cricket::CodecVendor& CodecVendorForTesting() { return codec_vendor_; }
protected:
// Constructor used by the static Create() method. Modifies the dependencies.
@@ -134,6 +137,7 @@
rtc::scoped_refptr<ConnectionContext> context_;
PeerConnectionFactoryInterface::Options options_
RTC_GUARDED_BY(signaling_thread());
+ cricket::CodecVendor codec_vendor_;
std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory_;
std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory_;
std::unique_ptr<NetworkStatePredictorFactoryInterface>
diff --git a/pc/peer_connection_media_unittest.cc b/pc/peer_connection_media_unittest.cc
index 3f301cd..f656494c 100644
--- a/pc/peer_connection_media_unittest.cc
+++ b/pc/peer_connection_media_unittest.cc
@@ -72,27 +72,30 @@
using ::testing::Bool;
using ::testing::Combine;
using ::testing::ElementsAre;
+using ::testing::Gt;
using ::testing::HasSubstr;
using ::testing::NotNull;
using ::testing::Values;
-cricket::MediaSendChannelInterface* SendChannelInternal(
+RtpTransceiver* RtpTransceiverInternal(
rtc::scoped_refptr<RtpTransceiverInterface> transceiver) {
auto transceiver_with_internal = static_cast<
RefCountedObject<RtpTransceiverProxyWithInternal<RtpTransceiver>>*>(
transceiver.get());
auto transceiver_internal =
static_cast<RtpTransceiver*>(transceiver_with_internal->internal());
+ return transceiver_internal;
+}
+
+cricket::MediaSendChannelInterface* SendChannelInternal(
+ rtc::scoped_refptr<RtpTransceiverInterface> transceiver) {
+ auto transceiver_internal = RtpTransceiverInternal(transceiver);
return transceiver_internal->channel()->media_send_channel();
}
cricket::MediaReceiveChannelInterface* ReceiveChannelInternal(
rtc::scoped_refptr<RtpTransceiverInterface> transceiver) {
- auto transceiver_with_internal = static_cast<
- RefCountedObject<RtpTransceiverProxyWithInternal<RtpTransceiver>>*>(
- transceiver.get());
- auto transceiver_internal =
- static_cast<RtpTransceiver*>(transceiver_with_internal->internal());
+ auto transceiver_internal = RtpTransceiverInternal(transceiver);
return transceiver_internal->channel()->media_receive_channel();
}
@@ -1550,7 +1553,8 @@
auto caller = CreatePeerConnectionWithAudio(std::move(fake_engine));
- auto transceiver = caller->pc()->GetTransceivers().front();
+ auto transceiver =
+ RtpTransceiverInternal(caller->pc()->GetTransceivers().front());
auto codecs =
caller->pc_factory()
->GetRtpSenderCapabilities(cricket::MediaType::MEDIA_TYPE_AUDIO)
@@ -1564,7 +1568,7 @@
codec.name == cricket::kUlpfecCodecName);
});
codecs_only_rtx_red_fec.erase(it, codecs_only_rtx_red_fec.end());
-
+ ASSERT_THAT(codecs_only_rtx_red_fec.size(), Gt(0));
auto result = transceiver->SetCodecPreferences(codecs_only_rtx_red_fec);
EXPECT_EQ(RTCErrorType::INVALID_MODIFICATION, result.type());
}
diff --git a/pc/typed_codec_vendor.cc b/pc/typed_codec_vendor.cc
index fd320cd..74741ae 100644
--- a/pc/typed_codec_vendor.cc
+++ b/pc/typed_codec_vendor.cc
@@ -100,20 +100,29 @@
bool is_sender,
bool rtx_enabled,
const webrtc::FieldTrialsView& trials) {
- // TODO: https://issues.webrtc.org/360058654 - move codec selection here
- // when field trial WebRTC-PayloadTypesInTransport is enabled.
if (trials.IsEnabled("WebRTC-PayloadTypesInTransport")) {
// Get the capabilities from the factory and compute the codecs.
- // Use legacy mechanisms for getting codecs from media engine.
if (type == MEDIA_TYPE_AUDIO) {
if (is_sender) {
- codecs_ = CodecList::CreateFromTrustedData(CollectAudioCodecs(
- media_engine->voice().encoder_factory()->GetSupportedEncoders()));
+ if (media_engine->voice().encoder_factory()) {
+ codecs_ = CodecList::CreateFromTrustedData(CollectAudioCodecs(
+ media_engine->voice().encoder_factory()->GetSupportedEncoders()));
+ } else {
+ RTC_LOG(LS_WARNING)
+ << "No voice encoder factory. Should only happen in test.";
+ }
} else {
- codecs_ = CodecList::CreateFromTrustedData(CollectAudioCodecs(
- media_engine->voice().decoder_factory()->GetSupportedDecoders()));
+ if (media_engine->voice().decoder_factory()) {
+ codecs_ = CodecList::CreateFromTrustedData(CollectAudioCodecs(
+ media_engine->voice().decoder_factory()->GetSupportedDecoders()));
+ } else {
+ RTC_LOG(LS_WARNING)
+ << "No voice decoder factory. Should only happen in test.";
+ }
}
} else {
+ // Use legacy mechanisms for getting codecs from video engine.
+ // TODO: https://issues.webrtc.org/360058654 - apply late assign to video.
if (is_sender) {
codecs_ = CodecList::CreateFromTrustedData(
media_engine->video().LegacySendCodecs(rtx_enabled));