From: Yukinori Yamazoe <[email protected]>

Signed-off-by: Luca Barbato <[email protected]>
---

 libavcodec/qsv.c      | 86 +++++++++++++++++++++++++++++++++++----------------
 libavcodec/qsv.h      |  3 ++
 libavcodec/qsv_h264.c |  7 +++++
 3 files changed, 69 insertions(+), 27 deletions(-)

diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
index ea09281..d014f96 100644
--- a/libavcodec/qsv.c
+++ b/libavcodec/qsv.c
@@ -117,7 +117,6 @@ int ff_qsv_init(AVCodecContext *c, QSVContext *q)
     int ret;
     mfxIMPL impl             = MFX_IMPL_AUTO_ANY;
     mfxVersion ver           = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } };
-    mfxBitstream *bs         = &q->bs;
     mfxFrameAllocRequest req = { { 0 } };

     if ((ret = codec_id_to_mfx(c->codec_id)) < 0)
@@ -125,15 +124,18 @@ int ff_qsv_init(AVCodecContext *c, QSVContext *q)

     q->param.mfx.CodecId = ret;

-    // replacement for MFXVideoDECODE_DecodeHeader()
-    if ((ret = pix_fmt_to_mfx_chroma(c->pix_fmt)) < 0)
-        return ret;
-    q->param.mfx.FrameInfo.ChromaFormat  = ret;
-    q->param.mfx.FrameInfo.FourCC        = MFX_FOURCC_NV12;
-    q->param.mfx.FrameInfo.Width         = FFALIGN(c->width, 16);
-    q->param.mfx.FrameInfo.Height        = FFALIGN(c->height, 32);
-    q->param.mfx.FrameInfo.FrameRateExtN = c->time_base.den;
-    q->param.mfx.FrameInfo.FrameRateExtD = c->time_base.num * 
c->ticks_per_frame;
+    // New video parameter value is already reflected when postinit
+    if (!q->need_postinit) {
+        // replacement for MFXVideoDECODE_DecodeHeader()
+        if ((ret = pix_fmt_to_mfx_chroma(c->pix_fmt)) < 0)
+            return ret;
+        q->param.mfx.FrameInfo.ChromaFormat  = ret;
+        q->param.mfx.FrameInfo.FourCC        = MFX_FOURCC_NV12;
+        q->param.mfx.FrameInfo.Width         = FFALIGN(c->width, 16);
+        q->param.mfx.FrameInfo.Height        = FFALIGN(c->height, 32);
+        q->param.mfx.FrameInfo.FrameRateExtN = c->time_base.den;
+        q->param.mfx.FrameInfo.FrameRateExtD = c->time_base.num * 
c->ticks_per_frame;
+    }

     c->pix_fmt = AV_PIX_FMT_NV12;

@@ -155,8 +157,7 @@ int ff_qsv_init(AVCodecContext *c, QSVContext *q)
     q->param.IOPattern  = MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
     q->param.AsyncDepth = ASYNC_DEPTH_DEFAULT;

-    bs->DataFlag   = MFX_BITSTREAM_COMPLETE_FRAME;
-    bs->DataLength = bs->DataOffset = 0;
+    q->bs.DataFlag = MFX_BITSTREAM_COMPLETE_FRAME;

     ret = MFXVideoDECODE_QueryIOSurf(q->session, &q->param, &req);
     if (ret < 0)
@@ -362,10 +363,16 @@ int ff_qsv_decode(AVCodecContext *avctx, QSVContext *q,
     if (size)
         ff_packet_list_put(&q->pending, &q->pending_end, avpkt);

+    // (2) Flush any internally cached frames before postinit
+    if (q->need_postinit)
+        bs = NULL;
+
     ret = q->last_decode_status;
     do {
         if (ret == MFX_ERR_MORE_DATA) {
-            if (q->pending) {
+            if (!bs) {
+                break;
+            } else if (q->pending) {
                 ff_packet_list_get(&q->pending, &q->pending_end, &pkt);

                 if (!(ret = put_dts(q, pkt.pts, pkt.dts, &timestamp_id))) {
@@ -377,12 +384,22 @@ int ff_qsv_decode(AVCodecContext *avctx, QSVContext *q,

                 if (ret < 0)
                     return ret;
-            } else if (!size && bs) {
+            } else if (!size) {
                 // Flush any internally cached frames because avpkt->size is 
zero
                 bs = NULL;
             } else {
                 break;
             }
+        } else if (ret == MFX_ERR_INCOMPATIBLE_VIDEO_PARAM) {
+            if (bs) {
+                // Get new parameter
+                ret = MFXVideoDECODE_DecodeHeader(q->session, bs, &q->param);
+                // (1) Flush any internally cached frames before postinit
+                bs = NULL;
+                q->need_postinit = 1;
+            } else {
+                return AVERROR_BUG;
+            }
         } else if (ret == MFX_WRN_DEVICE_BUSY) {
             av_usleep(1000);
         }
@@ -393,23 +410,13 @@ int ff_qsv_decode(AVCodecContext *avctx, QSVContext *q,
         ret = MFXVideoDECODE_DecodeFrameAsync(q->session, bs,
                                               insurf, &outsurf, &sync);
     } while (ret == MFX_ERR_MORE_SURFACE        || ret == MFX_ERR_MORE_DATA ||
-             ret == MFX_WRN_VIDEO_PARAM_CHANGED || ret == MFX_WRN_DEVICE_BUSY);
+             ret == MFX_WRN_VIDEO_PARAM_CHANGED || ret == MFX_WRN_DEVICE_BUSY 
||
+             ret == MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);

     q->last_decode_status = ret;

-    switch (ret) {
-    case 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);
+    if (ret == MFX_ERR_MORE_DATA)
         ret = 0;
-    default:
-        break;
-    }

     if (sync) {
         int64_t pts, dts;
@@ -479,3 +486,28 @@ int ff_qsv_close(QSVContext *q)

     return ff_qsv_error(ret);
 }
+
+int ff_qsv_postinit(AVCodecContext *avctx, QSVContext *q)
+{
+    int ret;
+
+    // New video parameter value to AVCodecContext
+    avctx->width         = q->param.mfx.FrameInfo.CropW;
+    avctx->height        = q->param.mfx.FrameInfo.CropH;
+    avctx->coded_width   = q->param.mfx.FrameInfo.Width;
+    avctx->coded_height  = q->param.mfx.FrameInfo.Height;
+    avctx->time_base.den = q->param.mfx.FrameInfo.FrameRateExtN * 
avctx->ticks_per_frame;
+    avctx->time_base.num = q->param.mfx.FrameInfo.FrameRateExtD;
+
+    MFXClose(q->session);
+
+    free_surface_list(q);
+
+    av_freep(&q->timestamps);
+
+    ret = ff_qsv_init(avctx, q);
+
+    q->need_postinit = 0;
+
+    return ret;
+}
diff --git a/libavcodec/qsv.h b/libavcodec/qsv.h
index 895eb93..078b918 100644
--- a/libavcodec/qsv.h
+++ b/libavcodec/qsv.h
@@ -60,6 +60,7 @@ typedef struct QSVContext {
     mfxSyncPoint sync;
     mfxBitstream bs;
     int last_decode_status;
+    int need_postinit;
     AVPacketList *pending, *pending_end;
 } QSVContext;

@@ -75,4 +76,6 @@ int ff_qsv_flush(QSVContext *q);

 int ff_qsv_close(QSVContext *q);

+int ff_qsv_postinit(AVCodecContext *s, QSVContext *q);
+
 #endif /* AVCODEC_QSV_H */
diff --git a/libavcodec/qsv_h264.c b/libavcodec/qsv_h264.c
index e696427..c10a456 100644
--- a/libavcodec/qsv_h264.c
+++ b/libavcodec/qsv_h264.c
@@ -66,6 +66,13 @@ static int qsv_dec_frame(AVCodecContext *avctx, void *data,
     int size;
     int ret;

+    if (q->qsv.need_postinit &&
+        q->qsv.last_decode_status == MFX_ERR_MORE_DATA) {
+        // Init so finished flushing old video parameter cached frames
+        if ((ret = ff_qsv_postinit(avctx, &q->qsv)) < 0)
+            return ret;
+    }
+
     av_bitstream_filter_filter(q->bsf, avctx, NULL,
                                &p, &size,
                                avpkt->data, avpkt->size, 0);
--
1.8.3.2

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

Reply via email to