mirror of https://git.videolan.org/git/ffmpeg.git
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;
|
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,
|
static int vaapi_encode_issue(AVCodecContext *avctx,
|
||||||
VAAPIEncodePicture *pic)
|
VAAPIEncodePicture *pic)
|
||||||
{
|
{
|
||||||
|
@ -407,7 +434,10 @@ static int vaapi_encode_issue(AVCodecContext *avctx,
|
||||||
goto fail;
|
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++) {
|
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;
|
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)
|
static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx)
|
||||||
{
|
{
|
||||||
VAAPIEncodeContext *ctx = avctx->priv_data;
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
||||||
VAConfigAttrib attr[2] = { { VAConfigAttribEncMaxSlices },
|
VAConfigAttrib attr[3] = { { VAConfigAttribEncMaxSlices },
|
||||||
{ VAConfigAttribEncSliceStructure } };
|
{ VAConfigAttribEncSliceStructure },
|
||||||
|
#if VA_CHECK_VERSION(1, 1, 0)
|
||||||
|
{ VAConfigAttribEncTileSupport },
|
||||||
|
#endif
|
||||||
|
};
|
||||||
VAStatus vas;
|
VAStatus vas;
|
||||||
uint32_t max_slices, slice_structure;
|
uint32_t max_slices, slice_structure;
|
||||||
int ret;
|
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_cols = (avctx->width + ctx->slice_block_width - 1) /
|
||||||
ctx->slice_block_width;
|
ctx->slice_block_width;
|
||||||
|
|
||||||
if (avctx->slices <= 1) {
|
if (avctx->slices <= 1 && !ctx->tile_rows && !ctx->tile_cols) {
|
||||||
ctx->nb_slices = 1;
|
ctx->nb_slices = 1;
|
||||||
ctx->slice_size = ctx->slice_block_rows;
|
ctx->slice_size = ctx->slice_block_rows;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1949,7 +2044,25 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx)
|
||||||
return AVERROR(EINVAL);
|
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)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -1965,9 +2078,8 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx)
|
||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
av_log(avctx, AV_LOG_VERBOSE, "Encoding pictures with %d slices "
|
av_log(avctx, AV_LOG_VERBOSE, "Encoding pictures with %d slices.\n",
|
||||||
"(default size %d block rows).\n",
|
ctx->nb_slices);
|
||||||
ctx->nb_slices, ctx->slice_size);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,10 @@ enum {
|
||||||
MAX_PICTURE_REFERENCES = 2,
|
MAX_PICTURE_REFERENCES = 2,
|
||||||
MAX_REORDER_DELAY = 16,
|
MAX_REORDER_DELAY = 16,
|
||||||
MAX_PARAM_BUFFER_SIZE = 1024,
|
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[];
|
extern const AVCodecHWConfigInternal *ff_vaapi_encode_hw_configs[];
|
||||||
|
@ -302,6 +306,18 @@ typedef struct VAAPIEncodeContext {
|
||||||
int nb_slices;
|
int nb_slices;
|
||||||
int slice_size;
|
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.
|
// Frame type decision.
|
||||||
int gop_size;
|
int gop_size;
|
||||||
int closed_gop;
|
int closed_gop;
|
||||||
|
|
Loading…
Reference in New Issue