Increase frame rate precision in libaom AV1 encoder wrapper

Before this change the AV1 encoder wrapper converted target frame rate from double to integer with rounding to the middle. That approach resulted in a bitrate mismatch caused by rounding error. The mismatch was especially high at low frame rates. For example, at target frame rate 1.4fps the bitrate mismatch reached 40%:

out/debug/video_codec_perf_tests --gtest_also_run_disabled_tests --gtest_filter=*EncodeDecode --framerate_fps=1.4 --width=320 --height=180 --bitrate_kbps=32 --num_frames=600
...
RESULT s0t0_bitrate_mismatch_pct: DISABLED_EncodeDecode= {39.171875,0} n%

After the change the mismatch reduced to ~2% in the same scenario:
RESULT s0t0_bitrate_mismatch_pct: DISABLED_EncodeDecode= {-2.178125,0} n%

Bug: b/337757868
Change-Id: Ia51f92b3dfdce103eed1d04cac0e084b69fa8213
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/356500
Reviewed-by: Erik Språng <sprang@webrtc.org>
Commit-Queue: Sergey Silkin <ssilkin@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#42601}
This commit is contained in:
Sergey Silkin 2024-07-08 07:42:17 +02:00 committed by WebRTC LUCI CQ
parent 41ffc51e45
commit b43cd86e64

View File

@ -131,6 +131,7 @@ class LibaomAv1Encoder final : public VideoEncoder {
aom_codec_ctx_t ctx_; aom_codec_ctx_t ctx_;
aom_codec_enc_cfg_t cfg_; aom_codec_enc_cfg_t cfg_;
EncodedImageCallback* encoded_image_callback_; EncodedImageCallback* encoded_image_callback_;
double framerate_fps_; // Current target frame rate.
int64_t timestamp_; int64_t timestamp_;
const LibaomAv1EncoderInfoSettings encoder_info_override_; const LibaomAv1EncoderInfoSettings encoder_info_override_;
int max_consec_frame_drop_; int max_consec_frame_drop_;
@ -179,6 +180,7 @@ LibaomAv1Encoder::LibaomAv1Encoder(const Environment& env,
settings_(std::move(settings)), settings_(std::move(settings)),
frame_for_encode_(nullptr), frame_for_encode_(nullptr),
encoded_image_callback_(nullptr), encoded_image_callback_(nullptr),
framerate_fps_(0),
timestamp_(0), timestamp_(0),
encoder_info_override_(env.field_trials()), encoder_info_override_(env.field_trials()),
max_consec_frame_drop_(GetMaxConsecutiveFrameDrop(env.field_trials())) {} max_consec_frame_drop_(GetMaxConsecutiveFrameDrop(env.field_trials())) {}
@ -658,8 +660,7 @@ int32_t LibaomAv1Encoder::Encode(
return WEBRTC_VIDEO_CODEC_ENCODER_FAILURE; return WEBRTC_VIDEO_CODEC_ENCODER_FAILURE;
} }
const uint32_t duration = const uint32_t duration = kRtpTicksPerSecond / framerate_fps_;
kRtpTicksPerSecond / static_cast<float>(encoder_settings_.maxFramerate);
timestamp_ += duration; timestamp_ += duration;
const size_t num_spatial_layers = const size_t num_spatial_layers =
@ -836,11 +837,9 @@ void LibaomAv1Encoder::SetRates(const RateControlParameters& parameters) {
SetEncoderControlParameters(AV1E_SET_SVC_PARAMS, &*svc_params_); SetEncoderControlParameters(AV1E_SET_SVC_PARAMS, &*svc_params_);
} }
rates_configured_ = true; framerate_fps_ = parameters.framerate_fps;
// Set frame rate to closest integer value. rates_configured_ = true;
encoder_settings_.maxFramerate =
static_cast<uint32_t>(parameters.framerate_fps + 0.5);
} }
VideoEncoder::EncoderInfo LibaomAv1Encoder::GetEncoderInfo() const { VideoEncoder::EncoderInfo LibaomAv1Encoder::GetEncoderInfo() const {