(cherry picked from commit e1c5d56b18b82e3fb42382b1b1f972e8b371fc38)
Unified · Split
| @@ -577,13 +577,62 @@ static int qsv_transfer_get_formats(AVHWFramesContext *ctx, · 576 unmodified lines | ||
| 577 | 577 | return 0; |
| 578 | 578 | } |
| 579 | 579 | |
| 580 | +static int qsv_frames_derive_from(AVHWFramesContext *dst_ctx, | |
| 581 | + AVHWFramesContext *src_ctx, int flags) | |
| 582 | +{ | |
| 583 | + AVQSVFramesContext *src_hwctx = src_ctx->hwctx; | |
| 584 | + int i; | |
| 585 | + | |
| 586 | + switch (dst_ctx->device_ctx->type) { | |
| 587 | +#if CONFIG_VAAPI | |
| 588 | + case AV_HWDEVICE_TYPE_VAAPI: | |
| 589 | + { | |
| 590 | + AVVAAPIFramesContext *dst_hwctx = dst_ctx->hwctx; | |
| 591 | + dst_hwctx->surface_ids = av_mallocz_array(src_hwctx->nb_surfaces, | |
| 592 | + sizeof(*dst_hwctx->surface_ids)); | |
| 593 | + if (!dst_hwctx->surface_ids) | |
| 594 | + return AVERROR(ENOMEM); | |
| 595 | + for (i = 0; i < src_hwctx->nb_surfaces; i++) | |
| 596 | + dst_hwctx->surface_ids[i] = | |
| 597 | + *(VASurfaceID*)src_hwctx->surfaces[i].Data.MemId; | |
| 598 | + dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces; | |
| 599 | + } | |
| 600 | + break; | |
| 601 | +#endif | |
| 602 | +#if CONFIG_DXVA2 | |
| 603 | + case AV_HWDEVICE_TYPE_DXVA2: | |
| 604 | + { | |
| 605 | + AVDXVA2FramesContext *dst_hwctx = dst_ctx->hwctx; | |
| 606 | + dst_hwctx->surfaces = av_mallocz_array(src_hwctx->nb_surfaces, | |
| 607 | + sizeof(*dst_hwctx->surfaces)); | |
| 608 | + if (!dst_hwctx->surfaces) | |
| 609 | + return AVERROR(ENOMEM); | |
| 610 | + for (i = 0; i < src_hwctx->nb_surfaces; i++) | |
| 611 | + dst_hwctx->surfaces[i] = | |
| 612 | + (IDirect3DSurface9*)src_hwctx->surfaces[i].Data.MemId; | |
| 613 | + dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces; | |
| 614 | + if (src_hwctx->frame_type == MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET) | |
| 615 | + dst_hwctx->surface_type = DXVA2_VideoDecoderRenderTarget; | |
| 616 | + else | |
| 617 | + dst_hwctx->surface_type = DXVA2_VideoProcessorRenderTarget; | |
| 618 | + } | |
| 619 | + break; | |
| 620 | +#endif | |
| 621 | + default: | |
| 622 | + return AVERROR(ENOSYS); | |
| 623 | + } | |
| 624 | + | |
| 625 | + return 0; | |
| 626 | +} | |
| 627 | + | |
| 580 | 628 | static int qsv_map_from(AVHWFramesContext *ctx, |
| 581 | 629 | AVFrame *dst, const AVFrame *src, int flags) |
| 582 | 630 | { |
| 583 | 631 | QSVFramesContext *s = ctx->internal->priv; |
| 584 | 632 | mfxFrameSurface1 *surf = (mfxFrameSurface1*)src->data[3]; |
| 585 | 633 | AVHWFramesContext *child_frames_ctx; |
| 586 | − | |
| 634 | + const AVPixFmtDescriptor *desc; | |
| 635 | + uint8_t *child_data; | |
| 587 | 636 | AVFrame *dummy; |
| 588 | 637 | int ret = 0; |
| 589 | 638 | |
| @@ -591,6 +640,40 @@ static int qsv_map_from(AVHWFramesContext *ctx, · 1 unmodified line | ||
| 591 | 640 | return AVERROR(ENOSYS); |
| 592 | 641 | child_frames_ctx = (AVHWFramesContext*)s->child_frames_ref->data; |
| 593 | 642 | |
| 643 | + switch (child_frames_ctx->device_ctx->type) { | |
| 644 | +#if CONFIG_VAAPI | |
| 645 | + case AV_HWDEVICE_TYPE_VAAPI: | |
| 646 | + child_data = (uint8_t*)(intptr_t)*(VASurfaceID*)surf->Data.MemId; | |
| 647 | + break; | |
| 648 | +#endif | |
| 649 | +#if CONFIG_DXVA2 | |
| 650 | + case AV_HWDEVICE_TYPE_DXVA2: | |
| 651 | + child_data = surf->Data.MemId; | |
| 652 | + break; | |
| 653 | +#endif | |
| 654 | + default: | |
| 655 | + return AVERROR(ENOSYS); | |
| 656 | + } | |
| 657 | + | |
| 658 | + if (dst->format == child_frames_ctx->format) { | |
| 659 | + ret = ff_hwframe_map_create(s->child_frames_ref, | |
| 660 | + dst, src, NULL, NULL); | |
| 661 | + if (ret < 0) | |
| 662 | + return ret; | |
| 663 | + | |
| 664 | + dst->width = src->width; | |
| 665 | + dst->height = src->height; | |
| 666 | + dst->data[3] = child_data; | |
| 667 | + | |
| 668 | + return 0; | |
| 669 | + } | |
| 670 | + | |
| 671 | + desc = av_pix_fmt_desc_get(dst->format); | |
| 672 | + if (desc && desc->flags & AV_PIX_FMT_FLAG_HWACCEL) { | |
| 673 | + // This only supports mapping to software. | |
| 674 | + return AVERROR(ENOSYS); | |
| 675 | + } | |
| 676 | + | |
| 594 | 677 | dummy = av_frame_alloc(); |
| 595 | 678 | if (!dummy) |
| 596 | 679 | return AVERROR(ENOMEM); |
| @@ -603,7 +686,7 @@ static int qsv_map_from(AVHWFramesContext *ctx, · 6 unmodified lines | ||
| 603 | 686 | dummy->format = child_frames_ctx->format; |
| 604 | 687 | dummy->width = src->width; |
| 605 | 688 | dummy->height = src->height; |
| 606 | − dummy->data[3] = surf->Data.MemId; | |
| 689 | + dummy->data[3] = child_data; | |
| 607 | 690 | |
| 608 | 691 | ret = av_hwframe_map(dst, dummy, flags); |
| 609 | 692 | |
| @@ -1042,6 +1125,7 @@ const HWContextType ff_hwcontext_type_qsv = { · 432 unmodified lines | ||
| 1042 | 1125 | .map_to = qsv_map_to, |
| 1043 | 1126 | .map_from = qsv_map_from, |
| 1044 | 1127 | .frames_derive_to = qsv_frames_derive_to, |
| 1128 | + .frames_derive_from = qsv_frames_derive_from, | |
| 1045 | 1129 | |
| 1046 | 1130 | .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, |
| 1047 | 1131 | }; |