webrtc/modules/rtp_rtcp/source/rtp_dependency_descriptor_reader.cc
Danil Chapovalov a5d9c1a45c In DependencyDescriptor rtp header extension drop partial chain support
i.e. when chain are used,
require each decode target to be protected by some chain.
where previously it was allowed to mark decode target as unprotected.

See https://github.com/AOMediaCodec/av1-rtp-spec/pull/125

Bug: webrtc:10342
Change-Id: Ia2800036e890db44bb1162abfa1a497ff68f3b24
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/178807
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Reviewed-by: Björn Terelius <terelius@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31772}
2020-07-21 14:01:27 +00:00

252 lines
8.4 KiB
C++

/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "modules/rtp_rtcp/source/rtp_dependency_descriptor_reader.h"
#include <memory>
#include <utility>
#include <vector>
#include "api/transport/rtp/dependency_descriptor.h"
#include "rtc_base/bit_buffer.h"
#include "rtc_base/checks.h"
namespace webrtc {
RtpDependencyDescriptorReader::RtpDependencyDescriptorReader(
rtc::ArrayView<const uint8_t> raw_data,
const FrameDependencyStructure* structure,
DependencyDescriptor* descriptor)
: descriptor_(descriptor), buffer_(raw_data.data(), raw_data.size()) {
RTC_DCHECK(descriptor);
ReadMandatoryFields();
if (raw_data.size() > 3)
ReadExtendedFields();
structure_ = descriptor->attached_structure
? descriptor->attached_structure.get()
: structure;
if (structure_ == nullptr || parsing_failed_) {
parsing_failed_ = true;
return;
}
if (active_decode_targets_present_flag_) {
descriptor->active_decode_targets_bitmask =
ReadBits(structure_->num_decode_targets);
}
ReadFrameDependencyDefinition();
}
uint32_t RtpDependencyDescriptorReader::ReadBits(size_t bit_count) {
uint32_t value = 0;
if (!buffer_.ReadBits(&value, bit_count))
parsing_failed_ = true;
return value;
}
uint32_t RtpDependencyDescriptorReader::ReadNonSymmetric(size_t num_values) {
uint32_t value = 0;
if (!buffer_.ReadNonSymmetric(&value, num_values))
parsing_failed_ = true;
return value;
}
void RtpDependencyDescriptorReader::ReadTemplateDependencyStructure() {
descriptor_->attached_structure =
std::make_unique<FrameDependencyStructure>();
descriptor_->attached_structure->structure_id = ReadBits(6);
descriptor_->attached_structure->num_decode_targets = ReadBits(5) + 1;
ReadTemplateLayers();
ReadTemplateDtis();
ReadTemplateFdiffs();
ReadTemplateChains();
uint32_t has_resolutions = ReadBits(1);
if (has_resolutions)
ReadResolutions();
}
void RtpDependencyDescriptorReader::ReadTemplateLayers() {
enum NextLayerIdc : uint32_t {
kSameLayer = 0,
kNextTemporalLayer = 1,
kNextSpatialLayer = 2,
kNoMoreTemplates = 3,
};
std::vector<FrameDependencyTemplate> templates;
int temporal_id = 0;
int spatial_id = 0;
NextLayerIdc next_layer_idc;
do {
if (templates.size() == DependencyDescriptor::kMaxTemplates) {
parsing_failed_ = true;
break;
}
templates.emplace_back();
FrameDependencyTemplate& last_template = templates.back();
last_template.temporal_id = temporal_id;
last_template.spatial_id = spatial_id;
next_layer_idc = static_cast<NextLayerIdc>(ReadBits(2));
if (next_layer_idc == kNextTemporalLayer) {
temporal_id++;
if (temporal_id >= DependencyDescriptor::kMaxTemporalIds) {
parsing_failed_ = true;
break;
}
} else if (next_layer_idc == kNextSpatialLayer) {
temporal_id = 0;
spatial_id++;
if (spatial_id >= DependencyDescriptor::kMaxSpatialIds) {
parsing_failed_ = true;
break;
}
}
} while (next_layer_idc != kNoMoreTemplates && !parsing_failed_);
descriptor_->attached_structure->templates = std::move(templates);
}
void RtpDependencyDescriptorReader::ReadTemplateDtis() {
FrameDependencyStructure* structure = descriptor_->attached_structure.get();
for (FrameDependencyTemplate& current_template : structure->templates) {
current_template.decode_target_indications.resize(
structure->num_decode_targets);
for (int i = 0; i < structure->num_decode_targets; ++i) {
current_template.decode_target_indications[i] =
static_cast<DecodeTargetIndication>(ReadBits(2));
}
}
}
void RtpDependencyDescriptorReader::ReadTemplateFdiffs() {
for (FrameDependencyTemplate& current_template :
descriptor_->attached_structure->templates) {
for (uint32_t fdiff_follows = ReadBits(1); fdiff_follows;
fdiff_follows = ReadBits(1)) {
uint32_t fdiff_minus_one = ReadBits(4);
current_template.frame_diffs.push_back(fdiff_minus_one + 1);
}
}
}
void RtpDependencyDescriptorReader::ReadTemplateChains() {
FrameDependencyStructure* structure = descriptor_->attached_structure.get();
structure->num_chains = ReadNonSymmetric(structure->num_decode_targets + 1);
if (structure->num_chains == 0)
return;
for (int i = 0; i < structure->num_decode_targets; ++i) {
uint32_t protected_by_chain = ReadNonSymmetric(structure->num_chains);
structure->decode_target_protected_by_chain.push_back(protected_by_chain);
}
for (FrameDependencyTemplate& frame_template : structure->templates) {
for (int chain_id = 0; chain_id < structure->num_chains; ++chain_id) {
frame_template.chain_diffs.push_back(ReadBits(4));
}
}
}
void RtpDependencyDescriptorReader::ReadResolutions() {
FrameDependencyStructure* structure = descriptor_->attached_structure.get();
// The way templates are bitpacked, they are always ordered by spatial_id.
int spatial_layers = structure->templates.back().spatial_id + 1;
structure->resolutions.reserve(spatial_layers);
for (int sid = 0; sid < spatial_layers; ++sid) {
uint16_t width_minus_1 = ReadBits(16);
uint16_t height_minus_1 = ReadBits(16);
structure->resolutions.emplace_back(width_minus_1 + 1, height_minus_1 + 1);
}
}
void RtpDependencyDescriptorReader::ReadMandatoryFields() {
descriptor_->first_packet_in_frame = ReadBits(1);
descriptor_->last_packet_in_frame = ReadBits(1);
frame_dependency_template_id_ = ReadBits(6);
descriptor_->frame_number = ReadBits(16);
}
void RtpDependencyDescriptorReader::ReadExtendedFields() {
bool template_dependency_structure_present_flag = ReadBits(1);
active_decode_targets_present_flag_ = ReadBits(1);
custom_dtis_flag_ = ReadBits(1);
custom_fdiffs_flag_ = ReadBits(1);
custom_chains_flag_ = ReadBits(1);
if (template_dependency_structure_present_flag) {
ReadTemplateDependencyStructure();
RTC_DCHECK(descriptor_->attached_structure);
descriptor_->active_decode_targets_bitmask =
(uint64_t{1} << descriptor_->attached_structure->num_decode_targets) -
1;
}
}
void RtpDependencyDescriptorReader::ReadFrameDependencyDefinition() {
size_t template_index =
(frame_dependency_template_id_ + DependencyDescriptor::kMaxTemplates -
structure_->structure_id) %
DependencyDescriptor::kMaxTemplates;
if (template_index >= structure_->templates.size()) {
parsing_failed_ = true;
return;
}
// Copy all the fields from the matching template
descriptor_->frame_dependencies = structure_->templates[template_index];
if (custom_dtis_flag_)
ReadFrameDtis();
if (custom_fdiffs_flag_)
ReadFrameFdiffs();
if (custom_chains_flag_)
ReadFrameChains();
if (structure_->resolutions.empty()) {
descriptor_->resolution = absl::nullopt;
} else {
// Format guarantees that if there were resolutions in the last structure,
// then each spatial layer got one.
RTC_DCHECK_LE(descriptor_->frame_dependencies.spatial_id,
structure_->resolutions.size());
descriptor_->resolution =
structure_->resolutions[descriptor_->frame_dependencies.spatial_id];
}
}
void RtpDependencyDescriptorReader::ReadFrameDtis() {
RTC_DCHECK_EQ(
descriptor_->frame_dependencies.decode_target_indications.size(),
structure_->num_decode_targets);
for (auto& dti : descriptor_->frame_dependencies.decode_target_indications) {
dti = static_cast<DecodeTargetIndication>(ReadBits(2));
}
}
void RtpDependencyDescriptorReader::ReadFrameFdiffs() {
descriptor_->frame_dependencies.frame_diffs.clear();
for (uint32_t next_fdiff_size = ReadBits(2); next_fdiff_size > 0;
next_fdiff_size = ReadBits(2)) {
uint32_t fdiff_minus_one = ReadBits(4 * next_fdiff_size);
descriptor_->frame_dependencies.frame_diffs.push_back(fdiff_minus_one + 1);
}
}
void RtpDependencyDescriptorReader::ReadFrameChains() {
RTC_DCHECK_EQ(descriptor_->frame_dependencies.chain_diffs.size(),
structure_->num_chains);
for (auto& chain_diff : descriptor_->frame_dependencies.chain_diffs) {
chain_diff = ReadBits(8);
}
}
} // namespace webrtc