|
|
|
@ -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 }, |
|
|
|
|
}; |
|
|
|
|