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.
Unified · Split
| @@ -218,6 +218,33 @@ static int vaapi_encode_make_row_slice(AVCodecContext *avctx, · 217 unmodified lines | ||
| 218 | 218 | return 0; |
| 219 | 219 | } |
| 220 | 220 | |
| 221 | +static int vaapi_encode_make_tile_slice(AVCodecContext *avctx, | |
| 222 | + VAAPIEncodePicture *pic) | |
| 223 | +{ | |
| 224 | + VAAPIEncodeContext *ctx = avctx->priv_data; | |
| 225 | + VAAPIEncodeSlice *slice; | |
| 226 | + int i, j, index; | |
| 227 | + | |
| 228 | + for (i = 0; i < ctx->tile_cols; i++) { | |
| 229 | + for (j = 0; j < ctx->tile_rows; j++) { | |
| 230 | + index = j * ctx->tile_cols + i; | |
| 231 | + slice = &pic->slices[index]; | |
| 232 | + slice->index = index; | |
| 233 | + | |
| 234 | + pic->slices[index].block_start = ctx->col_bd[i] + | |
| 235 | + ctx->row_bd[j] * ctx->slice_block_cols; | |
| 236 | + pic->slices[index].block_size = ctx->row_height[j] * ctx->col_width[i]; | |
| 237 | + | |
| 238 | + av_log(avctx, AV_LOG_DEBUG, "Slice %2d: (%2d, %2d) start at: %4d " | |
| 239 | + "width:%2d height:%2d (%d blocks).\n", index, ctx->col_bd[i], | |
| 240 | + ctx->row_bd[j], slice->block_start, ctx->col_width[i], | |
| 241 | + ctx->row_height[j], slice->block_size); | |
| 242 | + } | |
| 243 | + } | |
| 244 | + | |
| 245 | + return 0; | |
| 246 | +} | |
| 247 | + | |
| 221 | 248 | static int vaapi_encode_issue(AVCodecContext *avctx, |
| 222 | 249 | VAAPIEncodePicture *pic) |
| 223 | 250 | { |
| @@ -407,7 +434,10 @@ static int vaapi_encode_issue(AVCodecContext *avctx, · 183 unmodified lines | ||
| 407 | 434 | goto fail; |
| 408 | 435 | } |
| 409 | 436 | |
| 410 | − vaapi_encode_make_row_slice(avctx, pic); | |
| 437 | + if (ctx->tile_rows && ctx->tile_cols) | |
| 438 | + vaapi_encode_make_tile_slice(avctx, pic); | |
| 439 | + else | |
| 440 | + vaapi_encode_make_row_slice(avctx, pic); | |
| 411 | 441 | } |
| 412 | 442 | |
| 413 | 443 | for (i = 0; i < pic->nb_slices; i++) { |
| @@ -1903,11 +1933,76 @@ static av_cold int vaapi_encode_init_row_slice_structure(AVCodecContext *avctx, · 1489 unmodified lines | ||
| 1903 | 1933 | return 0; |
| 1904 | 1934 | } |
| 1905 | 1935 | |
| 1936 | +static av_cold int vaapi_encode_init_tile_slice_structure(AVCodecContext *avctx, | |
| 1937 | + uint32_t slice_structure) | |
| 1938 | +{ | |
| 1939 | + VAAPIEncodeContext *ctx = avctx->priv_data; | |
| 1940 | + int i, req_tiles; | |
| 1941 | + | |
| 1942 | + if (!(slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS || | |
| 1943 | + (slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS && | |
| 1944 | + ctx->tile_cols == 1))) { | |
| 1945 | + av_log(avctx, AV_LOG_ERROR, "Supported slice structure (%#x) doesn't work for " | |
| 1946 | + "current tile requirement.\n", slice_structure); | |
| 1947 | + return AVERROR(EINVAL); | |
| 1948 | + } | |
| 1949 | + | |
| 1950 | + if (ctx->tile_rows > ctx->slice_block_rows || | |
| 1951 | + ctx->tile_cols > ctx->slice_block_cols) { | |
| 1952 | + av_log(avctx, AV_LOG_WARNING, "Not enough block rows/cols (%d x %d) " | |
| 1953 | + "for configured number of tile (%d x %d); ", | |
| 1954 | + ctx->slice_block_rows, ctx->slice_block_cols, | |
| 1955 | + ctx->tile_rows, ctx->tile_cols); | |
| 1956 | + ctx->tile_rows = ctx->tile_rows > ctx->slice_block_rows ? | |
| 1957 | + ctx->slice_block_rows : ctx->tile_rows; | |
| 1958 | + ctx->tile_cols = ctx->tile_cols > ctx->slice_block_cols ? | |
| 1959 | + ctx->slice_block_cols : ctx->tile_cols; | |
| 1960 | + av_log(avctx, AV_LOG_WARNING, "using allowed maximum (%d x %d).\n", | |
| 1961 | + ctx->tile_rows, ctx->tile_cols); | |
| 1962 | + } | |
| 1963 | + | |
| 1964 | + req_tiles = ctx->tile_rows * ctx->tile_cols; | |
| 1965 | + | |
| 1966 | + // Tile slice is not allowed to cross the boundary of a tile due to | |
| 1967 | + // the constraints of media-driver. Currently we support one slice | |
| 1968 | + // per tile. This could be extended to multiple slices per tile. | |
| 1969 | + if (avctx->slices != req_tiles) | |
| 1970 | + av_log(avctx, AV_LOG_WARNING, "The number of requested slices " | |
| 1971 | + "mismatches with configured number of tile (%d != %d); " | |
| 1972 | + "using requested tile number for slice.\n", | |
| 1973 | + avctx->slices, req_tiles); | |
| 1974 | + | |
| 1975 | + ctx->nb_slices = req_tiles; | |
| 1976 | + | |
| 1977 | + // Default in uniform spacing | |
| 1978 | + // 6-3, 6-5 | |
| 1979 | + for (i = 0; i < ctx->tile_cols; i++) { | |
| 1980 | + ctx->col_width[i] = ( i + 1 ) * ctx->slice_block_cols / ctx->tile_cols - | |
| 1981 | + i * ctx->slice_block_cols / ctx->tile_cols; | |
| 1982 | + ctx->col_bd[i + 1] = ctx->col_bd[i] + ctx->col_width[i]; | |
| 1983 | + } | |
| 1984 | + // 6-4, 6-6 | |
| 1985 | + for (i = 0; i < ctx->tile_rows; i++) { | |
| 1986 | + ctx->row_height[i] = ( i + 1 ) * ctx->slice_block_rows / ctx->tile_rows - | |
| 1987 | + i * ctx->slice_block_rows / ctx->tile_rows; | |
| 1988 | + ctx->row_bd[i + 1] = ctx->row_bd[i] + ctx->row_height[i]; | |
| 1989 | + } | |
| 1990 | + | |
| 1991 | + av_log(avctx, AV_LOG_VERBOSE, "Encoding pictures with %d x %d tile.\n", | |
| 1992 | + ctx->tile_rows, ctx->tile_cols); | |
| 1993 | + | |
| 1994 | + return 0; | |
| 1995 | +} | |
| 1996 | + | |
| 1906 | 1997 | static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) |
| 1907 | 1998 | { |
| 1908 | 1999 | VAAPIEncodeContext *ctx = avctx->priv_data; |
| 1909 | − VAConfigAttrib attr[2] = { { VAConfigAttribEncMaxSlices }, | |
| 1910 | − { VAConfigAttribEncSliceStructure } }; | |
| 2000 | + VAConfigAttrib attr[3] = { { VAConfigAttribEncMaxSlices }, | |
| 2001 | + { VAConfigAttribEncSliceStructure }, | |
| 2002 | +#if VA_CHECK_VERSION(1, 1, 0) | |
| 2003 | + { VAConfigAttribEncTileSupport }, | |
| 2004 | +#endif | |
| 2005 | + }; | |
| 1911 | 2006 | VAStatus vas; |
| 1912 | 2007 | uint32_t max_slices, slice_structure; |
| 1913 | 2008 | int ret; |
| @@ -1925,7 +2020,7 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) · 11 unmodified lines | ||
| 1925 | 2020 | ctx->slice_block_cols = (avctx->width + ctx->slice_block_width - 1) / |
| 1926 | 2021 | ctx->slice_block_width; |
| 1927 | 2022 | |
| 1928 | − if (avctx->slices <= 1) { | |
| 2023 | + if (avctx->slices <= 1 && !ctx->tile_rows && !ctx->tile_cols) { | |
| 1929 | 2024 | ctx->nb_slices = 1; |
| 1930 | 2025 | ctx->slice_size = ctx->slice_block_rows; |
| 1931 | 2026 | return 0; |
| @@ -1949,7 +2044,25 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) · 17 unmodified lines | ||
| 1949 | 2044 | return AVERROR(EINVAL); |
| 1950 | 2045 | } |
| 1951 | 2046 | |
| 1952 | − ret = vaapi_encode_init_row_slice_structure(avctx, slice_structure); | |
| 2047 | + if (ctx->tile_rows && ctx->tile_cols) { | |
| 2048 | +#if VA_CHECK_VERSION(1, 1, 0) | |
| 2049 | + uint32_t tile_support = attr[2].value; | |
| 2050 | + if (tile_support == VA_ATTRIB_NOT_SUPPORTED) { | |
| 2051 | + av_log(avctx, AV_LOG_ERROR, "Driver does not support encoding " | |
| 2052 | + "pictures as multiple tiles.\n."); | |
| 2053 | + return AVERROR(EINVAL); | |
| 2054 | + } | |
| 2055 | +#else | |
| 2056 | + av_log(avctx, AV_LOG_ERROR, "Tile encoding option is " | |
| 2057 | + "not supported with this VAAPI version.\n"); | |
| 2058 | + return AVERROR(EINVAL); | |
| 2059 | +#endif | |
| 2060 | + } | |
| 2061 | + | |
| 2062 | + if (ctx->tile_rows && ctx->tile_cols) | |
| 2063 | + ret = vaapi_encode_init_tile_slice_structure(avctx, slice_structure); | |
| 2064 | + else | |
| 2065 | + ret = vaapi_encode_init_row_slice_structure(avctx, slice_structure); | |
| 1953 | 2066 | if (ret < 0) |
| 1954 | 2067 | return ret; |
| 1955 | 2068 | |
| @@ -1965,9 +2078,8 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) · 9 unmodified lines | ||
| 1965 | 2078 | return AVERROR(EINVAL); |
| 1966 | 2079 | } |
| 1967 | 2080 | |
| 1968 | − av_log(avctx, AV_LOG_VERBOSE, "Encoding pictures with %d slices " | |
| 1969 | − "(default size %d block rows).\n", | |
| 1970 | − ctx->nb_slices, ctx->slice_size); | |
| 2081 | + av_log(avctx, AV_LOG_VERBOSE, "Encoding pictures with %d slices.\n", | |
| 2082 | + ctx->nb_slices); | |
| 1971 | 2083 | return 0; |
| 1972 | 2084 | } |
| 1973 | 2085 | |
| @@ -43,6 +43,10 @@ enum { · 42 unmodified lines | ||
| 43 | 43 | MAX_PICTURE_REFERENCES = 2, |
| 44 | 44 | MAX_REORDER_DELAY = 16, |
| 45 | 45 | MAX_PARAM_BUFFER_SIZE = 1024, |
| 46 | + // A.4.1: table A.6 allows at most 22 tile rows for any level. | |
| 47 | + MAX_TILE_ROWS = 22, | |
| 48 | + // A.4.1: table A.6 allows at most 20 tile columns for any level. | |
| 49 | + MAX_TILE_COLS = 20, | |
| 46 | 50 | }; |
| 47 | 51 | |
| 48 | 52 | extern const AVCodecHWConfigInternal *ff_vaapi_encode_hw_configs[]; |
| @@ -302,6 +306,18 @@ typedef struct VAAPIEncodeContext { · 253 unmodified lines | ||
| 302 | 306 | int nb_slices; |
| 303 | 307 | int slice_size; |
| 304 | 308 | |
| 309 | + // Tile encoding. | |
| 310 | + int tile_rows; | |
| 311 | + int tile_cols; | |
| 312 | + // Tile width of the i-th column. | |
| 313 | + int col_width[MAX_TILE_COLS]; | |
| 314 | + // Tile height of i-th row. | |
| 315 | + int row_height[MAX_TILE_ROWS]; | |
| 316 | + // Location of the i-th tile column boundary. | |
| 317 | + int col_bd[MAX_TILE_COLS + 1]; | |
| 318 | + // Location of the i-th tile row boundary. | |
| 319 | + int row_bd[MAX_TILE_ROWS + 1]; | |
| 320 | + | |
| 305 | 321 | // Frame type decision. |
| 306 | 322 | int gop_size; |
| 307 | 323 | int closed_gop; |