hwcontext.c (26406B)
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.h" 20 21 #include "avassert.h" 22 #include "buffer.h" 23 #include "common.h" 24 #include "hwcontext.h" 25 #include "hwcontext_internal.h" 26 #include "imgutils.h" 27 #include "log.h" 28 #include "mem.h" 29 #include "pixdesc.h" 30 #include "pixfmt.h" 31 32 static const HWContextType * const hw_table[] = { 33 #if CONFIG_CUDA 34 &ff_hwcontext_type_cuda, 35 #endif 36 #if CONFIG_D3D11VA 37 &ff_hwcontext_type_d3d11va, 38 #endif 39 #if CONFIG_D3D12VA 40 &ff_hwcontext_type_d3d12va, 41 #endif 42 #if CONFIG_LIBDRM 43 &ff_hwcontext_type_drm, 44 #endif 45 #if CONFIG_DXVA2 46 &ff_hwcontext_type_dxva2, 47 #endif 48 #if CONFIG_OPENCL 49 &ff_hwcontext_type_opencl, 50 #endif 51 #if CONFIG_QSV 52 &ff_hwcontext_type_qsv, 53 #endif 54 #if CONFIG_VAAPI 55 &ff_hwcontext_type_vaapi, 56 #endif 57 #if CONFIG_VDPAU 58 &ff_hwcontext_type_vdpau, 59 #endif 60 #if CONFIG_VIDEOTOOLBOX 61 &ff_hwcontext_type_videotoolbox, 62 #endif 63 #if CONFIG_MEDIACODEC 64 &ff_hwcontext_type_mediacodec, 65 #endif 66 #if CONFIG_VULKAN 67 &ff_hwcontext_type_vulkan, 68 #endif 69 NULL, 70 }; 71 72 static const char *const hw_type_names[] = { 73 [AV_HWDEVICE_TYPE_CUDA] = "cuda", 74 [AV_HWDEVICE_TYPE_DRM] = "drm", 75 [AV_HWDEVICE_TYPE_DXVA2] = "dxva2", 76 [AV_HWDEVICE_TYPE_D3D11VA] = "d3d11va", 77 [AV_HWDEVICE_TYPE_D3D12VA] = "d3d12va", 78 [AV_HWDEVICE_TYPE_OPENCL] = "opencl", 79 [AV_HWDEVICE_TYPE_QSV] = "qsv", 80 [AV_HWDEVICE_TYPE_VAAPI] = "vaapi", 81 [AV_HWDEVICE_TYPE_VDPAU] = "vdpau", 82 [AV_HWDEVICE_TYPE_VIDEOTOOLBOX] = "videotoolbox", 83 [AV_HWDEVICE_TYPE_MEDIACODEC] = "mediacodec", 84 [AV_HWDEVICE_TYPE_VULKAN] = "vulkan", 85 }; 86 87 typedef struct FFHWDeviceContext { 88 /** 89 * The public AVHWDeviceContext. See hwcontext.h for it. 90 */ 91 AVHWDeviceContext p; 92 93 const HWContextType *hw_type; 94 95 /** 96 * For a derived device, a reference to the original device 97 * context it was derived from. 98 */ 99 AVBufferRef *source_device; 100 } FFHWDeviceContext; 101 102 enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name) 103 { 104 int type; 105 for (type = 0; type < FF_ARRAY_ELEMS(hw_type_names); type++) { 106 if (hw_type_names[type] && !strcmp(hw_type_names[type], name)) 107 return type; 108 } 109 return AV_HWDEVICE_TYPE_NONE; 110 } 111 112 const char *av_hwdevice_get_type_name(enum AVHWDeviceType type) 113 { 114 if (type > AV_HWDEVICE_TYPE_NONE && 115 type < FF_ARRAY_ELEMS(hw_type_names)) 116 return hw_type_names[type]; 117 else 118 return NULL; 119 } 120 121 enum AVHWDeviceType av_hwdevice_iterate_types(enum AVHWDeviceType prev) 122 { 123 enum AVHWDeviceType next; 124 int i, set = 0; 125 for (i = 0; hw_table[i]; i++) { 126 if (prev != AV_HWDEVICE_TYPE_NONE && hw_table[i]->type <= prev) 127 continue; 128 if (!set || hw_table[i]->type < next) { 129 next = hw_table[i]->type; 130 set = 1; 131 } 132 } 133 return set ? next : AV_HWDEVICE_TYPE_NONE; 134 } 135 136 static const AVClass hwdevice_ctx_class = { 137 .class_name = "AVHWDeviceContext", 138 .item_name = av_default_item_name, 139 .version = LIBAVUTIL_VERSION_INT, 140 }; 141 142 static void hwdevice_ctx_free(void *opaque, uint8_t *data) 143 { 144 FFHWDeviceContext *ctxi = (FFHWDeviceContext*)data; 145 AVHWDeviceContext *ctx = &ctxi->p; 146 147 /* uninit might still want access the hw context and the user 148 * free() callback might destroy it, so uninit has to be called first */ 149 if (ctxi->hw_type->device_uninit) 150 ctxi->hw_type->device_uninit(ctx); 151 152 if (ctx->free) 153 ctx->free(ctx); 154 155 av_buffer_unref(&ctxi->source_device); 156 157 av_freep(&ctx->hwctx); 158 av_freep(&ctx); 159 } 160 161 AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type) 162 { 163 FFHWDeviceContext *ctxi; 164 AVHWDeviceContext *ctx; 165 AVBufferRef *buf; 166 const HWContextType *hw_type = NULL; 167 int i; 168 169 for (i = 0; hw_table[i]; i++) { 170 if (hw_table[i]->type == type) { 171 hw_type = hw_table[i]; 172 break; 173 } 174 } 175 if (!hw_type) 176 return NULL; 177 178 ctxi = av_mallocz(sizeof(*ctxi)); 179 if (!ctxi) 180 return NULL; 181 ctx = &ctxi->p; 182 183 if (hw_type->device_hwctx_size) { 184 ctx->hwctx = av_mallocz(hw_type->device_hwctx_size); 185 if (!ctx->hwctx) 186 goto fail; 187 } 188 189 buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx), 190 hwdevice_ctx_free, NULL, 191 AV_BUFFER_FLAG_READONLY); 192 if (!buf) 193 goto fail; 194 195 ctx->type = type; 196 ctx->av_class = &hwdevice_ctx_class; 197 198 ctxi->hw_type = hw_type; 199 200 return buf; 201 202 fail: 203 av_freep(&ctx->hwctx); 204 av_freep(&ctx); 205 return NULL; 206 } 207 208 int av_hwdevice_ctx_init(AVBufferRef *ref) 209 { 210 FFHWDeviceContext *ctxi = (FFHWDeviceContext*)ref->data; 211 AVHWDeviceContext *ctx = &ctxi->p; 212 int ret = 0; 213 214 if (ctxi->hw_type->device_init) 215 ret = ctxi->hw_type->device_init(ctx); 216 217 return ret; 218 } 219 220 static const AVClass hwframe_ctx_class = { 221 .class_name = "AVHWFramesContext", 222 .item_name = av_default_item_name, 223 .version = LIBAVUTIL_VERSION_INT, 224 }; 225 226 static void hwframe_ctx_free(void *opaque, uint8_t *data) 227 { 228 FFHWFramesContext *ctxi = (FFHWFramesContext*)data; 229 AVHWFramesContext *ctx = &ctxi->p; 230 231 if (ctxi->pool_internal) 232 av_buffer_pool_uninit(&ctxi->pool_internal); 233 234 if (ctxi->hw_type->frames_uninit) 235 ctxi->hw_type->frames_uninit(ctx); 236 237 if (ctx->free) 238 ctx->free(ctx); 239 240 av_buffer_unref(&ctxi->source_frames); 241 242 av_buffer_unref(&ctx->device_ref); 243 244 av_freep(&ctx->hwctx); 245 av_freep(&ctx); 246 } 247 248 AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ref_in) 249 { 250 FFHWDeviceContext *device_ctx = (FFHWDeviceContext*)device_ref_in->data; 251 const HWContextType *hw_type = device_ctx->hw_type; 252 FFHWFramesContext *ctxi; 253 AVHWFramesContext *ctx; 254 AVBufferRef *buf, *device_ref = NULL; 255 256 ctxi = av_mallocz(sizeof(*ctxi)); 257 if (!ctxi) 258 return NULL; 259 ctx = &ctxi->p; 260 261 if (hw_type->frames_hwctx_size) { 262 ctx->hwctx = av_mallocz(hw_type->frames_hwctx_size); 263 if (!ctx->hwctx) 264 goto fail; 265 } 266 267 device_ref = av_buffer_ref(device_ref_in); 268 if (!device_ref) 269 goto fail; 270 271 buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx), 272 hwframe_ctx_free, NULL, 273 AV_BUFFER_FLAG_READONLY); 274 if (!buf) 275 goto fail; 276 277 ctx->av_class = &hwframe_ctx_class; 278 ctx->device_ref = device_ref; 279 ctx->device_ctx = &device_ctx->p; 280 ctx->format = AV_PIX_FMT_NONE; 281 ctx->sw_format = AV_PIX_FMT_NONE; 282 283 ctxi->hw_type = hw_type; 284 285 return buf; 286 287 fail: 288 av_buffer_unref(&device_ref); 289 av_freep(&ctx->hwctx); 290 av_freep(&ctx); 291 return NULL; 292 } 293 294 static int hwframe_pool_prealloc(AVBufferRef *ref) 295 { 296 AVHWFramesContext *ctx = (AVHWFramesContext*)ref->data; 297 AVFrame **frames; 298 int i, ret = 0; 299 300 frames = av_calloc(ctx->initial_pool_size, sizeof(*frames)); 301 if (!frames) 302 return AVERROR(ENOMEM); 303 304 for (i = 0; i < ctx->initial_pool_size; i++) { 305 frames[i] = av_frame_alloc(); 306 if (!frames[i]) 307 goto fail; 308 309 ret = av_hwframe_get_buffer(ref, frames[i], 0); 310 if (ret < 0) 311 goto fail; 312 } 313 314 fail: 315 for (i = 0; i < ctx->initial_pool_size; i++) 316 av_frame_free(&frames[i]); 317 av_freep(&frames); 318 319 return ret; 320 } 321 322 int av_hwframe_ctx_init(AVBufferRef *ref) 323 { 324 FFHWFramesContext *ctxi = (FFHWFramesContext*)ref->data; 325 AVHWFramesContext *ctx = &ctxi->p; 326 const enum AVPixelFormat *pix_fmt; 327 int ret; 328 329 if (ctxi->source_frames) { 330 /* A derived frame context is already initialised. */ 331 return 0; 332 } 333 334 /* validate the pixel format */ 335 for (pix_fmt = ctxi->hw_type->pix_fmts; *pix_fmt != AV_PIX_FMT_NONE; pix_fmt++) { 336 if (*pix_fmt == ctx->format) 337 break; 338 } 339 if (*pix_fmt == AV_PIX_FMT_NONE) { 340 av_log(ctx, AV_LOG_ERROR, 341 "The hardware pixel format '%s' is not supported by the device type '%s'\n", 342 av_get_pix_fmt_name(ctx->format), ctxi->hw_type->name); 343 return AVERROR(ENOSYS); 344 } 345 346 /* validate the dimensions */ 347 ret = av_image_check_size(ctx->width, ctx->height, 0, ctx); 348 if (ret < 0) 349 return ret; 350 351 /* format-specific init */ 352 if (ctxi->hw_type->frames_init) { 353 ret = ctxi->hw_type->frames_init(ctx); 354 if (ret < 0) 355 return ret; 356 } 357 358 if (ctxi->pool_internal && !ctx->pool) 359 ctx->pool = ctxi->pool_internal; 360 361 /* preallocate the frames in the pool, if requested */ 362 if (ctx->initial_pool_size > 0) { 363 ret = hwframe_pool_prealloc(ref); 364 if (ret < 0) 365 return ret; 366 } 367 368 return 0; 369 } 370 371 int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ref, 372 enum AVHWFrameTransferDirection dir, 373 enum AVPixelFormat **formats, int flags) 374 { 375 FFHWFramesContext *ctxi = (FFHWFramesContext*)hwframe_ref->data; 376 377 if (!ctxi->hw_type->transfer_get_formats) 378 return AVERROR(ENOSYS); 379 380 return ctxi->hw_type->transfer_get_formats(&ctxi->p, dir, formats); 381 } 382 383 static int transfer_data_alloc(AVFrame *dst, const AVFrame *src, int flags) 384 { 385 AVHWFramesContext *ctx; 386 AVFrame *frame_tmp; 387 int ret = 0; 388 389 if (!src->hw_frames_ctx) 390 return AVERROR(EINVAL); 391 ctx = (AVHWFramesContext*)src->hw_frames_ctx->data; 392 393 frame_tmp = av_frame_alloc(); 394 if (!frame_tmp) 395 return AVERROR(ENOMEM); 396 397 /* if the format is set, use that 398 * otherwise pick the first supported one */ 399 if (dst->format >= 0) { 400 frame_tmp->format = dst->format; 401 } else { 402 enum AVPixelFormat *formats; 403 404 ret = av_hwframe_transfer_get_formats(src->hw_frames_ctx, 405 AV_HWFRAME_TRANSFER_DIRECTION_FROM, 406 &formats, 0); 407 if (ret < 0) 408 goto fail; 409 frame_tmp->format = formats[0]; 410 av_freep(&formats); 411 } 412 frame_tmp->width = ctx->width; 413 frame_tmp->height = ctx->height; 414 415 ret = av_frame_get_buffer(frame_tmp, 0); 416 if (ret < 0) 417 goto fail; 418 419 ret = av_hwframe_transfer_data(frame_tmp, src, flags); 420 if (ret < 0) 421 goto fail; 422 423 frame_tmp->width = src->width; 424 frame_tmp->height = src->height; 425 426 av_frame_move_ref(dst, frame_tmp); 427 428 fail: 429 av_frame_free(&frame_tmp); 430 return ret; 431 } 432 433 int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags) 434 { 435 int ret; 436 437 if (!dst->buf[0]) 438 return transfer_data_alloc(dst, src, flags); 439 440 /* 441 * Hardware -> Hardware Transfer. 442 * Unlike Software -> Hardware or Hardware -> Software, the transfer 443 * function could be provided by either the src or dst, depending on 444 * the specific combination of hardware. 445 */ 446 if (src->hw_frames_ctx && dst->hw_frames_ctx) { 447 FFHWFramesContext *src_ctx = 448 (FFHWFramesContext*)src->hw_frames_ctx->data; 449 FFHWFramesContext *dst_ctx = 450 (FFHWFramesContext*)dst->hw_frames_ctx->data; 451 452 if (src_ctx->source_frames) { 453 av_log(src_ctx, AV_LOG_ERROR, 454 "A device with a derived frame context cannot be used as " 455 "the source of a HW -> HW transfer."); 456 return AVERROR(ENOSYS); 457 } 458 459 if (dst_ctx->source_frames) { 460 av_log(src_ctx, AV_LOG_ERROR, 461 "A device with a derived frame context cannot be used as " 462 "the destination of a HW -> HW transfer."); 463 return AVERROR(ENOSYS); 464 } 465 466 ret = src_ctx->hw_type->transfer_data_from(&src_ctx->p, dst, src); 467 if (ret == AVERROR(ENOSYS)) 468 ret = dst_ctx->hw_type->transfer_data_to(&dst_ctx->p, dst, src); 469 if (ret < 0) 470 return ret; 471 } else { 472 if (src->hw_frames_ctx) { 473 FFHWFramesContext *ctx = (FFHWFramesContext*)src->hw_frames_ctx->data; 474 475 ret = ctx->hw_type->transfer_data_from(&ctx->p, dst, src); 476 if (ret < 0) 477 return ret; 478 } else if (dst->hw_frames_ctx) { 479 FFHWFramesContext *ctx = (FFHWFramesContext*)dst->hw_frames_ctx->data; 480 481 ret = ctx->hw_type->transfer_data_to(&ctx->p, dst, src); 482 if (ret < 0) 483 return ret; 484 } else { 485 return AVERROR(ENOSYS); 486 } 487 } 488 return 0; 489 } 490 491 int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags) 492 { 493 FFHWFramesContext *ctxi = (FFHWFramesContext*)hwframe_ref->data; 494 AVHWFramesContext *ctx = &ctxi->p; 495 int ret; 496 497 if (ctxi->source_frames) { 498 // This is a derived frame context, so we allocate in the source 499 // and map the frame immediately. 500 AVFrame *src_frame; 501 502 frame->format = ctx->format; 503 frame->hw_frames_ctx = av_buffer_ref(hwframe_ref); 504 if (!frame->hw_frames_ctx) 505 return AVERROR(ENOMEM); 506 507 src_frame = av_frame_alloc(); 508 if (!src_frame) 509 return AVERROR(ENOMEM); 510 511 ret = av_hwframe_get_buffer(ctxi->source_frames, 512 src_frame, 0); 513 if (ret < 0) { 514 av_frame_free(&src_frame); 515 return ret; 516 } 517 518 ret = av_hwframe_map(frame, src_frame, 519 ctxi->source_allocation_map_flags); 520 if (ret) { 521 av_log(ctx, AV_LOG_ERROR, "Failed to map frame into derived " 522 "frame context: %d.\n", ret); 523 av_frame_free(&src_frame); 524 return ret; 525 } 526 527 // Free the source frame immediately - the mapped frame still 528 // contains a reference to it. 529 av_frame_free(&src_frame); 530 531 return 0; 532 } 533 534 if (!ctxi->hw_type->frames_get_buffer) 535 return AVERROR(ENOSYS); 536 537 if (!ctx->pool) 538 return AVERROR(EINVAL); 539 540 frame->hw_frames_ctx = av_buffer_ref(hwframe_ref); 541 if (!frame->hw_frames_ctx) 542 return AVERROR(ENOMEM); 543 544 ret = ctxi->hw_type->frames_get_buffer(ctx, frame); 545 if (ret < 0) { 546 av_buffer_unref(&frame->hw_frames_ctx); 547 return ret; 548 } 549 550 frame->extended_data = frame->data; 551 552 return 0; 553 } 554 555 void *av_hwdevice_hwconfig_alloc(AVBufferRef *ref) 556 { 557 FFHWDeviceContext *ctx = (FFHWDeviceContext*)ref->data; 558 const HWContextType *hw_type = ctx->hw_type; 559 560 if (hw_type->device_hwconfig_size == 0) 561 return NULL; 562 563 return av_mallocz(hw_type->device_hwconfig_size); 564 } 565 566 AVHWFramesConstraints *av_hwdevice_get_hwframe_constraints(AVBufferRef *ref, 567 const void *hwconfig) 568 { 569 FFHWDeviceContext *ctx = (FFHWDeviceContext*)ref->data; 570 const HWContextType *hw_type = ctx->hw_type; 571 AVHWFramesConstraints *constraints; 572 573 if (!hw_type->frames_get_constraints) 574 return NULL; 575 576 constraints = av_mallocz(sizeof(*constraints)); 577 if (!constraints) 578 return NULL; 579 580 constraints->min_width = constraints->min_height = 0; 581 constraints->max_width = constraints->max_height = INT_MAX; 582 583 if (hw_type->frames_get_constraints(&ctx->p, hwconfig, constraints) >= 0) { 584 return constraints; 585 } else { 586 av_hwframe_constraints_free(&constraints); 587 return NULL; 588 } 589 } 590 591 void av_hwframe_constraints_free(AVHWFramesConstraints **constraints) 592 { 593 if (*constraints) { 594 av_freep(&(*constraints)->valid_hw_formats); 595 av_freep(&(*constraints)->valid_sw_formats); 596 } 597 av_freep(constraints); 598 } 599 600 int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type, 601 const char *device, AVDictionary *opts, int flags) 602 { 603 AVBufferRef *device_ref = NULL; 604 FFHWDeviceContext *device_ctx; 605 int ret = 0; 606 607 device_ref = av_hwdevice_ctx_alloc(type); 608 if (!device_ref) { 609 ret = AVERROR(ENOMEM); 610 goto fail; 611 } 612 device_ctx = (FFHWDeviceContext*)device_ref->data; 613 614 if (!device_ctx->hw_type->device_create) { 615 ret = AVERROR(ENOSYS); 616 goto fail; 617 } 618 619 ret = device_ctx->hw_type->device_create(&device_ctx->p, device, 620 opts, flags); 621 if (ret < 0) 622 goto fail; 623 624 ret = av_hwdevice_ctx_init(device_ref); 625 if (ret < 0) 626 goto fail; 627 628 *pdevice_ref = device_ref; 629 return 0; 630 fail: 631 av_buffer_unref(&device_ref); 632 *pdevice_ref = NULL; 633 return ret; 634 } 635 636 int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ref_ptr, 637 enum AVHWDeviceType type, 638 AVBufferRef *src_ref, 639 AVDictionary *options, int flags) 640 { 641 AVBufferRef *dst_ref = NULL, *tmp_ref; 642 FFHWDeviceContext *dst_ctx; 643 int ret = 0; 644 645 tmp_ref = src_ref; 646 while (tmp_ref) { 647 FFHWDeviceContext *tmp_ctx = (FFHWDeviceContext*)tmp_ref->data; 648 if (tmp_ctx->p.type == type) { 649 dst_ref = av_buffer_ref(tmp_ref); 650 if (!dst_ref) { 651 ret = AVERROR(ENOMEM); 652 goto fail; 653 } 654 goto done; 655 } 656 tmp_ref = tmp_ctx->source_device; 657 } 658 659 dst_ref = av_hwdevice_ctx_alloc(type); 660 if (!dst_ref) { 661 ret = AVERROR(ENOMEM); 662 goto fail; 663 } 664 dst_ctx = (FFHWDeviceContext*)dst_ref->data; 665 666 tmp_ref = src_ref; 667 while (tmp_ref) { 668 FFHWDeviceContext *tmp_ctx = (FFHWDeviceContext*)tmp_ref->data; 669 if (dst_ctx->hw_type->device_derive) { 670 ret = dst_ctx->hw_type->device_derive(&dst_ctx->p, 671 &tmp_ctx->p, 672 options, flags); 673 if (ret == 0) { 674 dst_ctx->source_device = av_buffer_ref(src_ref); 675 if (!dst_ctx->source_device) { 676 ret = AVERROR(ENOMEM); 677 goto fail; 678 } 679 ret = av_hwdevice_ctx_init(dst_ref); 680 if (ret < 0) 681 goto fail; 682 goto done; 683 } 684 if (ret != AVERROR(ENOSYS)) 685 goto fail; 686 } 687 tmp_ref = tmp_ctx->source_device; 688 } 689 690 ret = AVERROR(ENOSYS); 691 goto fail; 692 693 done: 694 *dst_ref_ptr = dst_ref; 695 return 0; 696 697 fail: 698 av_buffer_unref(&dst_ref); 699 *dst_ref_ptr = NULL; 700 return ret; 701 } 702 703 int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ref_ptr, 704 enum AVHWDeviceType type, 705 AVBufferRef *src_ref, int flags) 706 { 707 return av_hwdevice_ctx_create_derived_opts(dst_ref_ptr, type, src_ref, 708 NULL, flags); 709 } 710 711 static void ff_hwframe_unmap(void *opaque, uint8_t *data) 712 { 713 HWMapDescriptor *hwmap = (HWMapDescriptor*)data; 714 AVHWFramesContext *ctx = opaque; 715 716 if (hwmap->unmap) 717 hwmap->unmap(ctx, hwmap); 718 719 av_frame_free(&hwmap->source); 720 721 av_buffer_unref(&hwmap->hw_frames_ctx); 722 723 av_free(hwmap); 724 } 725 726 int ff_hwframe_map_create(AVBufferRef *hwframe_ref, 727 AVFrame *dst, const AVFrame *src, 728 void (*unmap)(AVHWFramesContext *ctx, 729 HWMapDescriptor *hwmap), 730 void *priv) 731 { 732 AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data; 733 HWMapDescriptor *hwmap; 734 int ret; 735 736 hwmap = av_mallocz(sizeof(*hwmap)); 737 if (!hwmap) { 738 ret = AVERROR(ENOMEM); 739 goto fail; 740 } 741 742 hwmap->source = av_frame_alloc(); 743 if (!hwmap->source) { 744 ret = AVERROR(ENOMEM); 745 goto fail; 746 } 747 ret = av_frame_ref(hwmap->source, src); 748 if (ret < 0) 749 goto fail; 750 751 hwmap->hw_frames_ctx = av_buffer_ref(hwframe_ref); 752 if (!hwmap->hw_frames_ctx) { 753 ret = AVERROR(ENOMEM); 754 goto fail; 755 } 756 757 hwmap->unmap = unmap; 758 hwmap->priv = priv; 759 760 dst->buf[0] = av_buffer_create((uint8_t*)hwmap, sizeof(*hwmap), 761 &ff_hwframe_unmap, ctx, 0); 762 if (!dst->buf[0]) { 763 ret = AVERROR(ENOMEM); 764 goto fail; 765 } 766 767 return 0; 768 769 fail: 770 if (hwmap) { 771 av_buffer_unref(&hwmap->hw_frames_ctx); 772 av_frame_free(&hwmap->source); 773 } 774 av_free(hwmap); 775 return ret; 776 } 777 778 int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags) 779 { 780 AVBufferRef *orig_dst_frames = dst->hw_frames_ctx; 781 enum AVPixelFormat orig_dst_fmt = dst->format; 782 HWMapDescriptor *hwmap; 783 int ret; 784 785 if (src->hw_frames_ctx && dst->hw_frames_ctx) { 786 FFHWFramesContext *src_frames = (FFHWFramesContext*)src->hw_frames_ctx->data; 787 FFHWFramesContext *dst_frames = (FFHWFramesContext*)dst->hw_frames_ctx->data; 788 789 if ((src_frames == dst_frames && 790 src->format == dst_frames->p.sw_format && 791 dst->format == dst_frames->p.format) || 792 (src_frames->source_frames && 793 src_frames->source_frames->data == 794 (uint8_t*)dst_frames)) { 795 // This is an unmap operation. We don't need to directly 796 // do anything here other than fill in the original frame, 797 // because the real unmap will be invoked when the last 798 // reference to the mapped frame disappears. 799 if (!src->buf[0]) { 800 av_log(src_frames, AV_LOG_ERROR, "Invalid mapping " 801 "found when attempting unmap.\n"); 802 return AVERROR(EINVAL); 803 } 804 hwmap = (HWMapDescriptor*)src->buf[0]->data; 805 return av_frame_replace(dst, hwmap->source); 806 } 807 } 808 809 if (src->hw_frames_ctx) { 810 FFHWFramesContext *src_frames = (FFHWFramesContext*)src->hw_frames_ctx->data; 811 812 if (src_frames->p.format == src->format && 813 src_frames->hw_type->map_from) { 814 ret = src_frames->hw_type->map_from(&src_frames->p, 815 dst, src, flags); 816 if (ret >= 0) 817 return ret; 818 else if (ret != AVERROR(ENOSYS)) 819 goto fail; 820 } 821 } 822 823 if (dst->hw_frames_ctx) { 824 FFHWFramesContext *dst_frames = (FFHWFramesContext*)dst->hw_frames_ctx->data; 825 826 if (dst_frames->p.format == dst->format && 827 dst_frames->hw_type->map_to) { 828 ret = dst_frames->hw_type->map_to(&dst_frames->p, 829 dst, src, flags); 830 if (ret >= 0) 831 return ret; 832 else if (ret != AVERROR(ENOSYS)) 833 goto fail; 834 } 835 } 836 837 return AVERROR(ENOSYS); 838 839 fail: 840 // if the caller provided dst frames context, it should be preserved 841 // by this function 842 av_assert0(orig_dst_frames == NULL || 843 orig_dst_frames == dst->hw_frames_ctx); 844 845 // preserve user-provided dst frame fields, but clean 846 // anything we might have set 847 dst->hw_frames_ctx = NULL; 848 av_frame_unref(dst); 849 850 dst->hw_frames_ctx = orig_dst_frames; 851 dst->format = orig_dst_fmt; 852 853 return ret; 854 } 855 856 int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx, 857 enum AVPixelFormat format, 858 AVBufferRef *derived_device_ctx, 859 AVBufferRef *source_frame_ctx, 860 int flags) 861 { 862 AVBufferRef *dst_ref = NULL; 863 FFHWFramesContext *dsti = NULL; 864 FFHWFramesContext *srci = (FFHWFramesContext*)source_frame_ctx->data; 865 AVHWFramesContext *dst, *src = &srci->p; 866 int ret; 867 868 if (srci->source_frames) { 869 AVHWFramesContext *src_src = 870 (AVHWFramesContext*)srci->source_frames->data; 871 AVHWDeviceContext *dst_dev = 872 (AVHWDeviceContext*)derived_device_ctx->data; 873 874 if (src_src->device_ctx == dst_dev) { 875 // This is actually an unmapping, so we just return a 876 // reference to the source frame context. 877 *derived_frame_ctx = av_buffer_ref(srci->source_frames); 878 if (!*derived_frame_ctx) { 879 ret = AVERROR(ENOMEM); 880 goto fail; 881 } 882 return 0; 883 } 884 } 885 886 dst_ref = av_hwframe_ctx_alloc(derived_device_ctx); 887 if (!dst_ref) { 888 ret = AVERROR(ENOMEM); 889 goto fail; 890 } 891 892 dsti = (FFHWFramesContext*)dst_ref->data; 893 dst = &dsti->p; 894 895 dst->format = format; 896 dst->sw_format = src->sw_format; 897 dst->width = src->width; 898 dst->height = src->height; 899 900 dsti->source_frames = av_buffer_ref(source_frame_ctx); 901 if (!dsti->source_frames) { 902 ret = AVERROR(ENOMEM); 903 goto fail; 904 } 905 906 dsti->source_allocation_map_flags = 907 flags & (AV_HWFRAME_MAP_READ | 908 AV_HWFRAME_MAP_WRITE | 909 AV_HWFRAME_MAP_OVERWRITE | 910 AV_HWFRAME_MAP_DIRECT); 911 912 ret = AVERROR(ENOSYS); 913 if (srci->hw_type->frames_derive_from) 914 ret = srci->hw_type->frames_derive_from(dst, src, flags); 915 if (ret == AVERROR(ENOSYS) && 916 dsti->hw_type->frames_derive_to) 917 ret = dsti->hw_type->frames_derive_to(dst, src, flags); 918 if (ret == AVERROR(ENOSYS)) 919 ret = 0; 920 if (ret) 921 goto fail; 922 923 *derived_frame_ctx = dst_ref; 924 return 0; 925 926 fail: 927 if (dsti) 928 av_buffer_unref(&dsti->source_frames); 929 av_buffer_unref(&dst_ref); 930 return ret; 931 } 932 933 int ff_hwframe_map_replace(AVFrame *dst, const AVFrame *src) 934 { 935 HWMapDescriptor *hwmap = (HWMapDescriptor*)dst->buf[0]->data; 936 return av_frame_replace(hwmap->source, src); 937 }