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