Handle scenario when dependency descriptor fails to attach to a key frame
Bug: chromium:1232358
Change-Id: I2c8a92fb3ac4ab981782077e29179ff2bece6c6c
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/226861
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34552}
diff --git a/modules/rtp_rtcp/source/rtp_sender_video.cc b/modules/rtp_rtcp/source/rtp_sender_video.cc
index bb9080f..fa9c5ad 100644
--- a/modules/rtp_rtcp/source/rtp_sender_video.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_video.cc
@@ -539,6 +539,18 @@
AddRtpHeaderExtensions(video_header, absolute_capture_time,
/*first_packet=*/true, /*last_packet=*/true,
single_packet.get());
+ if (video_structure_ != nullptr &&
+ single_packet->IsRegistered<RtpDependencyDescriptorExtension>() &&
+ !single_packet->HasExtension<RtpDependencyDescriptorExtension>()) {
+ RTC_DCHECK_EQ(video_header.frame_type, VideoFrameType::kVideoFrameKey);
+ // Disable attaching dependency descriptor to delta packets (including
+ // non-first packet of a key frame) when it wasn't attached to a key frame,
+ // as dependency descriptor can't be usable in such case.
+ RTC_LOG(LS_WARNING) << "Disable dependency descriptor because failed to "
+ "attach it to a key frame.";
+ video_structure_ = nullptr;
+ }
+
AddRtpHeaderExtensions(video_header, absolute_capture_time,
/*first_packet=*/true, /*last_packet=*/false,
first_packet.get());
diff --git a/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc b/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc
index ea72782..6f1c038 100644
--- a/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc
@@ -572,6 +572,60 @@
ElementsAre(1, 501));
}
+TEST_P(RtpSenderVideoTest,
+ SkipsDependencyDescriptorOnDeltaFrameWhenFailedToAttachToKeyFrame) {
+ const int64_t kFrameId = 100000;
+ uint8_t kFrame[100];
+ rtp_module_->RegisterRtpHeaderExtension(
+ RtpDependencyDescriptorExtension::kUri, kDependencyDescriptorId);
+ rtp_module_->SetExtmapAllowMixed(false);
+ FrameDependencyStructure video_structure;
+ video_structure.num_decode_targets = 2;
+ // Use many templates so that key dependency descriptor would be too large
+ // to fit into 16 bytes (max size of one byte header rtp header extension)
+ video_structure.templates = {
+ FrameDependencyTemplate().S(0).T(0).Dtis("SS"),
+ FrameDependencyTemplate().S(1).T(0).Dtis("-S"),
+ FrameDependencyTemplate().S(1).T(1).Dtis("-D").FrameDiffs({1, 2, 3, 4}),
+ FrameDependencyTemplate().S(1).T(1).Dtis("-D").FrameDiffs({2, 3, 4, 5}),
+ FrameDependencyTemplate().S(1).T(1).Dtis("-D").FrameDiffs({3, 4, 5, 6}),
+ FrameDependencyTemplate().S(1).T(1).Dtis("-D").FrameDiffs({4, 5, 6, 7}),
+ };
+ rtp_sender_video_->SetVideoStructure(&video_structure);
+
+ // Send key frame.
+ RTPVideoHeader hdr;
+ RTPVideoHeader::GenericDescriptorInfo& generic = hdr.generic.emplace();
+ generic.frame_id = kFrameId;
+ generic.temporal_index = 0;
+ generic.spatial_index = 0;
+ generic.decode_target_indications = {DecodeTargetIndication::kSwitch,
+ DecodeTargetIndication::kSwitch};
+ hdr.frame_type = VideoFrameType::kVideoFrameKey;
+ rtp_sender_video_->SendVideo(kPayload, kType, kTimestamp, 0, kFrame, hdr,
+ kDefaultExpectedRetransmissionTimeMs);
+
+ ASSERT_EQ(transport_.packets_sent(), 1);
+ DependencyDescriptor descriptor_key;
+ ASSERT_FALSE(transport_.last_sent_packet()
+ .HasExtension<RtpDependencyDescriptorExtension>());
+
+ // Send delta frame.
+ generic.frame_id = kFrameId + 1;
+ generic.temporal_index = 1;
+ generic.spatial_index = 1;
+ generic.dependencies = {kFrameId, kFrameId - 500};
+ generic.decode_target_indications = {DecodeTargetIndication::kNotPresent,
+ DecodeTargetIndication::kRequired};
+ hdr.frame_type = VideoFrameType::kVideoFrameDelta;
+ rtp_sender_video_->SendVideo(kPayload, kType, kTimestamp, 0, kFrame, hdr,
+ kDefaultExpectedRetransmissionTimeMs);
+
+ EXPECT_EQ(transport_.packets_sent(), 2);
+ EXPECT_FALSE(transport_.last_sent_packet()
+ .HasExtension<RtpDependencyDescriptorExtension>());
+}
+
TEST_P(RtpSenderVideoTest, PropagatesChainDiffsIntoDependencyDescriptor) {
const int64_t kFrameId = 100000;
uint8_t kFrame[100];