Add factory to create scalability structures by name
according to webrtc-svc spec draft Bug: webrtc:11404 Change-Id: I318b8a1a5c5389f6e5d15c3dd7d93041459e37f9 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/178603 Reviewed-by: Philip Eliasson <philipel@webrtc.org> Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Cr-Commit-Position: refs/heads/master@{#31731}
This commit is contained in:
committed by
Commit Bot
parent
97910da4e1
commit
a13e7a1d46
@ -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",
|
||||
]
|
||||
}
|
||||
|
||||
@ -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 <memory>
|
||||
|
||||
#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<ScalableVideoController> (*factory)();
|
||||
};
|
||||
|
||||
// Wrap std::make_unique function to have correct return type.
|
||||
template <typename T>
|
||||
std::unique_ptr<ScalableVideoController> Create() {
|
||||
return std::make_unique<T>();
|
||||
}
|
||||
|
||||
constexpr NamedStructureFactory kFactories[] = {
|
||||
{"NONE", Create<ScalableVideoControllerNoLayering>},
|
||||
{"L1T2", Create<ScalabilityStructureL1T2>},
|
||||
{"L1T3", Create<ScalabilityStructureL1T3>},
|
||||
{"L2T1", Create<ScalabilityStructureL2T1>},
|
||||
{"L2T1h", Create<ScalabilityStructureL2T1h>},
|
||||
{"L2T1_KEY", Create<ScalabilityStructureL2T1Key>},
|
||||
{"L2T2", Create<ScalabilityStructureL2T2>},
|
||||
{"L2T2_KEY", Create<ScalabilityStructureL2T2Key>},
|
||||
{"L2T2_KEY_SHIFT", Create<ScalabilityStructureL2T2KeyShift>},
|
||||
{"L3T1", Create<ScalabilityStructureL3T1>},
|
||||
{"L3T3", Create<ScalabilityStructureL3T3>},
|
||||
{"S2T1", Create<ScalabilityStructureS2T1>},
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<ScalableVideoController> 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
|
||||
@ -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 <memory>
|
||||
#include <vector>
|
||||
|
||||
#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<ScalableVideoController> CreateScalabilityStructure(
|
||||
absl::string_view name);
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // MODULES_VIDEO_CODING_CODECS_AV1_CREATE_SCALABILITY_STRUCTURE_H_
|
||||
@ -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<std::unique_ptr<ScalableVideoController>()> svc_factory;
|
||||
std::string name;
|
||||
int num_frames_to_generate;
|
||||
std::map<LayerId, DataRate> configured_bitrates;
|
||||
};
|
||||
@ -190,7 +180,7 @@ class LibaomAv1SvcTest : public ::testing::TestWithParam<SvcTestParam> {};
|
||||
|
||||
TEST_P(LibaomAv1SvcTest, EncodeAndDecodeAllDecodeTargets) {
|
||||
std::unique_ptr<ScalableVideoController> 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<VideoEncoder> 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<ScalableVideoControllerNoLayering>,
|
||||
/*num_frames_to_generate=*/4},
|
||||
SvcTestParam{std::make_unique<ScalabilityStructureL1T2>,
|
||||
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<ScalabilityStructureL1T3>,
|
||||
/*num_frames_to_generate=*/8},
|
||||
SvcTestParam{std::make_unique<ScalabilityStructureL2T1>,
|
||||
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<ScalabilityStructureL2T1h>,
|
||||
SvcTestParam{"L2T1h",
|
||||
/*num_frames_to_generate=*/3,
|
||||
/*configured_bitrates=*/
|
||||
{{{0, 0}, DataRate::KilobitsPerSec(30)},
|
||||
{{1, 0}, DataRate::KilobitsPerSec(70)}}},
|
||||
SvcTestParam{std::make_unique<ScalabilityStructureL2T1Key>,
|
||||
/*num_frames_to_generate=*/3},
|
||||
SvcTestParam{std::make_unique<ScalabilityStructureL3T1>,
|
||||
/*num_frames_to_generate=*/3},
|
||||
SvcTestParam{std::make_unique<ScalabilityStructureL3T3>,
|
||||
/*num_frames_to_generate=*/8},
|
||||
SvcTestParam{std::make_unique<ScalabilityStructureS2T1>,
|
||||
/*num_frames_to_generate=*/3},
|
||||
SvcTestParam{std::make_unique<ScalabilityStructureL2T2>,
|
||||
/*num_frames_to_generate=*/4},
|
||||
SvcTestParam{std::make_unique<ScalabilityStructureL2T2Key>,
|
||||
/*num_frames_to_generate=*/4},
|
||||
SvcTestParam{std::make_unique<ScalabilityStructureL2T2KeyShift>,
|
||||
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<SvcTestParam>& info) {
|
||||
return info.param.name;
|
||||
});
|
||||
|
||||
} // namespace
|
||||
} // namespace webrtc
|
||||
|
||||
@ -11,7 +11,6 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
@ -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<std::unique_ptr<ScalableVideoController>()> svc_factory;
|
||||
int num_temporal_units;
|
||||
};
|
||||
|
||||
@ -69,7 +58,7 @@ class ScalabilityStructureTest : public TestWithParam<SvcTestParam> {
|
||||
FrameDependenciesCalculator frame_deps_calculator;
|
||||
ChainDiffCalculator chain_diff_calculator;
|
||||
std::unique_ptr<ScalableVideoController> 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<SvcTestParam> {
|
||||
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<GenericFrameInfo> 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<GenericFrameInfo> 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<GenericFrameInfo> 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<GenericFrameInfo> frame_infos = GenerateAllFrames();
|
||||
int64_t num_frames = frame_infos.size();
|
||||
std::vector<std::set<int64_t>> full_deps(num_frames);
|
||||
@ -288,29 +277,16 @@ TEST_P(ScalabilityStructureTest, NoFrameDependsThroughSwitchIndication) {
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
Svc,
|
||||
ScalabilityStructureTest,
|
||||
Values(SvcTestParam{"L1T2", std::make_unique<ScalabilityStructureL1T2>,
|
||||
/*num_temporal_units=*/4},
|
||||
SvcTestParam{"L1T3", std::make_unique<ScalabilityStructureL1T3>,
|
||||
/*num_temporal_units=*/8},
|
||||
SvcTestParam{"L2T1", std::make_unique<ScalabilityStructureL2T1>,
|
||||
/*num_temporal_units=*/3},
|
||||
SvcTestParam{"L2T1Key",
|
||||
std::make_unique<ScalabilityStructureL2T1Key>,
|
||||
/*num_temporal_units=*/3},
|
||||
SvcTestParam{"L3T1", std::make_unique<ScalabilityStructureL3T1>,
|
||||
/*num_temporal_units=*/3},
|
||||
SvcTestParam{"L3T3", std::make_unique<ScalabilityStructureL3T3>,
|
||||
/*num_temporal_units=*/8},
|
||||
SvcTestParam{"S2T1", std::make_unique<ScalabilityStructureS2T1>,
|
||||
/*num_temporal_units=*/3},
|
||||
SvcTestParam{"L2T2", std::make_unique<ScalabilityStructureL2T2>,
|
||||
/*num_temporal_units=*/4},
|
||||
SvcTestParam{"L2T2Key",
|
||||
std::make_unique<ScalabilityStructureL2T2Key>,
|
||||
/*num_temporal_units=*/4},
|
||||
SvcTestParam{"L2T2KeyShift",
|
||||
std::make_unique<ScalabilityStructureL2T2KeyShift>,
|
||||
/*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<SvcTestParam>& info) {
|
||||
return info.param.name;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user