diff --git a/modules/video_coding/BUILD.gn b/modules/video_coding/BUILD.gn index 58a92d5403..0e8c04a370 100644 --- a/modules/video_coding/BUILD.gn +++ b/modules/video_coding/BUILD.gn @@ -474,6 +474,7 @@ rtc_library("webrtc_h264") { deps = [ ":video_codec_interface", ":video_coding_utility", + "../../api/environment", "../../api/transport/rtp:dependency_descriptor", "../../api/video:video_codec_constants", "../../api/video:video_frame", @@ -497,6 +498,7 @@ rtc_library("webrtc_h264") { "//third_party/libyuv", ] absl_deps = [ + "//third_party/abseil-cpp/absl/base:nullability", "//third_party/abseil-cpp/absl/container:inlined_vector", "//third_party/abseil-cpp/absl/strings", "//third_party/abseil-cpp/absl/types:optional", @@ -584,6 +586,7 @@ rtc_library("webrtc_vp8") { ] absl_deps = [ "//third_party/abseil-cpp/absl/algorithm:container", + "//third_party/abseil-cpp/absl/base:nullability", "//third_party/abseil-cpp/absl/strings:strings", "//third_party/abseil-cpp/absl/types:optional", ] @@ -679,6 +682,7 @@ rtc_library("webrtc_vp9") { "../../api:field_trials_view", "../../api:refcountedbase", "../../api:scoped_refptr", + "../../api/environment", "../../api/transport:field_trial_based_config", "../../api/video:video_frame", "../../api/video:video_frame_i010", @@ -700,7 +704,6 @@ rtc_library("webrtc_vp9") { "../../rtc_base/experiments:field_trial_parser", "../../rtc_base/experiments:rate_control_settings", "../../rtc_base/synchronization:mutex", - "../../system_wrappers:field_trial", "../rtp_rtcp:rtp_rtcp_format", "svc:scalability_mode_util", "svc:scalability_structures", @@ -710,6 +713,7 @@ rtc_library("webrtc_vp9") { ] absl_deps = [ "//third_party/abseil-cpp/absl/algorithm:container", + "//third_party/abseil-cpp/absl/base:nullability", "//third_party/abseil-cpp/absl/container:inlined_vector", "//third_party/abseil-cpp/absl/memory", "//third_party/abseil-cpp/absl/strings:strings", @@ -829,6 +833,8 @@ if (rtc_include_tests) { "../../api:scoped_refptr", "../../api:sequence_checker", "../../api:videocodec_test_fixture_api", + "../../api/environment", + "../../api/environment:environment_factory", "../../api/numerics:numerics", "../../api/task_queue", "../../api/task_queue:default_task_queue_factory", @@ -1080,6 +1086,7 @@ if (rtc_include_tests) { "../../test:explicit_key_value_config", "../../test:field_trial", "../../test:fileutils", + "../../test:scoped_key_value_config", "../../test:test_support", "../../test:video_test_common", "../rtp_rtcp:rtp_rtcp_format", diff --git a/modules/video_coding/codecs/av1/BUILD.gn b/modules/video_coding/codecs/av1/BUILD.gn index 6465306731..8999b3218f 100644 --- a/modules/video_coding/codecs/av1/BUILD.gn +++ b/modules/video_coding/codecs/av1/BUILD.gn @@ -56,6 +56,7 @@ rtc_library("libaom_av1_encoder") { "../..:video_codec_interface", "../../../../api:field_trials_view", "../../../../api:scoped_refptr", + "../../../../api/environment", "../../../../api/transport:field_trial_based_config", "../../../../api/video:encoded_image", "../../../../api/video:video_frame", @@ -73,6 +74,7 @@ rtc_library("libaom_av1_encoder") { absl_deps = [ "//third_party/abseil-cpp/absl/algorithm:container", "//third_party/abseil-cpp/absl/base:core_headers", + "//third_party/abseil-cpp/absl/base:nullability", "//third_party/abseil-cpp/absl/strings:strings", "//third_party/abseil-cpp/absl/types:optional", ] @@ -102,10 +104,12 @@ if (rtc_include_tests) { "../../../../api:create_frame_generator", "../../../../api:frame_generator_api", "../../../../api:mock_video_encoder", + "../../../../api/environment", + "../../../../api/environment:environment_factory", "../../../../api/units:data_size", "../../../../api/units:time_delta", "../../../../api/video:video_frame", - "../../../../test:field_trial", + "../../../../test:scoped_key_value_config", "../../svc:scalability_mode_util", "../../svc:scalability_structures", "../../svc:scalable_video_controller", diff --git a/modules/video_coding/codecs/av1/libaom_av1_encoder.cc b/modules/video_coding/codecs/av1/libaom_av1_encoder.cc index 745471e321..4e2d9bd544 100644 --- a/modules/video_coding/codecs/av1/libaom_av1_encoder.cc +++ b/modules/video_coding/codecs/av1/libaom_av1_encoder.cc @@ -18,8 +18,10 @@ #include "absl/algorithm/container.h" #include "absl/base/macros.h" +#include "absl/base/nullability.h" #include "absl/strings/match.h" #include "absl/types/optional.h" +#include "api/environment/environment.h" #include "api/field_trials_view.h" #include "api/scoped_refptr.h" #include "api/transport/field_trial_based_config.h" @@ -872,6 +874,17 @@ VideoEncoder::EncoderInfo LibaomAv1Encoder::GetEncoderInfo() const { } // namespace +absl::Nonnull> CreateLibaomAv1Encoder( + const Environment& env, + LibaomAv1EncoderSettings settings) { + if (settings.max_pixel_count_to_cpu_speed.empty()) { + return std::make_unique(absl::nullopt, + env.field_trials()); + } else { + return std::make_unique(settings, env.field_trials()); + } +} + std::unique_ptr CreateLibaomAv1Encoder() { return std::make_unique(absl::nullopt, FieldTrialBasedConfig()); diff --git a/modules/video_coding/codecs/av1/libaom_av1_encoder.h b/modules/video_coding/codecs/av1/libaom_av1_encoder.h index 2fd1d5a754..cc804aaf14 100644 --- a/modules/video_coding/codecs/av1/libaom_av1_encoder.h +++ b/modules/video_coding/codecs/av1/libaom_av1_encoder.h @@ -13,15 +13,22 @@ #include #include -#include "absl/strings/string_view.h" +#include "absl/base/nullability.h" +#include "api/environment/environment.h" #include "api/video_codecs/video_encoder.h" namespace webrtc { -struct LibaomAv1EncoderAuxConfig { + +struct LibaomAv1EncoderSettings { // A map of max pixel count --> cpu speed. std::map max_pixel_count_to_cpu_speed; }; +absl::Nonnull> CreateLibaomAv1Encoder( + const Environment& env, + LibaomAv1EncoderSettings settings = {}); +// Deprecated, Use CreateLibaomAv1Encoder above, bugs.webrtc.org/15860 +using LibaomAv1EncoderAuxConfig = LibaomAv1EncoderSettings; std::unique_ptr CreateLibaomAv1Encoder(); std::unique_ptr CreateLibaomAv1Encoder( const LibaomAv1EncoderAuxConfig& aux_config); diff --git a/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc b/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc index 127aadb275..5b022592ce 100644 --- a/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc +++ b/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc @@ -12,22 +12,26 @@ #include #include +#include #include #include "absl/types/optional.h" +#include "api/environment/environment.h" +#include "api/environment/environment_factory.h" #include "api/test/create_frame_generator.h" #include "api/test/frame_generator_interface.h" #include "api/video_codecs/video_codec.h" #include "api/video_codecs/video_encoder.h" #include "modules/video_coding/codecs/test/encoded_video_frame_producer.h" #include "modules/video_coding/include/video_error_codes.h" -#include "test/field_trial.h" #include "test/gmock.h" #include "test/gtest.h" +#include "test/scoped_key_value_config.h" namespace webrtc { namespace { +using test::ScopedKeyValueConfig; using ::testing::ElementsAre; using ::testing::Eq; using ::testing::Field; @@ -52,12 +56,14 @@ VideoEncoder::Settings DefaultEncoderSettings() { } TEST(LibaomAv1EncoderTest, CanCreate) { - std::unique_ptr encoder = CreateLibaomAv1Encoder(); + std::unique_ptr encoder = + CreateLibaomAv1Encoder(CreateEnvironment()); EXPECT_TRUE(encoder); } TEST(LibaomAv1EncoderTest, InitAndRelease) { - std::unique_ptr encoder = CreateLibaomAv1Encoder(); + std::unique_ptr encoder = + CreateLibaomAv1Encoder(CreateEnvironment()); ASSERT_TRUE(encoder); VideoCodec codec_settings = DefaultCodecSettings(); EXPECT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()), @@ -67,7 +73,8 @@ TEST(LibaomAv1EncoderTest, InitAndRelease) { TEST(LibaomAv1EncoderTest, NoBitrateOnTopLayerRefecltedInActiveDecodeTargets) { // Configure encoder with 2 temporal layers. - std::unique_ptr encoder = CreateLibaomAv1Encoder(); + std::unique_ptr encoder = + CreateLibaomAv1Encoder(CreateEnvironment()); VideoCodec codec_settings = DefaultCodecSettings(); codec_settings.SetScalabilityMode(ScalabilityMode::kL1T2); ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()), @@ -93,7 +100,8 @@ TEST(LibaomAv1EncoderTest, NoBitrateOnTopLayerRefecltedInActiveDecodeTargets) { TEST(LibaomAv1EncoderTest, SpatialScalabilityInTemporalUnitReportedAsDeltaFrame) { - std::unique_ptr encoder = CreateLibaomAv1Encoder(); + std::unique_ptr encoder = + CreateLibaomAv1Encoder(CreateEnvironment()); VideoCodec codec_settings = DefaultCodecSettings(); codec_settings.SetScalabilityMode(ScalabilityMode::kL2T1); ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()), @@ -115,7 +123,8 @@ TEST(LibaomAv1EncoderTest, } TEST(LibaomAv1EncoderTest, NoBitrateOnTopSpatialLayerProduceDeltaFrames) { - std::unique_ptr encoder = CreateLibaomAv1Encoder(); + std::unique_ptr encoder = + CreateLibaomAv1Encoder(CreateEnvironment()); VideoCodec codec_settings = DefaultCodecSettings(); codec_settings.SetScalabilityMode(ScalabilityMode::kL2T1); ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()), @@ -142,7 +151,8 @@ TEST(LibaomAv1EncoderTest, SetsEndOfPictureForLastFrameInTemporalUnit) { allocation.SetBitrate(1, 0, 40000); allocation.SetBitrate(2, 0, 30000); - std::unique_ptr encoder = CreateLibaomAv1Encoder(); + std::unique_ptr encoder = + CreateLibaomAv1Encoder(CreateEnvironment()); VideoCodec codec_settings = DefaultCodecSettings(); // Configure encoder with 3 spatial layers. codec_settings.SetScalabilityMode(ScalabilityMode::kL3T1); @@ -169,7 +179,8 @@ TEST(LibaomAv1EncoderTest, CheckOddDimensionsWithSpatialLayers) { allocation.SetBitrate(0, 0, 30000); allocation.SetBitrate(1, 0, 40000); allocation.SetBitrate(2, 0, 30000); - std::unique_ptr encoder = CreateLibaomAv1Encoder(); + std::unique_ptr encoder = + CreateLibaomAv1Encoder(CreateEnvironment()); VideoCodec codec_settings = DefaultCodecSettings(); // Configure encoder with 3 spatial layers. codec_settings.SetScalabilityMode(ScalabilityMode::kL3T1); @@ -189,11 +200,12 @@ TEST(LibaomAv1EncoderTest, CheckOddDimensionsWithSpatialLayers) { } TEST(LibaomAv1EncoderTest, WithMaximumConsecutiveFrameDrop) { - test::ScopedFieldTrials field_trials( + auto field_trials = std::make_unique( "WebRTC-LibaomAv1Encoder-MaxConsecFrameDrop/maxdrop:2/"); + const Environment env = CreateEnvironment(std::move(field_trials)); VideoBitrateAllocation allocation; allocation.SetBitrate(0, 0, 1000); // some very low bitrate - std::unique_ptr encoder = CreateLibaomAv1Encoder(); + std::unique_ptr encoder = CreateLibaomAv1Encoder(env); VideoCodec codec_settings = DefaultCodecSettings(); codec_settings.SetFrameDropEnabled(true); codec_settings.SetScalabilityMode(ScalabilityMode::kL1T1); @@ -214,18 +226,20 @@ TEST(LibaomAv1EncoderTest, WithMaximumConsecutiveFrameDrop) { } TEST(LibaomAv1EncoderTest, EncoderInfoWithoutResolutionBitrateLimits) { - std::unique_ptr encoder = CreateLibaomAv1Encoder(); + std::unique_ptr encoder = + CreateLibaomAv1Encoder(CreateEnvironment()); EXPECT_TRUE(encoder->GetEncoderInfo().resolution_bitrate_limits.empty()); } TEST(LibaomAv1EncoderTest, EncoderInfoWithBitrateLimitsFromFieldTrial) { - test::ScopedFieldTrials field_trials( + auto field_trials = std::make_unique( "WebRTC-Av1-GetEncoderInfoOverride/" "frame_size_pixels:123|456|789," "min_start_bitrate_bps:11000|22000|33000," "min_bitrate_bps:44000|55000|66000," "max_bitrate_bps:77000|88000|99000/"); - std::unique_ptr encoder = CreateLibaomAv1Encoder(); + const Environment env = CreateEnvironment(std::move(field_trials)); + std::unique_ptr encoder = CreateLibaomAv1Encoder(env); EXPECT_THAT( encoder->GetEncoderInfo().resolution_bitrate_limits, @@ -236,7 +250,8 @@ TEST(LibaomAv1EncoderTest, EncoderInfoWithBitrateLimitsFromFieldTrial) { } TEST(LibaomAv1EncoderTest, EncoderInfoProvidesFpsAllocation) { - std::unique_ptr encoder = CreateLibaomAv1Encoder(); + std::unique_ptr encoder = + CreateLibaomAv1Encoder(CreateEnvironment()); VideoCodec codec_settings = DefaultCodecSettings(); codec_settings.SetScalabilityMode(ScalabilityMode::kL3T3); codec_settings.maxFramerate = 60; @@ -258,7 +273,8 @@ TEST(LibaomAv1EncoderTest, PopulatesEncodedFrameSize) { allocation.SetBitrate(0, 0, 30000); allocation.SetBitrate(1, 0, 40000); allocation.SetBitrate(2, 0, 30000); - std::unique_ptr encoder = CreateLibaomAv1Encoder(); + std::unique_ptr encoder = + CreateLibaomAv1Encoder(CreateEnvironment()); VideoCodec codec_settings = DefaultCodecSettings(); codec_settings.startBitrate = allocation.get_sum_kbps(); ASSERT_GT(codec_settings.width, 4); @@ -291,7 +307,8 @@ TEST(LibaomAv1EncoderTest, PopulatesEncodedFrameSize) { } TEST(LibaomAv1EncoderTest, RtpTimestampWrap) { - std::unique_ptr encoder = CreateLibaomAv1Encoder(); + std::unique_ptr encoder = + CreateLibaomAv1Encoder(CreateEnvironment()); VideoCodec codec_settings = DefaultCodecSettings(); codec_settings.SetScalabilityMode(ScalabilityMode::kL1T1); ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()), @@ -315,7 +332,8 @@ TEST(LibaomAv1EncoderTest, RtpTimestampWrap) { } TEST(LibaomAv1EncoderTest, TestCaptureTimeId) { - std::unique_ptr encoder = CreateLibaomAv1Encoder(); + std::unique_ptr encoder = + CreateLibaomAv1Encoder(CreateEnvironment()); const Timestamp capture_time_id = Timestamp::Micros(2000); VideoCodec codec_settings = DefaultCodecSettings(); codec_settings.SetScalabilityMode(ScalabilityMode::kL2T1); @@ -347,7 +365,8 @@ TEST(LibaomAv1EncoderTest, TestCaptureTimeId) { } TEST(LibaomAv1EncoderTest, AdheresToTargetBitrateDespiteUnevenFrameTiming) { - std::unique_ptr encoder = CreateLibaomAv1Encoder(); + std::unique_ptr encoder = + CreateLibaomAv1Encoder(CreateEnvironment()); VideoCodec codec_settings = DefaultCodecSettings(); codec_settings.SetScalabilityMode(ScalabilityMode::kL1T1); codec_settings.startBitrate = 300; // kbps @@ -425,7 +444,8 @@ TEST(LibaomAv1EncoderTest, AdheresToTargetBitrateDespiteUnevenFrameTiming) { } TEST(LibaomAv1EncoderTest, DisableAutomaticResize) { - std::unique_ptr encoder = CreateLibaomAv1Encoder(); + std::unique_ptr encoder = + CreateLibaomAv1Encoder(CreateEnvironment()); ASSERT_TRUE(encoder); VideoCodec codec_settings = DefaultCodecSettings(); codec_settings.AV1()->automatic_resize_on = false; diff --git a/modules/video_coding/codecs/av1/libaom_av1_unittest.cc b/modules/video_coding/codecs/av1/libaom_av1_unittest.cc index 6a135e2bab..763e3990cd 100644 --- a/modules/video_coding/codecs/av1/libaom_av1_unittest.cc +++ b/modules/video_coding/codecs/av1/libaom_av1_unittest.cc @@ -18,6 +18,8 @@ #include #include "absl/types/optional.h" +#include "api/environment/environment.h" +#include "api/environment/environment_factory.h" #include "api/units/data_size.h" #include "api/units/time_delta.h" #include "api/video_codecs/video_codec.h" @@ -134,8 +136,9 @@ class TestAv1Decoder { }; TEST(LibaomAv1Test, EncodeDecode) { + const Environment env = CreateEnvironment(); TestAv1Decoder decoder(0); - std::unique_ptr encoder = CreateLibaomAv1Encoder(); + std::unique_ptr encoder = CreateLibaomAv1Encoder(env); VideoCodec codec_settings = DefaultCodecSettings(); ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()), WEBRTC_VIDEO_CODEC_OK); @@ -216,7 +219,8 @@ TEST_P(LibaomAv1SvcTest, EncodeAndDecodeAllDecodeTargets) { size_t num_decode_targets = svc_controller->DependencyStructure().num_decode_targets; - std::unique_ptr encoder = CreateLibaomAv1Encoder(); + std::unique_ptr encoder = + CreateLibaomAv1Encoder(CreateEnvironment()); VideoCodec codec_settings = DefaultCodecSettings(); codec_settings.SetScalabilityMode(GetParam().GetScalabilityMode()); ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()), @@ -287,7 +291,8 @@ TEST_P(LibaomAv1SvcTest, SetRatesMatchMeasuredBitrate) { kv.second.bps()); } - std::unique_ptr encoder = CreateLibaomAv1Encoder(); + std::unique_ptr encoder = + CreateLibaomAv1Encoder(CreateEnvironment()); ASSERT_TRUE(encoder); VideoCodec codec_settings = DefaultCodecSettings(); codec_settings.SetScalabilityMode(param.GetScalabilityMode()); diff --git a/modules/video_coding/codecs/h264/h264.cc b/modules/video_coding/codecs/h264/h264.cc index 5b9f0338a9..0c6c4348d5 100644 --- a/modules/video_coding/codecs/h264/h264.cc +++ b/modules/video_coding/codecs/h264/h264.cc @@ -121,6 +121,18 @@ std::vector SupportedH264DecoderCodecs() { return supportedCodecs; } +absl::Nonnull> CreateH264Encoder( + const Environment& env, + H264EncoderSettings settings) { +#if defined(WEBRTC_USE_H264) + RTC_CHECK(g_rtc_use_h264); + RTC_LOG(LS_INFO) << "Creating H264EncoderImpl."; + return std::make_unique(env, settings); +#else + RTC_CHECK_NOTREACHED(); +#endif +} + std::unique_ptr H264Encoder::Create() { return Create(cricket::CreateVideoCodec(cricket::kH264CodecName)); } diff --git a/modules/video_coding/codecs/h264/h264_encoder_impl.cc b/modules/video_coding/codecs/h264/h264_encoder_impl.cc index ee69b9befb..71e80aaf30 100644 --- a/modules/video_coding/codecs/h264/h264_encoder_impl.cc +++ b/modules/video_coding/codecs/h264/h264_encoder_impl.cc @@ -170,20 +170,31 @@ static void RtpFragmentize(EncodedImage* encoded_image, SFrameBSInfo* info) { } } +H264EncoderImpl::H264EncoderImpl(const Environment& env, + H264EncoderSettings settings) + : H264EncoderImpl(settings.packetization_mode) {} + H264EncoderImpl::H264EncoderImpl(const cricket::VideoCodec& codec) - : packetization_mode_(H264PacketizationMode::SingleNalUnit), + : H264EncoderImpl([&] { + std::string packetization_mode_string; + if (codec.GetParam(cricket::kH264FmtpPacketizationMode, + &packetization_mode_string) && + packetization_mode_string == "1") { + return H264PacketizationMode::NonInterleaved; + } else { + return H264PacketizationMode::SingleNalUnit; + } + }()) { + RTC_CHECK(absl::EqualsIgnoreCase(codec.name, cricket::kH264CodecName)); +} + +H264EncoderImpl::H264EncoderImpl(H264PacketizationMode packetization_mode) + : packetization_mode_(packetization_mode), max_payload_size_(0), number_of_cores_(0), encoded_image_callback_(nullptr), has_reported_init_(false), has_reported_error_(false) { - RTC_CHECK(absl::EqualsIgnoreCase(codec.name, cricket::kH264CodecName)); - std::string packetization_mode_string; - if (codec.GetParam(cricket::kH264FmtpPacketizationMode, - &packetization_mode_string) && - packetization_mode_string == "1") { - packetization_mode_ = H264PacketizationMode::NonInterleaved; - } downscaled_buffers_.reserve(kMaxSimulcastStreams - 1); encoded_images_.reserve(kMaxSimulcastStreams); encoders_.reserve(kMaxSimulcastStreams); diff --git a/modules/video_coding/codecs/h264/h264_encoder_impl.h b/modules/video_coding/codecs/h264/h264_encoder_impl.h index 19c16f3d8b..e89f9f9e74 100644 --- a/modules/video_coding/codecs/h264/h264_encoder_impl.h +++ b/modules/video_coding/codecs/h264/h264_encoder_impl.h @@ -58,7 +58,9 @@ class H264EncoderImpl : public H264Encoder { void SetStreamState(bool send_stream); }; - public: + H264EncoderImpl(const Environment& env, H264EncoderSettings settings); + + // Deprecated, bugs.webrtc.org/15860 explicit H264EncoderImpl(const cricket::VideoCodec& codec); ~H264EncoderImpl() override; @@ -90,6 +92,8 @@ class H264EncoderImpl : public H264Encoder { } private: + explicit H264EncoderImpl(H264PacketizationMode packetization_mode); + SEncParamExt CreateEncoderParams(size_t i) const; webrtc::H264BitstreamParser h264_bitstream_parser_; diff --git a/modules/video_coding/codecs/h264/include/h264.h b/modules/video_coding/codecs/h264/include/h264.h index 025a6ba1f0..2dab731504 100644 --- a/modules/video_coding/codecs/h264/include/h264.h +++ b/modules/video_coding/codecs/h264/include/h264.h @@ -16,8 +16,11 @@ #include #include +#include "absl/base/nullability.h" +#include "api/environment/environment.h" #include "api/video_codecs/h264_profile_level_id.h" #include "api/video_codecs/scalability_mode.h" +#include "api/video_codecs/video_encoder.h" #include "media/base/codec.h" #include "modules/video_coding/include/video_codec_interface.h" #include "rtc_base/system/rtc_export.h" @@ -60,6 +63,14 @@ class RTC_EXPORT H264Encoder : public VideoEncoder { ~H264Encoder() override {} }; +struct H264EncoderSettings { + H264PacketizationMode packetization_mode = + H264PacketizationMode::NonInterleaved; +}; +absl::Nonnull> CreateH264Encoder( + const Environment& env, + H264EncoderSettings settings = {}); + class RTC_EXPORT H264Decoder : public VideoDecoder { public: static std::unique_ptr Create(); diff --git a/modules/video_coding/codecs/h264/test/h264_impl_unittest.cc b/modules/video_coding/codecs/h264/test/h264_impl_unittest.cc index b8a9addb2b..9bc72b2bed 100644 --- a/modules/video_coding/codecs/h264/test/h264_impl_unittest.cc +++ b/modules/video_coding/codecs/h264/test/h264_impl_unittest.cc @@ -34,7 +34,7 @@ namespace webrtc { class TestH264Impl : public VideoCodecUnitTest { protected: std::unique_ptr CreateEncoder() override { - return H264Encoder::Create(); + return CreateH264Encoder(env_); } std::unique_ptr CreateDecoder() override { diff --git a/modules/video_coding/codecs/test/video_codec_unittest.h b/modules/video_coding/codecs/test/video_codec_unittest.h index 7d05882b63..6ad46baece 100644 --- a/modules/video_coding/codecs/test/video_codec_unittest.h +++ b/modules/video_coding/codecs/test/video_codec_unittest.h @@ -14,6 +14,8 @@ #include #include +#include "api/environment/environment.h" +#include "api/environment/environment_factory.h" #include "api/test/frame_generator_interface.h" #include "api/video_codecs/video_decoder.h" #include "api/video_codecs/video_encoder.h" @@ -30,7 +32,8 @@ namespace webrtc { class VideoCodecUnitTest : public ::testing::Test { public: VideoCodecUnitTest() - : encode_complete_callback_(this), + : env_(CreateEnvironment()), + encode_complete_callback_(this), decode_complete_callback_(this), wait_for_encoded_frames_threshold_(1), last_input_frame_timestamp_(0) {} @@ -96,6 +99,7 @@ class VideoCodecUnitTest : public ::testing::Test { size_t GetNumEncodedFrames(); + const Environment env_; VideoCodec codec_settings_; std::unique_ptr encoder_; diff --git a/modules/video_coding/codecs/vp8/include/vp8.h b/modules/video_coding/codecs/vp8/include/vp8.h index cb49516aa9..625e5acf91 100644 --- a/modules/video_coding/codecs/vp8/include/vp8.h +++ b/modules/video_coding/codecs/vp8/include/vp8.h @@ -14,6 +14,7 @@ #include #include +#include "absl/base/nullability.h" #include "api/environment/environment.h" #include "api/video_codecs/video_encoder.h" #include "api/video_codecs/vp8_frame_buffer_controller.h" @@ -21,21 +22,25 @@ namespace webrtc { -// TODO(brandtr): Move these interfaces to the api/ folder. +struct Vp8EncoderSettings { + // Allows for overriding the Vp8FrameBufferController used by the encoder. + // If unset, a default Vp8FrameBufferController will be instantiated + // internally. + absl::Nullable> + frame_buffer_controller_factory; + + // Allows for overriding the resolution/bitrate limits exposed through + // VideoEncoder::GetEncoderInfo(). No override is done if empty. + std::vector resolution_bitrate_limits; +}; +absl::Nonnull> CreateVp8Encoder( + const Environment& env, + Vp8EncoderSettings settings = {}); + +// Deprecated, use CreateVp8Encoder above, bugs.webrtc.org/15860 class VP8Encoder { public: - struct Settings { - // Allows for overriding the Vp8FrameBufferController used by the encoder. - // If unset, a default Vp8FrameBufferController will be instantiated - // internally. - std::unique_ptr - frame_buffer_controller_factory = nullptr; - - // Allows for overriding the resolution/bitrate limits exposed through - // VideoEncoder::GetEncoderInfo(). No override is done if empty. - std::vector - resolution_bitrate_limits = {}; - }; + using Settings = Vp8EncoderSettings; static std::unique_ptr Create(); static std::unique_ptr Create(Settings settings); diff --git a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc index a9e3661e8e..3368b07946 100644 --- a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc +++ b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc @@ -264,6 +264,12 @@ absl::optional ParseFrameDropInterval() { } // namespace +std::unique_ptr CreateVp8Encoder(const Environment& env, + Vp8EncoderSettings settings) { + return std::make_unique(env, std::move(settings), + LibvpxInterface::Create()); +} + std::unique_ptr VP8Encoder::Create() { return std::make_unique(LibvpxInterface::Create(), VP8Encoder::Settings()); diff --git a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h index 5850aa46e9..3d9dca7cca 100644 --- a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h +++ b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h @@ -13,6 +13,7 @@ #include #include +#include #include #include "api/fec_controller_override.h" @@ -38,6 +39,14 @@ namespace webrtc { class LibvpxVp8Encoder : public VideoEncoder { public: + LibvpxVp8Encoder(const Environment& env, + Vp8EncoderSettings settings, + std::unique_ptr interface) + // TODO: bugs.webrtc.org/15860 - Save `env` and use field trials from it + // when constructor below can be removed. + : LibvpxVp8Encoder(std::move(interface), std::move(settings)) {} + + // Deprecated, bugs.webrtc.org/15860 LibvpxVp8Encoder(std::unique_ptr interface, VP8Encoder::Settings settings); ~LibvpxVp8Encoder() override; diff --git a/modules/video_coding/codecs/vp8/test/vp8_impl_unittest.cc b/modules/video_coding/codecs/vp8/test/vp8_impl_unittest.cc index 514d3d7e1d..6ecba2af7c 100644 --- a/modules/video_coding/codecs/vp8/test/vp8_impl_unittest.cc +++ b/modules/video_coding/codecs/vp8/test/vp8_impl_unittest.cc @@ -67,11 +67,11 @@ const VideoEncoder::Settings kSettings(kCapabilities, class TestVp8Impl : public VideoCodecUnitTest { protected: std::unique_ptr CreateEncoder() override { - return VP8Encoder::Create(); + return CreateVp8Encoder(env_); } std::unique_ptr CreateDecoder() override { - return CreateVp8Decoder(CreateEnvironment()); + return CreateVp8Decoder(env_); } void ModifyCodecSettings(VideoCodec* codec_settings) override { diff --git a/modules/video_coding/codecs/vp9/include/vp9.h b/modules/video_coding/codecs/vp9/include/vp9.h index 79d403ded3..ab080c037b 100644 --- a/modules/video_coding/codecs/vp9/include/vp9.h +++ b/modules/video_coding/codecs/vp9/include/vp9.h @@ -15,8 +15,12 @@ #include #include +#include "absl/base/nullability.h" +#include "api/environment/environment.h" #include "api/video_codecs/scalability_mode.h" #include "api/video_codecs/sdp_video_format.h" +#include "api/video_codecs/video_encoder.h" +#include "api/video_codecs/vp9_profile.h" #include "media/base/codec.h" #include "modules/video_coding/include/video_codec_interface.h" @@ -31,13 +35,19 @@ std::vector SupportedVP9Codecs( // preference. These will be availble for receive-only connections. std::vector SupportedVP9DecoderCodecs(); +struct Vp9EncoderSettings { + VP9Profile profile = VP9Profile::kProfile0; +}; +absl::Nonnull> CreateVp9Encoder( + const Environment& env, + Vp9EncoderSettings settings = {}); + class VP9Encoder : public VideoEncoder { public: - // Deprecated. Returns default implementation using VP9 Profile 0. - // TODO(emircan): Remove once this is no longer used. + // Deprecated. Use CreateVp9Encoder above, bugs.webrtc.org/15860 static std::unique_ptr Create(); - // Parses VP9 Profile from `codec` and returns the appropriate implementation. static std::unique_ptr Create(const cricket::VideoCodec& codec); + static bool SupportsScalabilityMode(ScalabilityMode scalability_mode); ~VP9Encoder() override {} diff --git a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc index 20c29abc7c..56267be98d 100644 --- a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc +++ b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc @@ -223,14 +223,28 @@ void LibvpxVp9Encoder::EncoderOutputCodedPacketCallback(vpx_codec_cx_pkt* pkt, enc->GetEncodedLayerFrame(pkt); } +LibvpxVp9Encoder::LibvpxVp9Encoder(const Environment& env, + Vp9EncoderSettings settings, + std::unique_ptr interface) + : LibvpxVp9Encoder(std::move(interface), + settings.profile, + env.field_trials()) {} + LibvpxVp9Encoder::LibvpxVp9Encoder(const cricket::VideoCodec& codec, std::unique_ptr interface, const FieldTrialsView& trials) + : LibvpxVp9Encoder( + std::move(interface), + ParseSdpForVP9Profile(codec.params).value_or(VP9Profile::kProfile0), + trials) {} + +LibvpxVp9Encoder::LibvpxVp9Encoder(std::unique_ptr interface, + VP9Profile profile, + const FieldTrialsView& trials) : libvpx_(std::move(interface)), encoded_image_(), encoded_complete_callback_(nullptr), - profile_( - ParseSdpForVP9Profile(codec.params).value_or(VP9Profile::kProfile0)), + profile_(profile), inited_(false), timestamp_(0), rc_max_intra_target_(0), diff --git a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h index 3ccaa5fa52..349ab0e2d6 100644 --- a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h +++ b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h @@ -37,6 +37,11 @@ namespace webrtc { class LibvpxVp9Encoder : public VP9Encoder { public: + LibvpxVp9Encoder(const Environment& env, + Vp9EncoderSettings settings, + std::unique_ptr interface); + + // Deprecated, bugs.webrtc.org/15860 LibvpxVp9Encoder(const cricket::VideoCodec& codec, std::unique_ptr interface, const FieldTrialsView& trials); @@ -61,6 +66,10 @@ class LibvpxVp9Encoder : public VP9Encoder { EncoderInfo GetEncoderInfo() const override; private: + LibvpxVp9Encoder(std::unique_ptr interface, + VP9Profile profile, + const FieldTrialsView& trials); + // Determine number of encoder threads to use. int NumberOfThreads(int width, int height, int number_of_cores); diff --git a/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc b/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc index 50e9cf2369..396e64de0b 100644 --- a/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc +++ b/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc @@ -102,7 +102,7 @@ void ConfigureSvc(VideoCodec& codec_settings, class TestVp9Impl : public VideoCodecUnitTest { protected: std::unique_ptr CreateEncoder() override { - return VP9Encoder::Create(); + return CreateVp9Encoder(env_); } std::unique_ptr CreateDecoder() override { @@ -255,7 +255,7 @@ TEST_F(TestVp9Impl, SwitchInputPixelFormatsWithoutReconfigure) { } TEST(Vp9ImplTest, ParserQpEqualsEncodedQp) { - std::unique_ptr encoder = VP9Encoder::Create(); + std::unique_ptr encoder = CreateVp9Encoder(CreateEnvironment()); VideoCodec codec_settings = DefaultCodecSettings(); encoder->InitEncode(&codec_settings, kSettings); @@ -272,7 +272,7 @@ TEST(Vp9ImplTest, ParserQpEqualsEncodedQp) { } TEST(Vp9ImplTest, EncodeAttachesTemplateStructureWithSvcController) { - std::unique_ptr encoder = VP9Encoder::Create(); + std::unique_ptr encoder = CreateVp9Encoder(CreateEnvironment()); VideoCodec codec_settings = DefaultCodecSettings(); EXPECT_EQ(encoder->InitEncode(&codec_settings, kSettings), WEBRTC_VIDEO_CODEC_OK); @@ -292,7 +292,7 @@ TEST(Vp9ImplTest, EncodeAttachesTemplateStructureWithSvcController) { } TEST(Vp9ImplTest, EncoderWith2TemporalLayers) { - std::unique_ptr encoder = VP9Encoder::Create(); + std::unique_ptr encoder = CreateVp9Encoder(CreateEnvironment()); VideoCodec codec_settings = DefaultCodecSettings(); codec_settings.VP9()->numberOfTemporalLayers = 2; // Tl0PidIdx is only used in non-flexible mode. @@ -314,7 +314,7 @@ TEST(Vp9ImplTest, EncoderWith2TemporalLayers) { } TEST(Vp9ImplTest, EncodeTemporalLayersWithSvcController) { - std::unique_ptr encoder = VP9Encoder::Create(); + std::unique_ptr encoder = CreateVp9Encoder(CreateEnvironment()); VideoCodec codec_settings = DefaultCodecSettings(); codec_settings.VP9()->numberOfTemporalLayers = 2; EXPECT_EQ(encoder->InitEncode(&codec_settings, kSettings), @@ -343,7 +343,7 @@ TEST(Vp9ImplTest, EncodeTemporalLayersWithSvcController) { } TEST(Vp9ImplTest, EncoderWith2SpatialLayers) { - std::unique_ptr encoder = VP9Encoder::Create(); + std::unique_ptr encoder = CreateVp9Encoder(CreateEnvironment()); VideoCodec codec_settings = DefaultCodecSettings(); codec_settings.VP9()->numberOfSpatialLayers = 2; EXPECT_EQ(encoder->InitEncode(&codec_settings, kSettings), @@ -361,7 +361,7 @@ TEST(Vp9ImplTest, EncoderWith2SpatialLayers) { } TEST(Vp9ImplTest, EncodeSpatialLayersWithSvcController) { - std::unique_ptr encoder = VP9Encoder::Create(); + std::unique_ptr encoder = CreateVp9Encoder(CreateEnvironment()); VideoCodec codec_settings = DefaultCodecSettings(); codec_settings.VP9()->numberOfSpatialLayers = 2; EXPECT_EQ(encoder->InitEncode(&codec_settings, kSettings), @@ -503,7 +503,7 @@ TEST(Vp9ImplTest, EnableDisableSpatialLayersWithSvcController) { // Note: bit rate allocation is high to avoid frame dropping due to rate // control, the encoder should always produce a frame. A dropped // frame indicates a problem and the test will fail. - std::unique_ptr encoder = VP9Encoder::Create(); + std::unique_ptr encoder = CreateVp9Encoder(CreateEnvironment()); VideoCodec codec_settings = DefaultCodecSettings(); ConfigureSvc(codec_settings, num_spatial_layers); codec_settings.SetFrameDropEnabled(true); @@ -570,7 +570,7 @@ MATCHER_P2(GenericLayerIs, spatial_id, temporal_id, "") { } TEST(Vp9ImplTest, SpatialUpswitchNotAtGOFBoundary) { - std::unique_ptr encoder = VP9Encoder::Create(); + std::unique_ptr encoder = CreateVp9Encoder(CreateEnvironment()); VideoCodec codec_settings = DefaultCodecSettings(); ConfigureSvc(codec_settings, /*num_spatial_layers=*/3, /*num_temporal_layers=*/3); @@ -774,7 +774,7 @@ TEST(Vp9ImplTest, // Must not be multiple of temporal period to exercise all code paths. const size_t num_frames_to_encode = 5; - std::unique_ptr encoder = VP9Encoder::Create(); + std::unique_ptr encoder = CreateVp9Encoder(CreateEnvironment()); VideoCodec codec_settings = DefaultCodecSettings(); ConfigureSvc(codec_settings, num_spatial_layers, num_temporal_layers); codec_settings.SetFrameDropEnabled(false); @@ -1851,7 +1851,7 @@ TEST_P(Vp9ImplWithLayeringTest, FlexibleMode) { // encoder and writes it into RTP payload descriptor. Check that reference // list in payload descriptor matches the predefined one, which is used // in non-flexible mode. - std::unique_ptr encoder = VP9Encoder::Create(); + std::unique_ptr encoder = CreateVp9Encoder(CreateEnvironment()); VideoCodec codec_settings = DefaultCodecSettings(); codec_settings.VP9()->flexibleMode = true; codec_settings.SetFrameDropEnabled(false); @@ -2040,11 +2040,7 @@ class TestVp9ImplProfile2 : public TestVp9Impl { } std::unique_ptr CreateEncoder() override { - cricket::VideoCodec profile2_codec = - cricket::CreateVideoCodec(cricket::kVp9CodecName); - profile2_codec.SetParam(kVP9FmtpProfileId, - VP9ProfileToString(VP9Profile::kProfile2)); - return VP9Encoder::Create(profile2_codec); + return CreateVp9Encoder(env_, {.profile = VP9Profile::kProfile2}); } std::unique_ptr CreateDecoder() override { diff --git a/modules/video_coding/codecs/vp9/vp9.cc b/modules/video_coding/codecs/vp9/vp9.cc index c1dbf3a451..8799f2cdd5 100644 --- a/modules/video_coding/codecs/vp9/vp9.cc +++ b/modules/video_coding/codecs/vp9/vp9.cc @@ -81,6 +81,17 @@ std::vector SupportedVP9DecoderCodecs() { #endif } +absl::Nonnull> CreateVp9Encoder( + const Environment& env, + Vp9EncoderSettings settings) { +#ifdef RTC_ENABLE_VP9 + return std::make_unique(env, settings, + LibvpxInterface::Create()); +#else + RTC_CHECK_NOTREACHED(); +#endif +} + std::unique_ptr VP9Encoder::Create() { #ifdef RTC_ENABLE_VP9 return std::make_unique(