• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   WriteMandatoryFields();
70   if (HasExtendedFields()) {
71     WriteExtendedFields();
72     WriteFrameDependencyDefinition();
73   }
74   size_t remaining_bits = bit_writer_.RemainingBitCount();
75   // Zero remaining memory to avoid leaving it uninitialized.
76   if (remaining_bits % 64 != 0) {
77     WriteBits(/*val=*/0, remaining_bits % 64);
78   }
79   for (size_t i = 0; i < remaining_bits / 64; ++i) {
80     WriteBits(/*val=*/0, 64);
81   }
82   return !build_failed_;
83 }
84 
ValueSizeBits() const85 int RtpDependencyDescriptorWriter::ValueSizeBits() const {
86   static constexpr int kMandatoryFields = 1 + 1 + 6 + 16;
87   int value_size_bits = kMandatoryFields + best_template_.extra_size_bits;
88   if (HasExtendedFields()) {
89     value_size_bits += 5;
90     if (descriptor_.attached_structure)
91       value_size_bits += StructureSizeBits();
92     if (ShouldWriteActiveDecodeTargetsBitmask())
93       value_size_bits += structure_.num_decode_targets;
94   }
95   return value_size_bits;
96 }
97 
StructureSizeBits() const98 int RtpDependencyDescriptorWriter::StructureSizeBits() const {
99   // template_id offset (6 bits) and number of decode targets (5 bits)
100   int bits = 11;
101   // template layers.
102   bits += 2 * structure_.templates.size();
103   // dtis.
104   bits += 2 * structure_.templates.size() * structure_.num_decode_targets;
105   // fdiffs. each templates uses 1 + 5 * sizeof(fdiff) bits.
106   bits += structure_.templates.size();
107   for (const FrameDependencyTemplate& frame_template : structure_.templates) {
108     bits += 5 * frame_template.frame_diffs.size();
109   }
110   bits += rtc::BitBufferWriter::SizeNonSymmetricBits(
111       structure_.num_chains, structure_.num_decode_targets + 1);
112   if (structure_.num_chains > 0) {
113     for (int protected_by : structure_.decode_target_protected_by_chain) {
114       bits += rtc::BitBufferWriter::SizeNonSymmetricBits(protected_by,
115                                                          structure_.num_chains);
116     }
117     bits += 4 * structure_.templates.size() * structure_.num_chains;
118   }
119   // Resolutions.
120   bits += 1 + 32 * structure_.resolutions.size();
121   return bits;
122 }
123 
124 RtpDependencyDescriptorWriter::TemplateMatch
CalculateMatch(TemplateIterator frame_template) const125 RtpDependencyDescriptorWriter::CalculateMatch(
126     TemplateIterator frame_template) const {
127   TemplateMatch result;
128   result.template_position = frame_template;
129   result.need_custom_fdiffs =
130       descriptor_.frame_dependencies.frame_diffs != frame_template->frame_diffs;
131   result.need_custom_dtis =
132       descriptor_.frame_dependencies.decode_target_indications !=
133       frame_template->decode_target_indications;
134   result.need_custom_chains = false;
135   for (int i = 0; i < structure_.num_chains; ++i) {
136     if (active_chains_[i] && descriptor_.frame_dependencies.chain_diffs[i] !=
137                                  frame_template->chain_diffs[i]) {
138       result.need_custom_chains = true;
139       break;
140     }
141   }
142 
143   result.extra_size_bits = 0;
144   if (result.need_custom_fdiffs) {
145     result.extra_size_bits +=
146         2 * (1 + descriptor_.frame_dependencies.frame_diffs.size());
147     for (int fdiff : descriptor_.frame_dependencies.frame_diffs) {
148       if (fdiff <= (1 << 4))
149         result.extra_size_bits += 4;
150       else if (fdiff <= (1 << 8))
151         result.extra_size_bits += 8;
152       else
153         result.extra_size_bits += 12;
154     }
155   }
156   if (result.need_custom_dtis) {
157     result.extra_size_bits +=
158         2 * descriptor_.frame_dependencies.decode_target_indications.size();
159   }
160   if (result.need_custom_chains)
161     result.extra_size_bits += 8 * structure_.num_chains;
162   return result;
163 }
164 
FindBestTemplate()165 void RtpDependencyDescriptorWriter::FindBestTemplate() {
166   const std::vector<FrameDependencyTemplate>& templates = structure_.templates;
167   // Find range of templates with matching spatial/temporal id.
168   auto same_layer = [&](const FrameDependencyTemplate& frame_template) {
169     return descriptor_.frame_dependencies.spatial_id ==
170                frame_template.spatial_id &&
171            descriptor_.frame_dependencies.temporal_id ==
172                frame_template.temporal_id;
173   };
174   auto first = absl::c_find_if(templates, same_layer);
175   RTC_CHECK(first != templates.end());
176   auto last = std::find_if_not(first, templates.end(), same_layer);
177 
178   best_template_ = CalculateMatch(first);
179   // Search if there any better template than the first one.
180   for (auto next = std::next(first); next != last; ++next) {
181     TemplateMatch match = CalculateMatch(next);
182     if (match.extra_size_bits < best_template_.extra_size_bits)
183       best_template_ = match;
184   }
185 }
186 
ShouldWriteActiveDecodeTargetsBitmask() const187 bool RtpDependencyDescriptorWriter::ShouldWriteActiveDecodeTargetsBitmask()
188     const {
189   if (!descriptor_.active_decode_targets_bitmask)
190     return false;
191   const uint64_t all_decode_targets_bitmask =
192       (uint64_t{1} << structure_.num_decode_targets) - 1;
193   if (descriptor_.attached_structure &&
194       descriptor_.active_decode_targets_bitmask == all_decode_targets_bitmask)
195     return false;
196   return true;
197 }
198 
HasExtendedFields() const199 bool RtpDependencyDescriptorWriter::HasExtendedFields() const {
200   return best_template_.extra_size_bits > 0 || descriptor_.attached_structure ||
201          descriptor_.active_decode_targets_bitmask;
202 }
203 
TemplateId() const204 uint64_t RtpDependencyDescriptorWriter::TemplateId() const {
205   return (best_template_.template_position - structure_.templates.begin() +
206           structure_.structure_id) %
207          DependencyDescriptor::kMaxTemplates;
208 }
209 
WriteBits(uint64_t val,size_t bit_count)210 void RtpDependencyDescriptorWriter::WriteBits(uint64_t val, size_t bit_count) {
211   if (!bit_writer_.WriteBits(val, bit_count))
212     build_failed_ = true;
213 }
214 
WriteNonSymmetric(uint32_t value,uint32_t num_values)215 void RtpDependencyDescriptorWriter::WriteNonSymmetric(uint32_t value,
216                                                       uint32_t num_values) {
217   if (!bit_writer_.WriteNonSymmetric(value, num_values))
218     build_failed_ = true;
219 }
220 
WriteTemplateDependencyStructure()221 void RtpDependencyDescriptorWriter::WriteTemplateDependencyStructure() {
222   RTC_DCHECK_GE(structure_.structure_id, 0);
223   RTC_DCHECK_LT(structure_.structure_id, DependencyDescriptor::kMaxTemplates);
224   RTC_DCHECK_GT(structure_.num_decode_targets, 0);
225   RTC_DCHECK_LE(structure_.num_decode_targets,
226                 DependencyDescriptor::kMaxDecodeTargets);
227 
228   WriteBits(structure_.structure_id, 6);
229   WriteBits(structure_.num_decode_targets - 1, 5);
230   WriteTemplateLayers();
231   WriteTemplateDtis();
232   WriteTemplateFdiffs();
233   WriteTemplateChains();
234   uint64_t has_resolutions = structure_.resolutions.empty() ? 0 : 1;
235   WriteBits(has_resolutions, 1);
236   if (has_resolutions)
237     WriteResolutions();
238 }
239 
WriteTemplateLayers()240 void RtpDependencyDescriptorWriter::WriteTemplateLayers() {
241   const auto& templates = structure_.templates;
242   RTC_DCHECK(!templates.empty());
243   RTC_DCHECK_LE(templates.size(), DependencyDescriptor::kMaxTemplates);
244   RTC_DCHECK_EQ(templates[0].spatial_id, 0);
245   RTC_DCHECK_EQ(templates[0].temporal_id, 0);
246 
247   for (size_t i = 1; i < templates.size(); ++i) {
248     uint64_t next_layer_idc =
249         static_cast<uint64_t>(GetNextLayerIdc(templates[i - 1], templates[i]));
250     RTC_DCHECK_LE(next_layer_idc, 3);
251     WriteBits(next_layer_idc, 2);
252   }
253   WriteBits(static_cast<uint64_t>(NextLayerIdc::kNoMoreLayers), 2);
254 }
255 
WriteTemplateDtis()256 void RtpDependencyDescriptorWriter::WriteTemplateDtis() {
257   for (const FrameDependencyTemplate& current_template : structure_.templates) {
258     RTC_DCHECK_EQ(current_template.decode_target_indications.size(),
259                   structure_.num_decode_targets);
260     for (DecodeTargetIndication dti :
261          current_template.decode_target_indications) {
262       WriteBits(static_cast<uint32_t>(dti), 2);
263     }
264   }
265 }
266 
WriteTemplateFdiffs()267 void RtpDependencyDescriptorWriter::WriteTemplateFdiffs() {
268   for (const FrameDependencyTemplate& current_template : structure_.templates) {
269     for (int fdiff : current_template.frame_diffs) {
270       RTC_DCHECK_GE(fdiff - 1, 0);
271       RTC_DCHECK_LT(fdiff - 1, 1 << 4);
272       WriteBits((1u << 4) | (fdiff - 1), 1 + 4);
273     }
274     // No more diffs for current template.
275     WriteBits(/*val=*/0, /*bit_count=*/1);
276   }
277 }
278 
WriteTemplateChains()279 void RtpDependencyDescriptorWriter::WriteTemplateChains() {
280   RTC_DCHECK_GE(structure_.num_chains, 0);
281   RTC_DCHECK_LE(structure_.num_chains, structure_.num_decode_targets);
282 
283   WriteNonSymmetric(structure_.num_chains, structure_.num_decode_targets + 1);
284   if (structure_.num_chains == 0)
285     return;
286 
287   RTC_DCHECK_EQ(structure_.decode_target_protected_by_chain.size(),
288                 structure_.num_decode_targets);
289   for (int protected_by : structure_.decode_target_protected_by_chain) {
290     RTC_DCHECK_GE(protected_by, 0);
291     RTC_DCHECK_LT(protected_by, structure_.num_chains);
292     WriteNonSymmetric(protected_by, structure_.num_chains);
293   }
294   for (const auto& frame_template : structure_.templates) {
295     RTC_DCHECK_EQ(frame_template.chain_diffs.size(), structure_.num_chains);
296     for (int chain_diff : frame_template.chain_diffs) {
297       RTC_DCHECK_GE(chain_diff, 0);
298       RTC_DCHECK_LT(chain_diff, 1 << 4);
299       WriteBits(chain_diff, 4);
300     }
301   }
302 }
303 
WriteResolutions()304 void RtpDependencyDescriptorWriter::WriteResolutions() {
305   int max_spatial_id = structure_.templates.back().spatial_id;
306   RTC_DCHECK_EQ(structure_.resolutions.size(), max_spatial_id + 1);
307   for (const RenderResolution& resolution : structure_.resolutions) {
308     RTC_DCHECK_GT(resolution.Width(), 0);
309     RTC_DCHECK_LE(resolution.Width(), 1 << 16);
310     RTC_DCHECK_GT(resolution.Height(), 0);
311     RTC_DCHECK_LE(resolution.Height(), 1 << 16);
312 
313     WriteBits(resolution.Width() - 1, 16);
314     WriteBits(resolution.Height() - 1, 16);
315   }
316 }
317 
WriteMandatoryFields()318 void RtpDependencyDescriptorWriter::WriteMandatoryFields() {
319   WriteBits(descriptor_.first_packet_in_frame, 1);
320   WriteBits(descriptor_.last_packet_in_frame, 1);
321   WriteBits(TemplateId(), 6);
322   WriteBits(descriptor_.frame_number, 16);
323 }
324 
WriteExtendedFields()325 void RtpDependencyDescriptorWriter::WriteExtendedFields() {
326   uint64_t template_dependency_structure_present_flag =
327       descriptor_.attached_structure ? 1u : 0u;
328   WriteBits(template_dependency_structure_present_flag, 1);
329   uint64_t active_decode_targets_present_flag =
330       ShouldWriteActiveDecodeTargetsBitmask() ? 1u : 0u;
331   WriteBits(active_decode_targets_present_flag, 1);
332   WriteBits(best_template_.need_custom_dtis, 1);
333   WriteBits(best_template_.need_custom_fdiffs, 1);
334   WriteBits(best_template_.need_custom_chains, 1);
335   if (template_dependency_structure_present_flag)
336     WriteTemplateDependencyStructure();
337   if (active_decode_targets_present_flag)
338     WriteBits(*descriptor_.active_decode_targets_bitmask,
339               structure_.num_decode_targets);
340 }
341 
WriteFrameDependencyDefinition()342 void RtpDependencyDescriptorWriter::WriteFrameDependencyDefinition() {
343   if (best_template_.need_custom_dtis)
344     WriteFrameDtis();
345   if (best_template_.need_custom_fdiffs)
346     WriteFrameFdiffs();
347   if (best_template_.need_custom_chains)
348     WriteFrameChains();
349 }
350 
WriteFrameDtis()351 void RtpDependencyDescriptorWriter::WriteFrameDtis() {
352   RTC_DCHECK_EQ(descriptor_.frame_dependencies.decode_target_indications.size(),
353                 structure_.num_decode_targets);
354   for (DecodeTargetIndication dti :
355        descriptor_.frame_dependencies.decode_target_indications) {
356     WriteBits(static_cast<uint32_t>(dti), 2);
357   }
358 }
359 
WriteFrameFdiffs()360 void RtpDependencyDescriptorWriter::WriteFrameFdiffs() {
361   for (int fdiff : descriptor_.frame_dependencies.frame_diffs) {
362     RTC_DCHECK_GT(fdiff, 0);
363     RTC_DCHECK_LE(fdiff, 1 << 12);
364     if (fdiff <= (1 << 4))
365       WriteBits((1u << 4) | (fdiff - 1), 2 + 4);
366     else if (fdiff <= (1 << 8))
367       WriteBits((2u << 8) | (fdiff - 1), 2 + 8);
368     else  // fdiff <= (1 << 12)
369       WriteBits((3u << 12) | (fdiff - 1), 2 + 12);
370   }
371   // No more diffs.
372   WriteBits(/*val=*/0, /*bit_count=*/2);
373 }
374 
WriteFrameChains()375 void RtpDependencyDescriptorWriter::WriteFrameChains() {
376   RTC_DCHECK_EQ(descriptor_.frame_dependencies.chain_diffs.size(),
377                 structure_.num_chains);
378   for (int i = 0; i < structure_.num_chains; ++i) {
379     int chain_diff =
380         active_chains_[i] ? descriptor_.frame_dependencies.chain_diffs[i] : 0;
381     RTC_DCHECK_GE(chain_diff, 0);
382     RTC_DCHECK_LT(chain_diff, 1 << 8);
383     WriteBits(chain_diff, 8);
384   }
385 }
386 
387 }  // namespace webrtc
388