/* * 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 #include #include #include "api/transport/rtp/dependency_descriptor.h" #include "rtc_base/bit_buffer.h" #include "rtc_base/checks.h" namespace webrtc { RtpDependencyDescriptorReader::RtpDependencyDescriptorReader( rtc::ArrayView 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(); 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 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(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(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(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