X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fvaapi_encode.c;h=518e5b2c00f8ff603d7d46c57e2c89f34bef9ca9;hb=76a4356a75fd1bb79101ac00bfb73303c369dfc8;hp=2cd2d1f82a8b3170fb498442dd98bc32278315b6;hpb=65f4d561c9dbd0a20ed9ed8c229dbbf3b89262ce;p=ffmpeg diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 2cd2d1f82a8..518e5b2c00f 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -28,7 +28,7 @@ #include "encode.h" #include "avcodec.h" -const AVCodecHWConfigInternal *ff_vaapi_encode_hw_configs[] = { +const AVCodecHWConfigInternal *const ff_vaapi_encode_hw_configs[] = { HW_CONFIG_ENCODER_FRAMES(VAAPI, VAAPI), NULL, }; @@ -218,6 +218,33 @@ static int vaapi_encode_make_row_slice(AVCodecContext *avctx, return 0; } +static int vaapi_encode_make_tile_slice(AVCodecContext *avctx, + VAAPIEncodePicture *pic) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeSlice *slice; + int i, j, index; + + for (i = 0; i < ctx->tile_cols; i++) { + for (j = 0; j < ctx->tile_rows; j++) { + index = j * ctx->tile_cols + i; + slice = &pic->slices[index]; + slice->index = index; + + pic->slices[index].block_start = ctx->col_bd[i] + + ctx->row_bd[j] * ctx->slice_block_cols; + pic->slices[index].block_size = ctx->row_height[j] * ctx->col_width[i]; + + av_log(avctx, AV_LOG_DEBUG, "Slice %2d: (%2d, %2d) start at: %4d " + "width:%2d height:%2d (%d blocks).\n", index, ctx->col_bd[i], + ctx->row_bd[j], slice->block_start, ctx->col_width[i], + ctx->row_height[j], slice->block_size); + } + } + + return 0; +} + static int vaapi_encode_issue(AVCodecContext *avctx, VAAPIEncodePicture *pic) { @@ -407,7 +434,10 @@ static int vaapi_encode_issue(AVCodecContext *avctx, goto fail; } - vaapi_encode_make_row_slice(avctx, pic); + if (ctx->tile_rows && ctx->tile_cols) + vaapi_encode_make_tile_slice(avctx, pic); + else + vaapi_encode_make_row_slice(avctx, pic); } for (i = 0; i < pic->nb_slices; i++) { @@ -577,11 +607,9 @@ fail_with_picture: fail: for(i = 0; i < pic->nb_param_buffers; i++) vaDestroyBuffer(ctx->hwctx->display, pic->param_buffers[i]); - for (i = 0; i < pic->nb_slices; i++) { - if (pic->slices) { - av_freep(&pic->slices[i].priv_data); + if (pic->slices) { + for (i = 0; i < pic->nb_slices; i++) av_freep(&pic->slices[i].codec_slice_params); - } } fail_at_end: av_freep(&pic->codec_picture_params); @@ -712,11 +740,9 @@ static int vaapi_encode_free(AVCodecContext *avctx, if (pic->encode_issued) vaapi_encode_discard(avctx, pic); - for (i = 0; i < pic->nb_slices; i++) { - if (pic->slices) { - av_freep(&pic->slices[i].priv_data); + if (pic->slices) { + for (i = 0; i < pic->nb_slices; i++) av_freep(&pic->slices[i].codec_slice_params); - } } av_freep(&pic->codec_picture_params); @@ -1218,6 +1244,9 @@ static const VAAPIEncodeRTFormat vaapi_encode_rt_formats[] = { { "YUV400", VA_RT_FORMAT_YUV400, 8, 1, }, { "YUV420", VA_RT_FORMAT_YUV420, 8, 3, 1, 1 }, { "YUV422", VA_RT_FORMAT_YUV422, 8, 3, 1, 0 }, +#if VA_CHECK_VERSION(1, 2, 0) + { "YUV422_10", VA_RT_FORMAT_YUV422_10, 10, 3, 1, 0 }, +#endif { "YUV444", VA_RT_FORMAT_YUV444, 8, 3, 0, 0 }, { "YUV411", VA_RT_FORMAT_YUV411, 8, 3, 2, 0 }, #if VA_CHECK_VERSION(0, 38, 1) @@ -1875,9 +1904,6 @@ static av_cold int vaapi_encode_init_row_slice_structure(AVCodecContext *avctx, req_slices = avctx->slices; } if (slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS || -#if VA_CHECK_VERSION(1, 8, 0) - slice_structure & VA_ENC_SLICE_STRUCTURE_EQUAL_MULTI_ROWS || -#endif slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS) { ctx->nb_slices = req_slices; ctx->slice_size = ctx->slice_block_rows / ctx->nb_slices; @@ -1903,11 +1929,76 @@ static av_cold int vaapi_encode_init_row_slice_structure(AVCodecContext *avctx, return 0; } +static av_cold int vaapi_encode_init_tile_slice_structure(AVCodecContext *avctx, + uint32_t slice_structure) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + int i, req_tiles; + + if (!(slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS || + (slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS && + ctx->tile_cols == 1))) { + av_log(avctx, AV_LOG_ERROR, "Supported slice structure (%#x) doesn't work for " + "current tile requirement.\n", slice_structure); + return AVERROR(EINVAL); + } + + if (ctx->tile_rows > ctx->slice_block_rows || + ctx->tile_cols > ctx->slice_block_cols) { + av_log(avctx, AV_LOG_WARNING, "Not enough block rows/cols (%d x %d) " + "for configured number of tile (%d x %d); ", + ctx->slice_block_rows, ctx->slice_block_cols, + ctx->tile_rows, ctx->tile_cols); + ctx->tile_rows = ctx->tile_rows > ctx->slice_block_rows ? + ctx->slice_block_rows : ctx->tile_rows; + ctx->tile_cols = ctx->tile_cols > ctx->slice_block_cols ? + ctx->slice_block_cols : ctx->tile_cols; + av_log(avctx, AV_LOG_WARNING, "using allowed maximum (%d x %d).\n", + ctx->tile_rows, ctx->tile_cols); + } + + req_tiles = ctx->tile_rows * ctx->tile_cols; + + // Tile slice is not allowed to cross the boundary of a tile due to + // the constraints of media-driver. Currently we support one slice + // per tile. This could be extended to multiple slices per tile. + if (avctx->slices != req_tiles) + av_log(avctx, AV_LOG_WARNING, "The number of requested slices " + "mismatches with configured number of tile (%d != %d); " + "using requested tile number for slice.\n", + avctx->slices, req_tiles); + + ctx->nb_slices = req_tiles; + + // Default in uniform spacing + // 6-3, 6-5 + for (i = 0; i < ctx->tile_cols; i++) { + ctx->col_width[i] = ( i + 1 ) * ctx->slice_block_cols / ctx->tile_cols - + i * ctx->slice_block_cols / ctx->tile_cols; + ctx->col_bd[i + 1] = ctx->col_bd[i] + ctx->col_width[i]; + } + // 6-4, 6-6 + for (i = 0; i < ctx->tile_rows; i++) { + ctx->row_height[i] = ( i + 1 ) * ctx->slice_block_rows / ctx->tile_rows - + i * ctx->slice_block_rows / ctx->tile_rows; + ctx->row_bd[i + 1] = ctx->row_bd[i] + ctx->row_height[i]; + } + + av_log(avctx, AV_LOG_VERBOSE, "Encoding pictures with %d x %d tile.\n", + ctx->tile_rows, ctx->tile_cols); + + return 0; +} + static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) { VAAPIEncodeContext *ctx = avctx->priv_data; - VAConfigAttrib attr[2] = { { VAConfigAttribEncMaxSlices }, - { VAConfigAttribEncSliceStructure } }; + VAConfigAttrib attr[3] = { { VAConfigAttribEncMaxSlices }, + { VAConfigAttribEncSliceStructure }, +#if VA_CHECK_VERSION(1, 1, 0) + { VAConfigAttribEncTileSupport }, +#endif + }; VAStatus vas; uint32_t max_slices, slice_structure; int ret; @@ -1925,7 +2016,7 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) ctx->slice_block_cols = (avctx->width + ctx->slice_block_width - 1) / ctx->slice_block_width; - if (avctx->slices <= 1) { + if (avctx->slices <= 1 && !ctx->tile_rows && !ctx->tile_cols) { ctx->nb_slices = 1; ctx->slice_size = ctx->slice_block_rows; return 0; @@ -1949,7 +2040,25 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) return AVERROR(EINVAL); } - ret = vaapi_encode_init_row_slice_structure(avctx, slice_structure); + if (ctx->tile_rows && ctx->tile_cols) { +#if VA_CHECK_VERSION(1, 1, 0) + uint32_t tile_support = attr[2].value; + if (tile_support == VA_ATTRIB_NOT_SUPPORTED) { + av_log(avctx, AV_LOG_ERROR, "Driver does not support encoding " + "pictures as multiple tiles.\n."); + return AVERROR(EINVAL); + } +#else + av_log(avctx, AV_LOG_ERROR, "Tile encoding option is " + "not supported with this VAAPI version.\n"); + return AVERROR(EINVAL); +#endif + } + + if (ctx->tile_rows && ctx->tile_cols) + ret = vaapi_encode_init_tile_slice_structure(avctx, slice_structure); + else + ret = vaapi_encode_init_row_slice_structure(avctx, slice_structure); if (ret < 0) return ret; @@ -1965,9 +2074,8 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) return AVERROR(EINVAL); } - av_log(avctx, AV_LOG_VERBOSE, "Encoding pictures with %d slices " - "(default size %d block rows).\n", - ctx->nb_slices, ctx->slice_size); + av_log(avctx, AV_LOG_VERBOSE, "Encoding pictures with %d slices.\n", + ctx->nb_slices); return 0; }