(cherry picked from commit e1c5d56b18b82e3fb42382b1b1f972e8b371fc38)
Unified · Split
| @@ -577,13 +577,62 @@ static int qsv_transfer_get_formats(AVHWFramesContext *ctx, · 576 unmodified lines | |||
| 577 | return 0; | 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 | static int qsv_map_from(AVHWFramesContext *ctx, | 628 | static int qsv_map_from(AVHWFramesContext *ctx, |
| 581 | AVFrame *dst, const AVFrame *src, int flags) | 629 | AVFrame *dst, const AVFrame *src, int flags) |
| 582 | { | 630 | { |
| 583 | QSVFramesContext *s = ctx->internal->priv; | 631 | QSVFramesContext *s = ctx->internal->priv; |
| 584 | mfxFrameSurface1 *surf = (mfxFrameSurface1*)src->data[3]; | 632 | mfxFrameSurface1 *surf = (mfxFrameSurface1*)src->data[3]; |
| 585 | AVHWFramesContext *child_frames_ctx; | 633 | AVHWFramesContext *child_frames_ctx; |
| 586 | 634 | const AVPixFmtDescriptor *desc; | |
| 635 | uint8_t *child_data; | ||
| 587 | AVFrame *dummy; | 636 | AVFrame *dummy; |
| 588 | int ret = 0; | 637 | int ret = 0; |
| 589 | 638 | ||
| @@ -591,6 +640,40 @@ static int qsv_map_from(AVHWFramesContext *ctx, · 1 unmodified line | |||
| 591 | return AVERROR(ENOSYS); | 640 | return AVERROR(ENOSYS); |
| 592 | child_frames_ctx = (AVHWFramesContext*)s->child_frames_ref->data; | 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 | dummy = av_frame_alloc(); | 677 | dummy = av_frame_alloc(); |
| 595 | if (!dummy) | 678 | if (!dummy) |
| 596 | return AVERROR(ENOMEM); | 679 | return AVERROR(ENOMEM); |
| @@ -603,7 +686,7 @@ static int qsv_map_from(AVHWFramesContext *ctx, · 6 unmodified lines | |||
| 603 | dummy->format = child_frames_ctx->format; | 686 | dummy->format = child_frames_ctx->format; |
| 604 | dummy->width = src->width; | 687 | dummy->width = src->width; |
| 605 | dummy->height = src->height; | 688 | dummy->height = src->height; |
| 606 | dummy->data[3] = surf->Data.MemId; | 689 | dummy->data[3] = child_data; |
| 607 | 690 | ||
| 608 | ret = av_hwframe_map(dst, dummy, flags); | 691 | ret = av_hwframe_map(dst, dummy, flags); |
| 609 | 692 | ||
| @@ -1042,6 +1125,7 @@ const HWContextType ff_hwcontext_type_qsv = { · 432 unmodified lines | |||
| 1042 | .map_to = qsv_map_to, | 1125 | .map_to = qsv_map_to, |
| 1043 | .map_from = qsv_map_from, | 1126 | .map_from = qsv_map_from, |
| 1044 | .frames_derive_to = qsv_frames_derive_to, | 1127 | .frames_derive_to = qsv_frames_derive_to, |
| 1128 | .frames_derive_from = qsv_frames_derive_from, | ||
| 1045 | 1129 | ||
| 1046 | .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, | 1130 | .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, |
| 1047 | }; | 1131 | }; |