Factorises out existing surface initialisation code to reuse. (cherry picked from commit eaa5e0710496db50fc164806e5f49eaaccc83bb5)
Unified · Split
| @@ -94,6 +94,16 @@ static const struct { · 93 unmodified lines | ||
| 94 | 94 | { AV_PIX_FMT_PAL8, MFX_FOURCC_P8 }, |
| 95 | 95 | }; |
| 96 | 96 | |
| 97 | +static uint32_t qsv_fourcc_from_pix_fmt(enum AVPixelFormat pix_fmt) | |
| 98 | +{ | |
| 99 | + int i; | |
| 100 | + for (i = 0; i < FF_ARRAY_ELEMS(supported_pixel_formats); i++) { | |
| 101 | + if (supported_pixel_formats[i].pix_fmt == pix_fmt) | |
| 102 | + return supported_pixel_formats[i].fourcc; | |
| 103 | + } | |
| 104 | + return 0; | |
| 105 | +} | |
| 106 | + | |
| 97 | 107 | static int qsv_device_init(AVHWDeviceContext *ctx) |
| 98 | 108 | { |
| 99 | 109 | AVQSVDeviceContext *hwctx = ctx->hwctx; |
| @@ -272,18 +282,48 @@ fail: · 172 unmodified lines | ||
| 272 | 282 | return ret; |
| 273 | 283 | } |
| 274 | 284 | |
| 285 | +static int qsv_init_surface(AVHWFramesContext *ctx, mfxFrameSurface1 *surf) | |
| 286 | +{ | |
| 287 | + const AVPixFmtDescriptor *desc; | |
| 288 | + uint32_t fourcc; | |
| 289 | + | |
| 290 | + desc = av_pix_fmt_desc_get(ctx->sw_format); | |
| 291 | + if (!desc) | |
| 292 | + return AVERROR(EINVAL); | |
| 293 | + | |
| 294 | + fourcc = qsv_fourcc_from_pix_fmt(ctx->sw_format); | |
| 295 | + if (!fourcc) | |
| 296 | + return AVERROR(EINVAL); | |
| 297 | + | |
| 298 | + surf->Info.BitDepthLuma = desc->comp[0].depth; | |
| 299 | + surf->Info.BitDepthChroma = desc->comp[0].depth; | |
| 300 | + surf->Info.Shift = desc->comp[0].depth > 8; | |
| 301 | + | |
| 302 | + if (desc->log2_chroma_w && desc->log2_chroma_h) | |
| 303 | + surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV420; | |
| 304 | + else if (desc->log2_chroma_w) | |
| 305 | + surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV422; | |
| 306 | + else | |
| 307 | + surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV444; | |
| 308 | + | |
| 309 | + surf->Info.FourCC = fourcc; | |
| 310 | + surf->Info.Width = ctx->width; | |
| 311 | + surf->Info.CropW = ctx->width; | |
| 312 | + surf->Info.Height = ctx->height; | |
| 313 | + surf->Info.CropH = ctx->height; | |
| 314 | + surf->Info.FrameRateExtN = 25; | |
| 315 | + surf->Info.FrameRateExtD = 1; | |
| 316 | + | |
| 317 | + return 0; | |
| 318 | +} | |
| 319 | + | |
| 275 | 320 | static int qsv_init_pool(AVHWFramesContext *ctx, uint32_t fourcc) |
| 276 | 321 | { |
| 277 | 322 | QSVFramesContext *s = ctx->internal->priv; |
| 278 | 323 | AVQSVFramesContext *frames_hwctx = ctx->hwctx; |
| 279 | − const AVPixFmtDescriptor *desc; | |
| 280 | 324 | |
| 281 | 325 | int i, ret = 0; |
| 282 | 326 | |
| 283 | − desc = av_pix_fmt_desc_get(ctx->sw_format); | |
| 284 | − if (!desc) | |
| 285 | − return AVERROR_BUG; | |
| 286 | − | |
| 287 | 327 | if (ctx->initial_pool_size <= 0) { |
| 288 | 328 | av_log(ctx, AV_LOG_ERROR, "QSV requires a fixed frame pool size\n"); |
| 289 | 329 | return AVERROR(EINVAL); |
| @@ -295,26 +335,9 @@ static int qsv_init_pool(AVHWFramesContext *ctx, uint32_t fourcc) · 5 unmodified lines | ||
| 295 | 335 | return AVERROR(ENOMEM); |
| 296 | 336 | |
| 297 | 337 | for (i = 0; i < ctx->initial_pool_size; i++) { |
| 298 | − mfxFrameSurface1 *surf = &s->surfaces_internal[i]; | |
| 299 | − | |
| 300 | − surf->Info.BitDepthLuma = desc->comp[0].depth; | |
| 301 | − surf->Info.BitDepthChroma = desc->comp[0].depth; | |
| 302 | − surf->Info.Shift = desc->comp[0].depth > 8; | |
| 303 | − | |
| 304 | − if (desc->log2_chroma_w && desc->log2_chroma_h) | |
| 305 | − surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV420; | |
| 306 | − else if (desc->log2_chroma_w) | |
| 307 | − surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV422; | |
| 308 | − else | |
| 309 | − surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV444; | |
| 310 | − | |
| 311 | − surf->Info.FourCC = fourcc; | |
| 312 | − surf->Info.Width = ctx->width; | |
| 313 | − surf->Info.CropW = ctx->width; | |
| 314 | − surf->Info.Height = ctx->height; | |
| 315 | − surf->Info.CropH = ctx->height; | |
| 316 | − surf->Info.FrameRateExtN = 25; | |
| 317 | − surf->Info.FrameRateExtD = 1; | |
| 338 | + ret = qsv_init_surface(ctx, &s->surfaces_internal[i]); | |
| 339 | + if (ret < 0) | |
| 340 | + return ret; | |
| 318 | 341 | } |
| 319 | 342 | |
| 320 | 343 | if (!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME)) { |
| @@ -466,15 +489,10 @@ static int qsv_frames_init(AVHWFramesContext *ctx) · 145 unmodified lines | ||
| 466 | 489 | |
| 467 | 490 | int opaque = !!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME); |
| 468 | 491 | |
| 469 | − uint32_t fourcc = 0; | |
| 492 | + uint32_t fourcc; | |
| 470 | 493 | int i, ret; |
| 471 | 494 | |
| 472 | − for (i = 0; i < FF_ARRAY_ELEMS(supported_pixel_formats); i++) { | |
| 473 | − if (supported_pixel_formats[i].pix_fmt == ctx->sw_format) { | |
| 474 | − fourcc = supported_pixel_formats[i].fourcc; | |
| 475 | − break; | |
| 476 | − } | |
| 477 | − } | |
| 495 | + fourcc = qsv_fourcc_from_pix_fmt(ctx->sw_format); | |
| 478 | 496 | if (!fourcc) { |
| 479 | 497 | av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format\n"); |
| 480 | 498 | return AVERROR(ENOSYS); |
| @@ -723,6 +741,96 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, · 242 unmodified lines | ||
| 723 | 741 | return 0; |
| 724 | 742 | } |
| 725 | 743 | |
| 744 | +static int qsv_frames_derive_to(AVHWFramesContext *dst_ctx, | |
| 745 | + AVHWFramesContext *src_ctx, int flags) | |
| 746 | +{ | |
| 747 | + QSVFramesContext *s = dst_ctx->internal->priv; | |
| 748 | + AVQSVFramesContext *dst_hwctx = dst_ctx->hwctx; | |
| 749 | + int i; | |
| 750 | + | |
| 751 | + switch (src_ctx->device_ctx->type) { | |
| 752 | +#if CONFIG_VAAPI | |
| 753 | + case AV_HWDEVICE_TYPE_VAAPI: | |
| 754 | + { | |
| 755 | + AVVAAPIFramesContext *src_hwctx = src_ctx->hwctx; | |
| 756 | + s->surfaces_internal = av_mallocz_array(src_hwctx->nb_surfaces, | |
| 757 | + sizeof(*s->surfaces_internal)); | |
| 758 | + if (!s->surfaces_internal) | |
| 759 | + return AVERROR(ENOMEM); | |
| 760 | + for (i = 0; i < src_hwctx->nb_surfaces; i++) { | |
| 761 | + qsv_init_surface(dst_ctx, &s->surfaces_internal[i]); | |
| 762 | + s->surfaces_internal[i].Data.MemId = src_hwctx->surface_ids + i; | |
| 763 | + } | |
| 764 | + dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces; | |
| 765 | + dst_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET; | |
| 766 | + } | |
| 767 | + break; | |
| 768 | +#endif | |
| 769 | +#if CONFIG_DXVA2 | |
| 770 | + case AV_HWDEVICE_TYPE_DXVA2: | |
| 771 | + { | |
| 772 | + AVDXVA2FramesContext *src_hwctx = src_ctx->hwctx; | |
| 773 | + s->surfaces_internal = av_mallocz_array(src_hwctx->nb_surfaces, | |
| 774 | + sizeof(*s->surfaces_internal)); | |
| 775 | + if (!s->surfaces_internal) | |
| 776 | + return AVERROR(ENOMEM); | |
| 777 | + for (i = 0; i < src_hwctx->nb_surfaces; i++) { | |
| 778 | + qsv_init_surface(dst_ctx, &s->surfaces_internal[i]); | |
| 779 | + s->surfaces_internal[i].Data.MemId = (mfxMemId)src_hwctx->surfaces[i]; | |
| 780 | + } | |
| 781 | + dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces; | |
| 782 | + if (src_hwctx->surface_type == DXVA2_VideoProcessorRenderTarget) | |
| 783 | + dst_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET; | |
| 784 | + else | |
| 785 | + dst_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET; | |
| 786 | + } | |
| 787 | + break; | |
| 788 | +#endif | |
| 789 | + default: | |
| 790 | + return AVERROR(ENOSYS); | |
| 791 | + } | |
| 792 | + | |
| 793 | + dst_hwctx->surfaces = s->surfaces_internal; | |
| 794 | + | |
| 795 | + return 0; | |
| 796 | +} | |
| 797 | + | |
| 798 | +static int qsv_map_to(AVHWFramesContext *dst_ctx, | |
| 799 | + AVFrame *dst, const AVFrame *src, int flags) | |
| 800 | +{ | |
| 801 | + AVQSVFramesContext *hwctx = dst_ctx->hwctx; | |
| 802 | + int i, err; | |
| 803 | + | |
| 804 | + for (i = 0; i < hwctx->nb_surfaces; i++) { | |
| 805 | +#if CONFIG_VAAPI | |
| 806 | + if (*(VASurfaceID*)hwctx->surfaces[i].Data.MemId == | |
| 807 | + (VASurfaceID)(uintptr_t)src->data[3]) | |
| 808 | + break; | |
| 809 | +#endif | |
| 810 | +#if CONFIG_DXVA2 | |
| 811 | + if ((IDirect3DSurface9*)hwctx->surfaces[i].Data.MemId == | |
| 812 | + (IDirect3DSurface9*)(uintptr_t)src->data[3]) | |
| 813 | + break; | |
| 814 | +#endif | |
| 815 | + } | |
| 816 | + if (i >= hwctx->nb_surfaces) { | |
| 817 | + av_log(dst_ctx, AV_LOG_ERROR, "Trying to map from a surface which " | |
| 818 | + "is not in the mapped frames context.\n"); | |
| 819 | + return AVERROR(EINVAL); | |
| 820 | + } | |
| 821 | + | |
| 822 | + err = ff_hwframe_map_create(dst->hw_frames_ctx, | |
| 823 | + dst, src, NULL, NULL); | |
| 824 | + if (err) | |
| 825 | + return err; | |
| 826 | + | |
| 827 | + dst->width = src->width; | |
| 828 | + dst->height = src->height; | |
| 829 | + dst->data[3] = (uint8_t*)&hwctx->surfaces[i]; | |
| 830 | + | |
| 831 | + return 0; | |
| 832 | +} | |
| 833 | + | |
| 726 | 834 | static int qsv_frames_get_constraints(AVHWDeviceContext *ctx, |
| 727 | 835 | const void *hwconfig, |
| 728 | 836 | AVHWFramesConstraints *constraints) |
| @@ -931,7 +1039,9 @@ const HWContextType ff_hwcontext_type_qsv = { · 202 unmodified lines | ||
| 931 | 1039 | .transfer_get_formats = qsv_transfer_get_formats, |
| 932 | 1040 | .transfer_data_to = qsv_transfer_data_to, |
| 933 | 1041 | .transfer_data_from = qsv_transfer_data_from, |
| 1042 | + .map_to = qsv_map_to, | |
| 934 | 1043 | .map_from = qsv_map_from, |
| 1044 | + .frames_derive_to = qsv_frames_derive_to, | |
| 935 | 1045 | |
| 936 | 1046 | .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, |
| 937 | 1047 | }; |