diff options
author | Sebastian Dröge <sebastian@centricular.com> | 2023-01-13 12:43:30 +0200 |
---|---|---|
committer | GStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org> | 2023-01-13 17:18:38 +0000 |
commit | 79e8d2c03e70488b9ae2c72739df6da819c6bd1d (patch) | |
tree | f547751fe166a96c10dfc7f9a702837c638d25ec | |
parent | 13ad8c8e4e2101c5a50c9e9232187b3ebf29f04d (diff) | |
download | gstreamer-79e8d2c03e70488b9ae2c72739df6da819c6bd1d.tar.gz |
avvidenc: Offset PTS to zero to fix bitrate control
Otherwise ffmpeg's rate control algorithm will not work correctly as
it is based on the absolute PTS values.
Fixes https://gitlab.freedesktop.org/gstreamer/gst-libav/-/issues/91
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3718>
-rw-r--r-- | subprojects/gst-libav/ext/libav/gstavvidenc.c | 37 | ||||
-rw-r--r-- | subprojects/gst-libav/ext/libav/gstavvidenc.h | 1 |
2 files changed, 30 insertions, 8 deletions
diff --git a/subprojects/gst-libav/ext/libav/gstavvidenc.c b/subprojects/gst-libav/ext/libav/gstavvidenc.c index d08e39644d..9659d694d4 100644 --- a/subprojects/gst-libav/ext/libav/gstavvidenc.c +++ b/subprojects/gst-libav/ext/libav/gstavvidenc.c @@ -399,6 +399,7 @@ gst_ffmpegvidenc_set_format (GstVideoEncoder * encoder, } /* success! */ + ffmpegenc->pts_offset = GST_CLOCK_TIME_NONE; ffmpegenc->opened = TRUE; return TRUE; @@ -618,9 +619,20 @@ gst_ffmpegvidenc_send_frame (GstFFMpegVidEnc * ffmpegenc, picture->width = GST_VIDEO_FRAME_WIDTH (&buffer_info->vframe); picture->height = GST_VIDEO_FRAME_HEIGHT (&buffer_info->vframe); - picture->pts = - gst_ffmpeg_time_gst_to_ff (frame->pts / - ffmpegenc->context->ticks_per_frame, ffmpegenc->context->time_base); + if (ffmpegenc->pts_offset == GST_CLOCK_TIME_NONE) { + ffmpegenc->pts_offset = frame->pts; + } + + if (frame->pts == GST_CLOCK_TIME_NONE) { + picture->pts = AV_NOPTS_VALUE; + } else if (frame->pts < ffmpegenc->pts_offset) { + GST_ERROR_OBJECT (ffmpegenc, "PTS is going backwards"); + picture->pts = AV_NOPTS_VALUE; + } else { + picture->pts = + gst_ffmpeg_time_gst_to_ff ((frame->pts - ffmpegenc->pts_offset) / + ffmpegenc->context->ticks_per_frame, ffmpegenc->context->time_base); + } send_frame: if (!picture) { @@ -703,14 +715,20 @@ gst_ffmpegvidenc_receive_packet (GstFFMpegVidEnc * ffmpegenc, GST_VIDEO_CODEC_FRAME_UNSET_SYNC_POINT (frame); } - frame->dts = - gst_ffmpeg_time_ff_to_gst (pkt->dts, ffmpegenc->context->time_base); + if (pkt->dts != AV_NOPTS_VALUE) { + frame->dts = + gst_ffmpeg_time_ff_to_gst (pkt->dts + ffmpegenc->pts_offset, + ffmpegenc->context->time_base); + } /* This will lose some precision compared to setting the PTS from the input * buffer directly, but that way we're sure PTS and DTS are consistent, in * particular DTS should always be <= PTS */ - frame->pts = - gst_ffmpeg_time_ff_to_gst (pkt->pts, ffmpegenc->context->time_base); + if (pkt->pts != AV_NOPTS_VALUE) { + frame->pts = + gst_ffmpeg_time_ff_to_gst (pkt->pts + ffmpegenc->pts_offset, + ffmpegenc->context->time_base); + } ret = gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (ffmpegenc), frame); @@ -804,6 +822,7 @@ gst_ffmpegvidenc_flush_buffers (GstFFMpegVidEnc * ffmpegenc, gboolean send) break; } while (got_packet); avcodec_flush_buffers (ffmpegenc->context); + ffmpegenc->pts_offset = GST_CLOCK_TIME_NONE; done: /* FFMpeg will return AVERROR_EOF if it's internal was fully drained @@ -879,8 +898,10 @@ gst_ffmpegvidenc_flush (GstVideoEncoder * encoder) { GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder; - if (ffmpegenc->opened) + if (ffmpegenc->opened) { avcodec_flush_buffers (ffmpegenc->context); + ffmpegenc->pts_offset = GST_CLOCK_TIME_NONE; + } return TRUE; } diff --git a/subprojects/gst-libav/ext/libav/gstavvidenc.h b/subprojects/gst-libav/ext/libav/gstavvidenc.h index 2d0b7c8b6b..340fb25204 100644 --- a/subprojects/gst-libav/ext/libav/gstavvidenc.h +++ b/subprojects/gst-libav/ext/libav/gstavvidenc.h @@ -40,6 +40,7 @@ struct _GstFFMpegVidEnc AVCodecContext *context; AVFrame *picture; + GstClockTime pts_offset; gboolean opened; gboolean need_reopen; gboolean discont; |