[FFmpeg-devel] [PATCH] libavcodec/qsvenc: Flush cached frames before reset encoder
wenbin.chen at intel.com
wenbin.chen at intel.com
Mon Feb 13 07:39:31 EET 2023
From: Wenbin Chen <wenbin.chen at intel.com>
According to https://github.com/Intel-Media-SDK/MediaSDK/blob/master/doc/mediasdk-man.md#configuration-change.
Before calling MFXVideoENCODE_Reset, The application needs to retrieve
any cached frames in the SDK encoder.
A loop is added before MFXVideoENCODE_Reset to retrieve cached frames
and add them to async_fifo, so that dynamic configuration works when
async_depth > 1.
Signed-off-by: Wenbin Chen <wenbin.chen at intel.com>
---
libavcodec/qsvenc.c | 118 +++++++++++++++++++++++---------------------
1 file changed, 63 insertions(+), 55 deletions(-)
diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
index 2f0e94a914..f3b488dec8 100644
--- a/libavcodec/qsvenc.c
+++ b/libavcodec/qsvenc.c
@@ -1600,7 +1600,7 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q)
q->param.AsyncDepth = q->async_depth;
- q->async_fifo = av_fifo_alloc2(q->async_depth, sizeof(QSVPacket), 0);
+ q->async_fifo = av_fifo_alloc2(q->async_depth, sizeof(QSVPacket), AV_FIFO_FLAG_AUTO_GROW);
if (!q->async_fifo)
return AVERROR(ENOMEM);
@@ -2296,58 +2296,6 @@ static int update_pic_timing_sei(AVCodecContext *avctx, QSVEncContext *q)
return updated;
}
-static int update_parameters(AVCodecContext *avctx, QSVEncContext *q,
- const AVFrame *frame)
-{
- int needReset = 0, ret = 0;
-
- if (!frame || avctx->codec_id == AV_CODEC_ID_MJPEG)
- return 0;
-
- needReset = update_qp(avctx, q);
- needReset |= update_max_frame_size(avctx, q);
- needReset |= update_gop_size(avctx, q);
- needReset |= update_rir(avctx, q);
- needReset |= update_low_delay_brc(avctx, q);
- needReset |= update_frame_rate(avctx, q);
- needReset |= update_bitrate(avctx, q);
- needReset |= update_pic_timing_sei(avctx, q);
- ret = update_min_max_qp(avctx, q);
- if (ret < 0)
- return ret;
- needReset |= ret;
- if (!needReset)
- return 0;
-
- if (avctx->hwaccel_context) {
- AVQSVContext *qsv = avctx->hwaccel_context;
- int i, j;
- q->param.ExtParam = q->extparam;
- for (i = 0; i < qsv->nb_ext_buffers; i++)
- q->param.ExtParam[i] = qsv->ext_buffers[i];
- q->param.NumExtParam = qsv->nb_ext_buffers;
-
- for (i = 0; i < q->nb_extparam_internal; i++) {
- for (j = 0; j < qsv->nb_ext_buffers; j++) {
- if (qsv->ext_buffers[j]->BufferId == q->extparam_internal[i]->BufferId)
- break;
- }
- if (j < qsv->nb_ext_buffers)
- continue;
- q->param.ExtParam[q->param.NumExtParam++] = q->extparam_internal[i];
- }
- } else {
- q->param.ExtParam = q->extparam_internal;
- q->param.NumExtParam = q->nb_extparam_internal;
- }
- av_log(avctx, AV_LOG_DEBUG, "Parameter change, call msdk reset.\n");
- ret = MFXVideoENCODE_Reset(q->session, &q->param);
- if (ret < 0)
- return ff_qsv_print_error(avctx, ret, "Error during resetting");
-
- return 0;
-}
-
static int encode_frame(AVCodecContext *avctx, QSVEncContext *q,
const AVFrame *frame)
{
@@ -2438,7 +2386,7 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q,
if (ret < 0) {
ret = (ret == MFX_ERR_MORE_DATA) ?
- 0 : ff_qsv_print_error(avctx, ret, "Error during encoding");
+ AVERROR(EAGAIN) : ff_qsv_print_error(avctx, ret, "Error during encoding");
goto free;
}
@@ -2466,6 +2414,66 @@ nomem:
goto free;
}
+static int update_parameters(AVCodecContext *avctx, QSVEncContext *q,
+ const AVFrame *frame)
+{
+ int needReset = 0, ret = 0;
+
+ if (!frame || avctx->codec_id == AV_CODEC_ID_MJPEG)
+ return 0;
+
+ needReset = update_qp(avctx, q);
+ needReset |= update_max_frame_size(avctx, q);
+ needReset |= update_gop_size(avctx, q);
+ needReset |= update_rir(avctx, q);
+ needReset |= update_low_delay_brc(avctx, q);
+ needReset |= update_frame_rate(avctx, q);
+ needReset |= update_bitrate(avctx, q);
+ needReset |= update_pic_timing_sei(avctx, q);
+ ret = update_min_max_qp(avctx, q);
+ if (ret < 0)
+ return ret;
+ needReset |= ret;
+ if (!needReset)
+ return 0;
+
+ if (avctx->hwaccel_context) {
+ AVQSVContext *qsv = avctx->hwaccel_context;
+ int i, j;
+ q->param.ExtParam = q->extparam;
+ for (i = 0; i < qsv->nb_ext_buffers; i++)
+ q->param.ExtParam[i] = qsv->ext_buffers[i];
+ q->param.NumExtParam = qsv->nb_ext_buffers;
+
+ for (i = 0; i < q->nb_extparam_internal; i++) {
+ for (j = 0; j < qsv->nb_ext_buffers; j++) {
+ if (qsv->ext_buffers[j]->BufferId == q->extparam_internal[i]->BufferId)
+ break;
+ }
+ if (j < qsv->nb_ext_buffers)
+ continue;
+ q->param.ExtParam[q->param.NumExtParam++] = q->extparam_internal[i];
+ }
+ } else {
+ q->param.ExtParam = q->extparam_internal;
+ q->param.NumExtParam = q->nb_extparam_internal;
+ }
+
+ // Flush codec before reset configuration.
+ while (ret != AVERROR(EAGAIN)) {
+ ret = encode_frame(avctx, q, NULL);
+ if (ret < 0 && ret != AVERROR(EAGAIN))
+ return ret;
+ }
+
+ av_log(avctx, AV_LOG_DEBUG, "Parameter change, call msdk reset.\n");
+ ret = MFXVideoENCODE_Reset(q->session, &q->param);
+ if (ret < 0)
+ return ff_qsv_print_error(avctx, ret, "Error during resetting");
+
+ return 0;
+}
+
int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q,
AVPacket *pkt, const AVFrame *frame, int *got_packet)
{
@@ -2476,7 +2484,7 @@ int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q,
return ret;
ret = encode_frame(avctx, q, frame);
- if (ret < 0)
+ if (ret < 0 && ret != AVERROR(EAGAIN))
return ret;
if ((av_fifo_can_read(q->async_fifo) >= q->async_depth) ||
--
2.34.1
More information about the ffmpeg-devel
mailing list