Add av1 test with temporal scalability.

Bug: webrtc:11404
Change-Id: Iaf2fcca0dd450f7b296bd0250a119b8e7dfef270
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/176181
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31397}
This commit is contained in:
Danil Chapovalov
2020-06-01 15:00:41 +02:00
committed by Commit Bot
parent f1c5b95e51
commit 00b172a6fa
4 changed files with 181 additions and 0 deletions

View File

@ -51,6 +51,22 @@ rtc_source_set("scalable_video_controller") {
]
}
rtc_source_set("scalability_structures") {
sources = [
"scalability_structure_l1t2.cc",
"scalability_structure_l1t2.h",
]
deps = [
":scalable_video_controller",
"../../../../api/transport/rtp:dependency_descriptor",
"../../../../common_video/generic_frame_descriptor",
"../../../../rtc_base:checks",
"../../../../rtc_base:logging",
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/types:optional",
]
}
rtc_library("libaom_av1_encoder") {
visibility = [ "*" ]
poisonous = [ "software_video_codecs" ]
@ -73,6 +89,7 @@ rtc_library("libaom_av1_encoder") {
"../../../../rtc_base:checks",
"../../../../rtc_base:logging",
"//third_party/abseil-cpp/absl/algorithm:container",
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/libaom",
]
} else {
@ -92,6 +109,7 @@ if (rtc_include_tests) {
deps = [
":libaom_av1_decoder",
":libaom_av1_encoder",
":scalability_structures",
":scalable_video_controller",
"../..:video_codec_interface",
"../../../../api:create_frame_generator",

View File

@ -21,6 +21,7 @@
#include "api/video_codecs/video_encoder.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/scalable_video_controller.h"
#include "modules/video_coding/codecs/av1/scalable_video_controller_no_layering.h"
#include "modules/video_coding/include/video_codec_interface.h"
@ -98,6 +99,7 @@ class TestAv1Encoder {
codec_settings.width = kWidth;
codec_settings.height = kHeight;
codec_settings.maxFramerate = kFramerate;
codec_settings.maxBitrate = 1000;
VideoEncoder::Settings encoder_settings(
VideoEncoder::Capabilities(/*loss_notification=*/false),
/*number_of_cores=*/1, /*max_payload_size=*/1200);
@ -271,6 +273,8 @@ INSTANTIATE_TEST_SUITE_P(
Svc,
LibaomAv1SvcTest,
Values(SvcTestParam{std::make_unique<ScalableVideoControllerNoLayering>,
/*num_frames_to_generate=*/4},
SvcTestParam{std::make_unique<ScalabilityStructureL1T2>,
/*num_frames_to_generate=*/4}));
} // namespace

View File

@ -0,0 +1,115 @@
/*
* 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/scalability_structure_l1t2.h"
#include <utility>
#include <vector>
#include "absl/base/macros.h"
#include "api/transport/rtp/dependency_descriptor.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
namespace webrtc {
namespace {
constexpr auto kNotPresent = DecodeTargetIndication::kNotPresent;
constexpr auto kDiscardable = DecodeTargetIndication::kDiscardable;
constexpr auto kSwitch = DecodeTargetIndication::kSwitch;
constexpr DecodeTargetIndication kDtis[3][2] = {
{kSwitch, kSwitch}, // KeyFrame
{kNotPresent, kDiscardable}, // DeltaFrame T1
{kSwitch, kSwitch}, // DeltaFrame T0
};
} // namespace
ScalabilityStructureL1T2::~ScalabilityStructureL1T2() = default;
ScalableVideoController::StreamLayersConfig
ScalabilityStructureL1T2::StreamConfig() const {
StreamLayersConfig result;
result.num_spatial_layers = 1;
result.num_temporal_layers = 2;
return result;
}
FrameDependencyStructure ScalabilityStructureL1T2::DependencyStructure() const {
using Builder = GenericFrameInfo::Builder;
FrameDependencyStructure structure;
structure.num_decode_targets = 2;
structure.num_chains = 1;
structure.decode_target_protected_by_chain = {0};
structure.templates = {
Builder().T(0).Dtis("SS").ChainDiffs({0}).Build(),
Builder().T(0).Dtis("SS").ChainDiffs({2}).Fdiffs({2}).Build(),
Builder().T(1).Dtis("-D").ChainDiffs({1}).Fdiffs({1}).Build(),
};
return structure;
}
std::vector<ScalableVideoController::LayerFrameConfig>
ScalabilityStructureL1T2::NextFrameConfig(bool restart) {
if (restart) {
next_pattern_ = kKeyFrame;
}
std::vector<LayerFrameConfig> result(1);
switch (next_pattern_) {
case kKeyFrame:
result[0].id = 0;
result[0].temporal_id = 0;
result[0].is_keyframe = true;
result[0].buffers = {{/*id=*/0, /*references=*/false, /*updates=*/true}};
next_pattern_ = kDeltaFrameT1;
break;
case kDeltaFrameT1:
result[0].id = 1;
result[0].temporal_id = 1;
result[0].is_keyframe = false;
result[0].buffers = {{/*id=*/0, /*references=*/true, /*updates=*/false}};
next_pattern_ = kDeltaFrameT0;
break;
case kDeltaFrameT0:
result[0].id = 2;
result[0].temporal_id = 0;
result[0].is_keyframe = false;
result[0].buffers = {{/*id=*/0, /*references=*/true, /*updates=*/true}};
next_pattern_ = kDeltaFrameT1;
break;
}
RTC_DCHECK(!result.empty());
return result;
}
absl::optional<GenericFrameInfo> ScalabilityStructureL1T2::OnEncodeDone(
LayerFrameConfig config) {
// Encoder may have generated a keyframe even when not asked for it. Treat
// such frame same as requested keyframe, in particular restart the sequence.
if (config.is_keyframe) {
config = NextFrameConfig(/*restart=*/true).front();
}
absl::optional<GenericFrameInfo> frame_info;
if (config.id < 0 || config.id >= int{ABSL_ARRAYSIZE(kDtis)}) {
RTC_LOG(LS_ERROR) << "Unexpected config id " << config.id;
return frame_info;
}
frame_info.emplace();
frame_info->temporal_id = config.temporal_id;
frame_info->encoder_buffers = std::move(config.buffers);
frame_info->decode_target_indications.assign(std::begin(kDtis[config.id]),
std::end(kDtis[config.id]));
frame_info->part_of_chain = {config.temporal_id == 0};
return frame_info;
}
} // namespace webrtc

View File

@ -0,0 +1,44 @@
/*
* 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_SCALABILITY_STRUCTURE_L1T2_H_
#define MODULES_VIDEO_CODING_CODECS_AV1_SCALABILITY_STRUCTURE_L1T2_H_
#include <vector>
#include "api/transport/rtp/dependency_descriptor.h"
#include "common_video/generic_frame_descriptor/generic_frame_info.h"
#include "modules/video_coding/codecs/av1/scalable_video_controller.h"
namespace webrtc {
class ScalabilityStructureL1T2 : public ScalableVideoController {
public:
~ScalabilityStructureL1T2() override;
StreamLayersConfig StreamConfig() const override;
FrameDependencyStructure DependencyStructure() const override;
std::vector<LayerFrameConfig> NextFrameConfig(bool restart) override;
absl::optional<GenericFrameInfo> OnEncodeDone(
LayerFrameConfig config) override;
private:
enum FramePattern {
kKeyFrame,
kDeltaFrameT1,
kDeltaFrameT0,
};
FramePattern next_pattern_ = kKeyFrame;
};
} // namespace webrtc
#endif // MODULES_VIDEO_CODING_CODECS_AV1_SCALABILITY_STRUCTURE_L1T2_H_