EncoderSimulcastProxy: Respect "supports_simulcast" info.
Encoders that do not support simulcast in the first place does not expect to have to handle simulcast configurations, and as such may not necessarily return WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED from InitEncode(). This CL updates EncoderSimulcastProxy to respect this info to avoid silent errors when LibvpxVp9Encoder (which does not support simulcast) is attempted to be used in simulcast. Alternatively we can try to get rid of EncoderSimulcastProxy altogether since SimulcastEncoderAdapter already has a passthrough mode. A TODO is added to get rid of the proxy. Bug: webrtc:14884 Change-Id: Id3703f1768b0aebf617b7d9b935914cd5f1b0f52 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/296885 Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Commit-Queue: Henrik Boström <hbos@webrtc.org> Reviewed-by: Erik Språng <sprang@webrtc.org> Cr-Commit-Position: refs/heads/main@{#39541}
This commit is contained in:
parent
1f8169f04b
commit
e744af5455
@ -36,7 +36,21 @@ void EncoderSimulcastProxy::SetFecControllerOverride(
|
||||
// TODO(eladalon): s/inst/codec_settings/g.
|
||||
int EncoderSimulcastProxy::InitEncode(const VideoCodec* inst,
|
||||
const VideoEncoder::Settings& settings) {
|
||||
int ret = encoder_->InitEncode(inst, settings);
|
||||
int ret;
|
||||
if (inst->numberOfSimulcastStreams <= 1 ||
|
||||
encoder_->GetEncoderInfo().supports_simulcast) {
|
||||
// A simulcast capable encoder may still return
|
||||
// WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED if the current
|
||||
// configuration is not supported.
|
||||
ret = encoder_->InitEncode(inst, settings);
|
||||
} else {
|
||||
// If the encoder does not support simulcast, fallback to
|
||||
// SimulcastEncoderAdapter without trying to InitEncode().
|
||||
// TODO(https://crbug.com/webrtc/14884): Delete EncoderSimulcastProxy and
|
||||
// always use the simulcast adapter instead; it has a passthrough mode so
|
||||
// this proxy is an unnecessary layer.
|
||||
ret = WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED;
|
||||
}
|
||||
if (ret == WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED) {
|
||||
encoder_.reset(new SimulcastEncoderAdapter(factory_, video_format_));
|
||||
if (callback_) {
|
||||
|
||||
@ -27,19 +27,14 @@
|
||||
namespace webrtc {
|
||||
namespace testing {
|
||||
namespace {
|
||||
|
||||
const VideoEncoder::Capabilities kCapabilities(false);
|
||||
const VideoEncoder::Settings kSettings(kCapabilities, 4, 1200);
|
||||
} // namespace
|
||||
constexpr const char* kImplementationName = "Fake";
|
||||
constexpr const char* kSimulcastAdaptedImplementationName =
|
||||
"SimulcastEncoderAdapter (Fake, Fake, Fake)";
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::ByMove;
|
||||
using ::testing::NiceMock;
|
||||
using ::testing::Return;
|
||||
|
||||
TEST(EncoderSimulcastProxy, ChoosesCorrectImplementation) {
|
||||
const std::string kImplementationName = "Fake";
|
||||
const std::string kSimulcastAdaptedImplementationName =
|
||||
"SimulcastEncoderAdapter (Fake, Fake, Fake)";
|
||||
VideoCodec CreateSimulcastVideoCodec() {
|
||||
VideoCodec codec_settings;
|
||||
webrtc::test::CodecSettings(kVideoCodecVP8, &codec_settings);
|
||||
codec_settings.simulcastStream[0] = {.width = test::kTestWidth,
|
||||
@ -70,60 +65,106 @@ TEST(EncoderSimulcastProxy, ChoosesCorrectImplementation) {
|
||||
.qpMax = 56,
|
||||
.active = true};
|
||||
codec_settings.numberOfSimulcastStreams = 3;
|
||||
return codec_settings;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::ByMove;
|
||||
using ::testing::Invoke;
|
||||
using ::testing::NiceMock;
|
||||
using ::testing::Return;
|
||||
|
||||
TEST(EncoderSimulcastProxy, ImplementationSupportsSimulcast) {
|
||||
VideoCodec codec_settings = CreateSimulcastVideoCodec();
|
||||
|
||||
auto mock_encoder = std::make_unique<NiceMock<MockVideoEncoder>>();
|
||||
NiceMock<MockVideoEncoderFactory> simulcast_factory;
|
||||
|
||||
EXPECT_CALL(*mock_encoder, InitEncode(_, _))
|
||||
.WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
|
||||
VideoEncoder::EncoderInfo encoder_info;
|
||||
encoder_info.supports_simulcast = true;
|
||||
encoder_info.implementation_name = kImplementationName;
|
||||
EXPECT_CALL(*mock_encoder, GetEncoderInfo())
|
||||
.WillRepeatedly(Return(encoder_info));
|
||||
|
||||
NiceMock<MockVideoEncoderFactory> simulcast_factory;
|
||||
EXPECT_CALL(simulcast_factory, CreateVideoEncoder)
|
||||
.Times(1)
|
||||
.WillOnce(Return(ByMove(std::move(mock_encoder))));
|
||||
|
||||
EncoderSimulcastProxy simulcast_enabled_proxy(&simulcast_factory,
|
||||
SdpVideoFormat("VP8"));
|
||||
EncoderSimulcastProxy simulcast_proxy(&simulcast_factory,
|
||||
SdpVideoFormat("VP8"));
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
||||
simulcast_enabled_proxy.InitEncode(&codec_settings, kSettings));
|
||||
simulcast_proxy.InitEncode(&codec_settings, kSettings));
|
||||
EXPECT_EQ(kImplementationName,
|
||||
simulcast_enabled_proxy.GetEncoderInfo().implementation_name);
|
||||
simulcast_proxy.GetEncoderInfo().implementation_name);
|
||||
|
||||
NiceMock<MockVideoEncoderFactory> nonsimulcast_factory;
|
||||
// Cleanup.
|
||||
simulcast_proxy.Release();
|
||||
}
|
||||
|
||||
EXPECT_CALL(nonsimulcast_factory, CreateVideoEncoder)
|
||||
TEST(EncoderSimulcastProxy, ImplementationDoesNotSupportSimulcast) {
|
||||
VideoCodec codec_settings = CreateSimulcastVideoCodec();
|
||||
|
||||
NiceMock<MockVideoEncoderFactory> simulcast_factory;
|
||||
EXPECT_CALL(simulcast_factory, CreateVideoEncoder)
|
||||
.Times(4)
|
||||
.WillOnce([&] {
|
||||
auto mock_encoder = std::make_unique<NiceMock<MockVideoEncoder>>();
|
||||
EXPECT_CALL(*mock_encoder, InitEncode(_, _))
|
||||
.WillOnce(Return(
|
||||
WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED));
|
||||
ON_CALL(*mock_encoder, GetEncoderInfo)
|
||||
.WillByDefault(Return(encoder_info));
|
||||
return mock_encoder;
|
||||
})
|
||||
.WillRepeatedly([&] {
|
||||
auto mock_encoder = std::make_unique<NiceMock<MockVideoEncoder>>();
|
||||
EXPECT_CALL(*mock_encoder, InitEncode(_, _))
|
||||
.WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
|
||||
ON_CALL(*mock_encoder, GetEncoderInfo)
|
||||
.WillByDefault(Return(encoder_info));
|
||||
.WillRepeatedly(Return(WEBRTC_VIDEO_CODEC_OK));
|
||||
VideoEncoder::EncoderInfo encoder_info;
|
||||
encoder_info.supports_simulcast = false;
|
||||
encoder_info.implementation_name = kImplementationName;
|
||||
EXPECT_CALL(*mock_encoder, GetEncoderInfo())
|
||||
.WillRepeatedly(Return(encoder_info));
|
||||
return mock_encoder;
|
||||
});
|
||||
|
||||
EncoderSimulcastProxy simulcast_disabled_proxy(&nonsimulcast_factory,
|
||||
SdpVideoFormat("VP8"));
|
||||
EncoderSimulcastProxy simulcast_proxy(&simulcast_factory,
|
||||
SdpVideoFormat("VP8"));
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
||||
simulcast_disabled_proxy.InitEncode(&codec_settings, kSettings));
|
||||
simulcast_proxy.InitEncode(&codec_settings, kSettings));
|
||||
EXPECT_EQ(kSimulcastAdaptedImplementationName,
|
||||
simulcast_disabled_proxy.GetEncoderInfo().implementation_name);
|
||||
simulcast_proxy.GetEncoderInfo().implementation_name);
|
||||
|
||||
// Cleanup.
|
||||
simulcast_enabled_proxy.Release();
|
||||
simulcast_disabled_proxy.Release();
|
||||
simulcast_proxy.Release();
|
||||
}
|
||||
|
||||
TEST(EncoderSimulcastProxy, ImplementationFailsToInitSimulcast) {
|
||||
VideoCodec codec_settings = CreateSimulcastVideoCodec();
|
||||
|
||||
NiceMock<MockVideoEncoderFactory> encoder_factory;
|
||||
EXPECT_CALL(encoder_factory, CreateVideoEncoder).Times(4).WillRepeatedly([&] {
|
||||
// This encoder claims to have simulcast support and thus will be
|
||||
// attempted, but fails during InitEncode().
|
||||
auto mock_encoder = std::make_unique<NiceMock<MockVideoEncoder>>();
|
||||
EXPECT_CALL(*mock_encoder, InitEncode(_, _))
|
||||
.WillRepeatedly(Invoke([](const VideoCodec* codec_settings,
|
||||
const VideoEncoder::Settings& settings) {
|
||||
if (codec_settings->numberOfSimulcastStreams > 1) {
|
||||
return WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED;
|
||||
}
|
||||
return WEBRTC_VIDEO_CODEC_OK;
|
||||
}));
|
||||
VideoEncoder::EncoderInfo encoder_info;
|
||||
encoder_info.supports_simulcast = true;
|
||||
encoder_info.implementation_name = kImplementationName;
|
||||
ON_CALL(*mock_encoder, GetEncoderInfo).WillByDefault(Return(encoder_info));
|
||||
return mock_encoder;
|
||||
});
|
||||
|
||||
EncoderSimulcastProxy simulcast_proxy(&encoder_factory,
|
||||
SdpVideoFormat("VP8"));
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
||||
simulcast_proxy.InitEncode(&codec_settings, kSettings));
|
||||
EXPECT_EQ(kSimulcastAdaptedImplementationName,
|
||||
simulcast_proxy.GetEncoderInfo().implementation_name);
|
||||
|
||||
// Cleanup.
|
||||
simulcast_proxy.Release();
|
||||
}
|
||||
|
||||
TEST(EncoderSimulcastProxy, ForwardsTrustedSetting) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user