[FFmpeg-cvslog] lavc/vaapi_encode: add tile slice encoding support
Linjie Fu
git at videolan.org
Mon Jul 20 10:49:43 EEST 2020
ffmpeg | branch: master | Linjie Fu <linjie.fu at intel.com> | Tue May 12 21:47:12 2020 +0800| [a7c2cdf0f6bc53d2bdf05fc92f20415a3de7045f] | committer: Linjie Fu
lavc/vaapi_encode: add tile slice encoding support
Add functions to initialize tile slice structure and make tile slice:
- vaapi_encode_init_tile_slice_structure
- vaapi_encode_make_tile_slice
Tile slice is not allowed to cross the boundary of a tile due to
the constraints of media-driver. Currently adding support for one
slice per tile.
N x N tile encoding is supposed to be supported with the the
capability of ARBITRARY_MACROBLOCKS slice structures.
N X 1 tile encoding should also work in ARBITRARY_ROWS slice
structure.
Signed-off-by: Linjie Fu <linjie.justin.fu at gmail.com>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=a7c2cdf0f6bc53d2bdf05fc92f20415a3de7045f
---
libavcodec/vaapi_encode.c | 128 +++++++++++++++++++++++++++++++++++++++++++---
libavcodec/vaapi_encode.h | 16 ++++++
2 files changed, 136 insertions(+), 8 deletions(-)
diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
index 2cd2d1f82a..1de43cc977 100644
--- a/libavcodec/vaapi_encode.c
+++ b/libavcodec/vaapi_encode.c
@@ -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++) {
@@ -1903,11 +1933,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 +2020,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 +2044,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 +2078,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;
}
diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h
index 85d2a8f616..6487a99604 100644
--- a/libavcodec/vaapi_encode.h
+++ b/libavcodec/vaapi_encode.h
@@ -43,6 +43,10 @@ enum {
MAX_PICTURE_REFERENCES = 2,
MAX_REORDER_DELAY = 16,
MAX_PARAM_BUFFER_SIZE = 1024,
+ // A.4.1: table A.6 allows at most 22 tile rows for any level.
+ MAX_TILE_ROWS = 22,
+ // A.4.1: table A.6 allows at most 20 tile columns for any level.
+ MAX_TILE_COLS = 20,
};
extern const AVCodecHWConfigInternal *ff_vaapi_encode_hw_configs[];
@@ -302,6 +306,18 @@ typedef struct VAAPIEncodeContext {
int nb_slices;
int slice_size;
+ // Tile encoding.
+ int tile_rows;
+ int tile_cols;
+ // Tile width of the i-th column.
+ int col_width[MAX_TILE_COLS];
+ // Tile height of i-th row.
+ int row_height[MAX_TILE_ROWS];
+ // Location of the i-th tile column boundary.
+ int col_bd[MAX_TILE_COLS + 1];
+ // Location of the i-th tile row boundary.
+ int row_bd[MAX_TILE_ROWS + 1];
+
// Frame type decision.
int gop_size;
int closed_gop;
More information about the ffmpeg-cvslog
mailing list