From 3f8e2e9953240365361e939ca2ecd788dd5bef59 Mon Sep 17 00:00:00 2001 From: Ivan Uskov Date: Thu, 6 Aug 2015 12:10:24 -0400 Subject: [PATCH] libavcodec/qsvdec.c: correct flush() handler has been implemented Signed-off-by: Michael Niedermayer --- libavcodec/qsvdec.c | 45 +++++++++++++++++++++++++++++++++++++++ libavcodec/qsvdec.h | 2 ++ libavcodec/qsvdec_h2645.c | 4 ++-- libavcodec/qsvdec_mpeg2.c | 2 ++ libavcodec/qsvdec_vc1.c | 8 ++++++- 5 files changed, 58 insertions(+), 3 deletions(-) diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 51ad2f7090..00990badb1 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -517,6 +517,51 @@ int ff_qsv_decode(AVCodecContext *avctx, QSVContext *q, return ret; } +/* + This function resets decoder and corresponded buffers before seek operation +*/ +void ff_qsv_decode_reset(AVCodecContext *avctx, QSVContext *q) +{ + QSVFrame *cur; + AVPacket pkt; + int ret = 0; + mfxVideoParam param = { { 0 } }; + + if (q->reinit_pending) { + close_decoder(q); + } else if (q->engine_ready) { + ret = MFXVideoDECODE_GetVideoParam(q->session, ¶m); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "MFX decode get param error %d\n", ret); + } + + ret = MFXVideoDECODE_Reset(q->session, ¶m); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "MFX decode reset error %d\n", ret); + } + + /* Free all frames*/ + cur = q->work_frames; + while (cur) { + q->work_frames = cur->next; + av_frame_free(&cur->frame); + av_freep(&cur); + cur = q->work_frames; + } + } + + /* Reset output surfaces */ + av_fifo_reset(q->async_fifo); + + /* Reset input packets fifo */ + while (av_fifo_size(q->pkt_fifo)) { + av_fifo_generic_read(q->pkt_fifo, &pkt, sizeof(pkt), NULL); + av_packet_unref(&pkt); + } + + /* Reset input bitstream fifo */ + av_fifo_reset(q->input_fifo); +} int ff_qsv_decode_close(QSVContext *q) { diff --git a/libavcodec/qsvdec.h b/libavcodec/qsvdec.h index 5211fb2ee8..2b989c259a 100644 --- a/libavcodec/qsvdec.h +++ b/libavcodec/qsvdec.h @@ -84,6 +84,8 @@ int ff_qsv_decode(AVCodecContext *s, QSVContext *q, AVFrame *frame, int *got_frame, AVPacket *avpkt); +void ff_qsv_decode_reset(AVCodecContext *avctx, QSVContext *q); + int ff_qsv_decode_close(QSVContext *q); #endif /* AVCODEC_QSVDEC_H */ diff --git a/libavcodec/qsvdec_h2645.c b/libavcodec/qsvdec_h2645.c index 569b765bf4..2d787225b1 100644 --- a/libavcodec/qsvdec_h2645.c +++ b/libavcodec/qsvdec_h2645.c @@ -137,8 +137,8 @@ static int qsv_decode_frame(AVCodecContext *avctx, void *data, static void qsv_decode_flush(AVCodecContext *avctx) { -// QSVH2645Context *s = avctx->priv_data; - /* TODO: flush qsv engine if necessary */ + QSVH2645Context *s = avctx->priv_data; + ff_qsv_decode_reset(avctx, &s->qsv); } #define OFFSET(x) offsetof(QSVH2645Context, x) diff --git a/libavcodec/qsvdec_mpeg2.c b/libavcodec/qsvdec_mpeg2.c index 975dd9e571..36fd3b07d2 100644 --- a/libavcodec/qsvdec_mpeg2.c +++ b/libavcodec/qsvdec_mpeg2.c @@ -57,6 +57,8 @@ static int qsv_decode_frame(AVCodecContext *avctx, void *data, static void qsv_decode_flush(AVCodecContext *avctx) { + QSVMPEG2Context *s = avctx->priv_data; + ff_qsv_decode_reset(avctx, &s->qsv); } AVHWAccel ff_mpeg2_qsv_hwaccel = { diff --git a/libavcodec/qsvdec_vc1.c b/libavcodec/qsvdec_vc1.c index a80fc83617..3311d90f0f 100644 --- a/libavcodec/qsvdec_vc1.c +++ b/libavcodec/qsvdec_vc1.c @@ -52,6 +52,12 @@ static int qsv_decode_frame(AVCodecContext *avctx, void *data, return ff_qsv_decode(avctx, &s->qsv, frame, got_frame, avpkt); } +static void qsv_decode_flush(AVCodecContext *avctx) +{ + QSVVC1Context *s = avctx->priv_data; + ff_qsv_decode_reset(avctx, &s->qsv); +} + AVHWAccel ff_vc1_qsv_hwaccel = { .name = "vc1_qsv", .type = AVMEDIA_TYPE_VIDEO, @@ -81,7 +87,7 @@ AVCodec ff_vc1_qsv_decoder = { .id = AV_CODEC_ID_VC1, .init = NULL, .decode = qsv_decode_frame, - .flush = NULL, + .flush = qsv_decode_flush, .close = qsv_decode_close, .capabilities = AV_CODEC_CAP_DELAY, .priv_class = &class,