diff --git a/modules/video_coding/codecs/av1/BUILD.gn b/modules/video_coding/codecs/av1/BUILD.gn index edaa30ab14..b6d55671f0 100644 --- a/modules/video_coding/codecs/av1/BUILD.gn +++ b/modules/video_coding/codecs/av1/BUILD.gn @@ -54,6 +54,8 @@ rtc_source_set("scalable_video_controller") { rtc_source_set("scalability_structures") { sources = [ + "create_scalability_structure.cc", + "create_scalability_structure.h", "scalability_structure_l1t2.cc", "scalability_structure_l1t2.h", "scalability_structure_l1t3.cc", @@ -86,6 +88,7 @@ rtc_source_set("scalability_structures") { ] absl_deps = [ "//third_party/abseil-cpp/absl/base:core_headers", + "//third_party/abseil-cpp/absl/strings", "//third_party/abseil-cpp/absl/types:optional", ] } diff --git a/modules/video_coding/codecs/av1/create_scalability_structure.cc b/modules/video_coding/codecs/av1/create_scalability_structure.cc new file mode 100644 index 0000000000..17375547c5 --- /dev/null +++ b/modules/video_coding/codecs/av1/create_scalability_structure.cc @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include "modules/video_coding/codecs/av1/create_scalability_structure.h" + +#include + +#include "absl/strings/string_view.h" +#include "modules/video_coding/codecs/av1/scalability_structure_l1t2.h" +#include "modules/video_coding/codecs/av1/scalability_structure_l1t3.h" +#include "modules/video_coding/codecs/av1/scalability_structure_l2t1.h" +#include "modules/video_coding/codecs/av1/scalability_structure_l2t1_key.h" +#include "modules/video_coding/codecs/av1/scalability_structure_l2t1h.h" +#include "modules/video_coding/codecs/av1/scalability_structure_l2t2.h" +#include "modules/video_coding/codecs/av1/scalability_structure_l2t2_key.h" +#include "modules/video_coding/codecs/av1/scalability_structure_l2t2_key_shift.h" +#include "modules/video_coding/codecs/av1/scalability_structure_l3t1.h" +#include "modules/video_coding/codecs/av1/scalability_structure_l3t3.h" +#include "modules/video_coding/codecs/av1/scalability_structure_s2t1.h" +#include "modules/video_coding/codecs/av1/scalable_video_controller.h" +#include "modules/video_coding/codecs/av1/scalable_video_controller_no_layering.h" +#include "rtc_base/checks.h" + +namespace webrtc { +namespace { + +struct NamedStructureFactory { + absl::string_view name; + // Use function pointer to make NamedStructureFactory trivally destructable. + std::unique_ptr (*factory)(); +}; + +// Wrap std::make_unique function to have correct return type. +template +std::unique_ptr Create() { + return std::make_unique(); +} + +constexpr NamedStructureFactory kFactories[] = { + {"NONE", Create}, + {"L1T2", Create}, + {"L1T3", Create}, + {"L2T1", Create}, + {"L2T1h", Create}, + {"L2T1_KEY", Create}, + {"L2T2", Create}, + {"L2T2_KEY", Create}, + {"L2T2_KEY_SHIFT", Create}, + {"L3T1", Create}, + {"L3T3", Create}, + {"S2T1", Create}, +}; + +} // namespace + +std::unique_ptr CreateScalabilityStructure( + absl::string_view name) { + RTC_DCHECK(!name.empty()); + for (const auto& entry : kFactories) { + if (entry.name == name) { + return entry.factory(); + } + } + return nullptr; +} + +} // namespace webrtc diff --git a/modules/video_coding/codecs/av1/create_scalability_structure.h b/modules/video_coding/codecs/av1/create_scalability_structure.h new file mode 100644 index 0000000000..fe4a283ae4 --- /dev/null +++ b/modules/video_coding/codecs/av1/create_scalability_structure.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef MODULES_VIDEO_CODING_CODECS_AV1_CREATE_SCALABILITY_STRUCTURE_H_ +#define MODULES_VIDEO_CODING_CODECS_AV1_CREATE_SCALABILITY_STRUCTURE_H_ + +#include +#include + +#include "absl/strings/string_view.h" +#include "modules/video_coding/codecs/av1/scalable_video_controller.h" + +namespace webrtc { + +// Creates a structure by name according to +// https://w3c.github.io/webrtc-svc/#scalabilitymodes* +// Returns nullptr for unknown name. +std::unique_ptr CreateScalabilityStructure( + absl::string_view name); + +} // namespace webrtc + +#endif // MODULES_VIDEO_CODING_CODECS_AV1_CREATE_SCALABILITY_STRUCTURE_H_ diff --git a/modules/video_coding/codecs/av1/libaom_av1_unittest.cc b/modules/video_coding/codecs/av1/libaom_av1_unittest.cc index afd54e1fc0..970d43c066 100644 --- a/modules/video_coding/codecs/av1/libaom_av1_unittest.cc +++ b/modules/video_coding/codecs/av1/libaom_av1_unittest.cc @@ -22,19 +22,9 @@ #include "api/units/time_delta.h" #include "api/video_codecs/video_codec.h" #include "api/video_codecs/video_encoder.h" +#include "modules/video_coding/codecs/av1/create_scalability_structure.h" #include "modules/video_coding/codecs/av1/libaom_av1_decoder.h" #include "modules/video_coding/codecs/av1/libaom_av1_encoder.h" -#include "modules/video_coding/codecs/av1/scalability_structure_l1t2.h" -#include "modules/video_coding/codecs/av1/scalability_structure_l1t3.h" -#include "modules/video_coding/codecs/av1/scalability_structure_l2t1.h" -#include "modules/video_coding/codecs/av1/scalability_structure_l2t1_key.h" -#include "modules/video_coding/codecs/av1/scalability_structure_l2t1h.h" -#include "modules/video_coding/codecs/av1/scalability_structure_l2t2.h" -#include "modules/video_coding/codecs/av1/scalability_structure_l2t2_key.h" -#include "modules/video_coding/codecs/av1/scalability_structure_l2t2_key_shift.h" -#include "modules/video_coding/codecs/av1/scalability_structure_l3t1.h" -#include "modules/video_coding/codecs/av1/scalability_structure_l3t3.h" -#include "modules/video_coding/codecs/av1/scalability_structure_s2t1.h" #include "modules/video_coding/codecs/av1/scalable_video_controller.h" #include "modules/video_coding/codecs/av1/scalable_video_controller_no_layering.h" #include "modules/video_coding/codecs/test/encoded_video_frame_producer.h" @@ -181,7 +171,7 @@ struct LayerId { }; struct SvcTestParam { - std::function()> svc_factory; + std::string name; int num_frames_to_generate; std::map configured_bitrates; }; @@ -190,7 +180,7 @@ class LibaomAv1SvcTest : public ::testing::TestWithParam {}; TEST_P(LibaomAv1SvcTest, EncodeAndDecodeAllDecodeTargets) { std::unique_ptr svc_controller = - GetParam().svc_factory(); + CreateScalabilityStructure(GetParam().name); size_t num_decode_targets = svc_controller->DependencyStructure().num_decode_targets; @@ -262,7 +252,7 @@ TEST_P(LibaomAv1SvcTest, SetRatesMatchMeasuredBitrate) { } std::unique_ptr encoder = - CreateLibaomAv1Encoder(param.svc_factory()); + CreateLibaomAv1Encoder(CreateScalabilityStructure(param.name)); ASSERT_TRUE(encoder); VideoCodec codec_settings = DefaultCodecSettings(); codec_settings.maxBitrate = allocation.get_sum_kbps(); @@ -304,44 +294,39 @@ TEST_P(LibaomAv1SvcTest, SetRatesMatchMeasuredBitrate) { INSTANTIATE_TEST_SUITE_P( Svc, LibaomAv1SvcTest, - Values(SvcTestParam{std::make_unique, - /*num_frames_to_generate=*/4}, - SvcTestParam{std::make_unique, + Values(SvcTestParam{"NONE", /*num_frames_to_generate=*/4}, + SvcTestParam{"L1T2", /*num_frames_to_generate=*/4, /*configured_bitrates=*/ {{{0, 0}, DataRate::KilobitsPerSec(60)}, {{0, 1}, DataRate::KilobitsPerSec(40)}}}, - SvcTestParam{std::make_unique, - /*num_frames_to_generate=*/8}, - SvcTestParam{std::make_unique, + SvcTestParam{"L1T3", /*num_frames_to_generate=*/8}, + SvcTestParam{"L2T1", /*num_frames_to_generate=*/3, /*configured_bitrates=*/ {{{0, 0}, DataRate::KilobitsPerSec(30)}, {{1, 0}, DataRate::KilobitsPerSec(70)}}}, - SvcTestParam{std::make_unique, + SvcTestParam{"L2T1h", /*num_frames_to_generate=*/3, /*configured_bitrates=*/ {{{0, 0}, DataRate::KilobitsPerSec(30)}, {{1, 0}, DataRate::KilobitsPerSec(70)}}}, - SvcTestParam{std::make_unique, - /*num_frames_to_generate=*/3}, - SvcTestParam{std::make_unique, - /*num_frames_to_generate=*/3}, - SvcTestParam{std::make_unique, - /*num_frames_to_generate=*/8}, - SvcTestParam{std::make_unique, - /*num_frames_to_generate=*/3}, - SvcTestParam{std::make_unique, - /*num_frames_to_generate=*/4}, - SvcTestParam{std::make_unique, - /*num_frames_to_generate=*/4}, - SvcTestParam{std::make_unique, + SvcTestParam{"L2T1_KEY", /*num_frames_to_generate=*/3}, + SvcTestParam{"L3T1", /*num_frames_to_generate=*/3}, + SvcTestParam{"L3T3", /*num_frames_to_generate=*/8}, + SvcTestParam{"S2T1", /*num_frames_to_generate=*/3}, + SvcTestParam{"L2T2", /*num_frames_to_generate=*/4}, + SvcTestParam{"L2T2_KEY", /*num_frames_to_generate=*/4}, + SvcTestParam{"L2T2_KEY_SHIFT", /*num_frames_to_generate=*/4, /*configured_bitrates=*/ {{{0, 0}, DataRate::KilobitsPerSec(70)}, {{0, 1}, DataRate::KilobitsPerSec(30)}, {{1, 0}, DataRate::KilobitsPerSec(140)}, - {{1, 1}, DataRate::KilobitsPerSec(80)}}})); + {{1, 1}, DataRate::KilobitsPerSec(80)}}}), + [](const testing::TestParamInfo& info) { + return info.param.name; + }); } // namespace } // namespace webrtc diff --git a/modules/video_coding/codecs/av1/scalability_structure_unittest.cc b/modules/video_coding/codecs/av1/scalability_structure_unittest.cc index d2a0516567..77b34c3ce1 100644 --- a/modules/video_coding/codecs/av1/scalability_structure_unittest.cc +++ b/modules/video_coding/codecs/av1/scalability_structure_unittest.cc @@ -11,7 +11,6 @@ #include #include -#include #include #include #include @@ -20,16 +19,7 @@ #include "api/transport/rtp/dependency_descriptor.h" #include "api/video/video_frame_type.h" #include "modules/video_coding/chain_diff_calculator.h" -#include "modules/video_coding/codecs/av1/scalability_structure_l1t2.h" -#include "modules/video_coding/codecs/av1/scalability_structure_l1t3.h" -#include "modules/video_coding/codecs/av1/scalability_structure_l2t1.h" -#include "modules/video_coding/codecs/av1/scalability_structure_l2t1_key.h" -#include "modules/video_coding/codecs/av1/scalability_structure_l2t2.h" -#include "modules/video_coding/codecs/av1/scalability_structure_l2t2_key.h" -#include "modules/video_coding/codecs/av1/scalability_structure_l2t2_key_shift.h" -#include "modules/video_coding/codecs/av1/scalability_structure_l3t1.h" -#include "modules/video_coding/codecs/av1/scalability_structure_l3t3.h" -#include "modules/video_coding/codecs/av1/scalability_structure_s2t1.h" +#include "modules/video_coding/codecs/av1/create_scalability_structure.h" #include "modules/video_coding/codecs/av1/scalable_video_controller.h" #include "modules/video_coding/frame_dependencies_calculator.h" #include "test/gmock.h" @@ -57,7 +47,6 @@ struct SvcTestParam { } std::string name; - std::function()> svc_factory; int num_temporal_units; }; @@ -69,7 +58,7 @@ class ScalabilityStructureTest : public TestWithParam { FrameDependenciesCalculator frame_deps_calculator; ChainDiffCalculator chain_diff_calculator; std::unique_ptr structure_controller = - GetParam().svc_factory(); + CreateScalabilityStructure(GetParam().name); FrameDependencyStructure structure = structure_controller->DependencyStructure(); for (int i = 0; i < GetParam().num_temporal_units; ++i) { @@ -104,7 +93,7 @@ class ScalabilityStructureTest : public TestWithParam { TEST_P(ScalabilityStructureTest, NumberOfDecodeTargetsAndChainsAreInRangeAndConsistent) { FrameDependencyStructure structure = - GetParam().svc_factory()->DependencyStructure(); + CreateScalabilityStructure(GetParam().name)->DependencyStructure(); EXPECT_GT(structure.num_decode_targets, 0); EXPECT_LE(structure.num_decode_targets, DependencyDescriptor::kMaxDecodeTargets); @@ -123,7 +112,7 @@ TEST_P(ScalabilityStructureTest, TEST_P(ScalabilityStructureTest, TemplatesAreSortedByLayerId) { FrameDependencyStructure structure = - GetParam().svc_factory()->DependencyStructure(); + CreateScalabilityStructure(GetParam().name)->DependencyStructure(); ASSERT_THAT(structure.templates, Not(IsEmpty())); const auto& first_templates = structure.templates.front(); EXPECT_EQ(first_templates.spatial_id, 0); @@ -154,7 +143,7 @@ TEST_P(ScalabilityStructureTest, TemplatesAreSortedByLayerId) { TEST_P(ScalabilityStructureTest, TemplatesMatchNumberOfDecodeTargetsAndChains) { FrameDependencyStructure structure = - GetParam().svc_factory()->DependencyStructure(); + CreateScalabilityStructure(GetParam().name)->DependencyStructure(); EXPECT_THAT( structure.templates, Each(AllOf(Field(&FrameDependencyTemplate::decode_target_indications, @@ -165,7 +154,7 @@ TEST_P(ScalabilityStructureTest, TemplatesMatchNumberOfDecodeTargetsAndChains) { TEST_P(ScalabilityStructureTest, FrameInfoMatchesFrameDependencyStructure) { FrameDependencyStructure structure = - GetParam().svc_factory()->DependencyStructure(); + CreateScalabilityStructure(GetParam().name)->DependencyStructure(); std::vector frame_infos = GenerateAllFrames(); for (size_t frame_id = 0; frame_id < frame_infos.size(); ++frame_id) { const auto& frame = frame_infos[frame_id]; @@ -181,7 +170,7 @@ TEST_P(ScalabilityStructureTest, FrameInfoMatchesFrameDependencyStructure) { TEST_P(ScalabilityStructureTest, ThereIsAPerfectTemplateForEachFrame) { FrameDependencyStructure structure = - GetParam().svc_factory()->DependencyStructure(); + CreateScalabilityStructure(GetParam().name)->DependencyStructure(); std::vector frame_infos = GenerateAllFrames(); for (size_t frame_id = 0; frame_id < frame_infos.size(); ++frame_id) { EXPECT_THAT(structure.templates, Contains(frame_infos[frame_id])) @@ -210,7 +199,7 @@ TEST_P(ScalabilityStructureTest, NoFrameDependsOnDiscardableOrNotPresent) { std::vector frame_infos = GenerateAllFrames(); int64_t num_frames = frame_infos.size(); FrameDependencyStructure structure = - GetParam().svc_factory()->DependencyStructure(); + CreateScalabilityStructure(GetParam().name)->DependencyStructure(); for (int dt = 0; dt < structure.num_decode_targets; ++dt) { for (int64_t frame_id = 0; frame_id < num_frames; ++frame_id) { @@ -237,7 +226,7 @@ TEST_P(ScalabilityStructureTest, NoFrameDependsOnDiscardableOrNotPresent) { TEST_P(ScalabilityStructureTest, NoFrameDependsThroughSwitchIndication) { FrameDependencyStructure structure = - GetParam().svc_factory()->DependencyStructure(); + CreateScalabilityStructure(GetParam().name)->DependencyStructure(); std::vector frame_infos = GenerateAllFrames(); int64_t num_frames = frame_infos.size(); std::vector> full_deps(num_frames); @@ -288,29 +277,16 @@ TEST_P(ScalabilityStructureTest, NoFrameDependsThroughSwitchIndication) { INSTANTIATE_TEST_SUITE_P( Svc, ScalabilityStructureTest, - Values(SvcTestParam{"L1T2", std::make_unique, - /*num_temporal_units=*/4}, - SvcTestParam{"L1T3", std::make_unique, - /*num_temporal_units=*/8}, - SvcTestParam{"L2T1", std::make_unique, - /*num_temporal_units=*/3}, - SvcTestParam{"L2T1Key", - std::make_unique, - /*num_temporal_units=*/3}, - SvcTestParam{"L3T1", std::make_unique, - /*num_temporal_units=*/3}, - SvcTestParam{"L3T3", std::make_unique, - /*num_temporal_units=*/8}, - SvcTestParam{"S2T1", std::make_unique, - /*num_temporal_units=*/3}, - SvcTestParam{"L2T2", std::make_unique, - /*num_temporal_units=*/4}, - SvcTestParam{"L2T2Key", - std::make_unique, - /*num_temporal_units=*/4}, - SvcTestParam{"L2T2KeyShift", - std::make_unique, - /*num_temporal_units=*/4}), + Values(SvcTestParam{"L1T2", /*num_temporal_units=*/4}, + SvcTestParam{"L1T3", /*num_temporal_units=*/8}, + SvcTestParam{"L2T1", /*num_temporal_units=*/3}, + SvcTestParam{"L2T1_KEY", /*num_temporal_units=*/3}, + SvcTestParam{"L3T1", /*num_temporal_units=*/3}, + SvcTestParam{"L3T3", /*num_temporal_units=*/8}, + SvcTestParam{"S2T1", /*num_temporal_units=*/3}, + SvcTestParam{"L2T2", /*num_temporal_units=*/4}, + SvcTestParam{"L2T2_KEY", /*num_temporal_units=*/4}, + SvcTestParam{"L2T2_KEY_SHIFT", /*num_temporal_units=*/4}), [](const testing::TestParamInfo& info) { return info.param.name; });