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, ×tamp_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