1 /*
2 * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10 #include "modules/video_coding/codecs/av1/scalability_structure_l1t2.h"
11
12 #include <utility>
13 #include <vector>
14
15 #include "absl/base/macros.h"
16 #include "api/transport/rtp/dependency_descriptor.h"
17 #include "rtc_base/checks.h"
18 #include "rtc_base/logging.h"
19
20 namespace webrtc {
21 namespace {
22
23 constexpr auto kNotPresent = DecodeTargetIndication::kNotPresent;
24 constexpr auto kDiscardable = DecodeTargetIndication::kDiscardable;
25 constexpr auto kSwitch = DecodeTargetIndication::kSwitch;
26
27 constexpr DecodeTargetIndication kDtis[3][2] = {
28 {kSwitch, kSwitch}, // KeyFrame
29 {kNotPresent, kDiscardable}, // DeltaFrame T1
30 {kSwitch, kSwitch}, // DeltaFrame T0
31 };
32
33 } // namespace
34
35 ScalabilityStructureL1T2::~ScalabilityStructureL1T2() = default;
36
37 ScalableVideoController::StreamLayersConfig
StreamConfig() const38 ScalabilityStructureL1T2::StreamConfig() const {
39 StreamLayersConfig result;
40 result.num_spatial_layers = 1;
41 result.num_temporal_layers = 2;
42 return result;
43 }
44
DependencyStructure() const45 FrameDependencyStructure ScalabilityStructureL1T2::DependencyStructure() const {
46 FrameDependencyStructure structure;
47 structure.num_decode_targets = 2;
48 structure.num_chains = 1;
49 structure.decode_target_protected_by_chain = {0, 0};
50 structure.templates.resize(3);
51 structure.templates[0].T(0).Dtis("SS").ChainDiffs({0});
52 structure.templates[1].T(0).Dtis("SS").ChainDiffs({2}).FrameDiffs({2});
53 structure.templates[2].T(1).Dtis("-D").ChainDiffs({1}).FrameDiffs({1});
54 return structure;
55 }
56
57 std::vector<ScalableVideoController::LayerFrameConfig>
NextFrameConfig(bool restart)58 ScalabilityStructureL1T2::NextFrameConfig(bool restart) {
59 if (!active_decode_targets_[0]) {
60 RTC_LOG(LS_WARNING) << "No bitrate allocated for temporal layer 0, yet "
61 "frame is requested. No frame will be encoded.";
62 return {};
63 }
64 if (restart) {
65 next_pattern_ = kKeyFrame;
66 } else if (!active_decode_targets_[1]) {
67 next_pattern_ = kDeltaFrameT0;
68 }
69 std::vector<LayerFrameConfig> result(1);
70
71 switch (next_pattern_) {
72 case kKeyFrame:
73 result[0].Id(0).T(0).Keyframe().Update(0);
74 next_pattern_ = kDeltaFrameT1;
75 break;
76 case kDeltaFrameT1:
77 result[0].Id(1).T(1).Reference(0);
78 next_pattern_ = kDeltaFrameT0;
79 break;
80 case kDeltaFrameT0:
81 result[0].Id(2).T(0).ReferenceAndUpdate(0);
82 next_pattern_ = kDeltaFrameT1;
83 break;
84 }
85 return result;
86 }
87
OnEncodeDone(LayerFrameConfig config)88 absl::optional<GenericFrameInfo> ScalabilityStructureL1T2::OnEncodeDone(
89 LayerFrameConfig config) {
90 // Encoder may have generated a keyframe even when not asked for it. Treat
91 // such frame same as requested keyframe, in particular restart the sequence.
92 if (config.IsKeyframe()) {
93 config = NextFrameConfig(/*restart=*/true).front();
94 }
95
96 absl::optional<GenericFrameInfo> frame_info;
97 if (config.Id() < 0 || config.Id() >= int{ABSL_ARRAYSIZE(kDtis)}) {
98 RTC_LOG(LS_ERROR) << "Unexpected config id " << config.Id();
99 return frame_info;
100 }
101 frame_info.emplace();
102 frame_info->temporal_id = config.TemporalId();
103 frame_info->encoder_buffers = config.Buffers();
104 frame_info->decode_target_indications.assign(std::begin(kDtis[config.Id()]),
105 std::end(kDtis[config.Id()]));
106 frame_info->part_of_chain = {config.TemporalId() == 0};
107 frame_info->active_decode_targets = active_decode_targets_;
108 return frame_info;
109 }
110
OnRatesUpdated(const VideoBitrateAllocation & bitrates)111 void ScalabilityStructureL1T2::OnRatesUpdated(
112 const VideoBitrateAllocation& bitrates) {
113 if (bitrates.GetBitrate(0, 0) == 0) {
114 // It is unclear what frame can be produced when base layer is disabled,
115 // so mark all decode targets as inactive to produce no frames.
116 active_decode_targets_.reset();
117 return;
118 }
119 active_decode_targets_.set(0, true);
120 active_decode_targets_.set(1, bitrates.GetBitrate(0, 1) > 0);
121 }
122
123 } // namespace webrtc
124