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