diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 22e7a46a85..6753e596a1 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -372,6 +372,8 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, ++q->zero_consume_run; if (q->zero_consume_run > 1) ff_qsv_print_warning(avctx, ret, "A decode call did not consume any data"); + } else if (!*sync && bs.DataOffset) { + ++q->buffered_count; } else { q->zero_consume_run = 0; } @@ -526,6 +528,16 @@ int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q, AV_PIX_FMT_NONE, AV_PIX_FMT_NONE }; enum AVPixelFormat qsv_format; + AVPacket zero_pkt = {0}; + + if (q->buffered_count) { + q->reinit_flag = 1; + /* decode zero-size pkt to flush the buffered pkt before reinit */ + q->buffered_count--; + return qsv_decode(avctx, q, frame, got_frame, &zero_pkt); + } + + q->reinit_flag = 0; qsv_format = ff_qsv_map_pixfmt(q->parser->format, &q->fourcc); if (qsv_format < 0) { diff --git a/libavcodec/qsvdec.h b/libavcodec/qsvdec.h index 5b7b03a48b..111536caba 100644 --- a/libavcodec/qsvdec.h +++ b/libavcodec/qsvdec.h @@ -53,6 +53,8 @@ typedef struct QSVContext { AVFifoBuffer *async_fifo; int zero_consume_run; + int buffered_count; + int reinit_flag; // the internal parser and codec context for parsing the data AVCodecParserContext *parser; diff --git a/libavcodec/qsvdec_h2645.c b/libavcodec/qsvdec_h2645.c index d9d2318d1a..b8a78aa81b 100644 --- a/libavcodec/qsvdec_h2645.c +++ b/libavcodec/qsvdec_h2645.c @@ -146,10 +146,11 @@ static int qsv_decode_frame(AVCodecContext *avctx, void *data, /* no more data */ if (av_fifo_size(s->packet_fifo) < sizeof(AVPacket)) return avpkt->size ? avpkt->size : ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, avpkt); - - av_packet_unref(&s->buffer_pkt); - - av_fifo_generic_read(s->packet_fifo, &s->buffer_pkt, sizeof(s->buffer_pkt), NULL); + /* in progress of reinit, no read from fifo and keep the buffer_pkt */ + if (!s->qsv.reinit_flag) { + av_packet_unref(&s->buffer_pkt); + av_fifo_generic_read(s->packet_fifo, &s->buffer_pkt, sizeof(s->buffer_pkt), NULL); + } } ret = ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, &s->buffer_pkt); @@ -159,6 +160,8 @@ static int qsv_decode_frame(AVCodecContext *avctx, void *data, av_packet_unref(&s->buffer_pkt); return ret; } + if (s->qsv.reinit_flag) + continue; s->buffer_pkt.size -= ret; s->buffer_pkt.data += ret; diff --git a/libavcodec/qsvdec_other.c b/libavcodec/qsvdec_other.c index 993c7a8e80..03251d2c85 100644 --- a/libavcodec/qsvdec_other.c +++ b/libavcodec/qsvdec_other.c @@ -132,9 +132,11 @@ static int qsv_decode_frame(AVCodecContext *avctx, void *data, /* no more data */ if (av_fifo_size(s->packet_fifo) < sizeof(AVPacket)) return avpkt->size ? avpkt->size : ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, avpkt); - - av_packet_unref(&s->input_ref); - av_fifo_generic_read(s->packet_fifo, &s->input_ref, sizeof(s->input_ref), NULL); + /* in progress of reinit, no read from fifo and keep the buffer_pkt */ + if (!s->qsv.reinit_flag) { + av_packet_unref(&s->input_ref); + av_fifo_generic_read(s->packet_fifo, &s->input_ref, sizeof(s->input_ref), NULL); + } } ret = ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, &s->input_ref); @@ -145,6 +147,8 @@ static int qsv_decode_frame(AVCodecContext *avctx, void *data, return ret; } + if (s->qsv.reinit_flag) + continue; s->input_ref.size -= ret; s->input_ref.data += ret;