From: Sebastian Dröge Date: Fri, 13 Jan 2023 10:43:30 +0000 (+0200) Subject: avvidenc: Offset PTS to zero to fix bitrate control X-Git-Tag: 1.22.0~38 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=79e8d2c03e70488b9ae2c72739df6da819c6bd1d;p=platform%2Fupstream%2Fgstreamer.git 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: --- diff --git a/subprojects/gst-libav/ext/libav/gstavvidenc.c b/subprojects/gst-libav/ext/libav/gstavvidenc.c index d08e396..9659d69 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 2d0b7c8..340fb25 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;