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