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.
Showing the changes to libavcodec/vaapi_encode.c (1 of 2 files). Show all
Unified · Split
| @@ -218,6 +218,33 @@ static int vaapi_encode_make_row_slice(AVCodecContext *avctx, · 217 unmodified lines | |||
| 218 | return 0; | 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 | static int vaapi_encode_issue(AVCodecContext *avctx, | 248 | static int vaapi_encode_issue(AVCodecContext *avctx, |
| 222 | VAAPIEncodePicture *pic) | 249 | VAAPIEncodePicture *pic) |
| 223 | { | 250 | { |
| @@ -407,7 +434,10 @@ static int vaapi_encode_issue(AVCodecContext *avctx, · 183 unmodified lines | |||
| 407 | goto fail; | 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 | for (i = 0; i < pic->nb_slices; i++) { | 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 | return 0; | 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 | static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) | 1997 | static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) |
| 1907 | { | 1998 | { |
| 1908 | VAAPIEncodeContext *ctx = avctx->priv_data; | 1999 | VAAPIEncodeContext *ctx = avctx->priv_data; |
| 1909 | VAConfigAttrib attr[2] = { { VAConfigAttribEncMaxSlices }, | 2000 | VAConfigAttrib attr[3] = { { VAConfigAttribEncMaxSlices }, |
| 1910 | { VAConfigAttribEncSliceStructure } }; | 2001 | { VAConfigAttribEncSliceStructure }, |
| 2002 | #if VA_CHECK_VERSION(1, 1, 0) | ||
| 2003 | { VAConfigAttribEncTileSupport }, | ||
| 2004 | #endif | ||
| 2005 | }; | ||
| 1911 | VAStatus vas; | 2006 | VAStatus vas; |
| 1912 | uint32_t max_slices, slice_structure; | 2007 | uint32_t max_slices, slice_structure; |
| 1913 | int ret; | 2008 | int ret; |
| @@ -1925,7 +2020,7 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) · 11 unmodified lines | |||
| 1925 | ctx->slice_block_cols = (avctx->width + ctx->slice_block_width - 1) / | 2020 | ctx->slice_block_cols = (avctx->width + ctx->slice_block_width - 1) / |
| 1926 | ctx->slice_block_width; | 2021 | ctx->slice_block_width; |
| 1927 | 2022 | ||
| 1928 | if (avctx->slices <= 1) { | 2023 | if (avctx->slices <= 1 && !ctx->tile_rows && !ctx->tile_cols) { |
| 1929 | ctx->nb_slices = 1; | 2024 | ctx->nb_slices = 1; |
| 1930 | ctx->slice_size = ctx->slice_block_rows; | 2025 | ctx->slice_size = ctx->slice_block_rows; |
| 1931 | return 0; | 2026 | return 0; |
| @@ -1949,7 +2044,25 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) · 17 unmodified lines | |||
| 1949 | return AVERROR(EINVAL); | 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 | if (ret < 0) | 2066 | if (ret < 0) |
| 1954 | return ret; | 2067 | return ret; |
| 1955 | 2068 | ||
| @@ -1965,9 +2078,8 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) · 9 unmodified lines | |||
| 1965 | return AVERROR(EINVAL); | 2078 | return AVERROR(EINVAL); |
| 1966 | } | 2079 | } |
| 1967 | 2080 | ||
| 1968 | av_log(avctx, AV_LOG_VERBOSE, "Encoding pictures with %d slices " | 2081 | av_log(avctx, AV_LOG_VERBOSE, "Encoding pictures with %d slices.\n", |
| 1969 | "(default size %d block rows).\n", | 2082 | ctx->nb_slices); |
| 1970 | ctx->nb_slices, ctx->slice_size); | ||
| 1971 | return 0; | 2083 | return 0; |
| 1972 | } | 2084 | } |
| 1973 | 2085 | ||