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@gmail.com>
This commit is contained in:
Linjie Fu 2020-05-12 21:47:12 +08:00
parent 65f4d561c9
commit a7c2cdf0f6
2 changed files with 136 additions and 8 deletions

View File

@ -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;
}

View File

@ -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;