diff --git a/experiments/field_trials.py b/experiments/field_trials.py index dff1ad1982..32ab6bf351 100755 --- a/experiments/field_trials.py +++ b/experiments/field_trials.py @@ -89,6 +89,9 @@ ACTIVE_FIELD_TRIALS: FrozenSet[FieldTrial] = frozenset([ FieldTrial('WebRTC-LibaomAv1Encoder-DisableFrameDropping', 'webrtc:15225', date(2024, 4, 1)), + FieldTrial('WebRTC-LibaomAv1Encoder-MaxConsecFrameDrop', + 'webrtc:15821', + date(2024, 4, 1)), FieldTrial('WebRTC-Pacer-FastRetransmissions', 'chromium:1354491', date(2024, 4, 1)), diff --git a/modules/video_coding/codecs/av1/libaom_av1_encoder.cc b/modules/video_coding/codecs/av1/libaom_av1_encoder.cc index 4ff22bfe34..03bb367fe0 100644 --- a/modules/video_coding/codecs/av1/libaom_av1_encoder.cc +++ b/modules/video_coding/codecs/av1/libaom_av1_encoder.cc @@ -133,6 +133,7 @@ class LibaomAv1Encoder final : public VideoEncoder { // TODO(webrtc:15225): Kill switch for disabling frame dropping. Remove it // after frame dropping is fully rolled out. bool disable_frame_dropping_; + int max_consec_frame_drop_; }; int32_t VerifyCodecSettings(const VideoCodec& codec_settings) { @@ -163,6 +164,14 @@ int32_t VerifyCodecSettings(const VideoCodec& codec_settings) { return WEBRTC_VIDEO_CODEC_OK; } +int GetMaxConsecutiveFrameDrop(const FieldTrialsView& field_trials) { + webrtc::FieldTrialParameter maxdrop("maxdrop", 0); + webrtc::ParseFieldTrial( + {&maxdrop}, + field_trials.Lookup("WebRTC-LibaomAv1Encoder-MaxConsecFrameDrop")); + return maxdrop; +} + LibaomAv1Encoder::LibaomAv1Encoder( const absl::optional& aux_config, const FieldTrialsView& trials) @@ -174,7 +183,8 @@ LibaomAv1Encoder::LibaomAv1Encoder( timestamp_(0), disable_frame_dropping_(absl::StartsWith( trials.Lookup("WebRTC-LibaomAv1Encoder-DisableFrameDropping"), - "Enabled")) {} + "Enabled")), + max_consec_frame_drop_(GetMaxConsecutiveFrameDrop(trials)) {} LibaomAv1Encoder::~LibaomAv1Encoder() { Release(); @@ -297,6 +307,12 @@ int LibaomAv1Encoder::InitEncode(const VideoCodec* codec_settings, SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_ENABLE_PALETTE, 0); } + if (codec_settings->mode == VideoCodecMode::kRealtimeVideo && + encoder_settings_.GetFrameDropEnabled() && max_consec_frame_drop_ > 0) { + SET_ENCODER_PARAM_OR_RETURN_ERROR(AV1E_SET_MAX_CONSEC_FRAME_DROP_CBR, + max_consec_frame_drop_); + } + if (cfg_.g_threads == 8) { // Values passed to AV1E_SET_TILE_ROWS and AV1E_SET_TILE_COLUMNS are log2() // based. diff --git a/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc b/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc index 04ee9162ba..127aadb275 100644 --- a/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc +++ b/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc @@ -188,6 +188,31 @@ TEST(LibaomAv1EncoderTest, CheckOddDimensionsWithSpatialLayers) { ASSERT_THAT(encoded_frames, SizeIs(6)); } +TEST(LibaomAv1EncoderTest, WithMaximumConsecutiveFrameDrop) { + test::ScopedFieldTrials field_trials( + "WebRTC-LibaomAv1Encoder-MaxConsecFrameDrop/maxdrop:2/"); + VideoBitrateAllocation allocation; + allocation.SetBitrate(0, 0, 1000); // some very low bitrate + std::unique_ptr encoder = CreateLibaomAv1Encoder(); + VideoCodec codec_settings = DefaultCodecSettings(); + codec_settings.SetFrameDropEnabled(true); + codec_settings.SetScalabilityMode(ScalabilityMode::kL1T1); + codec_settings.startBitrate = allocation.get_sum_kbps(); + ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()), + WEBRTC_VIDEO_CODEC_OK); + encoder->SetRates(VideoEncoder::RateControlParameters( + allocation, codec_settings.maxFramerate)); + EncodedVideoFrameProducer evfp(*encoder); + evfp.SetResolution( + RenderResolution{codec_settings.width, codec_settings.height}); + // We should code the first frame, skip two, then code another frame. + std::vector encoded_frames = + evfp.SetNumInputFrames(4).Encode(); + ASSERT_THAT(encoded_frames, SizeIs(2)); + // The 4 frames have default Rtp-timestamps of 1000, 4000, 7000, 10000. + ASSERT_THAT(encoded_frames[1].encoded_image.RtpTimestamp(), 10000); +} + TEST(LibaomAv1EncoderTest, EncoderInfoWithoutResolutionBitrateLimits) { std::unique_ptr encoder = CreateLibaomAv1Encoder(); EXPECT_TRUE(encoder->GetEncoderInfo().resolution_bitrate_limits.empty());