From f7448fb8829b7cd639cdd5a6928c51722b7f17bc Mon Sep 17 00:00:00 2001 From: Danil Chapovalov Date: Fri, 23 Jul 2021 15:06:36 +0200 Subject: [PATCH] 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 Commit-Queue: Danil Chapovalov Cr-Commit-Position: refs/heads/master@{#34552} --- modules/rtp_rtcp/source/rtp_sender_video.cc | 12 +++++ .../source/rtp_sender_video_unittest.cc | 54 +++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/modules/rtp_rtcp/source/rtp_sender_video.cc b/modules/rtp_rtcp/source/rtp_sender_video.cc index bb9080ff69..fa9c5ad8b1 100644 --- a/modules/rtp_rtcp/source/rtp_sender_video.cc +++ b/modules/rtp_rtcp/source/rtp_sender_video.cc @@ -539,6 +539,18 @@ bool RTPSenderVideo::SendVideo( AddRtpHeaderExtensions(video_header, absolute_capture_time, /*first_packet=*/true, /*last_packet=*/true, single_packet.get()); + if (video_structure_ != nullptr && + single_packet->IsRegistered() && + !single_packet->HasExtension()) { + 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 ea727828cc..6f1c038f7b 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 @@ TEST_P(RtpSenderVideoTest, SendsDependencyDescriptorWhenVideoStructureIsSet) { 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()); + + // 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()); +} + TEST_P(RtpSenderVideoTest, PropagatesChainDiffsIntoDependencyDescriptor) { const int64_t kFrameId = 100000; uint8_t kFrame[100];