From 910973765417f06a4a9ccbd006e4df74c32ecb01 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 5 Oct 2016 13:39:44 +0200 Subject: hwcontext_dxva2: frame mapping support Signed-off-by: Maxym Dmytrychenko --- libavutil/hwcontext_dxva2.c | 89 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 68 insertions(+), 21 deletions(-) (limited to 'libavutil') diff --git a/libavutil/hwcontext_dxva2.c b/libavutil/hwcontext_dxva2.c index da89453..eb1bc46 100644 --- a/libavutil/hwcontext_dxva2.c +++ b/libavutil/hwcontext_dxva2.c @@ -241,21 +241,22 @@ static int dxva2_transfer_get_formats(AVHWFramesContext *ctx, return 0; } -static int dxva2_transfer_data(AVHWFramesContext *ctx, AVFrame *dst, - const AVFrame *src) +static void dxva2_unmap_frame(AVHWFramesContext *ctx, HWMapDescriptor *hwmap) +{ + IDirect3DSurface9 *surface = (IDirect3DSurface9*)hwmap->source->data[3]; + IDirect3DSurface9_UnlockRect(surface); +} + +static int dxva2_map_frame(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src, + int flags) { - IDirect3DSurface9 *surface; + IDirect3DSurface9 *surface = (IDirect3DSurface9*)src->data[3]; D3DSURFACE_DESC surfaceDesc; D3DLOCKED_RECT LockedRect; HRESULT hr; + int i, err, nb_planes; - uint8_t *surf_data[4] = { NULL }; - int surf_linesize[4] = { 0 }; - int i; - - int download = !!src->hw_frames_ctx; - - surface = (IDirect3DSurface9*)(download ? src->data[3] : dst->data[3]); + nb_planes = av_pix_fmt_count_planes(dst->format); hr = IDirect3DSurface9_GetDesc(surface, &surfaceDesc); if (FAILED(hr)) { @@ -264,32 +265,77 @@ static int dxva2_transfer_data(AVHWFramesContext *ctx, AVFrame *dst, } hr = IDirect3DSurface9_LockRect(surface, &LockedRect, NULL, - download ? D3DLOCK_READONLY : D3DLOCK_DISCARD); + flags & AV_HWFRAME_MAP_READ ? D3DLOCK_READONLY : D3DLOCK_DISCARD); if (FAILED(hr)) { av_log(ctx, AV_LOG_ERROR, "Unable to lock DXVA2 surface\n"); return AVERROR_UNKNOWN; } - for (i = 0; download ? dst->data[i] : src->data[i]; i++) - surf_linesize[i] = LockedRect.Pitch; + err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, + dxva2_unmap_frame, NULL); + if (err < 0) + goto fail; + + for (i = 0; i < nb_planes; i++) + dst->linesize[i] = LockedRect.Pitch; + + av_image_fill_pointers(dst->data, dst->format, surfaceDesc.Height, + (uint8_t*)LockedRect.pBits, dst->linesize); + + return 0; +fail: + IDirect3DSurface9_UnlockRect(surface); + return err; +} + +static int dxva2_transfer_data(AVHWFramesContext *ctx, AVFrame *dst, + const AVFrame *src) +{ + int download = !!src->hw_frames_ctx; + + AVFrame *map; + int ret, i; - av_image_fill_pointers(surf_data, ctx->sw_format, surfaceDesc.Height, - (uint8_t*)LockedRect.pBits, surf_linesize); + map = av_frame_alloc(); + if (!map) + return AVERROR(ENOMEM); + map->format = dst->format; + + ret = dxva2_map_frame(ctx, map, download ? src : dst, + download ? AV_HWFRAME_MAP_READ : AV_HWFRAME_MAP_WRITE); + if (ret < 0) + goto fail; if (download) { - ptrdiff_t src_linesize1[4], dst_linesize1[4]; + ptrdiff_t src_linesize[4], dst_linesize[4]; for (i = 0; i < 4; i++) { - dst_linesize1[i] = dst->linesize[i]; - src_linesize1[i] = surf_linesize[i]; + dst_linesize[i] = dst->linesize[i]; + src_linesize[i] = map->linesize[i]; } - av_image_copy_uc_from(dst->data, dst_linesize1, surf_data, src_linesize1, + av_image_copy_uc_from(dst->data, dst_linesize, map->data, src_linesize, ctx->sw_format, src->width, src->height); } else { - av_image_copy(surf_data, surf_linesize, src->data, src->linesize, + av_image_copy(map->data, map->linesize, src->data, src->linesize, ctx->sw_format, src->width, src->height); } - IDirect3DSurface9_UnlockRect(surface); +fail: + av_frame_free(&map); + return ret; +} + +static int dxva2_map_from(AVHWFramesContext *ctx, + AVFrame *dst, const AVFrame *src, int flags) +{ + int err; + + err = dxva2_map_frame(ctx, dst, src, flags); + if (err < 0) + return err; + + err = av_frame_copy_props(dst, src); + if (err < 0) + return err; return 0; } @@ -428,6 +474,7 @@ const HWContextType ff_hwcontext_type_dxva2 = { .transfer_get_formats = dxva2_transfer_get_formats, .transfer_data_to = dxva2_transfer_data, .transfer_data_from = dxva2_transfer_data, + .map_from = dxva2_map_from, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_DXVA2_VLD, AV_PIX_FMT_NONE }, }; -- cgit v1.1