Validate frame consistency when writing DependencyDescriptor

To write DependencyDescriptor frame properties should be consistent with
the FrameDependencyStructure.
Historically that was ensured by webrtc codec wrappers, but with with frame transform api interface there are now more ways to inject video frame for packetizing.
Thus DependencyDescriptorWriter should be more protective to avoid crashes.

Bug: chromium:379282549
Change-Id: I98f226ff09c32154e18888c8e811e7981567ad45
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/371301
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#43551}
This commit is contained in:
Danil Chapovalov 2024-12-12 14:48:13 +01:00 committed by WebRTC LUCI CQ
parent 74ace1a6e3
commit 200fd82771
5 changed files with 61 additions and 1 deletions

View File

@ -483,6 +483,10 @@ void RtpPayloadParams::H264ToGeneric(const CodecSpecificInfoH264& h264_info,
temporal_index, DecodeTargetIndication::kNotPresent);
std::fill(it, generic.decode_target_indications.end(),
DecodeTargetIndication::kSwitch);
generic.chain_diffs = {
(is_keyframe || last_frame_id_[0][0] < 0)
? 0
: static_cast<int>(frame_id - last_frame_id_[0][0])};
if (is_keyframe) {
RTC_DCHECK_EQ(temporal_index, 0);

View File

@ -136,6 +136,7 @@ rtc_library("rtp_rtcp_format") {
"../../rtc_base:event_tracer",
"../../rtc_base:logging",
"../../rtc_base:macromagic",
"../../rtc_base:safe_compare",
"../../rtc_base:safe_conversions",
"../../rtc_base:stringutils",
"../../rtc_base/network:ecn_marking",

View File

@ -132,5 +132,48 @@ TEST(RtpDependencyDescriptorExtensionTest, FailsToWriteInvalidDescriptor) {
descriptor));
}
TEST(RtpDependencyDescriptorExtensionTest,
FailsToWriteWhenNumberOfChainsMismatch) {
uint8_t buffer[256];
FrameDependencyStructure structure;
structure.num_decode_targets = 2;
structure.num_chains = 2;
structure.templates = {
FrameDependencyTemplate().T(0).Dtis("SR").ChainDiffs({2, 2})};
DependencyDescriptor descriptor;
descriptor.frame_dependencies = structure.templates[0];
// Structure has 2 chains, but frame provide 1 chain diff,
descriptor.frame_dependencies.chain_diffs = {2};
EXPECT_EQ(
RtpDependencyDescriptorExtension::ValueSize(structure, 0b11, descriptor),
0u);
EXPECT_FALSE(RtpDependencyDescriptorExtension::Write(buffer, structure, 0b11,
descriptor));
}
TEST(RtpDependencyDescriptorExtensionTest,
FailsToWriteWhenNumberOfDecodeTargetsMismatch) {
uint8_t buffer[256];
FrameDependencyStructure structure;
structure.num_decode_targets = 2;
structure.num_chains = 2;
structure.templates = {
FrameDependencyTemplate().T(0).Dtis("SR").ChainDiffs({2, 2})};
DependencyDescriptor descriptor;
descriptor.frame_dependencies = structure.templates[0];
// Structure has 2 decode targets, but frame provide 1 indication,
descriptor.frame_dependencies.decode_target_indications = {
DecodeTargetIndication::kSwitch};
EXPECT_EQ(
RtpDependencyDescriptorExtension::ValueSize(structure, 0b11, descriptor),
0u);
EXPECT_FALSE(RtpDependencyDescriptorExtension::Write(buffer, structure, 0b11,
descriptor));
}
} // namespace
} // namespace webrtc

View File

@ -20,6 +20,7 @@
#include "api/transport/rtp/dependency_descriptor.h"
#include "rtc_base/bit_buffer.h"
#include "rtc_base/checks.h"
#include "rtc_base/numerics/safe_compare.h"
namespace webrtc {
namespace {
@ -62,6 +63,17 @@ RtpDependencyDescriptorWriter::RtpDependencyDescriptorWriter(
structure_(structure),
active_chains_(active_chains),
bit_writer_(data.data(), data.size()) {
if (rtc::SafeNe(descriptor.frame_dependencies.chain_diffs.size(),
structure_.num_chains)) {
build_failed_ = true;
return;
}
if (rtc::SafeNe(
descriptor.frame_dependencies.decode_target_indications.size(),
structure_.num_decode_targets)) {
build_failed_ = true;
return;
}
FindBestTemplate();
}

View File

@ -1308,7 +1308,7 @@ TEST_F(RtpVideoStreamReceiver2DependencyDescriptorTest, UnwrapsFrameId) {
deltaframe1_descriptor.frame_number = 0xfffe;
DependencyDescriptor deltaframe2_descriptor;
deltaframe1_descriptor.frame_dependencies = stream_structure.templates[1];
deltaframe2_descriptor.frame_dependencies = stream_structure.templates[1];
deltaframe2_descriptor.frame_number = 0x0002;
// Parser should unwrap frame ids correctly even if packets were reordered by