xref: /aosp_15_r20/external/webrtc/modules/video_coding/svc/scalability_structure_l2t2_key_shift.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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/svc/scalability_structure_l2t2_key_shift.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 DecodeTargetIndication
Dti(int sid,int tid,const ScalableVideoController::LayerFrameConfig & config)24 Dti(int sid, int tid, const ScalableVideoController::LayerFrameConfig& config) {
25   if (config.IsKeyframe()) {
26     RTC_DCHECK_EQ(config.TemporalId(), 0);
27     return sid < config.SpatialId() ? DecodeTargetIndication::kNotPresent
28                                     : DecodeTargetIndication::kSwitch;
29   }
30 
31   if (sid != config.SpatialId() || tid < config.TemporalId()) {
32     return DecodeTargetIndication::kNotPresent;
33   }
34   if (tid == config.TemporalId() && tid > 0) {
35     return DecodeTargetIndication::kDiscardable;
36   }
37   return DecodeTargetIndication::kSwitch;
38 }
39 
40 }  // namespace
41 
42 constexpr int ScalabilityStructureL2T2KeyShift::kNumSpatialLayers;
43 constexpr int ScalabilityStructureL2T2KeyShift::kNumTemporalLayers;
44 
45 ScalabilityStructureL2T2KeyShift::~ScalabilityStructureL2T2KeyShift() = default;
46 
47 ScalableVideoController::StreamLayersConfig
StreamConfig() const48 ScalabilityStructureL2T2KeyShift::StreamConfig() const {
49   StreamLayersConfig result;
50   result.num_spatial_layers = 2;
51   result.num_temporal_layers = 2;
52   result.scaling_factor_num[0] = 1;
53   result.scaling_factor_den[0] = 2;
54   result.uses_reference_scaling = true;
55   return result;
56 }
57 
DependencyStructure() const58 FrameDependencyStructure ScalabilityStructureL2T2KeyShift::DependencyStructure()
59     const {
60   FrameDependencyStructure structure;
61   structure.num_decode_targets = 4;
62   structure.num_chains = 2;
63   structure.decode_target_protected_by_chain = {0, 0, 1, 1};
64   structure.templates.resize(7);
65   auto& templates = structure.templates;
66   templates[0].S(0).T(0).Dtis("SSSS").ChainDiffs({0, 0});
67   templates[1].S(0).T(0).Dtis("SS--").ChainDiffs({2, 1}).FrameDiffs({2});
68   templates[2].S(0).T(0).Dtis("SS--").ChainDiffs({4, 1}).FrameDiffs({4});
69   templates[3].S(0).T(1).Dtis("-D--").ChainDiffs({2, 3}).FrameDiffs({2});
70   templates[4].S(1).T(0).Dtis("--SS").ChainDiffs({1, 1}).FrameDiffs({1});
71   templates[5].S(1).T(0).Dtis("--SS").ChainDiffs({3, 4}).FrameDiffs({4});
72   templates[6].S(1).T(1).Dtis("---D").ChainDiffs({1, 2}).FrameDiffs({2});
73   return structure;
74 }
75 
76 std::vector<ScalableVideoController::LayerFrameConfig>
NextFrameConfig(bool restart)77 ScalabilityStructureL2T2KeyShift::NextFrameConfig(bool restart) {
78   std::vector<LayerFrameConfig> configs;
79   configs.reserve(2);
80   if (restart) {
81     next_pattern_ = kKey;
82   }
83 
84   // Buffer0 keeps latest S0T0 frame,
85   // Buffer1 keeps latest S1T0 frame.
86   switch (next_pattern_) {
87     case kKey:
88       if (DecodeTargetIsActive(/*sid=*/0, /*tid=*/0)) {
89         configs.emplace_back();
90         configs.back().S(0).T(0).Update(0).Keyframe();
91       }
92       if (DecodeTargetIsActive(/*sid=*/1, /*tid=*/0)) {
93         configs.emplace_back();
94         configs.back().S(1).T(0).Update(1);
95         if (DecodeTargetIsActive(/*sid=*/0, /*tid=*/0)) {
96           configs.back().Reference(0);
97         } else {
98           configs.back().Keyframe();
99         }
100       }
101       next_pattern_ = kDelta0;
102       break;
103     case kDelta0:
104       if (DecodeTargetIsActive(/*sid=*/0, /*tid=*/0)) {
105         configs.emplace_back();
106         configs.back().S(0).T(0).ReferenceAndUpdate(0);
107       }
108       if (DecodeTargetIsActive(/*sid=*/1, /*tid=*/1)) {
109         configs.emplace_back();
110         configs.back().S(1).T(1).Reference(1);
111       }
112       if (configs.empty() && DecodeTargetIsActive(/*sid=*/1, /*tid=*/0)) {
113         configs.emplace_back();
114         configs.back().S(1).T(0).ReferenceAndUpdate(1);
115       }
116       next_pattern_ = kDelta1;
117       break;
118     case kDelta1:
119       if (DecodeTargetIsActive(/*sid=*/0, /*tid=*/1)) {
120         configs.emplace_back();
121         configs.back().S(0).T(1).Reference(0);
122       }
123       if (DecodeTargetIsActive(/*sid=*/1, /*tid=*/0)) {
124         configs.emplace_back();
125         configs.back().S(1).T(0).ReferenceAndUpdate(1);
126       }
127       if (configs.empty() && DecodeTargetIsActive(/*sid=*/0, /*tid=*/0)) {
128         configs.emplace_back();
129         configs.back().S(0).T(0).ReferenceAndUpdate(0);
130       }
131       next_pattern_ = kDelta0;
132       break;
133   }
134 
135   RTC_DCHECK(!configs.empty() || active_decode_targets_.none());
136   return configs;
137 }
138 
OnEncodeDone(const LayerFrameConfig & config)139 GenericFrameInfo ScalabilityStructureL2T2KeyShift::OnEncodeDone(
140     const LayerFrameConfig& config) {
141   GenericFrameInfo frame_info;
142   frame_info.spatial_id = config.SpatialId();
143   frame_info.temporal_id = config.TemporalId();
144   frame_info.encoder_buffers = config.Buffers();
145   for (int sid = 0; sid < kNumSpatialLayers; ++sid) {
146     for (int tid = 0; tid < kNumTemporalLayers; ++tid) {
147       frame_info.decode_target_indications.push_back(Dti(sid, tid, config));
148     }
149   }
150   if (config.IsKeyframe()) {
151     frame_info.part_of_chain = {true, true};
152   } else if (config.TemporalId() == 0) {
153     frame_info.part_of_chain = {config.SpatialId() == 0,
154                                 config.SpatialId() == 1};
155   } else {
156     frame_info.part_of_chain = {false, false};
157   }
158   return frame_info;
159 }
160 
OnRatesUpdated(const VideoBitrateAllocation & bitrates)161 void ScalabilityStructureL2T2KeyShift::OnRatesUpdated(
162     const VideoBitrateAllocation& bitrates) {
163   for (int sid = 0; sid < kNumSpatialLayers; ++sid) {
164     // Enable/disable spatial layers independetely.
165     bool active = bitrates.GetBitrate(sid, /*tid=*/0) > 0;
166     if (!DecodeTargetIsActive(sid, /*tid=*/0) && active) {
167       // Key frame is required to reenable any spatial layer.
168       next_pattern_ = kKey;
169     }
170 
171     SetDecodeTargetIsActive(sid, /*tid=*/0, active);
172     SetDecodeTargetIsActive(sid, /*tid=*/1,
173                             active && bitrates.GetBitrate(sid, /*tid=*/1) > 0);
174   }
175 }
176 
177 }  // namespace webrtc
178