mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-14 22:30:40 +01:00

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}
252 lines
8.4 KiB
C++
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
|