mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
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:
parent
65f4d561c9
commit
a7c2cdf0f6
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user