Add factory functions to pass Environment to VideoEncoders

Bug: webrtc:15860
Change-Id: I4a9d2678dcfe5b0f178863242e27600fcc95325d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/342480
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#41879}
This commit is contained in:
Danil Chapovalov 2024-03-11 13:17:45 +01:00 committed by WebRTC LUCI CQ
parent 83d29d5988
commit b4913a549f
21 changed files with 231 additions and 73 deletions

View File

@ -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",

View File

@ -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",

View File

@ -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<std::unique_ptr<VideoEncoder>> CreateLibaomAv1Encoder(
const Environment& env,
LibaomAv1EncoderSettings settings) {
if (settings.max_pixel_count_to_cpu_speed.empty()) {
return std::make_unique<LibaomAv1Encoder>(absl::nullopt,
env.field_trials());
} else {
return std::make_unique<LibaomAv1Encoder>(settings, env.field_trials());
}
}
std::unique_ptr<VideoEncoder> CreateLibaomAv1Encoder() {
return std::make_unique<LibaomAv1Encoder>(absl::nullopt,
FieldTrialBasedConfig());

View File

@ -13,15 +13,22 @@
#include <map>
#include <memory>
#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<int, int> max_pixel_count_to_cpu_speed;
};
absl::Nonnull<std::unique_ptr<VideoEncoder>> CreateLibaomAv1Encoder(
const Environment& env,
LibaomAv1EncoderSettings settings = {});
// Deprecated, Use CreateLibaomAv1Encoder above, bugs.webrtc.org/15860
using LibaomAv1EncoderAuxConfig = LibaomAv1EncoderSettings;
std::unique_ptr<VideoEncoder> CreateLibaomAv1Encoder();
std::unique_ptr<VideoEncoder> CreateLibaomAv1Encoder(
const LibaomAv1EncoderAuxConfig& aux_config);

View File

@ -12,22 +12,26 @@
#include <limits>
#include <memory>
#include <utility>
#include <vector>
#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<VideoEncoder> encoder = CreateLibaomAv1Encoder();
std::unique_ptr<VideoEncoder> encoder =
CreateLibaomAv1Encoder(CreateEnvironment());
EXPECT_TRUE(encoder);
}
TEST(LibaomAv1EncoderTest, InitAndRelease) {
std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> encoder = CreateLibaomAv1Encoder();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> encoder = CreateLibaomAv1Encoder();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> encoder = CreateLibaomAv1Encoder();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> encoder = CreateLibaomAv1Encoder();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> encoder = CreateLibaomAv1Encoder();
std::unique_ptr<VideoEncoder> 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<ScopedKeyValueConfig>(
"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<VideoEncoder> encoder = CreateLibaomAv1Encoder();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> encoder = CreateLibaomAv1Encoder();
std::unique_ptr<VideoEncoder> encoder =
CreateLibaomAv1Encoder(CreateEnvironment());
EXPECT_TRUE(encoder->GetEncoderInfo().resolution_bitrate_limits.empty());
}
TEST(LibaomAv1EncoderTest, EncoderInfoWithBitrateLimitsFromFieldTrial) {
test::ScopedFieldTrials field_trials(
auto field_trials = std::make_unique<ScopedKeyValueConfig>(
"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<VideoEncoder> encoder = CreateLibaomAv1Encoder();
const Environment env = CreateEnvironment(std::move(field_trials));
std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder(env);
EXPECT_THAT(
encoder->GetEncoderInfo().resolution_bitrate_limits,
@ -236,7 +250,8 @@ TEST(LibaomAv1EncoderTest, EncoderInfoWithBitrateLimitsFromFieldTrial) {
}
TEST(LibaomAv1EncoderTest, EncoderInfoProvidesFpsAllocation) {
std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> encoder = CreateLibaomAv1Encoder();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> encoder = CreateLibaomAv1Encoder();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> encoder = CreateLibaomAv1Encoder();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> encoder = CreateLibaomAv1Encoder();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> encoder = CreateLibaomAv1Encoder();
std::unique_ptr<VideoEncoder> encoder =
CreateLibaomAv1Encoder(CreateEnvironment());
ASSERT_TRUE(encoder);
VideoCodec codec_settings = DefaultCodecSettings();
codec_settings.AV1()->automatic_resize_on = false;

View File

@ -18,6 +18,8 @@
#include <vector>
#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<VideoEncoder> encoder = CreateLibaomAv1Encoder();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> encoder = CreateLibaomAv1Encoder();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> encoder = CreateLibaomAv1Encoder();
std::unique_ptr<VideoEncoder> encoder =
CreateLibaomAv1Encoder(CreateEnvironment());
ASSERT_TRUE(encoder);
VideoCodec codec_settings = DefaultCodecSettings();
codec_settings.SetScalabilityMode(param.GetScalabilityMode());

View File

@ -121,6 +121,18 @@ std::vector<SdpVideoFormat> SupportedH264DecoderCodecs() {
return supportedCodecs;
}
absl::Nonnull<std::unique_ptr<VideoEncoder>> 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<H264EncoderImpl>(env, settings);
#else
RTC_CHECK_NOTREACHED();
#endif
}
std::unique_ptr<H264Encoder> H264Encoder::Create() {
return Create(cricket::CreateVideoCodec(cricket::kH264CodecName));
}

View File

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

View File

@ -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_;

View File

@ -16,8 +16,11 @@
#include <string>
#include <vector>
#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<std::unique_ptr<VideoEncoder>> CreateH264Encoder(
const Environment& env,
H264EncoderSettings settings = {});
class RTC_EXPORT H264Decoder : public VideoDecoder {
public:
static std::unique_ptr<H264Decoder> Create();

View File

@ -34,7 +34,7 @@ namespace webrtc {
class TestH264Impl : public VideoCodecUnitTest {
protected:
std::unique_ptr<VideoEncoder> CreateEncoder() override {
return H264Encoder::Create();
return CreateH264Encoder(env_);
}
std::unique_ptr<VideoDecoder> CreateDecoder() override {

View File

@ -14,6 +14,8 @@
#include <memory>
#include <vector>
#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<VideoEncoder> encoder_;

View File

@ -14,6 +14,7 @@
#include <memory>
#include <vector>
#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<std::unique_ptr<Vp8FrameBufferControllerFactory>>
frame_buffer_controller_factory;
// Allows for overriding the resolution/bitrate limits exposed through
// VideoEncoder::GetEncoderInfo(). No override is done if empty.
std::vector<VideoEncoder::ResolutionBitrateLimits> resolution_bitrate_limits;
};
absl::Nonnull<std::unique_ptr<VideoEncoder>> 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<Vp8FrameBufferControllerFactory>
frame_buffer_controller_factory = nullptr;
// Allows for overriding the resolution/bitrate limits exposed through
// VideoEncoder::GetEncoderInfo(). No override is done if empty.
std::vector<VideoEncoder::ResolutionBitrateLimits>
resolution_bitrate_limits = {};
};
using Settings = Vp8EncoderSettings;
static std::unique_ptr<VideoEncoder> Create();
static std::unique_ptr<VideoEncoder> Create(Settings settings);

View File

@ -264,6 +264,12 @@ absl::optional<TimeDelta> ParseFrameDropInterval() {
} // namespace
std::unique_ptr<VideoEncoder> CreateVp8Encoder(const Environment& env,
Vp8EncoderSettings settings) {
return std::make_unique<LibvpxVp8Encoder>(env, std::move(settings),
LibvpxInterface::Create());
}
std::unique_ptr<VideoEncoder> VP8Encoder::Create() {
return std::make_unique<LibvpxVp8Encoder>(LibvpxInterface::Create(),
VP8Encoder::Settings());

View File

@ -13,6 +13,7 @@
#include <memory>
#include <string>
#include <utility>
#include <vector>
#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<LibvpxInterface> 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<LibvpxInterface> interface,
VP8Encoder::Settings settings);
~LibvpxVp8Encoder() override;

View File

@ -67,11 +67,11 @@ const VideoEncoder::Settings kSettings(kCapabilities,
class TestVp8Impl : public VideoCodecUnitTest {
protected:
std::unique_ptr<VideoEncoder> CreateEncoder() override {
return VP8Encoder::Create();
return CreateVp8Encoder(env_);
}
std::unique_ptr<VideoDecoder> CreateDecoder() override {
return CreateVp8Decoder(CreateEnvironment());
return CreateVp8Decoder(env_);
}
void ModifyCodecSettings(VideoCodec* codec_settings) override {

View File

@ -15,8 +15,12 @@
#include <memory>
#include <vector>
#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<SdpVideoFormat> SupportedVP9Codecs(
// preference. These will be availble for receive-only connections.
std::vector<SdpVideoFormat> SupportedVP9DecoderCodecs();
struct Vp9EncoderSettings {
VP9Profile profile = VP9Profile::kProfile0;
};
absl::Nonnull<std::unique_ptr<VideoEncoder>> 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<VP9Encoder> Create();
// Parses VP9 Profile from `codec` and returns the appropriate implementation.
static std::unique_ptr<VP9Encoder> Create(const cricket::VideoCodec& codec);
static bool SupportsScalabilityMode(ScalabilityMode scalability_mode);
~VP9Encoder() override {}

View File

@ -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<LibvpxInterface> interface)
: LibvpxVp9Encoder(std::move(interface),
settings.profile,
env.field_trials()) {}
LibvpxVp9Encoder::LibvpxVp9Encoder(const cricket::VideoCodec& codec,
std::unique_ptr<LibvpxInterface> interface,
const FieldTrialsView& trials)
: LibvpxVp9Encoder(
std::move(interface),
ParseSdpForVP9Profile(codec.params).value_or(VP9Profile::kProfile0),
trials) {}
LibvpxVp9Encoder::LibvpxVp9Encoder(std::unique_ptr<LibvpxInterface> 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),

View File

@ -37,6 +37,11 @@ namespace webrtc {
class LibvpxVp9Encoder : public VP9Encoder {
public:
LibvpxVp9Encoder(const Environment& env,
Vp9EncoderSettings settings,
std::unique_ptr<LibvpxInterface> interface);
// Deprecated, bugs.webrtc.org/15860
LibvpxVp9Encoder(const cricket::VideoCodec& codec,
std::unique_ptr<LibvpxInterface> interface,
const FieldTrialsView& trials);
@ -61,6 +66,10 @@ class LibvpxVp9Encoder : public VP9Encoder {
EncoderInfo GetEncoderInfo() const override;
private:
LibvpxVp9Encoder(std::unique_ptr<LibvpxInterface> interface,
VP9Profile profile,
const FieldTrialsView& trials);
// Determine number of encoder threads to use.
int NumberOfThreads(int width, int height, int number_of_cores);

View File

@ -102,7 +102,7 @@ void ConfigureSvc(VideoCodec& codec_settings,
class TestVp9Impl : public VideoCodecUnitTest {
protected:
std::unique_ptr<VideoEncoder> CreateEncoder() override {
return VP9Encoder::Create();
return CreateVp9Encoder(env_);
}
std::unique_ptr<VideoDecoder> CreateDecoder() override {
@ -255,7 +255,7 @@ TEST_F(TestVp9Impl, SwitchInputPixelFormatsWithoutReconfigure) {
}
TEST(Vp9ImplTest, ParserQpEqualsEncodedQp) {
std::unique_ptr<VideoEncoder> encoder = VP9Encoder::Create();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> encoder = VP9Encoder::Create();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> encoder = VP9Encoder::Create();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> encoder = VP9Encoder::Create();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> encoder = VP9Encoder::Create();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> encoder = VP9Encoder::Create();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> encoder = VP9Encoder::Create();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> encoder = VP9Encoder::Create();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> encoder = VP9Encoder::Create();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> encoder = VP9Encoder::Create();
std::unique_ptr<VideoEncoder> 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<VideoEncoder> 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<VideoDecoder> CreateDecoder() override {

View File

@ -81,6 +81,17 @@ std::vector<SdpVideoFormat> SupportedVP9DecoderCodecs() {
#endif
}
absl::Nonnull<std::unique_ptr<VideoEncoder>> CreateVp9Encoder(
const Environment& env,
Vp9EncoderSettings settings) {
#ifdef RTC_ENABLE_VP9
return std::make_unique<LibvpxVp9Encoder>(env, settings,
LibvpxInterface::Create());
#else
RTC_CHECK_NOTREACHED();
#endif
}
std::unique_ptr<VP9Encoder> VP9Encoder::Create() {
#ifdef RTC_ENABLE_VP9
return std::make_unique<LibvpxVp9Encoder>(