diff options
author | Linjie Fu <linjie.fu@intel.com> | 2020-05-12 21:47:11 +0800 |
---|---|---|
committer | Linjie Fu <linjie.fu@intel.com> | 2020-07-20 15:26:35 +0800 |
commit | 65f4d561c9dbd0a20ed9ed8c229dbbf3b89262ce (patch) | |
tree | 7632d6b4439d1958fcf4133bb833ab7862ec6263 /libavcodec | |
parent | 2c1cc326e9a76f4d0a1b30345f4b803272efde17 (diff) | |
download | ffmpeg-65f4d561c9dbd0a20ed9ed8c229dbbf3b89262ce.tar.gz |
lavc/vaapi_encode: wrap slice codes into row slice functions
Wrap current whole-row slice codes into following functions:
- vaapi_encode_make_row_slice()
- vaapi_encode_init_row_slice_structure()
Signed-off-by: Linjie Fu <linjie.justin.fu@gmail.com>
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/vaapi_encode.c | 190 |
1 files changed, 109 insertions, 81 deletions
diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index d6a986d5f0..2cd2d1f82a 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -163,6 +163,61 @@ static int vaapi_encode_wait(AVCodecContext *avctx, return 0; } +static int vaapi_encode_make_row_slice(AVCodecContext *avctx, + VAAPIEncodePicture *pic) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeSlice *slice; + int i, rounding; + + for (i = 0; i < pic->nb_slices; i++) + pic->slices[i].row_size = ctx->slice_size; + + rounding = ctx->slice_block_rows - ctx->nb_slices * ctx->slice_size; + if (rounding > 0) { + // Place rounding error at top and bottom of frame. + av_assert0(rounding < pic->nb_slices); + // Some Intel drivers contain a bug where the encoder will fail + // if the last slice is smaller than the one before it. Since + // that's straightforward to avoid here, just do so. + if (rounding <= 2) { + for (i = 0; i < rounding; i++) + ++pic->slices[i].row_size; + } else { + for (i = 0; i < (rounding + 1) / 2; i++) + ++pic->slices[pic->nb_slices - i - 1].row_size; + for (i = 0; i < rounding / 2; i++) + ++pic->slices[i].row_size; + } + } else if (rounding < 0) { + // Remove rounding error from last slice only. + av_assert0(rounding < ctx->slice_size); + pic->slices[pic->nb_slices - 1].row_size += rounding; + } + + for (i = 0; i < pic->nb_slices; i++) { + slice = &pic->slices[i]; + slice->index = i; + if (i == 0) { + slice->row_start = 0; + slice->block_start = 0; + } else { + const VAAPIEncodeSlice *prev = &pic->slices[i - 1]; + slice->row_start = prev->row_start + prev->row_size; + slice->block_start = prev->block_start + prev->block_size; + } + slice->block_size = slice->row_size * ctx->slice_block_cols; + + av_log(avctx, AV_LOG_DEBUG, "Slice %d: %d-%d (%d rows), " + "%d-%d (%d blocks).\n", i, slice->row_start, + slice->row_start + slice->row_size - 1, slice->row_size, + slice->block_start, slice->block_start + slice->block_size - 1, + slice->block_size); + } + + return 0; +} + static int vaapi_encode_issue(AVCodecContext *avctx, VAAPIEncodePicture *pic) { @@ -346,57 +401,17 @@ static int vaapi_encode_issue(AVCodecContext *avctx, if (pic->nb_slices == 0) pic->nb_slices = ctx->nb_slices; if (pic->nb_slices > 0) { - int rounding; - pic->slices = av_mallocz_array(pic->nb_slices, sizeof(*pic->slices)); if (!pic->slices) { err = AVERROR(ENOMEM); goto fail; } - for (i = 0; i < pic->nb_slices; i++) - pic->slices[i].row_size = ctx->slice_size; - - rounding = ctx->slice_block_rows - ctx->nb_slices * ctx->slice_size; - if (rounding > 0) { - // Place rounding error at top and bottom of frame. - av_assert0(rounding < pic->nb_slices); - // Some Intel drivers contain a bug where the encoder will fail - // if the last slice is smaller than the one before it. Since - // that's straightforward to avoid here, just do so. - if (rounding <= 2) { - for (i = 0; i < rounding; i++) - ++pic->slices[i].row_size; - } else { - for (i = 0; i < (rounding + 1) / 2; i++) - ++pic->slices[pic->nb_slices - i - 1].row_size; - for (i = 0; i < rounding / 2; i++) - ++pic->slices[i].row_size; - } - } else if (rounding < 0) { - // Remove rounding error from last slice only. - av_assert0(rounding < ctx->slice_size); - pic->slices[pic->nb_slices - 1].row_size += rounding; - } + vaapi_encode_make_row_slice(avctx, pic); } + for (i = 0; i < pic->nb_slices; i++) { slice = &pic->slices[i]; - slice->index = i; - if (i == 0) { - slice->row_start = 0; - slice->block_start = 0; - } else { - const VAAPIEncodeSlice *prev = &pic->slices[i - 1]; - slice->row_start = prev->row_start + prev->row_size; - slice->block_start = prev->block_start + prev->block_size; - } - slice->block_size = slice->row_size * ctx->slice_block_cols; - - av_log(avctx, AV_LOG_DEBUG, "Slice %d: %d-%d (%d rows), " - "%d-%d (%d blocks).\n", i, slice->row_start, - slice->row_start + slice->row_size - 1, slice->row_size, - slice->block_start, slice->block_start + slice->block_size - 1, - slice->block_size); if (ctx->codec->slice_params_size > 0) { slice->codec_slice_params = av_mallocz(ctx->codec->slice_params_size); @@ -1840,6 +1855,54 @@ static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx) return 0; } +static av_cold int vaapi_encode_init_row_slice_structure(AVCodecContext *avctx, + uint32_t slice_structure) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + int req_slices; + + // For fixed-size slices currently we only support whole rows, making + // rectangular slices. This could be extended to arbitrary runs of + // blocks, but since slices tend to be a conformance requirement and + // most cases (such as broadcast or bluray) want rectangular slices + // only it would need to be gated behind another option. + if (avctx->slices > ctx->slice_block_rows) { + av_log(avctx, AV_LOG_WARNING, "Not enough rows to use " + "configured number of slices (%d < %d); using " + "maximum.\n", ctx->slice_block_rows, avctx->slices); + req_slices = ctx->slice_block_rows; + } else { + 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; + } else if (slice_structure & VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS) { + int k; + for (k = 1;; k *= 2) { + if (2 * k * (req_slices - 1) + 1 >= ctx->slice_block_rows) + break; + } + ctx->nb_slices = (ctx->slice_block_rows + k - 1) / k; + ctx->slice_size = k; +#if VA_CHECK_VERSION(1, 0, 0) + } else if (slice_structure & VA_ENC_SLICE_STRUCTURE_EQUAL_ROWS) { + ctx->nb_slices = ctx->slice_block_rows; + ctx->slice_size = 1; +#endif + } else { + av_log(avctx, AV_LOG_ERROR, "Driver does not support any usable " + "slice structure modes (%#x).\n", slice_structure); + return AVERROR(EINVAL); + } + + return 0; +} + static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) { VAAPIEncodeContext *ctx = avctx->priv_data; @@ -1847,7 +1910,7 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) { VAConfigAttribEncSliceStructure } }; VAStatus vas; uint32_t max_slices, slice_structure; - int req_slices; + int ret; if (!(ctx->codec->flags & FLAG_SLICE_CONTROL)) { if (avctx->slices > 0) { @@ -1886,44 +1949,9 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) return AVERROR(EINVAL); } - // For fixed-size slices currently we only support whole rows, making - // rectangular slices. This could be extended to arbitrary runs of - // blocks, but since slices tend to be a conformance requirement and - // most cases (such as broadcast or bluray) want rectangular slices - // only it would need to be gated behind another option. - if (avctx->slices > ctx->slice_block_rows) { - av_log(avctx, AV_LOG_WARNING, "Not enough rows to use " - "configured number of slices (%d < %d); using " - "maximum.\n", ctx->slice_block_rows, avctx->slices); - req_slices = ctx->slice_block_rows; - } else { - 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; - } else if (slice_structure & VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS) { - int k; - for (k = 1;; k *= 2) { - if (2 * k * (req_slices - 1) + 1 >= ctx->slice_block_rows) - break; - } - ctx->nb_slices = (ctx->slice_block_rows + k - 1) / k; - ctx->slice_size = k; -#if VA_CHECK_VERSION(1, 0, 0) - } else if (slice_structure & VA_ENC_SLICE_STRUCTURE_EQUAL_ROWS) { - ctx->nb_slices = ctx->slice_block_rows; - ctx->slice_size = 1; -#endif - } else { - av_log(avctx, AV_LOG_ERROR, "Driver does not support any usable " - "slice structure modes (%#x).\n", slice_structure); - return AVERROR(EINVAL); - } + ret = vaapi_encode_init_row_slice_structure(avctx, slice_structure); + if (ret < 0) + return ret; if (ctx->nb_slices > avctx->slices) { av_log(avctx, AV_LOG_WARNING, "Slice count rounded up to " |