---
 libavcodec/qsv.c      | 62 ++++++++++++++++++++++++++++++++++++++-------------
 libavcodec/qsv.h      |  3 +++
 libavcodec/qsv_h264.c |  5 +++++
 3 files changed, 55 insertions(+), 15 deletions(-)

diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
index 622b0b3..c9393d6 100644
--- a/libavcodec/qsv.c
+++ b/libavcodec/qsv.c
@@ -124,8 +124,17 @@ int ff_qsv_init(AVCodecContext *c, QSVContext *q)
     if ((ret = MFXVideoDECODE_DecodeHeader(q->session, bs, &q->param)) < 0)
         return ff_qsv_error(ret);
 
-    bs->DataFlag   = MFX_BITSTREAM_COMPLETE_FRAME;
-    bs->DataLength = bs->DataOffset = 0;
+    c->width         = q->param.mfx.FrameInfo.CropW;
+    c->height        = q->param.mfx.FrameInfo.CropH;
+    c->coded_width   = q->param.mfx.FrameInfo.Width;
+    c->coded_height  = q->param.mfx.FrameInfo.Height;
+    c->time_base.den = q->param.mfx.FrameInfo.FrameRateExtN * 
c->ticks_per_frame;
+    c->time_base.num = q->param.mfx.FrameInfo.FrameRateExtD;
+
+    if (!q->need_reinit)
+        bs->DataLength = bs->DataOffset = 0;
+
+    bs->DataFlag = MFX_BITSTREAM_COMPLETE_FRAME;
 
     ret = MFXVideoDECODE_QueryIOSurf(q->session, &q->param, &req);
     if (ret < 0)
@@ -336,6 +345,10 @@ int ff_qsv_decode(AVCodecContext *avctx, QSVContext *q,
     if (size)
         ff_packet_list_put(&q->pending, &q->pending_end, avpkt);
 
+    // (2) Flush cached frames before reinit
+    if (q->need_reinit)
+        bs = NULL;
+
     ret = q->last_ret;
     do {
         if (ret == MFX_ERR_MORE_DATA) {
@@ -362,6 +375,18 @@ int ff_qsv_decode(AVCodecContext *avctx, QSVContext *q,
             } else {
                 break;
             }
+        } else if (ret == MFX_WRN_VIDEO_PARAM_CHANGED) {
+            // Detected new seaquence header has compatible video parameter
+            // Automatically bitstream move forward next time
+        } else if (ret == MFX_ERR_INCOMPATIBLE_VIDEO_PARAM) {
+            // Detected new seaquence header has incompatible video parameter
+            if (bs) {
+                // (1) Flush cached frames before reinit
+                bs = NULL;
+                q->need_reinit = 1;
+            } else {
+                return AVERROR_BUG;
+            }
         }
 
         if (!(insurf = get_surface(avctx, q)))
@@ -382,23 +407,13 @@ int ff_qsv_decode(AVCodecContext *avctx, QSVContext *q,
             busymsec = 0;
         }
     } while (ret == MFX_ERR_MORE_SURFACE || ret == MFX_ERR_MORE_DATA ||
-             ret == MFX_WRN_DEVICE_BUSY);
+             ret == MFX_WRN_DEVICE_BUSY  || ret == MFX_WRN_VIDEO_PARAM_CHANGED 
||
+             ret == MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
 
     q->last_ret = ret;
 
-    switch (ret) {
-    case MFX_ERR_MORE_DATA:
+    if (ret == MFX_ERR_MORE_DATA)
         ret = 0;
-        break;
-    case MFX_WRN_VIDEO_PARAM_CHANGED:
-    // FIXME handle the param change properly.
-    //  ret = MFXVideoDECODE_QueryIOSurf(q->session, &q->qsv.param, &req);
-    //    if (ret < 0)
-    //        return ff_qsv_error(ret);
-        ret = 0;
-    default:
-        break;
-    }
 
     if (sync) {
         int64_t dts;
@@ -470,3 +485,20 @@ int ff_qsv_close(QSVContext *q)
 
     return ff_qsv_error(ret);
 }
+
+int ff_qsv_reinit(AVCodecContext *avctx, QSVContext *q)
+{
+    int ret;
+
+    MFXClose(q->session);
+
+    free_surface_list(q);
+
+    av_freep(&q->timestamps);
+
+    ret = ff_qsv_init(avctx, q);
+
+    q->need_reinit = 0;
+
+    return ret;
+}
diff --git a/libavcodec/qsv.h b/libavcodec/qsv.h
index dd2a53d..992b0b3 100644
--- a/libavcodec/qsv.h
+++ b/libavcodec/qsv.h
@@ -59,6 +59,7 @@ typedef struct QSVContext {
     mfxSyncPoint sync;
     mfxBitstream bs;
     int last_ret;
+    int need_reinit;
     int timeout;
     AVPacketList *pending, *pending_end;
 } QSVContext;
@@ -75,4 +76,6 @@ int ff_qsv_flush(QSVContext *q);
 
 int ff_qsv_close(QSVContext *q);
 
+int ff_qsv_reinit(AVCodecContext *s, QSVContext *q);
+
 #endif /* AVCODEC_QSV_H */
diff --git a/libavcodec/qsv_h264.c b/libavcodec/qsv_h264.c
index 504b8ab..1b43e6c 100644
--- a/libavcodec/qsv_h264.c
+++ b/libavcodec/qsv_h264.c
@@ -83,6 +83,11 @@ static int qsv_dec_frame(AVCodecContext *avctx, void *data,
     int size;
     int ret;
 
+    // Reinit so finished flushing old video parameter cached frames
+    if (q->qsv.need_reinit && q->qsv.last_ret == MFX_ERR_MORE_DATA)
+        if ((ret = ff_qsv_reinit(avctx, &q->qsv)) < 0)
+            return ret;
+
     av_bitstream_filter_filter(q->bsf, avctx, NULL,
                                &p, &size,
                                avpkt->data, avpkt->size, 0);
-- 
1.8.3.msysgit.0

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to