Revert the deletion of WebRTC-VideoH26xPacketBuffer flag.
This unlaunches the experiment for H264 due to issues reported for H264
where the old packet buffer behaves better than the new one. A recently
introduced issue will be fixed separately from this CL and rollout
restarted.
This CL is not a clean revert though (see delta with PS#1):
we will continue to use the H26xPacketBuffer for the new codec H265
because it does not work with the old packet buffer anyway.
Bug: webrtc:41480904
Change-Id: Icac49fa70f1c78d1ed596a7838d1417f6588a8b4
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/380861
Reviewed-by: Evan Shrubsole <eshr@webrtc.org>
Reviewed-by: Jianlin Qiu <jianlin.qiu@intel.com>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#44104}
diff --git a/experiments/field_trials.py b/experiments/field_trials.py
index d9e46f3..df107e0 100755
--- a/experiments/field_trials.py
+++ b/experiments/field_trials.py
@@ -182,6 +182,9 @@
FieldTrial('WebRTC-ZeroHertzQueueOverload',
42225879,
date(2024, 7, 1)),
+ FieldTrial('WebRTC-Video-H26xPacketBuffer',
+ 41480904,
+ date(2024, 6, 1)),
FieldTrial('WebRTC-Video-Vp9FlexibleMode',
329396373,
date(2025, 6, 26)),
diff --git a/video/rtp_video_stream_receiver2.cc b/video/rtp_video_stream_receiver2.cc
index b23b04a..0474393 100644
--- a/video/rtp_video_stream_receiver2.cc
+++ b/video/rtp_video_stream_receiver2.cc
@@ -738,7 +738,7 @@
if (codec_payload.size() == 0) {
NotifyReceiverOfEmptyPacket(packet->seq_num(),
- IsH26xPayloadType(packet->payload_type));
+ GetCodecFromPayloadType(packet->payload_type));
rtcp_feedback_buffer_.SendBufferedRtcpFeedback();
return false;
}
@@ -753,7 +753,8 @@
}
}
- if (packet->codec() == kVideoCodecH264 && !h26x_packet_buffer_) {
+ if (packet->codec() == kVideoCodecH264 &&
+ !UseH26xPacketBuffer(packet->codec())) {
video_coding::H264SpsPpsTracker::FixedBitstream fixed =
tracker_.CopyAndFixBitstream(
rtc::MakeArrayView(codec_payload.cdata(), codec_payload.size()),
@@ -778,9 +779,7 @@
rtcp_feedback_buffer_.SendBufferedRtcpFeedback();
frame_counter_.Add(packet->timestamp);
- if ((packet->codec() == kVideoCodecH264 ||
- packet->codec() == kVideoCodecH265) &&
- h26x_packet_buffer_) {
+ if (h26x_packet_buffer_ && UseH26xPacketBuffer(packet->codec())) {
OnInsertedPacket(h26x_packet_buffer_->InsertPacket(std::move(packet)));
} else {
OnInsertedPacket(packet_buffer_.InsertPacket(std::move(packet)));
@@ -1170,13 +1169,26 @@
return rtp_rtcp_->GetSenderReportStats();
}
-bool RtpVideoStreamReceiver2::IsH26xPayloadType(uint8_t payload_type) const {
+std::optional<VideoCodecType> RtpVideoStreamReceiver2::GetCodecFromPayloadType(
+ uint8_t payload_type) const {
RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
auto it = pt_codec_.find(payload_type);
if (it == pt_codec_.end()) {
- return false;
+ return std::nullopt;
}
- return it->second == kVideoCodecH264 || it->second == kVideoCodecH265;
+ return it->second;
+}
+
+bool RtpVideoStreamReceiver2::UseH26xPacketBuffer(
+ std::optional<VideoCodecType> codec) const {
+ RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
+ if (codec == kVideoCodecH265) {
+ return true;
+ }
+ if (codec == kVideoCodecH264) {
+ return env_.field_trials().IsEnabled("WebRTC-Video-H26xPacketBuffer");
+ }
+ return false;
}
void RtpVideoStreamReceiver2::ManageFrame(
@@ -1193,7 +1205,7 @@
// TODO(nisse): Could drop empty packets earlier, but need to figure out how
// they should be counted in stats.
NotifyReceiverOfEmptyPacket(packet.SequenceNumber(),
- IsH26xPayloadType(packet.PayloadType()));
+ GetCodecFromPayloadType(packet.PayloadType()));
return;
}
if (packet.PayloadType() == red_payload_type_) {
@@ -1264,7 +1276,7 @@
// Notify video_receiver about received FEC packets to avoid NACKing these
// packets.
NotifyReceiverOfEmptyPacket(packet.SequenceNumber(),
- IsH26xPayloadType(packet.PayloadType()));
+ GetCodecFromPayloadType(packet.PayloadType()));
}
if (ulpfec_receiver_->AddReceivedRedPacket(packet)) {
ulpfec_receiver_->ProcessReceivedFec();
@@ -1274,14 +1286,15 @@
// In the case of a video stream without picture ids and no rtx the
// RtpFrameReferenceFinder will need to know about padding to
// correctly calculate frame references.
-void RtpVideoStreamReceiver2::NotifyReceiverOfEmptyPacket(uint16_t seq_num,
- bool is_h26x) {
+void RtpVideoStreamReceiver2::NotifyReceiverOfEmptyPacket(
+ uint16_t seq_num,
+ std::optional<VideoCodecType> codec) {
RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
RTC_DCHECK_RUN_ON(&worker_task_checker_);
OnCompleteFrames(reference_finder_->PaddingReceived(seq_num));
- if (is_h26x && h26x_packet_buffer_) {
+ if (h26x_packet_buffer_ && UseH26xPacketBuffer(codec)) {
OnInsertedPacket(h26x_packet_buffer_->InsertPadding(seq_num));
} else {
OnInsertedPacket(packet_buffer_.InsertPadding(seq_num));
@@ -1428,7 +1441,8 @@
tracker_.InsertSpsPpsNalus(sprop_decoder.sps_nalu(),
sprop_decoder.pps_nalu());
- if (h26x_packet_buffer_) {
+ if (h26x_packet_buffer_ &&
+ UseH26xPacketBuffer(GetCodecFromPayloadType(payload_type))) {
h26x_packet_buffer_->SetSpropParameterSets(sprop_base64_it->second);
}
}
diff --git a/video/rtp_video_stream_receiver2.h b/video/rtp_video_stream_receiver2.h
index b514d8f..8cfabff 100644
--- a/video/rtp_video_stream_receiver2.h
+++ b/video/rtp_video_stream_receiver2.h
@@ -300,7 +300,8 @@
// This function assumes that it's being called from only one thread.
void ParseAndHandleEncapsulatingHeader(const RtpPacketReceived& packet)
RTC_RUN_ON(packet_sequence_checker_);
- void NotifyReceiverOfEmptyPacket(uint16_t seq_num, bool is_h26x)
+ void NotifyReceiverOfEmptyPacket(uint16_t seq_num,
+ std::optional<VideoCodecType> codec)
RTC_RUN_ON(packet_sequence_checker_);
bool IsRedEnabled() const;
void InsertSpsPpsIntoTracker(uint8_t payload_type)
@@ -320,7 +321,9 @@
FrameInstrumentationData>& frame_instrumentation_data,
int spatial_idx);
- bool IsH26xPayloadType(uint8_t payload_type) const
+ std::optional<VideoCodecType> GetCodecFromPayloadType(
+ uint8_t payload_type) const RTC_RUN_ON(packet_sequence_checker_);
+ bool UseH26xPacketBuffer(std::optional<VideoCodecType> codec) const
RTC_RUN_ON(packet_sequence_checker_);
const Environment env_;
@@ -371,7 +374,9 @@
video_coding::PacketBuffer packet_buffer_
RTC_GUARDED_BY(packet_sequence_checker_);
- // `h26x_packet_buffer_` is null if codec list doens't contain H.264 or H.265.
+ // h26x_packet_buffer_ is applicable to H.264 and H.265. For H.265 it is
+ // always used but for H.264 it is only used if WebRTC-Video-H26xPacketBuffer
+ // is enabled, see condition inside UseH26xPacketBuffer().
std::unique_ptr<H26xPacketBuffer> h26x_packet_buffer_
RTC_GUARDED_BY(packet_sequence_checker_);
UniqueTimestampCounter frame_counter_
diff --git a/video/rtp_video_stream_receiver2_unittest.cc b/video/rtp_video_stream_receiver2_unittest.cc
index 4e635b0..74941da 100644
--- a/video/rtp_video_stream_receiver2_unittest.cc
+++ b/video/rtp_video_stream_receiver2_unittest.cc
@@ -765,7 +765,11 @@
INSTANTIATE_TEST_SUITE_P(SpsPpsIdrIsKeyframeAndH26xPacketBuffer,
RtpVideoStreamReceiver2TestH264,
- Values("", "WebRTC-SpsPpsIdrIsH264Keyframe/Enabled/"));
+ Values("",
+ "WebRTC-SpsPpsIdrIsH264Keyframe/Enabled/",
+ "WebRTC-Video-H26xPacketBuffer/Enabled/",
+ "WebRTC-SpsPpsIdrIsH264Keyframe/Enabled/"
+ "WebRTC-Video-H26xPacketBuffer/Enabled/"));
TEST_P(RtpVideoStreamReceiver2TestH264, InBandSpsPps) {
constexpr int kH264PayloadType = 98;
@@ -865,7 +869,8 @@
// IDR frames without SPS/PPS are not returned by
// |H26xPacketBuffer.InsertPacket| until SPS and PPS are received when
// WebRTC-SpsPpsIdrIsH264Keyframe is enabled.
- if (!env_.field_trials().IsEnabled("WebRTC-SpsPpsIdrIsH264Keyframe")) {
+ if (!env_.field_trials().IsEnabled("WebRTC-SpsPpsIdrIsH264Keyframe") ||
+ !env_.field_trials().IsEnabled("WebRTC-Video-H26xPacketBuffer")) {
EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
}
rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
@@ -939,17 +944,30 @@
// IDR frames without SPS/PPS are not returned by
// |H26xPacketBuffer.InsertPacket| until SPS and PPS are received, while
// |PacketBuffer| returns it as a delta frame.
- EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame).Times(0);
+ if (env_.field_trials().IsEnabled("WebRTC-Video-H26xPacketBuffer")) {
+ EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame).Times(0);
+ } else {
+ EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
+ .WillOnce(
+ [&](EncodedFrame* frame) { EXPECT_FALSE(frame->is_keyframe()); });
+ }
rtp_video_stream_receiver_->OnReceivedPayloadData(idr_data, rtp_packet,
idr_video_header, 0);
}
-class RtpVideoStreamReceiver2TestPadding : public RtpVideoStreamReceiver2Test {
+class RtpVideoStreamReceiver2TestPadding
+ : public RtpVideoStreamReceiver2Test,
+ public ::testing::WithParamInterface<std::string> {
protected:
- RtpVideoStreamReceiver2TestPadding() : RtpVideoStreamReceiver2Test("") {}
+ RtpVideoStreamReceiver2TestPadding()
+ : RtpVideoStreamReceiver2Test(GetParam()) {}
};
-TEST_F(RtpVideoStreamReceiver2TestPadding, PaddingInMediaStream) {
+INSTANTIATE_TEST_SUITE_P(PaddingInMediaStreamAndH26xPacketBuffer,
+ RtpVideoStreamReceiver2TestPadding,
+ Values("", "WebRTC-Video-H26xPacketBuffer/Enabled/"));
+
+TEST_P(RtpVideoStreamReceiver2TestPadding, PaddingInMediaStream) {
RtpPacketReceived rtp_packet;
RTPVideoHeader video_header = GetDefaultH264VideoHeader();
rtc::CopyOnWriteBuffer data({'1', '2', '3'});
@@ -986,7 +1004,7 @@
video_header, 0);
}
-TEST_F(RtpVideoStreamReceiver2TestPadding, EmptyPaddingInMediaStream) {
+TEST_P(RtpVideoStreamReceiver2TestPadding, EmptyPaddingInMediaStream) {
constexpr int kH264PayloadType = 98;
RtpPacketReceived rtp_packet_idr, rtp_packet_padding, rtp_packet_slice;
// Example Stap-A packet with SPS, PPS, and IDR.