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