From: Mark Thompson Date: Mon, 12 Dec 2016 21:25:28 +0000 (+0000) Subject: vaapi_encode: Support forcing IDR frames via AVFrame.pict_type X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=c667c0979cbc2e04d1d00964b82ac49746caa43c;p=ffmpeg vaapi_encode: Support forcing IDR frames via AVFrame.pict_type (cherry picked from commit a3c3a5eac20a51d402c332cdf5220fff40a7943f) --- diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index d050ead1ada..6aaf14aa368 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -590,6 +590,10 @@ static int vaapi_encode_step(AVCodecContext *avctx, } else if (ctx->issue_mode == ISSUE_MODE_MAXIMISE_THROUGHPUT) { int activity; + // Run through the list of all available pictures repeatedly + // and issue the first one found which has all dependencies + // available (including previously-issued but not necessarily + // completed pictures). do { activity = 0; for (pic = ctx->pic_start; pic; pic = pic->next) { @@ -605,9 +609,15 @@ static int vaapi_encode_step(AVCodecContext *avctx, if (err < 0) return err; activity = 1; + // Start again from the beginning of the list, + // because issuing this picture may have satisfied + // forward dependencies of earlier ones. + break; } } while(activity); + // If we had a defined target for this step then it will + // always have been issued by now. if (target) { av_assert0(target->encode_issued && "broken dependencies?"); } @@ -639,8 +649,10 @@ static int vaapi_encode_get_next(AVCodecContext *avctx, if (!pic) return AVERROR(ENOMEM); - if (ctx->input_order == 0 || ctx->gop_counter >= avctx->gop_size) { + if (ctx->input_order == 0 || ctx->force_idr || + ctx->gop_counter >= avctx->gop_size) { pic->type = PICTURE_TYPE_IDR; + ctx->force_idr = 0; ctx->gop_counter = 1; ctx->p_counter = 0; } else if (ctx->p_counter >= ctx->p_per_i) { @@ -722,7 +734,7 @@ fail: return AVERROR(ENOMEM); } -static int vaapi_encode_mangle_end(AVCodecContext *avctx) +static int vaapi_encode_truncate_gop(AVCodecContext *avctx) { VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodePicture *pic, *last_pic, *next; @@ -772,7 +784,7 @@ static int vaapi_encode_mangle_end(AVCodecContext *avctx) // mangle anything. } - av_log(avctx, AV_LOG_DEBUG, "Pictures at end of stream:"); + av_log(avctx, AV_LOG_DEBUG, "Pictures ending truncated GOP:"); for (pic = ctx->pic_start; pic; pic = pic->next) { av_log(avctx, AV_LOG_DEBUG, " %s (%"PRId64"/%"PRId64")", picture_type_name[pic->type], @@ -826,6 +838,13 @@ int ff_vaapi_encode2(AVCodecContext *avctx, AVPacket *pkt, av_log(avctx, AV_LOG_DEBUG, "Encode frame: %ux%u (%"PRId64").\n", input_image->width, input_image->height, input_image->pts); + if (input_image->pict_type == AV_PICTURE_TYPE_I) { + err = vaapi_encode_truncate_gop(avctx); + if (err < 0) + goto fail; + ctx->force_idr = 1; + } + err = vaapi_encode_get_next(avctx, &pic); if (err) { av_log(avctx, AV_LOG_ERROR, "Input setup failed: %d.\n", err); @@ -854,7 +873,7 @@ int ff_vaapi_encode2(AVCodecContext *avctx, AVPacket *pkt, } else { if (!ctx->end_of_stream) { - err = vaapi_encode_mangle_end(avctx); + err = vaapi_encode_truncate_gop(avctx); if (err < 0) goto fail; ctx->end_of_stream = 1; diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index 7db219186ef..ed209c0c6e9 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -192,6 +192,7 @@ typedef struct VAAPIEncodeContext { // Frame type decision. int p_per_i; int b_per_p; + int force_idr; int gop_counter; int p_counter; int end_of_stream;