diff mbox series

[FFmpeg-devel,v4,15/21] lavfi/qsvvpp: set PTS for output frame

Message ID 20210729052509.30992-16-haihao.xiang@intel.com
State New
Headers show
Series clean-up QSV filters
Related show

Checks

Context Check Description
andriy/x86_make success Make finished
andriy/x86_make_fate success Make fate finished
andriy/PPC64_make success Make finished
andriy/PPC64_make_fate success Make fate finished

Commit Message

Haihao Xiang July 29, 2021, 5:25 a.m. UTC
When the SDK returns MFX_ERR_MORE_SURFACE, the PTS is not set for the
output frame. We assign a PTS calculated from the input frame to the
output frame. After applying this patch, we may avoid the error below:

[null @ 0x56395cab4ae0] Application provided invalid, non monotonically
increasing dts to muxer in stream 0: 456 >= 0

Note this patch only fixes PTS issue when deinterlacing is enabled
---
 libavfilter/qsvvpp.c     | 21 +++++++++++++++++++--
 libavfilter/qsvvpp.h     |  3 +++
 libavfilter/vf_vpp_qsv.c |  2 ++
 3 files changed, 24 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c
index 82a8e29387..01d9d754d3 100644
--- a/libavfilter/qsvvpp.c
+++ b/libavfilter/qsvvpp.c
@@ -653,6 +653,7 @@  int ff_qsvvpp_init(AVFilterContext *avctx, QSVVPPParam *param)
     int ret;
     QSVVPPContext *s = avctx->priv;
 
+    s->last_in_pts   = AV_NOPTS_VALUE;
     s->filter_frame  = param->filter_frame;
     if (!s->filter_frame)
         s->filter_frame = ff_filter_frame;
@@ -769,6 +770,8 @@  int ff_qsvvpp_close(AVFilterContext *avctx)
         s->session = NULL;
     }
 
+    s->last_in_pts = AV_NOPTS_VALUE;
+
     /* release all the resources */
     clear_frame_list(&s->in_frame_list);
     clear_frame_list(&s->out_frame_list);
@@ -788,6 +791,7 @@  int ff_qsvvpp_filter_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *picr
     mfxSyncPoint      sync;
     QSVFrame         *in_frame, *out_frame, *tmp;
     int               ret, ret1, filter_ret;
+    int64_t           dpts = 0;
 
     while (s->eof && qsv_fifo_size(s->async_fifo)) {
         av_fifo_generic_read(s->async_fifo, &tmp, sizeof(tmp), NULL);
@@ -836,8 +840,19 @@  int ff_qsvvpp_filter_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *picr
                 ret = AVERROR(EAGAIN);
             break;
         }
-        out_frame->frame->pts = av_rescale_q(out_frame->surface.Data.TimeStamp,
-                                             default_tb, outlink->time_base);
+
+        /* TODO: calculate the PTS for other cases */
+        if (s->deinterlace_enabled &&
+            s->last_in_pts != AV_NOPTS_VALUE &&
+            ret == MFX_ERR_MORE_SURFACE &&
+            out_frame->surface.Data.TimeStamp == MFX_TIMESTAMP_UNKNOWN)
+            dpts = (in_frame->frame->pts - s->last_in_pts) / 2;
+        else
+            dpts = 0;
+
+        out_frame->frame->pts = av_rescale_q(in_frame->frame->pts - dpts,
+                                             inlink->time_base,
+                                             outlink->time_base);
 
         out_frame->queued++;
         av_fifo_generic_write(s->async_fifo, &out_frame, sizeof(out_frame), NULL);
@@ -870,5 +885,7 @@  int ff_qsvvpp_filter_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *picr
         }
     } while(ret == MFX_ERR_MORE_SURFACE);
 
+    s->last_in_pts = in_frame->frame->pts;
+
     return ret;
 }
diff --git a/libavfilter/qsvvpp.h b/libavfilter/qsvvpp.h
index b6fe0d3fa7..8627c8c868 100644
--- a/libavfilter/qsvvpp.h
+++ b/libavfilter/qsvvpp.h
@@ -74,8 +74,11 @@  typedef struct QSVVPPContext {
     int got_frame;
     int async_depth;
     int eof;
+    int deinterlace_enabled;
     /** order with frame_out, sync */
     AVFifoBuffer *async_fifo;
+
+    int64_t last_in_pts;
 } QSVVPPContext;
 
 typedef struct QSVVPPCrop {
diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c
index e16bd09585..b234417663 100644
--- a/libavfilter/vf_vpp_qsv.c
+++ b/libavfilter/vf_vpp_qsv.c
@@ -364,6 +364,8 @@  static int config_output(AVFilterLink *outlink)
         vpp->extbuf.field = value; \
     } while (0)
 
+    vpp->qsv.deinterlace_enabled = !!vpp->deinterlace;
+
     if (vpp->deinterlace) {
         INIT_MFX_EXTBUF(deinterlace_conf, MFX_EXTBUFF_VPP_DEINTERLACING);
         SET_MFX_PARAM_FIELD(deinterlace_conf, Mode, (vpp->deinterlace == 1 ?