xref: /aosp_15_r20/external/webrtc/modules/rtp_rtcp/source/rtp_dependency_descriptor_writer.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2019 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/rtp_rtcp/source/rtp_dependency_descriptor_writer.h"
11 
12 #include <bitset>
13 #include <cstddef>
14 #include <cstdint>
15 #include <iterator>
16 #include <vector>
17 
18 #include "absl/algorithm/container.h"
19 #include "api/array_view.h"
20 #include "api/transport/rtp/dependency_descriptor.h"
21 #include "rtc_base/bit_buffer.h"
22 #include "rtc_base/checks.h"
23 
24 namespace webrtc {
25 namespace {
26 
27 enum class NextLayerIdc : uint64_t {
28   kSameLayer = 0,
29   kNextTemporal = 1,
30   kNewSpatial = 2,
31   kNoMoreLayers = 3,
32   kInvalid = 4
33 };
34 
GetNextLayerIdc(const FrameDependencyTemplate & previous,const FrameDependencyTemplate & next)35 NextLayerIdc GetNextLayerIdc(const FrameDependencyTemplate& previous,
36                              const FrameDependencyTemplate& next) {
37   RTC_DCHECK_LT(next.spatial_id, DependencyDescriptor::kMaxSpatialIds);
38   RTC_DCHECK_LT(next.temporal_id, DependencyDescriptor::kMaxTemporalIds);
39 
40   if (next.spatial_id == previous.spatial_id &&
41       next.temporal_id == previous.temporal_id) {
42     return NextLayerIdc::kSameLayer;
43   } else if (next.spatial_id == previous.spatial_id &&
44              next.temporal_id == previous.temporal_id + 1) {
45     return NextLayerIdc::kNextTemporal;
46   } else if (next.spatial_id == previous.spatial_id + 1 &&
47              next.temporal_id == 0) {
48     return NextLayerIdc::kNewSpatial;
49   }
50   // Everything else is unsupported.
51   return NextLayerIdc::kInvalid;
52 }
53 
54 }  // namespace
55 
RtpDependencyDescriptorWriter(rtc::ArrayView<uint8_t> data,const FrameDependencyStructure & structure,std::bitset<32> active_chains,const DependencyDescriptor & descriptor)56 RtpDependencyDescriptorWriter::RtpDependencyDescriptorWriter(
57     rtc::ArrayView<uint8_t> data,
58     const FrameDependencyStructure& structure,
59     std::bitset<32> active_chains,
60     const DependencyDescriptor& descriptor)
61     : descriptor_(descriptor),
62       structure_(structure),
63       active_chains_(active_chains),
64       bit_writer_(data.data(), data.size()) {
65   FindBestTemplate();
66 }
67 
Write()68 bool RtpDependencyDescriptorWriter::Write() {
69   if (build_failed_) {
70     return false;
71   }
72   WriteMandatoryFields();
73   if (HasExtendedFields()) {
74     WriteExtendedFields();
75     WriteFrameDependencyDefinition();
76   }
77   size_t remaining_bits = bit_writer_.RemainingBitCount();
78   // Zero remaining memory to avoid leaving it uninitialized.
79   if (remaining_bits % 64 != 0) {
80     WriteBits(/*val=*/0, remaining_bits % 64);
81   }
82   for (size_t i = 0; i < remaining_bits / 64; ++i) {
83     WriteBits(/*val=*/0, 64);
84   }
85   return !build_failed_;
86 }
87 
ValueSizeBits() const88 int RtpDependencyDescriptorWriter::ValueSizeBits() const {
89   if (build_failed_) {
90     return 0;
91   }
92   static constexpr int kMandatoryFields = 1 + 1 + 6 + 16;
93   int value_size_bits = kMandatoryFields + best_template_.extra_size_bits;
94   if (HasExtendedFields()) {
95     value_size_bits += 5;
96     if (descriptor_.attached_structure)
97       value_size_bits += StructureSizeBits();
98     if (ShouldWriteActiveDecodeTargetsBitmask())
99       value_size_bits += structure_.num_decode_targets;
100   }
101   return value_size_bits;
102 }
103 
StructureSizeBits() const104 int RtpDependencyDescriptorWriter::StructureSizeBits() const {
105   // template_id offset (6 bits) and number of decode targets (5 bits)
106   int bits = 11;
107   // template layers.
108   bits += 2 * structure_.templates.size();
109   // dtis.
110   bits += 2 * structure_.templates.size() * structure_.num_decode_targets;
111   // fdiffs. each templates uses 1 + 5 * sizeof(fdiff) bits.
112   bits += structure_.templates.size();
113   for (const FrameDependencyTemplate& frame_template : structure_.templates) {
114     bits += 5 * frame_template.frame_diffs.size();
115   }
116   bits += rtc::BitBufferWriter::SizeNonSymmetricBits(
117       structure_.num_chains, structure_.num_decode_targets + 1);
118   if (structure_.num_chains > 0) {
119     for (int protected_by : structure_.decode_target_protected_by_chain) {
120       bits += rtc::BitBufferWriter::SizeNonSymmetricBits(protected_by,
121                                                          structure_.num_chains);
122     }
123     bits += 4 * structure_.templates.size() * structure_.num_chains;
124   }
125   // Resolutions.
126   bits += 1 + 32 * structure_.resolutions.size();
127   return bits;
128 }
129 
130 RtpDependencyDescriptorWriter::TemplateMatch
CalculateMatch(TemplateIterator frame_template) const131 RtpDependencyDescriptorWriter::CalculateMatch(
132     TemplateIterator frame_template) const {
133   TemplateMatch result;
134   result.template_position = frame_template;
135   result.need_custom_fdiffs =
136       descriptor_.frame_dependencies.frame_diffs != frame_template->frame_diffs;
137   result.need_custom_dtis =
138       descriptor_.frame_dependencies.decode_target_indications !=
139       frame_template->decode_target_indications;
140   result.need_custom_chains = false;
141   for (int i = 0; i < structure_.num_chains; ++i) {
142     if (active_chains_[i] && descriptor_.frame_dependencies.chain_diffs[i] !=
143                                  frame_template->chain_diffs[i]) {
144       result.need_custom_chains = true;
145       break;
146     }
147   }
148 
149   result.extra_size_bits = 0;
150   if (result.need_custom_fdiffs) {
151     result.extra_size_bits +=
152         2 * (1 + descriptor_.frame_dependencies.frame_diffs.size());
153     for (int fdiff : descriptor_.frame_dependencies.frame_diffs) {
154       if (fdiff <= (1 << 4))
155         result.extra_size_bits += 4;
156       else if (fdiff <= (1 << 8))
157         result.extra_size_bits += 8;
158       else
159         result.extra_size_bits += 12;
160     }
161   }
162   if (result.need_custom_dtis) {
163     result.extra_size_bits +=
164         2 * descriptor_.frame_dependencies.decode_target_indications.size();
165   }
166   if (result.need_custom_chains)
167     result.extra_size_bits += 8 * structure_.num_chains;
168   return result;
169 }
170 
FindBestTemplate()171 void RtpDependencyDescriptorWriter::FindBestTemplate() {
172   const std::vector<FrameDependencyTemplate>& templates = structure_.templates;
173   // Find range of templates with matching spatial/temporal id.
174   auto same_layer = [&](const FrameDependencyTemplate& frame_template) {
175     return descriptor_.frame_dependencies.spatial_id ==
176                frame_template.spatial_id &&
177            descriptor_.frame_dependencies.temporal_id ==
178                frame_template.temporal_id;
179   };
180   auto first = absl::c_find_if(templates, same_layer);
181   if (first == templates.end()) {
182     build_failed_ = true;
183     return;
184   }
185   auto last = std::find_if_not(first, templates.end(), same_layer);
186 
187   best_template_ = CalculateMatch(first);
188   // Search if there any better template than the first one.
189   for (auto next = std::next(first); next != last; ++next) {
190     TemplateMatch match = CalculateMatch(next);
191     if (match.extra_size_bits < best_template_.extra_size_bits)
192       best_template_ = match;
193   }
194 }
195 
ShouldWriteActiveDecodeTargetsBitmask() const196 bool RtpDependencyDescriptorWriter::ShouldWriteActiveDecodeTargetsBitmask()
197     const {
198   if (!descriptor_.active_decode_targets_bitmask)
199     return false;
200   const uint64_t all_decode_targets_bitmask =
201       (uint64_t{1} << structure_.num_decode_targets) - 1;
202   if (descriptor_.attached_structure &&
203       descriptor_.active_decode_targets_bitmask == all_decode_targets_bitmask)
204     return false;
205   return true;
206 }
207 
HasExtendedFields() const208 bool RtpDependencyDescriptorWriter::HasExtendedFields() const {
209   return best_template_.extra_size_bits > 0 || descriptor_.attached_structure ||
210          descriptor_.active_decode_targets_bitmask;
211 }
212 
TemplateId() const213 uint64_t RtpDependencyDescriptorWriter::TemplateId() const {
214   return (best_template_.template_position - structure_.templates.begin() +
215           structure_.structure_id) %
216          DependencyDescriptor::kMaxTemplates;
217 }
218 
WriteBits(uint64_t val,size_t bit_count)219 void RtpDependencyDescriptorWriter::WriteBits(uint64_t val, size_t bit_count) {
220   if (!bit_writer_.WriteBits(val, bit_count))
221     build_failed_ = true;
222 }
223 
WriteNonSymmetric(uint32_t value,uint32_t num_values)224 void RtpDependencyDescriptorWriter::WriteNonSymmetric(uint32_t value,
225                                                       uint32_t num_values) {
226   if (!bit_writer_.WriteNonSymmetric(value, num_values))
227     build_failed_ = true;
228 }
229 
WriteTemplateDependencyStructure()230 void RtpDependencyDescriptorWriter::WriteTemplateDependencyStructure() {
231   RTC_DCHECK_GE(structure_.structure_id, 0);
232   RTC_DCHECK_LT(structure_.structure_id, DependencyDescriptor::kMaxTemplates);
233   RTC_DCHECK_GT(structure_.num_decode_targets, 0);
234   RTC_DCHECK_LE(structure_.num_decode_targets,
235                 DependencyDescriptor::kMaxDecodeTargets);
236 
237   WriteBits(structure_.structure_id, 6);
238   WriteBits(structure_.num_decode_targets - 1, 5);
239   WriteTemplateLayers();
240   WriteTemplateDtis();
241   WriteTemplateFdiffs();
242   WriteTemplateChains();
243   uint64_t has_resolutions = structure_.resolutions.empty() ? 0 : 1;
244   WriteBits(has_resolutions, 1);
245   if (has_resolutions)
246     WriteResolutions();
247 }
248 
WriteTemplateLayers()249 void RtpDependencyDescriptorWriter::WriteTemplateLayers() {
250   const auto& templates = structure_.templates;
251   RTC_DCHECK(!templates.empty());
252   RTC_DCHECK_LE(templates.size(), DependencyDescriptor::kMaxTemplates);
253   RTC_DCHECK_EQ(templates[0].spatial_id, 0);
254   RTC_DCHECK_EQ(templates[0].temporal_id, 0);
255 
256   for (size_t i = 1; i < templates.size(); ++i) {
257     uint64_t next_layer_idc =
258         static_cast<uint64_t>(GetNextLayerIdc(templates[i - 1], templates[i]));
259     RTC_DCHECK_LE(next_layer_idc, 3);
260     WriteBits(next_layer_idc, 2);
261   }
262   WriteBits(static_cast<uint64_t>(NextLayerIdc::kNoMoreLayers), 2);
263 }
264 
WriteTemplateDtis()265 void RtpDependencyDescriptorWriter::WriteTemplateDtis() {
266   for (const FrameDependencyTemplate& current_template : structure_.templates) {
267     RTC_DCHECK_EQ(current_template.decode_target_indications.size(),
268                   structure_.num_decode_targets);
269     for (DecodeTargetIndication dti :
270          current_template.decode_target_indications) {
271       WriteBits(static_cast<uint32_t>(dti), 2);
272     }
273   }
274 }
275 
WriteTemplateFdiffs()276 void RtpDependencyDescriptorWriter::WriteTemplateFdiffs() {
277   for (const FrameDependencyTemplate& current_template : structure_.templates) {
278     for (int fdiff : current_template.frame_diffs) {
279       RTC_DCHECK_GE(fdiff - 1, 0);
280       RTC_DCHECK_LT(fdiff - 1, 1 << 4);
281       WriteBits((1u << 4) | (fdiff - 1), 1 + 4);
282     }
283     // No more diffs for current template.
284     WriteBits(/*val=*/0, /*bit_count=*/1);
285   }
286 }
287 
WriteTemplateChains()288 void RtpDependencyDescriptorWriter::WriteTemplateChains() {
289   RTC_DCHECK_GE(structure_.num_chains, 0);
290   RTC_DCHECK_LE(structure_.num_chains, structure_.num_decode_targets);
291 
292   WriteNonSymmetric(structure_.num_chains, structure_.num_decode_targets + 1);
293   if (structure_.num_chains == 0)
294     return;
295 
296   RTC_DCHECK_EQ(structure_.decode_target_protected_by_chain.size(),
297                 structure_.num_decode_targets);
298   for (int protected_by : structure_.decode_target_protected_by_chain) {
299     RTC_DCHECK_GE(protected_by, 0);
300     RTC_DCHECK_LT(protected_by, structure_.num_chains);
301     WriteNonSymmetric(protected_by, structure_.num_chains);
302   }
303   for (const auto& frame_template : structure_.templates) {
304     RTC_DCHECK_EQ(frame_template.chain_diffs.size(), structure_.num_chains);
305     for (int chain_diff : frame_template.chain_diffs) {
306       RTC_DCHECK_GE(chain_diff, 0);
307       RTC_DCHECK_LT(chain_diff, 1 << 4);
308       WriteBits(chain_diff, 4);
309     }
310   }
311 }
312 
WriteResolutions()313 void RtpDependencyDescriptorWriter::WriteResolutions() {
314   int max_spatial_id = structure_.templates.back().spatial_id;
315   RTC_DCHECK_EQ(structure_.resolutions.size(), max_spatial_id + 1);
316   for (const RenderResolution& resolution : structure_.resolutions) {
317     RTC_DCHECK_GT(resolution.Width(), 0);
318     RTC_DCHECK_LE(resolution.Width(), 1 << 16);
319     RTC_DCHECK_GT(resolution.Height(), 0);
320     RTC_DCHECK_LE(resolution.Height(), 1 << 16);
321 
322     WriteBits(resolution.Width() - 1, 16);
323     WriteBits(resolution.Height() - 1, 16);
324   }
325 }
326 
WriteMandatoryFields()327 void RtpDependencyDescriptorWriter::WriteMandatoryFields() {
328   WriteBits(descriptor_.first_packet_in_frame, 1);
329   WriteBits(descriptor_.last_packet_in_frame, 1);
330   WriteBits(TemplateId(), 6);
331   WriteBits(descriptor_.frame_number, 16);
332 }
333 
WriteExtendedFields()334 void RtpDependencyDescriptorWriter::WriteExtendedFields() {
335   uint64_t template_dependency_structure_present_flag =
336       descriptor_.attached_structure ? 1u : 0u;
337   WriteBits(template_dependency_structure_present_flag, 1);
338   uint64_t active_decode_targets_present_flag =
339       ShouldWriteActiveDecodeTargetsBitmask() ? 1u : 0u;
340   WriteBits(active_decode_targets_present_flag, 1);
341   WriteBits(best_template_.need_custom_dtis, 1);
342   WriteBits(best_template_.need_custom_fdiffs, 1);
343   WriteBits(best_template_.need_custom_chains, 1);
344   if (template_dependency_structure_present_flag)
345     WriteTemplateDependencyStructure();
346   if (active_decode_targets_present_flag)
347     WriteBits(*descriptor_.active_decode_targets_bitmask,
348               structure_.num_decode_targets);
349 }
350 
WriteFrameDependencyDefinition()351 void RtpDependencyDescriptorWriter::WriteFrameDependencyDefinition() {
352   if (best_template_.need_custom_dtis)
353     WriteFrameDtis();
354   if (best_template_.need_custom_fdiffs)
355     WriteFrameFdiffs();
356   if (best_template_.need_custom_chains)
357     WriteFrameChains();
358 }
359 
WriteFrameDtis()360 void RtpDependencyDescriptorWriter::WriteFrameDtis() {
361   RTC_DCHECK_EQ(descriptor_.frame_dependencies.decode_target_indications.size(),
362                 structure_.num_decode_targets);
363   for (DecodeTargetIndication dti :
364        descriptor_.frame_dependencies.decode_target_indications) {
365     WriteBits(static_cast<uint32_t>(dti), 2);
366   }
367 }
368 
WriteFrameFdiffs()369 void RtpDependencyDescriptorWriter::WriteFrameFdiffs() {
370   for (int fdiff : descriptor_.frame_dependencies.frame_diffs) {
371     RTC_DCHECK_GT(fdiff, 0);
372     RTC_DCHECK_LE(fdiff, 1 << 12);
373     if (fdiff <= (1 << 4))
374       WriteBits((1u << 4) | (fdiff - 1), 2 + 4);
375     else if (fdiff <= (1 << 8))
376       WriteBits((2u << 8) | (fdiff - 1), 2 + 8);
377     else  // fdiff <= (1 << 12)
378       WriteBits((3u << 12) | (fdiff - 1), 2 + 12);
379   }
380   // No more diffs.
381   WriteBits(/*val=*/0, /*bit_count=*/2);
382 }
383 
WriteFrameChains()384 void RtpDependencyDescriptorWriter::WriteFrameChains() {
385   RTC_DCHECK_EQ(descriptor_.frame_dependencies.chain_diffs.size(),
386                 structure_.num_chains);
387   for (int i = 0; i < structure_.num_chains; ++i) {
388     int chain_diff =
389         active_chains_[i] ? descriptor_.frame_dependencies.chain_diffs[i] : 0;
390     RTC_DCHECK_GE(chain_diff, 0);
391     RTC_DCHECK_LT(chain_diff, 1 << 8);
392     WriteBits(chain_diff, 8);
393   }
394 }
395 
396 }  // namespace webrtc
397