diff --git a/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/modules/rtp_rtcp/source/rtp_sender_unittest.cc index 3c7a6d2df5..ce8d0fab02 100644 --- a/modules/rtp_rtcp/source/rtp_sender_unittest.cc +++ b/modules/rtp_rtcp/source/rtp_sender_unittest.cc @@ -67,6 +67,7 @@ using ::testing::_; using ::testing::ElementsAre; using ::testing::ElementsAreArray; using ::testing::Invoke; +using ::testing::SizeIs; uint64_t ConvertMsToAbsSendTime(int64_t time_ms) { return (((time_ms << 18) + 500) / 1000) & 0x00ffffff; @@ -2052,6 +2053,32 @@ TEST_P(RtpSenderVideoTest, PopulateGenericFrameDescriptor) { EXPECT_EQ(spatial_bitmask, descriptor_wire.SpatialLayersBitmask()); } +TEST_P(RtpSenderVideoTest, + UsesMinimalVp8DescriptorWhenGenericFrameDescriptorExtensionIsUsed) { + const int64_t kFrameId = 100000; + const size_t kFrameSize = 100; + uint8_t kFrame[kFrameSize]; + ASSERT_TRUE(rtp_sender_->RegisterRtpHeaderExtension( + RtpGenericFrameDescriptorExtension::kUri, kGenericDescriptorId)); + + RTPVideoHeader hdr; + hdr.codec = kVideoCodecVP8; + RTPVideoHeaderVP8& vp8 = hdr.video_type_header.emplace(); + vp8.pictureId = kFrameId % 0X7FFF; + vp8.tl0PicIdx = 13; + vp8.temporalIdx = 1; + vp8.keyIdx = 2; + RTPVideoHeader::GenericDescriptorInfo& generic = hdr.generic.emplace(); + generic.frame_id = kFrameId; + rtp_sender_video_->SendVideo(kVideoCodecVP8, kVideoFrameDelta, kPayload, + kTimestamp, 0, kFrame, sizeof(kFrame), nullptr, + &hdr, kDefaultExpectedRetransmissionTimeMs); + + ASSERT_THAT(transport_.sent_packets_, SizeIs(1)); + // Expect only minimal 1-byte vp8 descriptor was generated. + EXPECT_THAT(transport_.sent_packets_[0].payload_size(), 1 + kFrameSize); +} + TEST_P(RtpSenderTest, OnOverheadChanged) { MockOverheadObserver mock_overhead_observer; rtp_sender_.reset(new RTPSender( diff --git a/modules/rtp_rtcp/source/rtp_sender_video.cc b/modules/rtp_rtcp/source/rtp_sender_video.cc index 8f69dda9b5..e8f0ea5c8d 100644 --- a/modules/rtp_rtcp/source/rtp_sender_video.cc +++ b/modules/rtp_rtcp/source/rtp_sender_video.cc @@ -97,6 +97,20 @@ void AddRtpHeaderExtensions(const RTPVideoHeader& video_header, } } +bool MinimizeDescriptor(const RTPVideoHeader& full, RTPVideoHeader* minimized) { + if (full.codec == VideoCodecType::kVideoCodecVP8) { + minimized->codec = VideoCodecType::kVideoCodecVP8; + const auto& vp8 = absl::get(full.video_type_header); + // Set minimum fields the RtpPacketizer is using to create vp8 packets. + auto& min_vp8 = minimized->video_type_header.emplace(); + min_vp8.InitRTPVideoHeaderVP8(); + min_vp8.nonReference = vp8.nonReference; + return true; + } + // TODO(danilchap): Reduce vp9 codec specific descriptor too. + return false; +} + } // namespace RTPSenderVideo::RTPSenderVideo(Clock* clock, @@ -408,9 +422,16 @@ bool RTPSenderVideo::SendVideo(enum VideoCodecType video_type, limits.last_packet_reduction_len = last_packet->headers_size() - middle_packet->headers_size(); + RTPVideoHeader minimized_video_header; + const RTPVideoHeader* packetize_video_header = video_header; + if (first_packet->HasExtension() && + MinimizeDescriptor(*video_header, &minimized_video_header)) { + packetize_video_header = &minimized_video_header; + } + std::unique_ptr packetizer = RtpPacketizer::Create( video_type, rtc::MakeArrayView(payload_data, payload_size), limits, - *video_header, frame_type, fragmentation); + *packetize_video_header, frame_type, fragmentation); const uint8_t temporal_id = GetTemporalId(*video_header); StorageType storage = GetStorageType(temporal_id, retransmission_settings,