av1enc: Fix last timestamp tracking so it actually works

This behaves exactly the same as in vp8enc / vp9enc now.

Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3546

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6909>
This commit is contained in:
Sebastian Dröge 2024-05-21 16:46:40 +03:00 committed by GStreamer Marge Bot
parent 36a2eb0f03
commit afe74a0181
2 changed files with 22 additions and 15 deletions

View file

@ -874,6 +874,8 @@ gst_av1_enc_set_format (GstVideoEncoder * encoder, GstVideoCodecState * state)
return FALSE; return FALSE;
} }
av1enc->encoder_inited = TRUE; av1enc->encoder_inited = TRUE;
av1enc->last_pts = GST_CLOCK_TIME_NONE;
av1enc->last_input_duration = GST_CLOCK_TIME_NONE;
GST_AV1_ENC_APPLY_CODEC_CONTROL (av1enc, AOME_SET_CPUUSED, av1enc->cpu_used); GST_AV1_ENC_APPLY_CODEC_CONTROL (av1enc, AOME_SET_CPUUSED, av1enc->cpu_used);
#ifdef AOM_CTRL_AV1E_SET_ROW_MT #ifdef AOM_CTRL_AV1E_SET_ROW_MT
@ -972,30 +974,31 @@ gst_av1_enc_handle_frame (GstVideoEncoder * encoder, GstVideoCodecFrame * frame)
gst_segment_to_running_time (&encoder->input_segment, gst_segment_to_running_time (&encoder->input_segment,
GST_FORMAT_TIME, frame->pts); GST_FORMAT_TIME, frame->pts);
if (GST_CLOCK_TIME_IS_VALID (av1enc->next_pts) if (GST_CLOCK_TIME_IS_VALID (av1enc->last_pts)
&& pts_rt <= av1enc->next_pts) { && pts_rt <= av1enc->last_pts) {
GST_WARNING_OBJECT (av1enc, GST_WARNING_OBJECT (av1enc,
"decreasing pts %" GST_TIME_FORMAT " previous buffer was %" "decreasing pts %" GST_TIME_FORMAT " previous buffer was %"
GST_TIME_FORMAT " enforce increasing pts", GST_TIME_ARGS (pts_rt), GST_TIME_FORMAT " enforce increasing pts", GST_TIME_ARGS (pts_rt),
GST_TIME_ARGS (av1enc->next_pts)); GST_TIME_ARGS (av1enc->last_pts));
pts_rt = av1enc->next_pts + 1; pts_rt = av1enc->last_pts + 1;
} }
av1enc->next_pts = pts_rt; av1enc->last_pts = pts_rt;
// Convert the pts from nanoseconds to timebase units // Convert the pts from nanoseconds to timebase units
scaled_pts = scaled_pts =
gst_util_uint64_scale_int (pts_rt, gst_util_uint64_scale (pts_rt,
av1enc->aom_cfg.g_timebase.den, av1enc->aom_cfg.g_timebase.den,
av1enc->aom_cfg.g_timebase.num * (GstClockTime) GST_SECOND); av1enc->aom_cfg.g_timebase.num * (GstClockTime) GST_SECOND);
if (frame->duration != GST_CLOCK_TIME_NONE) { if (frame->duration != GST_CLOCK_TIME_NONE) {
duration = duration =
gst_util_uint64_scale (frame->duration, av1enc->aom_cfg.g_timebase.den, gst_util_uint64_scale_round (frame->duration,
av1enc->aom_cfg.g_timebase.den,
av1enc->aom_cfg.g_timebase.num * (GstClockTime) GST_SECOND); av1enc->aom_cfg.g_timebase.num * (GstClockTime) GST_SECOND);
if (duration > 0) { if (duration > 0) {
av1enc->next_pts += frame->duration; av1enc->last_input_duration = frame->duration;
} else { } else {
/* We force the path ignoring the duration if we end up with a zero /* We force the path ignoring the duration if we end up with a zero
* value for duration after scaling (e.g. duration value too small) */ * value for duration after scaling (e.g. duration value too small) */
@ -1003,11 +1006,9 @@ gst_av1_enc_handle_frame (GstVideoEncoder * encoder, GstVideoCodecFrame * frame)
"Ignoring too small frame duration %" GST_TIME_FORMAT, "Ignoring too small frame duration %" GST_TIME_FORMAT,
GST_TIME_ARGS (frame->duration)); GST_TIME_ARGS (frame->duration));
duration = 1; duration = 1;
av1enc->next_pts += 1;
} }
} else { } else {
duration = 1; duration = 1;
av1enc->next_pts += 1;
} }
if (aom_codec_encode (&av1enc->encoder, &raw, scaled_pts, duration, flags) if (aom_codec_encode (&av1enc->encoder, &raw, scaled_pts, duration, flags)
@ -1042,8 +1043,11 @@ gst_av1_enc_finish (GstVideoEncoder * encoder)
GST_DEBUG_OBJECT (encoder, "Calling finish"); GST_DEBUG_OBJECT (encoder, "Calling finish");
g_mutex_lock (&av1enc->encoder_lock); g_mutex_lock (&av1enc->encoder_lock);
if (GST_CLOCK_TIME_IS_VALID (av1enc->next_pts)) if (GST_CLOCK_TIME_IS_VALID (av1enc->last_pts))
pts = av1enc->next_pts; pts = av1enc->last_pts;
if (GST_CLOCK_TIME_IS_VALID (av1enc->last_input_duration))
pts += av1enc->last_input_duration;
scaled_pts = scaled_pts =
gst_util_uint64_scale (pts, gst_util_uint64_scale (pts,
av1enc->aom_cfg.g_timebase.den, av1enc->aom_cfg.g_timebase.den,
@ -1075,7 +1079,8 @@ gst_av1_enc_destroy_encoder (GstAV1Enc * av1enc)
av1enc->encoder_inited = FALSE; av1enc->encoder_inited = FALSE;
} }
av1enc->next_pts = GST_CLOCK_TIME_NONE; av1enc->last_pts = GST_CLOCK_TIME_NONE;
av1enc->last_input_duration = GST_CLOCK_TIME_NONE;
g_mutex_unlock (&av1enc->encoder_lock); g_mutex_unlock (&av1enc->encoder_lock);
} }

View file

@ -194,8 +194,10 @@ struct _GstAV1Enc
aom_img_fmt_t format; aom_img_fmt_t format;
GMutex encoder_lock; GMutex encoder_lock;
/* next pts, in running time */ /* Last inputi pts, in running time */
GstClockTime next_pts; GstClockTime last_pts;
/* duration of the last input buffer */
GstClockTime last_input_duration;
gboolean target_bitrate_set; gboolean target_bitrate_set;
}; };