[FFmpeg-devel] [PATCH v2 2/4] lavc/vaapi_encode: wrap slice codes into row slice functions
Linjie Fu
linjie.fu at intel.com
Tue May 12 16:47:11 EEST 2020
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.fu at intel.com>
---
libavcodec/vaapi_encode.c | 190 ++++++++++++++++++++++++++--------------------
1 file changed, 109 insertions(+), 81 deletions(-)
diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
index 234618a..8deec02 100644
--- a/libavcodec/vaapi_encode.c
+++ b/libavcodec/vaapi_encode.c
@@ -162,6 +162,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)
{
@@ -345,57 +400,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);
@@ -1828,6 +1843,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;
@@ -1835,7 +1898,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) {
@@ -1874,44 +1937,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 "
--
2.7.4
More information about the ffmpeg-devel
mailing list