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_l3t3.h"
11
12 #include <utility>
13 #include <vector>
14
15 #include "absl/base/macros.h"
16 #include "absl/types/optional.h"
17 #include "api/transport/rtp/dependency_descriptor.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 constexpr auto kRequired = DecodeTargetIndication::kRequired;
27
28 constexpr DecodeTargetIndication kDtis[12][9] = {
29 // Key, S0
30 {kSwitch, kSwitch, kSwitch, // S0
31 kSwitch, kSwitch, kSwitch, // S1
32 kSwitch, kSwitch, kSwitch}, // S2
33 // Key, S1
34 {kNotPresent, kNotPresent, kNotPresent, // S0
35 kSwitch, kSwitch, kSwitch, // S1
36 kSwitch, kSwitch, kSwitch}, // S2
37 // Key, S2
38 {kNotPresent, kNotPresent, kNotPresent, // S0
39 kNotPresent, kNotPresent, kNotPresent, // S1
40 kSwitch, kSwitch, kSwitch}, // S2
41 // Delta, S0T2
42 {kNotPresent, kNotPresent, kDiscardable, // S0
43 kNotPresent, kNotPresent, kRequired, // S1
44 kNotPresent, kNotPresent, kRequired}, // S2
45 // Delta, S1T2
46 {kNotPresent, kNotPresent, kNotPresent, // S0
47 kNotPresent, kNotPresent, kDiscardable, // S1
48 kNotPresent, kNotPresent, kRequired}, // S2
49 // Delta, S2T2
50 {kNotPresent, kNotPresent, kNotPresent, // S0
51 kNotPresent, kNotPresent, kNotPresent, // S1
52 kNotPresent, kNotPresent, kDiscardable}, // S2
53 // Delta, S0T1
54 {kNotPresent, kDiscardable, kSwitch, // S0
55 kNotPresent, kRequired, kRequired, // S1
56 kNotPresent, kRequired, kRequired}, // S2
57 // Delta, S1T1
58 {kNotPresent, kNotPresent, kNotPresent, // S0
59 kNotPresent, kDiscardable, kSwitch, // S1
60 kNotPresent, kRequired, kRequired}, // S2
61 // Delta, S2T1
62 {kNotPresent, kNotPresent, kNotPresent, // S0
63 kNotPresent, kNotPresent, kNotPresent, // S1
64 kNotPresent, kDiscardable, kSwitch}, // S2
65 // Delta, S0T0
66 {kSwitch, kSwitch, kSwitch, // S0
67 kRequired, kRequired, kRequired, // S1
68 kRequired, kRequired, kRequired}, // S2
69 // Delta, S1T0
70 {kNotPresent, kNotPresent, kNotPresent, // S0
71 kSwitch, kSwitch, kSwitch, // S1
72 kRequired, kRequired, kRequired}, // S2
73 // Delta, S2T0
74 {kNotPresent, kNotPresent, kNotPresent, // S0
75 kNotPresent, kNotPresent, kNotPresent, // S1
76 kSwitch, kSwitch, kSwitch}, // S2
77 };
78
79 } // namespace
80
81 ScalabilityStructureL3T3::~ScalabilityStructureL3T3() = default;
82
83 ScalableVideoController::StreamLayersConfig
StreamConfig() const84 ScalabilityStructureL3T3::StreamConfig() const {
85 StreamLayersConfig result;
86 result.num_spatial_layers = 3;
87 result.num_temporal_layers = 3;
88 result.scaling_factor_num[0] = 1;
89 result.scaling_factor_den[0] = 4;
90 result.scaling_factor_num[1] = 1;
91 result.scaling_factor_den[1] = 2;
92 return result;
93 }
94
DependencyStructure() const95 FrameDependencyStructure ScalabilityStructureL3T3::DependencyStructure() const {
96 FrameDependencyStructure structure;
97 structure.num_decode_targets = 9;
98 structure.num_chains = 3;
99 structure.decode_target_protected_by_chain = {0, 0, 0, 1, 1, 1, 2, 2, 2};
100 auto& t = structure.templates;
101 t.resize(15);
102 // Templates are shown in the order frames following them appear in the
103 // stream, but in `structure.templates` array templates are sorted by
104 // (`spatial_id`, `temporal_id`) since that is a dependency descriptor
105 // requirement. Indexes are written in hex for nicer alignment.
106 t[0x1].S(0).T(0).Dtis("SSSSSSSSS").ChainDiffs({0, 0, 0});
107 t[0x6].S(1).T(0).Dtis("---SSSSSS").ChainDiffs({1, 1, 1}).FrameDiffs({1});
108 t[0xB].S(2).T(0).Dtis("------SSS").ChainDiffs({2, 1, 1}).FrameDiffs({1});
109 t[0x3].S(0).T(2).Dtis("--D--R--R").ChainDiffs({3, 2, 1}).FrameDiffs({3});
110 t[0x8].S(1).T(2).Dtis("-----D--R").ChainDiffs({4, 3, 2}).FrameDiffs({3, 1});
111 t[0xD].S(2).T(2).Dtis("--------D").ChainDiffs({5, 4, 3}).FrameDiffs({3, 1});
112 t[0x2].S(0).T(1).Dtis("-DS-RR-RR").ChainDiffs({6, 5, 4}).FrameDiffs({6});
113 t[0x7].S(1).T(1).Dtis("----DS-RR").ChainDiffs({7, 6, 5}).FrameDiffs({6, 1});
114 t[0xC].S(2).T(1).Dtis("-------DS").ChainDiffs({8, 7, 6}).FrameDiffs({6, 1});
115 t[0x4].S(0).T(2).Dtis("--D--R--R").ChainDiffs({9, 8, 7}).FrameDiffs({3});
116 t[0x9].S(1).T(2).Dtis("-----D--R").ChainDiffs({10, 9, 8}).FrameDiffs({3, 1});
117 t[0xE].S(2).T(2).Dtis("--------D").ChainDiffs({11, 10, 9}).FrameDiffs({3, 1});
118 t[0x0].S(0).T(0).Dtis("SSSRRRRRR").ChainDiffs({12, 11, 10}).FrameDiffs({12});
119 t[0x5].S(1).T(0).Dtis("---SSSRRR").ChainDiffs({1, 1, 1}).FrameDiffs({12, 1});
120 t[0xA].S(2).T(0).Dtis("------SSS").ChainDiffs({2, 1, 1}).FrameDiffs({12, 1});
121 return structure;
122 }
123
124 ScalableVideoController::LayerFrameConfig
KeyFrameConfig() const125 ScalabilityStructureL3T3::KeyFrameConfig() const {
126 return LayerFrameConfig().Id(0).S(0).T(0).Keyframe().Update(0);
127 }
128
129 std::vector<ScalableVideoController::LayerFrameConfig>
NextFrameConfig(bool restart)130 ScalabilityStructureL3T3::NextFrameConfig(bool restart) {
131 if (restart) {
132 next_pattern_ = kKeyFrame;
133 }
134 std::vector<LayerFrameConfig> config(3);
135
136 // For this structure name each of 8 buffers after the layer of the frame that
137 // buffer keeps.
138 static constexpr int kS0T0 = 0;
139 static constexpr int kS1T0 = 1;
140 static constexpr int kS2T0 = 2;
141 static constexpr int kS0T1 = 3;
142 static constexpr int kS1T1 = 4;
143 static constexpr int kS2T1 = 5;
144 static constexpr int kS0T2 = 6;
145 static constexpr int kS1T2 = 7;
146 switch (next_pattern_) {
147 case kKeyFrame:
148 config[0].Id(0).S(0).T(0).Keyframe().Update(kS0T0);
149 config[1].Id(1).S(1).T(0).Update(kS1T0).Reference(kS0T0);
150 config[2].Id(2).S(2).T(0).Update(kS2T0).Reference(kS1T0);
151 next_pattern_ = kDeltaFrameT2A;
152 break;
153 case kDeltaFrameT2A:
154 config[0].Id(3).S(0).T(2).Reference(kS0T0).Update(kS0T2);
155 config[1].Id(4).S(1).T(2).Reference(kS1T0).Reference(kS0T2).Update(kS1T2);
156 config[2].Id(5).S(2).T(2).Reference(kS2T0).Reference(kS1T2);
157 next_pattern_ = kDeltaFrameT1;
158 break;
159 case kDeltaFrameT1:
160 config[0].Id(6).S(0).T(1).Reference(kS0T0).Update(kS0T1);
161 config[1].Id(7).S(1).T(1).Reference(kS1T0).Reference(kS0T1).Update(kS1T1);
162 config[2].Id(8).S(2).T(1).Reference(kS2T0).Reference(kS1T1).Update(kS2T1);
163 next_pattern_ = kDeltaFrameT2B;
164 break;
165 case kDeltaFrameT2B:
166 config[0].Id(3).S(0).T(2).Reference(kS0T1).Update(kS0T2);
167 config[1].Id(4).S(1).T(2).Reference(kS1T1).Reference(kS0T2).Update(kS1T2);
168 config[2].Id(5).S(2).T(2).Reference(kS2T1).Reference(kS1T2);
169 next_pattern_ = kDeltaFrameT0;
170 break;
171 case kDeltaFrameT0:
172 config[0].Id(9).S(0).T(0).ReferenceAndUpdate(kS0T0);
173 config[1].Id(10).S(1).T(0).ReferenceAndUpdate(kS1T0).Reference(kS0T0);
174 config[2].Id(11).S(2).T(0).ReferenceAndUpdate(kS2T0).Reference(kS1T0);
175 next_pattern_ = kDeltaFrameT2A;
176 break;
177 }
178 return config;
179 }
180
OnEncodeDone(LayerFrameConfig config)181 absl::optional<GenericFrameInfo> ScalabilityStructureL3T3::OnEncodeDone(
182 LayerFrameConfig config) {
183 if (config.IsKeyframe() && config.Id() != 0) {
184 // Encoder generated a key frame without asking to.
185 if (config.SpatialId() > 0) {
186 RTC_LOG(LS_WARNING) << "Unexpected spatial id " << config.SpatialId()
187 << " for key frame.";
188 }
189 config = LayerFrameConfig()
190 .Keyframe()
191 .Id(0)
192 .S(0)
193 .T(0)
194 .Update(0)
195 .Update(1)
196 .Update(2)
197 .Update(3)
198 .Update(4)
199 .Update(5)
200 .Update(6)
201 .Update(7);
202 }
203
204 absl::optional<GenericFrameInfo> frame_info;
205 if (config.Id() < 0 || config.Id() >= int{ABSL_ARRAYSIZE(kDtis)}) {
206 RTC_LOG(LS_ERROR) << "Unexpected config id " << config.Id();
207 return frame_info;
208 }
209 frame_info.emplace();
210 frame_info->spatial_id = config.SpatialId();
211 frame_info->temporal_id = config.TemporalId();
212 frame_info->encoder_buffers = config.Buffers();
213 frame_info->decode_target_indications.assign(std::begin(kDtis[config.Id()]),
214 std::end(kDtis[config.Id()]));
215 if (config.TemporalId() == 0) {
216 frame_info->part_of_chain = {config.SpatialId() == 0,
217 config.SpatialId() <= 1, true};
218 } else {
219 frame_info->part_of_chain = {false, false, false};
220 }
221 return frame_info;
222 }
223
224 } // namespace webrtc
225