| File: | root/firefox-clang/media/ffvpx/libavcodec/vaapi_decode.c |
| Warning: | line 386, column 5 5th function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* | |||
| 2 | * This file is part of FFmpeg. | |||
| 3 | * | |||
| 4 | * FFmpeg is free software; you can redistribute it and/or | |||
| 5 | * modify it under the terms of the GNU Lesser General Public | |||
| 6 | * License as published by the Free Software Foundation; either | |||
| 7 | * version 2.1 of the License, or (at your option) any later version. | |||
| 8 | * | |||
| 9 | * FFmpeg is distributed in the hope that it will be useful, | |||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| 12 | * Lesser General Public License for more details. | |||
| 13 | * | |||
| 14 | * You should have received a copy of the GNU Lesser General Public | |||
| 15 | * License along with FFmpeg; if not, write to the Free Software | |||
| 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| 17 | */ | |||
| 18 | ||||
| 19 | #include "config_components.h" | |||
| 20 | ||||
| 21 | #include "libavutil/avassert.h" | |||
| 22 | #include "libavutil/common.h" | |||
| 23 | #include "libavutil/mem.h" | |||
| 24 | #include "libavutil/pixdesc.h" | |||
| 25 | ||||
| 26 | #include "avcodec.h" | |||
| 27 | #include "codec_desc.h" | |||
| 28 | #include "decode.h" | |||
| 29 | #include "internal.h" | |||
| 30 | #include "vaapi_decode.h" | |||
| 31 | #include "vaapi_hevc.h" | |||
| 32 | ||||
| 33 | ||||
| 34 | int ff_vaapi_decode_make_param_buffer(AVCodecContext *avctx, | |||
| 35 | VAAPIDecodePicture *pic, | |||
| 36 | int type, | |||
| 37 | const void *data, | |||
| 38 | size_t size) | |||
| 39 | { | |||
| 40 | VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; | |||
| 41 | VAStatus vas; | |||
| 42 | ||||
| 43 | av_assert0(pic->nb_param_buffers <= pic->nb_param_buffers_allocated)do { if (!(pic->nb_param_buffers <= pic->nb_param_buffers_allocated )) { av_log(((void*)0), 0, "Assertion %s failed at %s:%d\n", "pic->nb_param_buffers <= pic->nb_param_buffers_allocated" , "/root/firefox-clang/media/ffvpx/libavcodec/vaapi_decode.c" , 43); abort(); } } while (0); | |||
| 44 | if (pic->nb_param_buffers == pic->nb_param_buffers_allocated) { | |||
| 45 | VABufferID *tmp = | |||
| 46 | av_realloc_array(pic->param_buffers, | |||
| 47 | pic->nb_param_buffers_allocated + 16, | |||
| 48 | sizeof(*pic->param_buffers)); | |||
| 49 | if (!tmp) | |||
| 50 | return AVERROR(ENOMEM)(-(12)); | |||
| 51 | ||||
| 52 | pic->param_buffers = tmp; | |||
| 53 | pic->nb_param_buffers_allocated += 16; | |||
| 54 | } | |||
| 55 | av_assert0(pic->nb_param_buffers + 1 <= pic->nb_param_buffers_allocated)do { if (!(pic->nb_param_buffers + 1 <= pic->nb_param_buffers_allocated )) { av_log(((void*)0), 0, "Assertion %s failed at %s:%d\n", "pic->nb_param_buffers + 1 <= pic->nb_param_buffers_allocated" , "/root/firefox-clang/media/ffvpx/libavcodec/vaapi_decode.c" , 55); abort(); } } while (0); | |||
| 56 | ||||
| 57 | vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, | |||
| 58 | type, size, 1, (void*)data, | |||
| 59 | &pic->param_buffers[pic->nb_param_buffers]); | |||
| 60 | if (vas != VA_STATUS_SUCCESS0x00000000) { | |||
| 61 | av_log(avctx, AV_LOG_ERROR16, "Failed to create parameter " | |||
| 62 | "buffer (type %d): %d (%s).\n", | |||
| 63 | type, vas, vaErrorStr(vas)); | |||
| 64 | return AVERROR(EIO)(-(5)); | |||
| 65 | } | |||
| 66 | ||||
| 67 | av_log(avctx, AV_LOG_DEBUG48, "Param buffer (type %d, %zu bytes) " | |||
| 68 | "is %#x.\n", type, size, pic->param_buffers[pic->nb_param_buffers]); | |||
| 69 | ||||
| 70 | ++pic->nb_param_buffers; | |||
| 71 | ||||
| 72 | return 0; | |||
| 73 | } | |||
| 74 | ||||
| 75 | int ff_vaapi_decode_make_slice_buffer(AVCodecContext *avctx, | |||
| 76 | VAAPIDecodePicture *pic, | |||
| 77 | const void *params_data, | |||
| 78 | int nb_params, | |||
| 79 | size_t params_size, | |||
| 80 | const void *slice_data, | |||
| 81 | size_t slice_size) | |||
| 82 | { | |||
| 83 | VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; | |||
| 84 | VAStatus vas; | |||
| 85 | int index; | |||
| 86 | ||||
| 87 | av_assert0(pic->nb_slices <= pic->nb_slice_buffers_allocated)do { if (!(pic->nb_slices <= pic->nb_slice_buffers_allocated )) { av_log(((void*)0), 0, "Assertion %s failed at %s:%d\n", "pic->nb_slices <= pic->nb_slice_buffers_allocated" , "/root/firefox-clang/media/ffvpx/libavcodec/vaapi_decode.c" , 87); abort(); } } while (0); | |||
| 88 | if (pic->nb_slices == pic->nb_slice_buffers_allocated) { | |||
| 89 | VABufferID *tmp = | |||
| 90 | av_realloc_array(pic->slice_buffers, | |||
| 91 | pic->nb_slice_buffers_allocated ? pic->nb_slice_buffers_allocated * 2 : 64, | |||
| 92 | 2 * sizeof(*pic->slice_buffers)); | |||
| 93 | if (!tmp) | |||
| 94 | return AVERROR(ENOMEM)(-(12)); | |||
| 95 | ||||
| 96 | pic->slice_buffers = tmp; | |||
| 97 | pic->nb_slice_buffers_allocated = pic->nb_slice_buffers_allocated ? pic->nb_slice_buffers_allocated * 2 : 64; | |||
| 98 | } | |||
| 99 | av_assert0(pic->nb_slices + 1 <= pic->nb_slice_buffers_allocated)do { if (!(pic->nb_slices + 1 <= pic->nb_slice_buffers_allocated )) { av_log(((void*)0), 0, "Assertion %s failed at %s:%d\n", "pic->nb_slices + 1 <= pic->nb_slice_buffers_allocated" , "/root/firefox-clang/media/ffvpx/libavcodec/vaapi_decode.c" , 99); abort(); } } while (0); | |||
| 100 | ||||
| 101 | index = 2 * pic->nb_slices; | |||
| 102 | ||||
| 103 | vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, | |||
| 104 | VASliceParameterBufferType, | |||
| 105 | params_size, nb_params, (void*)params_data, | |||
| 106 | &pic->slice_buffers[index]); | |||
| 107 | if (vas != VA_STATUS_SUCCESS0x00000000) { | |||
| 108 | av_log(avctx, AV_LOG_ERROR16, "Failed to create slice " | |||
| 109 | "parameter buffer: %d (%s).\n", vas, vaErrorStr(vas)); | |||
| 110 | return AVERROR(EIO)(-(5)); | |||
| 111 | } | |||
| 112 | ||||
| 113 | av_log(avctx, AV_LOG_DEBUG48, "Slice %d param buffer (%zu bytes) " | |||
| 114 | "is %#x.\n", pic->nb_slices, params_size, | |||
| 115 | pic->slice_buffers[index]); | |||
| 116 | ||||
| 117 | vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, | |||
| 118 | VASliceDataBufferType, | |||
| 119 | slice_size, 1, (void*)slice_data, | |||
| 120 | &pic->slice_buffers[index + 1]); | |||
| 121 | if (vas != VA_STATUS_SUCCESS0x00000000) { | |||
| 122 | av_log(avctx, AV_LOG_ERROR16, "Failed to create slice " | |||
| 123 | "data buffer (size %zu): %d (%s).\n", | |||
| 124 | slice_size, vas, vaErrorStr(vas)); | |||
| 125 | vaDestroyBuffer(ctx->hwctx->display, | |||
| 126 | pic->slice_buffers[index]); | |||
| 127 | return AVERROR(EIO)(-(5)); | |||
| 128 | } | |||
| 129 | ||||
| 130 | av_log(avctx, AV_LOG_DEBUG48, "Slice %d data buffer (%zu bytes) " | |||
| 131 | "is %#x.\n", pic->nb_slices, slice_size, | |||
| 132 | pic->slice_buffers[index + 1]); | |||
| 133 | ||||
| 134 | ++pic->nb_slices; | |||
| 135 | return 0; | |||
| 136 | } | |||
| 137 | ||||
| 138 | static void ff_vaapi_decode_destroy_buffers(AVCodecContext *avctx, | |||
| 139 | VAAPIDecodePicture *pic) | |||
| 140 | { | |||
| 141 | VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; | |||
| 142 | VAStatus vas; | |||
| 143 | int i; | |||
| 144 | ||||
| 145 | for (i = 0; i < pic->nb_param_buffers; i++) { | |||
| 146 | vas = vaDestroyBuffer(ctx->hwctx->display, | |||
| 147 | pic->param_buffers[i]); | |||
| 148 | if (vas != VA_STATUS_SUCCESS0x00000000) { | |||
| 149 | av_log(avctx, AV_LOG_ERROR16, "Failed to destroy " | |||
| 150 | "parameter buffer %#x: %d (%s).\n", | |||
| 151 | pic->param_buffers[i], vas, vaErrorStr(vas)); | |||
| 152 | } | |||
| 153 | } | |||
| 154 | ||||
| 155 | for (i = 0; i < 2 * pic->nb_slices; i++) { | |||
| 156 | vas = vaDestroyBuffer(ctx->hwctx->display, | |||
| 157 | pic->slice_buffers[i]); | |||
| 158 | if (vas != VA_STATUS_SUCCESS0x00000000) { | |||
| 159 | av_log(avctx, AV_LOG_ERROR16, "Failed to destroy slice " | |||
| 160 | "slice buffer %#x: %d (%s).\n", | |||
| 161 | pic->slice_buffers[i], vas, vaErrorStr(vas)); | |||
| 162 | } | |||
| 163 | } | |||
| 164 | } | |||
| 165 | ||||
| 166 | int ff_vaapi_decode_issue(AVCodecContext *avctx, | |||
| 167 | VAAPIDecodePicture *pic) | |||
| 168 | { | |||
| 169 | VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; | |||
| 170 | VAStatus vas; | |||
| 171 | int err; | |||
| 172 | ||||
| 173 | if (pic->nb_slices <= 0) { | |||
| 174 | err = AVERROR(EINVAL)(-(22)); | |||
| 175 | goto fail; | |||
| 176 | } | |||
| 177 | ||||
| 178 | av_log(avctx, AV_LOG_DEBUG48, "Decode to surface %#x.\n", | |||
| 179 | pic->output_surface); | |||
| 180 | ||||
| 181 | vas = vaBeginPicture(ctx->hwctx->display, ctx->va_context, | |||
| 182 | pic->output_surface); | |||
| 183 | if (vas != VA_STATUS_SUCCESS0x00000000) { | |||
| 184 | av_log(avctx, AV_LOG_ERROR16, "Failed to begin picture decode " | |||
| 185 | "issue: %d (%s).\n", vas, vaErrorStr(vas)); | |||
| 186 | err = AVERROR(EIO)(-(5)); | |||
| 187 | goto fail_with_picture; | |||
| 188 | } | |||
| 189 | ||||
| 190 | vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context, | |||
| 191 | pic->param_buffers, pic->nb_param_buffers); | |||
| 192 | if (vas != VA_STATUS_SUCCESS0x00000000) { | |||
| 193 | av_log(avctx, AV_LOG_ERROR16, "Failed to upload decode " | |||
| 194 | "parameters: %d (%s).\n", vas, vaErrorStr(vas)); | |||
| 195 | err = AVERROR(EIO)(-(5)); | |||
| 196 | goto fail_with_picture; | |||
| 197 | } | |||
| 198 | ||||
| 199 | vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context, | |||
| 200 | pic->slice_buffers, 2 * pic->nb_slices); | |||
| 201 | if (vas != VA_STATUS_SUCCESS0x00000000) { | |||
| 202 | av_log(avctx, AV_LOG_ERROR16, "Failed to upload slices: " | |||
| 203 | "%d (%s).\n", vas, vaErrorStr(vas)); | |||
| 204 | err = AVERROR(EIO)(-(5)); | |||
| 205 | goto fail_with_picture; | |||
| 206 | } | |||
| 207 | ||||
| 208 | vas = vaEndPicture(ctx->hwctx->display, ctx->va_context); | |||
| 209 | if (vas != VA_STATUS_SUCCESS0x00000000) { | |||
| 210 | av_log(avctx, AV_LOG_ERROR16, "Failed to end picture decode " | |||
| 211 | "issue: %d (%s).\n", vas, vaErrorStr(vas)); | |||
| 212 | err = AVERROR(EIO)(-(5)); | |||
| 213 | if (CONFIG_VAAPI_11 || ctx->hwctx->driver_quirks & | |||
| 214 | AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) | |||
| 215 | goto fail; | |||
| 216 | else | |||
| 217 | goto fail_at_end; | |||
| 218 | } | |||
| 219 | ||||
| 220 | if (CONFIG_VAAPI_11 || ctx->hwctx->driver_quirks & | |||
| 221 | AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) | |||
| 222 | ff_vaapi_decode_destroy_buffers(avctx, pic); | |||
| 223 | ||||
| 224 | err = 0; | |||
| 225 | goto exit; | |||
| 226 | ||||
| 227 | fail_with_picture: | |||
| 228 | vas = vaEndPicture(ctx->hwctx->display, ctx->va_context); | |||
| 229 | if (vas != VA_STATUS_SUCCESS0x00000000) { | |||
| 230 | av_log(avctx, AV_LOG_ERROR16, "Failed to end picture decode " | |||
| 231 | "after error: %d (%s).\n", vas, vaErrorStr(vas)); | |||
| 232 | } | |||
| 233 | fail: | |||
| 234 | ff_vaapi_decode_destroy_buffers(avctx, pic); | |||
| 235 | fail_at_end: | |||
| 236 | exit: | |||
| 237 | pic->nb_param_buffers = 0; | |||
| 238 | pic->nb_param_buffers_allocated = 0; | |||
| 239 | av_freep(&pic->param_buffers); | |||
| 240 | pic->nb_slices = 0; | |||
| 241 | pic->nb_slice_buffers_allocated = 0; | |||
| 242 | av_freep(&pic->slice_buffers); | |||
| 243 | ||||
| 244 | return err; | |||
| 245 | } | |||
| 246 | ||||
| 247 | int ff_vaapi_decode_cancel(AVCodecContext *avctx, | |||
| 248 | VAAPIDecodePicture *pic) | |||
| 249 | { | |||
| 250 | ff_vaapi_decode_destroy_buffers(avctx, pic); | |||
| 251 | ||||
| 252 | pic->nb_param_buffers = 0; | |||
| 253 | pic->nb_param_buffers_allocated = 0; | |||
| 254 | av_freep(&pic->param_buffers); | |||
| 255 | pic->nb_slices = 0; | |||
| 256 | pic->nb_slice_buffers_allocated = 0; | |||
| 257 | av_freep(&pic->slice_buffers); | |||
| 258 | ||||
| 259 | return 0; | |||
| 260 | } | |||
| 261 | ||||
| 262 | static const struct { | |||
| 263 | uint32_t fourcc; | |||
| 264 | enum AVPixelFormat pix_fmt; | |||
| 265 | } vaapi_format_map[] = { | |||
| 266 | #define MAP(va, av) { VA_FOURCC_ ## va, AV_PIX_FMT_ ## av } | |||
| 267 | // 4:0:0 | |||
| 268 | MAP(Y800, GRAY8), | |||
| 269 | // 4:2:0 | |||
| 270 | MAP(NV12, NV12), | |||
| 271 | MAP(YV12, YUV420P), | |||
| 272 | MAP(IYUV, YUV420P), | |||
| 273 | #ifdef VA_FOURCC_I4200x30323449 | |||
| 274 | MAP(I420, YUV420P), | |||
| 275 | #endif | |||
| 276 | MAP(IMC3, YUV420P), | |||
| 277 | // 4:1:1 | |||
| 278 | MAP(411P, YUV411P), | |||
| 279 | // 4:2:2 | |||
| 280 | MAP(422H, YUV422P), | |||
| 281 | #ifdef VA_FOURCC_YV160x36315659 | |||
| 282 | MAP(YV16, YUV422P), | |||
| 283 | #endif | |||
| 284 | MAP(YUY2, YUYV422), | |||
| 285 | #ifdef VA_FOURCC_Y2100x30313259 | |||
| 286 | MAP(Y210, Y210), | |||
| 287 | #endif | |||
| 288 | #ifdef VA_FOURCC_Y2120x32313259 | |||
| 289 | MAP(Y212, Y212), | |||
| 290 | #endif | |||
| 291 | // 4:4:0 | |||
| 292 | MAP(422V, YUV440P), | |||
| 293 | // 4:4:4 | |||
| 294 | MAP(444P, YUV444P), | |||
| 295 | #ifdef VA_FOURCC_XYUV0x56555958 | |||
| 296 | MAP(XYUV, VUYX), | |||
| 297 | #endif | |||
| 298 | #ifdef VA_FOURCC_Y4100x30313459 | |||
| 299 | MAP(Y410, XV30), | |||
| 300 | #endif | |||
| 301 | #ifdef VA_FOURCC_Y4120x32313459 | |||
| 302 | MAP(Y412, XV36), | |||
| 303 | #endif | |||
| 304 | // 4:2:0 10-bit | |||
| 305 | #ifdef VA_FOURCC_P0100x30313050 | |||
| 306 | MAP(P010, P010), | |||
| 307 | #endif | |||
| 308 | #ifdef VA_FOURCC_P0120x32313050 | |||
| 309 | MAP(P012, P012), | |||
| 310 | #endif | |||
| 311 | #ifdef VA_FOURCC_I0100x30313049 | |||
| 312 | MAP(I010, YUV420P10), | |||
| 313 | #endif | |||
| 314 | #undef MAP | |||
| 315 | }; | |||
| 316 | ||||
| 317 | static int vaapi_decode_find_best_format(AVCodecContext *avctx, | |||
| 318 | AVHWDeviceContext *device, | |||
| 319 | VAConfigID config_id, | |||
| 320 | AVHWFramesContext *frames) | |||
| 321 | { | |||
| 322 | AVVAAPIDeviceContext *hwctx = device->hwctx; | |||
| 323 | VAStatus vas; | |||
| 324 | VASurfaceAttrib *attr; | |||
| 325 | enum AVPixelFormat source_format, best_format, format; | |||
| 326 | uint32_t best_fourcc, fourcc; | |||
| ||||
| 327 | int i, j, nb_attr; | |||
| 328 | ||||
| 329 | source_format = avctx->sw_pix_fmt; | |||
| 330 | av_assert0(source_format != AV_PIX_FMT_NONE)do { if (!(source_format != AV_PIX_FMT_NONE)) { av_log(((void *)0), 0, "Assertion %s failed at %s:%d\n", "source_format != AV_PIX_FMT_NONE" , "/root/firefox-clang/media/ffvpx/libavcodec/vaapi_decode.c" , 330); abort(); } } while (0); | |||
| 331 | ||||
| 332 | vas = vaQuerySurfaceAttributes(hwctx->display, config_id, | |||
| 333 | NULL((void*)0), &nb_attr); | |||
| 334 | if (vas != VA_STATUS_SUCCESS0x00000000) { | |||
| 335 | av_log(avctx, AV_LOG_ERROR16, "Failed to query surface attributes: " | |||
| 336 | "%d (%s).\n", vas, vaErrorStr(vas)); | |||
| 337 | return AVERROR(ENOSYS)(-(38)); | |||
| 338 | } | |||
| 339 | ||||
| 340 | attr = av_malloc_array(nb_attr, sizeof(*attr)); | |||
| 341 | if (!attr) | |||
| 342 | return AVERROR(ENOMEM)(-(12)); | |||
| 343 | ||||
| 344 | vas = vaQuerySurfaceAttributes(hwctx->display, config_id, | |||
| 345 | attr, &nb_attr); | |||
| 346 | if (vas != VA_STATUS_SUCCESS0x00000000) { | |||
| 347 | av_log(avctx, AV_LOG_ERROR16, "Failed to query surface attributes: " | |||
| 348 | "%d (%s).\n", vas, vaErrorStr(vas)); | |||
| 349 | av_freep(&attr); | |||
| 350 | return AVERROR(ENOSYS)(-(38)); | |||
| 351 | } | |||
| 352 | ||||
| 353 | best_format = AV_PIX_FMT_NONE; | |||
| 354 | ||||
| 355 | for (i = 0; i < nb_attr; i++) { | |||
| 356 | if (attr[i].type != VASurfaceAttribPixelFormat) | |||
| 357 | continue; | |||
| 358 | ||||
| 359 | fourcc = attr[i].value.value.i; | |||
| 360 | for (j = 0; j < FF_ARRAY_ELEMS(vaapi_format_map)(sizeof(vaapi_format_map) / sizeof((vaapi_format_map)[0])); j++) { | |||
| 361 | if (fourcc == vaapi_format_map[j].fourcc) | |||
| 362 | break; | |||
| 363 | } | |||
| 364 | if (j >= FF_ARRAY_ELEMS(vaapi_format_map)(sizeof(vaapi_format_map) / sizeof((vaapi_format_map)[0]))) { | |||
| 365 | av_log(avctx, AV_LOG_DEBUG48, "Ignoring unknown format %#x.\n", | |||
| 366 | fourcc); | |||
| 367 | continue; | |||
| 368 | } | |||
| 369 | format = vaapi_format_map[j].pix_fmt; | |||
| 370 | av_log(avctx, AV_LOG_DEBUG48, "Considering format %#x -> %s.\n", | |||
| 371 | fourcc, av_get_pix_fmt_name(format)); | |||
| 372 | ||||
| 373 | best_format = av_find_best_pix_fmt_of_2(format, best_format, | |||
| 374 | source_format, 0, NULL((void*)0)); | |||
| 375 | if (format == best_format) | |||
| 376 | best_fourcc = fourcc; | |||
| 377 | } | |||
| 378 | ||||
| 379 | av_freep(&attr); | |||
| 380 | ||||
| 381 | if (best_format == AV_PIX_FMT_NONE) { | |||
| 382 | av_log(avctx, AV_LOG_ERROR16, "No usable formats for decoding!\n"); | |||
| 383 | return AVERROR(EINVAL)(-(22)); | |||
| 384 | } | |||
| 385 | ||||
| 386 | av_log(avctx, AV_LOG_DEBUG48, "Picked %s (%#x) as best match for %s.\n", | |||
| ||||
| 387 | av_get_pix_fmt_name(best_format), best_fourcc, | |||
| 388 | av_get_pix_fmt_name(source_format)); | |||
| 389 | ||||
| 390 | frames->sw_format = best_format; | |||
| 391 | if (avctx->internal->hwaccel_priv_data) { | |||
| 392 | VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; | |||
| 393 | AVVAAPIFramesContext *avfc = frames->hwctx; | |||
| 394 | ||||
| 395 | ctx->pixel_format_attribute = (VASurfaceAttrib) { | |||
| 396 | .type = VASurfaceAttribPixelFormat, | |||
| 397 | .flags = VA_SURFACE_ATTRIB_SETTABLE0x00000002, | |||
| 398 | .value.type = VAGenericValueTypeInteger, | |||
| 399 | .value.value.i = best_fourcc, | |||
| 400 | }; | |||
| 401 | ||||
| 402 | avfc->attributes = &ctx->pixel_format_attribute; | |||
| 403 | avfc->nb_attributes = 1; | |||
| 404 | } | |||
| 405 | ||||
| 406 | return 0; | |||
| 407 | } | |||
| 408 | ||||
| 409 | static const struct { | |||
| 410 | enum AVCodecID codec_id; | |||
| 411 | int codec_profile; | |||
| 412 | VAProfile va_profile; | |||
| 413 | VAProfile (*profile_parser)(AVCodecContext *avctx); | |||
| 414 | } vaapi_profile_map[] = { | |||
| 415 | #define MAP(c, p, v, ...) { AV_CODEC_ID_ ## c, AV_PROFILE_ ## p, VAProfile ## v, __VA_ARGS__ } | |||
| 416 | MAP(MPEG2VIDEO, MPEG2_SIMPLE, MPEG2Simple ), | |||
| 417 | MAP(MPEG2VIDEO, MPEG2_MAIN, MPEG2Main ), | |||
| 418 | MAP(H263, UNKNOWN, H263Baseline), | |||
| 419 | MAP(MPEG4, MPEG4_SIMPLE, MPEG4Simple ), | |||
| 420 | MAP(MPEG4, MPEG4_ADVANCED_SIMPLE, | |||
| 421 | MPEG4AdvancedSimple), | |||
| 422 | MAP(MPEG4, MPEG4_MAIN, MPEG4Main ), | |||
| 423 | #if VA_CHECK_VERSION(1, 18, 0)(1 > (1) || (1 == (1) && 13 > (18)) || (1 == (1 ) && 13 == (18) && 0 >= (0))) | |||
| 424 | MAP(H264, H264_HIGH_10_INTRA, | |||
| 425 | H264High10 ), | |||
| 426 | MAP(H264, H264_HIGH_10, H264High10 ), | |||
| 427 | #endif | |||
| 428 | MAP(H264, H264_CONSTRAINED_BASELINE, | |||
| 429 | H264ConstrainedBaseline), | |||
| 430 | MAP(H264, H264_MAIN, H264Main ), | |||
| 431 | MAP(H264, H264_HIGH, H264High ), | |||
| 432 | #if VA_CHECK_VERSION(0, 37, 0)(1 > (0) || (1 == (0) && 13 > (37)) || (1 == (0 ) && 13 == (37) && 0 >= (0))) | |||
| 433 | MAP(HEVC, HEVC_MAIN, HEVCMain ), | |||
| 434 | MAP(HEVC, HEVC_MAIN_10, HEVCMain10 ), | |||
| 435 | MAP(HEVC, HEVC_MAIN_STILL_PICTURE, | |||
| 436 | HEVCMain ), | |||
| 437 | #endif | |||
| 438 | #if VA_CHECK_VERSION(1, 2, 0)(1 > (1) || (1 == (1) && 13 > (2)) || (1 == (1) && 13 == (2) && 0 >= (0))) && CONFIG_HEVC_VAAPI_HWACCEL0 | |||
| 439 | MAP(HEVC, HEVC_REXT, None, | |||
| 440 | ff_vaapi_parse_hevc_rext_scc_profile ), | |||
| 441 | MAP(HEVC, HEVC_SCC, None, | |||
| 442 | ff_vaapi_parse_hevc_rext_scc_profile ), | |||
| 443 | #endif | |||
| 444 | MAP(MJPEG, MJPEG_HUFFMAN_BASELINE_DCT, | |||
| 445 | JPEGBaseline), | |||
| 446 | MAP(WMV3, VC1_SIMPLE, VC1Simple ), | |||
| 447 | MAP(WMV3, VC1_MAIN, VC1Main ), | |||
| 448 | MAP(WMV3, VC1_COMPLEX, VC1Advanced ), | |||
| 449 | MAP(WMV3, VC1_ADVANCED, VC1Advanced ), | |||
| 450 | MAP(VC1, VC1_SIMPLE, VC1Simple ), | |||
| 451 | MAP(VC1, VC1_MAIN, VC1Main ), | |||
| 452 | MAP(VC1, VC1_COMPLEX, VC1Advanced ), | |||
| 453 | MAP(VC1, VC1_ADVANCED, VC1Advanced ), | |||
| 454 | MAP(VP8, UNKNOWN, VP8Version0_3 ), | |||
| 455 | #if VA_CHECK_VERSION(0, 38, 0)(1 > (0) || (1 == (0) && 13 > (38)) || (1 == (0 ) && 13 == (38) && 0 >= (0))) | |||
| 456 | MAP(VP9, VP9_0, VP9Profile0 ), | |||
| 457 | #endif | |||
| 458 | #if VA_CHECK_VERSION(0, 39, 0)(1 > (0) || (1 == (0) && 13 > (39)) || (1 == (0 ) && 13 == (39) && 0 >= (0))) | |||
| 459 | MAP(VP9, VP9_1, VP9Profile1 ), | |||
| 460 | MAP(VP9, VP9_2, VP9Profile2 ), | |||
| 461 | MAP(VP9, VP9_3, VP9Profile3 ), | |||
| 462 | #endif | |||
| 463 | #if VA_CHECK_VERSION(1, 8, 0)(1 > (1) || (1 == (1) && 13 > (8)) || (1 == (1) && 13 == (8) && 0 >= (0))) | |||
| 464 | MAP(AV1, AV1_MAIN, AV1Profile0), | |||
| 465 | MAP(AV1, AV1_HIGH, AV1Profile1), | |||
| 466 | #endif | |||
| 467 | #if VA_CHECK_VERSION(1, 22, 0)(1 > (1) || (1 == (1) && 13 > (22)) || (1 == (1 ) && 13 == (22) && 0 >= (0))) | |||
| 468 | MAP(H266, VVC_MAIN_10, VVCMain10), | |||
| 469 | #endif | |||
| 470 | ||||
| 471 | #undef MAP | |||
| 472 | }; | |||
| 473 | ||||
| 474 | /* | |||
| 475 | * Set *va_config and the frames_ref fields from the current codec parameters | |||
| 476 | * in avctx. | |||
| 477 | */ | |||
| 478 | static int vaapi_decode_make_config(AVCodecContext *avctx, | |||
| 479 | AVBufferRef *device_ref, | |||
| 480 | VAConfigID *va_config, | |||
| 481 | AVBufferRef *frames_ref) | |||
| 482 | { | |||
| 483 | AVVAAPIHWConfig *hwconfig = NULL((void*)0); | |||
| 484 | AVHWFramesConstraints *constraints = NULL((void*)0); | |||
| 485 | VAStatus vas; | |||
| 486 | int err, i, j; | |||
| 487 | const AVCodecDescriptor *codec_desc; | |||
| 488 | VAProfile *profile_list = NULL((void*)0), matched_va_profile, va_profile; | |||
| 489 | int profile_count, exact_match, matched_ff_profile, codec_profile; | |||
| 490 | ||||
| 491 | AVHWDeviceContext *device = (AVHWDeviceContext*)device_ref->data; | |||
| 492 | AVVAAPIDeviceContext *hwctx = device->hwctx; | |||
| 493 | ||||
| 494 | codec_desc = avcodec_descriptor_get(avctx->codec_id); | |||
| 495 | if (!codec_desc) { | |||
| 496 | err = AVERROR(EINVAL)(-(22)); | |||
| 497 | goto fail; | |||
| 498 | } | |||
| 499 | ||||
| 500 | profile_count = vaMaxNumProfiles(hwctx->display); | |||
| 501 | profile_list = av_malloc_array(profile_count, | |||
| 502 | sizeof(VAProfile)); | |||
| 503 | if (!profile_list) { | |||
| 504 | err = AVERROR(ENOMEM)(-(12)); | |||
| 505 | goto fail; | |||
| 506 | } | |||
| 507 | ||||
| 508 | vas = vaQueryConfigProfiles(hwctx->display, | |||
| 509 | profile_list, &profile_count); | |||
| 510 | if (vas != VA_STATUS_SUCCESS0x00000000) { | |||
| 511 | av_log(avctx, AV_LOG_ERROR16, "Failed to query profiles: " | |||
| 512 | "%d (%s).\n", vas, vaErrorStr(vas)); | |||
| 513 | err = AVERROR(ENOSYS)(-(38)); | |||
| 514 | goto fail; | |||
| 515 | } | |||
| 516 | ||||
| 517 | matched_va_profile = VAProfileNone; | |||
| 518 | exact_match = 0; | |||
| 519 | ||||
| 520 | for (i = 0; i < FF_ARRAY_ELEMS(vaapi_profile_map)(sizeof(vaapi_profile_map) / sizeof((vaapi_profile_map)[0])); i++) { | |||
| 521 | int profile_match = 0; | |||
| 522 | if (avctx->codec_id != vaapi_profile_map[i].codec_id) | |||
| 523 | continue; | |||
| 524 | if (avctx->profile == vaapi_profile_map[i].codec_profile || | |||
| 525 | vaapi_profile_map[i].codec_profile == AV_PROFILE_UNKNOWN-99) | |||
| 526 | profile_match = 1; | |||
| 527 | ||||
| 528 | va_profile = vaapi_profile_map[i].profile_parser ? | |||
| 529 | vaapi_profile_map[i].profile_parser(avctx) : | |||
| 530 | vaapi_profile_map[i].va_profile; | |||
| 531 | codec_profile = vaapi_profile_map[i].codec_profile; | |||
| 532 | ||||
| 533 | for (j = 0; j < profile_count; j++) { | |||
| 534 | if (va_profile == profile_list[j]) { | |||
| 535 | exact_match = profile_match; | |||
| 536 | break; | |||
| 537 | } | |||
| 538 | } | |||
| 539 | if (j < profile_count) { | |||
| 540 | matched_va_profile = va_profile; | |||
| 541 | matched_ff_profile = codec_profile; | |||
| 542 | if (exact_match) | |||
| 543 | break; | |||
| 544 | } | |||
| 545 | } | |||
| 546 | av_freep(&profile_list); | |||
| 547 | ||||
| 548 | if (matched_va_profile == VAProfileNone) { | |||
| 549 | av_log(avctx, AV_LOG_ERROR16, "No support for codec %s " | |||
| 550 | "profile %d.\n", codec_desc->name, avctx->profile); | |||
| 551 | err = AVERROR(ENOSYS)(-(38)); | |||
| 552 | goto fail; | |||
| 553 | } | |||
| 554 | if (!exact_match) { | |||
| 555 | if (avctx->hwaccel_flags & | |||
| 556 | AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH(1 << 2)) { | |||
| 557 | av_log(avctx, AV_LOG_VERBOSE40, "Codec %s profile %d not " | |||
| 558 | "supported for hardware decode.\n", | |||
| 559 | codec_desc->name, avctx->profile); | |||
| 560 | av_log(avctx, AV_LOG_WARNING24, "Using possibly-" | |||
| 561 | "incompatible profile %d instead.\n", | |||
| 562 | matched_ff_profile); | |||
| 563 | } else { | |||
| 564 | av_log(avctx, AV_LOG_VERBOSE40, "Codec %s profile %d not " | |||
| 565 | "supported for hardware decode.\n", | |||
| 566 | codec_desc->name, avctx->profile); | |||
| 567 | err = AVERROR(EINVAL)(-(22)); | |||
| 568 | goto fail; | |||
| 569 | } | |||
| 570 | } | |||
| 571 | ||||
| 572 | vas = vaCreateConfig(hwctx->display, matched_va_profile, | |||
| 573 | VAEntrypointVLD, NULL((void*)0), 0, | |||
| 574 | va_config); | |||
| 575 | if (vas != VA_STATUS_SUCCESS0x00000000) { | |||
| 576 | av_log(avctx, AV_LOG_ERROR16, "Failed to create decode " | |||
| 577 | "configuration: %d (%s).\n", vas, vaErrorStr(vas)); | |||
| 578 | err = AVERROR(EIO)(-(5)); | |||
| 579 | goto fail; | |||
| 580 | } | |||
| 581 | ||||
| 582 | hwconfig = av_hwdevice_hwconfig_alloc(device_ref); | |||
| 583 | if (!hwconfig) { | |||
| 584 | err = AVERROR(ENOMEM)(-(12)); | |||
| 585 | goto fail; | |||
| 586 | } | |||
| 587 | hwconfig->config_id = *va_config; | |||
| 588 | ||||
| 589 | constraints = | |||
| 590 | av_hwdevice_get_hwframe_constraints(device_ref, hwconfig); | |||
| 591 | if (!constraints) { | |||
| 592 | err = AVERROR(ENOMEM)(-(12)); | |||
| 593 | goto fail; | |||
| 594 | } | |||
| 595 | ||||
| 596 | if (avctx->coded_width < constraints->min_width || | |||
| 597 | avctx->coded_height < constraints->min_height || | |||
| 598 | avctx->coded_width > constraints->max_width || | |||
| 599 | avctx->coded_height > constraints->max_height) { | |||
| 600 | av_log(avctx, AV_LOG_ERROR16, "Hardware does not support image " | |||
| 601 | "size %dx%d (constraints: width %d-%d height %d-%d).\n", | |||
| 602 | avctx->coded_width, avctx->coded_height, | |||
| 603 | constraints->min_width, constraints->max_width, | |||
| 604 | constraints->min_height, constraints->max_height); | |||
| 605 | err = AVERROR(EINVAL)(-(22)); | |||
| 606 | goto fail; | |||
| 607 | } | |||
| 608 | if (!constraints->valid_sw_formats || | |||
| 609 | constraints->valid_sw_formats[0] == AV_PIX_FMT_NONE) { | |||
| 610 | av_log(avctx, AV_LOG_ERROR16, "Hardware does not offer any " | |||
| 611 | "usable surface formats.\n"); | |||
| 612 | err = AVERROR(EINVAL)(-(22)); | |||
| 613 | goto fail; | |||
| 614 | } | |||
| 615 | ||||
| 616 | if (frames_ref) { | |||
| 617 | AVHWFramesContext *frames = (AVHWFramesContext *)frames_ref->data; | |||
| 618 | ||||
| 619 | frames->format = AV_PIX_FMT_VAAPI; | |||
| 620 | frames->width = avctx->coded_width; | |||
| 621 | frames->height = avctx->coded_height; | |||
| 622 | ||||
| 623 | err = vaapi_decode_find_best_format(avctx, device, | |||
| 624 | *va_config, frames); | |||
| 625 | if (err < 0) | |||
| 626 | goto fail; | |||
| 627 | ||||
| 628 | if (CONFIG_VAAPI_11) | |||
| 629 | frames->initial_pool_size = 0; | |||
| 630 | else { | |||
| 631 | frames->initial_pool_size = 1; | |||
| 632 | // Add per-codec number of surfaces used for storing reference frames. | |||
| 633 | switch (avctx->codec_id) { | |||
| 634 | case AV_CODEC_ID_H264: | |||
| 635 | case AV_CODEC_ID_H266AV_CODEC_ID_VVC: | |||
| 636 | case AV_CODEC_ID_HEVC: | |||
| 637 | case AV_CODEC_ID_AV1: | |||
| 638 | frames->initial_pool_size += 16; | |||
| 639 | break; | |||
| 640 | case AV_CODEC_ID_VP9: | |||
| 641 | frames->initial_pool_size += 8; | |||
| 642 | break; | |||
| 643 | case AV_CODEC_ID_VP8: | |||
| 644 | frames->initial_pool_size += 3; | |||
| 645 | break; | |||
| 646 | default: | |||
| 647 | frames->initial_pool_size += 2; | |||
| 648 | } | |||
| 649 | } | |||
| 650 | } | |||
| 651 | ||||
| 652 | av_hwframe_constraints_free(&constraints); | |||
| 653 | av_freep(&hwconfig); | |||
| 654 | ||||
| 655 | return 0; | |||
| 656 | ||||
| 657 | fail: | |||
| 658 | av_hwframe_constraints_free(&constraints); | |||
| 659 | av_freep(&hwconfig); | |||
| 660 | if (*va_config != VA_INVALID_ID0xffffffff) { | |||
| 661 | vaDestroyConfig(hwctx->display, *va_config); | |||
| 662 | *va_config = VA_INVALID_ID0xffffffff; | |||
| 663 | } | |||
| 664 | av_freep(&profile_list); | |||
| 665 | return err; | |||
| 666 | } | |||
| 667 | ||||
| 668 | int ff_vaapi_common_frame_params(AVCodecContext *avctx, | |||
| 669 | AVBufferRef *hw_frames_ctx) | |||
| 670 | { | |||
| 671 | AVHWFramesContext *hw_frames = (AVHWFramesContext *)hw_frames_ctx->data; | |||
| 672 | AVHWDeviceContext *device_ctx = hw_frames->device_ctx; | |||
| 673 | AVVAAPIDeviceContext *hwctx; | |||
| 674 | VAConfigID va_config = VA_INVALID_ID0xffffffff; | |||
| 675 | int err; | |||
| 676 | ||||
| 677 | if (device_ctx->type != AV_HWDEVICE_TYPE_VAAPI) | |||
| 678 | return AVERROR(EINVAL)(-(22)); | |||
| 679 | hwctx = device_ctx->hwctx; | |||
| 680 | ||||
| 681 | err = vaapi_decode_make_config(avctx, hw_frames->device_ref, &va_config, | |||
| 682 | hw_frames_ctx); | |||
| 683 | if (err) | |||
| 684 | return err; | |||
| 685 | ||||
| 686 | if (va_config != VA_INVALID_ID0xffffffff) | |||
| 687 | vaDestroyConfig(hwctx->display, va_config); | |||
| 688 | ||||
| 689 | return 0; | |||
| 690 | } | |||
| 691 | ||||
| 692 | int ff_vaapi_decode_init(AVCodecContext *avctx) | |||
| 693 | { | |||
| 694 | VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; | |||
| 695 | VAStatus vas; | |||
| 696 | int err; | |||
| 697 | ||||
| 698 | ctx->va_config = VA_INVALID_ID0xffffffff; | |||
| 699 | ctx->va_context = VA_INVALID_ID0xffffffff; | |||
| 700 | ||||
| 701 | err = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_VAAPI); | |||
| 702 | if (err < 0) | |||
| 703 | goto fail; | |||
| 704 | ||||
| 705 | ctx->frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data; | |||
| 706 | ctx->hwfc = ctx->frames->hwctx; | |||
| 707 | ctx->device = ctx->frames->device_ctx; | |||
| 708 | ctx->hwctx = ctx->device->hwctx; | |||
| 709 | ||||
| 710 | err = vaapi_decode_make_config(avctx, ctx->frames->device_ref, | |||
| 711 | &ctx->va_config, NULL((void*)0)); | |||
| 712 | if (err) | |||
| 713 | goto fail; | |||
| 714 | ||||
| 715 | vas = vaCreateContext(ctx->hwctx->display, ctx->va_config, | |||
| 716 | avctx->coded_width, avctx->coded_height, | |||
| 717 | VA_PROGRESSIVE0x1, | |||
| 718 | ctx->hwfc->surface_ids, | |||
| 719 | ctx->hwfc->nb_surfaces, | |||
| 720 | &ctx->va_context); | |||
| 721 | if (vas != VA_STATUS_SUCCESS0x00000000) { | |||
| 722 | av_log(avctx, AV_LOG_ERROR16, "Failed to create decode " | |||
| 723 | "context: %d (%s).\n", vas, vaErrorStr(vas)); | |||
| 724 | err = AVERROR(EIO)(-(5)); | |||
| 725 | goto fail; | |||
| 726 | } | |||
| 727 | ||||
| 728 | av_log(avctx, AV_LOG_DEBUG48, "Decode context initialised: " | |||
| 729 | "%#x/%#x.\n", ctx->va_config, ctx->va_context); | |||
| 730 | ||||
| 731 | return 0; | |||
| 732 | ||||
| 733 | fail: | |||
| 734 | ff_vaapi_decode_uninit(avctx); | |||
| 735 | return err; | |||
| 736 | } | |||
| 737 | ||||
| 738 | int ff_vaapi_decode_uninit(AVCodecContext *avctx) | |||
| 739 | { | |||
| 740 | VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; | |||
| 741 | VAStatus vas; | |||
| 742 | ||||
| 743 | if (ctx->va_context != VA_INVALID_ID0xffffffff) { | |||
| 744 | vas = vaDestroyContext(ctx->hwctx->display, ctx->va_context); | |||
| 745 | if (vas != VA_STATUS_SUCCESS0x00000000) { | |||
| 746 | av_log(avctx, AV_LOG_ERROR16, "Failed to destroy decode " | |||
| 747 | "context %#x: %d (%s).\n", | |||
| 748 | ctx->va_context, vas, vaErrorStr(vas)); | |||
| 749 | } | |||
| 750 | } | |||
| 751 | if (ctx->va_config != VA_INVALID_ID0xffffffff) { | |||
| 752 | vas = vaDestroyConfig(ctx->hwctx->display, ctx->va_config); | |||
| 753 | if (vas != VA_STATUS_SUCCESS0x00000000) { | |||
| 754 | av_log(avctx, AV_LOG_ERROR16, "Failed to destroy decode " | |||
| 755 | "configuration %#x: %d (%s).\n", | |||
| 756 | ctx->va_config, vas, vaErrorStr(vas)); | |||
| 757 | } | |||
| 758 | } | |||
| 759 | ||||
| 760 | return 0; | |||
| 761 | } |