---
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 6e69e52..5bee49a 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)
@@ -331,6 +340,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) {
@@ -357,6 +370,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)))
@@ -377,23 +402,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 pts, dts;
@@ -466,3 +481,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 555edd5..030dc92 100644
--- a/libavcodec/qsv.h
+++ b/libavcodec/qsv.h
@@ -61,6 +61,7 @@ typedef struct QSVContext {
mfxSyncPoint sync;
mfxBitstream bs;
int last_ret;
+ int need_reinit;
int timeout;
AVPacketList *pending, *pending_end;
} QSVContext;
@@ -77,4 +78,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