forked from FFmpeg/FFmpeg
libavutil/hwcontext_d3d11va: adding more texture information to the D3D11 hwcontext API
Microsoft VideoProcessor requires texture with D3DUSAGE_RENDERTARGET flag as output. There is no way to allocate array of textures with D3D11_BIND_RENDER_TARGET flag and .ArraySize > 2 by ID3D11Device_CreateTexture2D due to the Microsoft limitation. Adding AVD3D11FrameDescriptors array to store array of single textures instead of texture with multiple slices resolves this. Signed-off-by: Artem Galin <artem.galin@intel.com>
This commit is contained in:
parent
f1cd1dc6ce
commit
4f78711f9c
5 changed files with 58 additions and 19 deletions
|
@ -14,6 +14,9 @@ libavutil: 2021-04-27
|
||||||
|
|
||||||
API changes, most recent first:
|
API changes, most recent first:
|
||||||
|
|
||||||
|
2021-09-08 - xxxxxxxxxx - lavu 57.5.100 - hwcontext_d3d11va.h
|
||||||
|
Add AVD3D11VAFramesContext.texture_infos
|
||||||
|
|
||||||
2021-09-06 - xxxxxxxxxx - lsws 6.1.100 - swscale.h
|
2021-09-06 - xxxxxxxxxx - lsws 6.1.100 - swscale.h
|
||||||
Add AVFrame-based scaling API:
|
Add AVFrame-based scaling API:
|
||||||
- sws_scale_frame()
|
- sws_scale_frame()
|
||||||
|
|
|
@ -72,6 +72,7 @@ static av_cold void load_functions(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct D3D11VAFramesContext {
|
typedef struct D3D11VAFramesContext {
|
||||||
|
int nb_surfaces;
|
||||||
int nb_surfaces_used;
|
int nb_surfaces_used;
|
||||||
|
|
||||||
DXGI_FORMAT format;
|
DXGI_FORMAT format;
|
||||||
|
@ -112,6 +113,8 @@ static void d3d11va_frames_uninit(AVHWFramesContext *ctx)
|
||||||
if (s->staging_texture)
|
if (s->staging_texture)
|
||||||
ID3D11Texture2D_Release(s->staging_texture);
|
ID3D11Texture2D_Release(s->staging_texture);
|
||||||
s->staging_texture = NULL;
|
s->staging_texture = NULL;
|
||||||
|
|
||||||
|
av_freep(&frames_hwctx->texture_infos);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int d3d11va_frames_get_constraints(AVHWDeviceContext *ctx,
|
static int d3d11va_frames_get_constraints(AVHWDeviceContext *ctx,
|
||||||
|
@ -152,15 +155,21 @@ static void free_texture(void *opaque, uint8_t *data)
|
||||||
av_free(data);
|
av_free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static AVBufferRef *wrap_texture_buf(ID3D11Texture2D *tex, int index)
|
static AVBufferRef *wrap_texture_buf(AVHWFramesContext *ctx, ID3D11Texture2D *tex, int index)
|
||||||
{
|
{
|
||||||
AVBufferRef *buf;
|
AVBufferRef *buf;
|
||||||
AVD3D11FrameDescriptor *desc = av_mallocz(sizeof(*desc));
|
AVD3D11FrameDescriptor *desc = av_mallocz(sizeof(*desc));
|
||||||
|
D3D11VAFramesContext *s = ctx->internal->priv;
|
||||||
|
AVD3D11VAFramesContext *frames_hwctx = ctx->hwctx;
|
||||||
if (!desc) {
|
if (!desc) {
|
||||||
ID3D11Texture2D_Release(tex);
|
ID3D11Texture2D_Release(tex);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frames_hwctx->texture_infos[s->nb_surfaces_used].texture = tex;
|
||||||
|
frames_hwctx->texture_infos[s->nb_surfaces_used].index = index;
|
||||||
|
s->nb_surfaces_used++;
|
||||||
|
|
||||||
desc->texture = tex;
|
desc->texture = tex;
|
||||||
desc->index = index;
|
desc->index = index;
|
||||||
|
|
||||||
|
@ -199,7 +208,7 @@ static AVBufferRef *d3d11va_alloc_single(AVHWFramesContext *ctx)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wrap_texture_buf(tex, 0);
|
return wrap_texture_buf(ctx, tex, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static AVBufferRef *d3d11va_pool_alloc(void *opaque, size_t size)
|
static AVBufferRef *d3d11va_pool_alloc(void *opaque, size_t size)
|
||||||
|
@ -220,7 +229,7 @@ static AVBufferRef *d3d11va_pool_alloc(void *opaque, size_t size)
|
||||||
}
|
}
|
||||||
|
|
||||||
ID3D11Texture2D_AddRef(hwctx->texture);
|
ID3D11Texture2D_AddRef(hwctx->texture);
|
||||||
return wrap_texture_buf(hwctx->texture, s->nb_surfaces_used++);
|
return wrap_texture_buf(ctx, hwctx->texture, s->nb_surfaces_used);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int d3d11va_frames_init(AVHWFramesContext *ctx)
|
static int d3d11va_frames_init(AVHWFramesContext *ctx)
|
||||||
|
@ -267,7 +276,7 @@ static int d3d11va_frames_init(AVHWFramesContext *ctx)
|
||||||
av_log(ctx, AV_LOG_ERROR, "User-provided texture has mismatching parameters\n");
|
av_log(ctx, AV_LOG_ERROR, "User-provided texture has mismatching parameters\n");
|
||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
}
|
}
|
||||||
} else if (texDesc.ArraySize > 0) {
|
} else if (!(texDesc.BindFlags & D3D11_BIND_RENDER_TARGET) && texDesc.ArraySize > 0) {
|
||||||
hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &hwctx->texture);
|
hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &hwctx->texture);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
av_log(ctx, AV_LOG_ERROR, "Could not create the texture (%lx)\n", (long)hr);
|
av_log(ctx, AV_LOG_ERROR, "Could not create the texture (%lx)\n", (long)hr);
|
||||||
|
@ -275,6 +284,11 @@ static int d3d11va_frames_init(AVHWFramesContext *ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hwctx->texture_infos = av_mallocz_array(ctx->initial_pool_size, sizeof(*hwctx->texture_infos));
|
||||||
|
if (!hwctx->texture_infos)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
s->nb_surfaces = ctx->initial_pool_size;
|
||||||
|
|
||||||
ctx->internal->pool_internal = av_buffer_pool_init2(sizeof(AVD3D11FrameDescriptor),
|
ctx->internal->pool_internal = av_buffer_pool_init2(sizeof(AVD3D11FrameDescriptor),
|
||||||
ctx, d3d11va_pool_alloc, NULL);
|
ctx, d3d11va_pool_alloc, NULL);
|
||||||
if (!ctx->internal->pool_internal)
|
if (!ctx->internal->pool_internal)
|
||||||
|
|
|
@ -164,6 +164,15 @@ typedef struct AVD3D11VAFramesContext {
|
||||||
* This field is ignored/invalid if a user-allocated texture is provided.
|
* This field is ignored/invalid if a user-allocated texture is provided.
|
||||||
*/
|
*/
|
||||||
UINT MiscFlags;
|
UINT MiscFlags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In case if texture structure member above is not NULL contains the same texture
|
||||||
|
* pointer for all elements and different indexes into the array texture.
|
||||||
|
* In case if texture structure member above is NULL, all elements contains
|
||||||
|
* pointers to separate non-array textures and 0 indexes.
|
||||||
|
* This field is ignored/invalid if a user-allocated texture is provided.
|
||||||
|
*/
|
||||||
|
AVD3D11FrameDescriptor *texture_infos;
|
||||||
} AVD3D11VAFramesContext;
|
} AVD3D11VAFramesContext;
|
||||||
|
|
||||||
#endif /* AVUTIL_HWCONTEXT_D3D11VA_H */
|
#endif /* AVUTIL_HWCONTEXT_D3D11VA_H */
|
||||||
|
|
|
@ -120,6 +120,23 @@ static uint32_t qsv_fourcc_from_pix_fmt(enum AVPixelFormat pix_fmt)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_D3D11VA
|
||||||
|
static uint32_t qsv_get_d3d11va_bind_flags(int mem_type)
|
||||||
|
{
|
||||||
|
uint32_t bind_flags = 0;
|
||||||
|
|
||||||
|
if ((mem_type & MFX_MEMTYPE_VIDEO_MEMORY_ENCODER_TARGET) && (mem_type & MFX_MEMTYPE_INTERNAL_FRAME))
|
||||||
|
bind_flags = D3D11_BIND_DECODER | D3D11_BIND_VIDEO_ENCODER;
|
||||||
|
else
|
||||||
|
bind_flags = D3D11_BIND_DECODER;
|
||||||
|
|
||||||
|
if ((MFX_MEMTYPE_FROM_VPPOUT & mem_type) || (MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET & mem_type))
|
||||||
|
bind_flags = D3D11_BIND_RENDER_TARGET;
|
||||||
|
|
||||||
|
return bind_flags;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int qsv_device_init(AVHWDeviceContext *ctx)
|
static int qsv_device_init(AVHWDeviceContext *ctx)
|
||||||
{
|
{
|
||||||
AVQSVDeviceContext *hwctx = ctx->hwctx;
|
AVQSVDeviceContext *hwctx = ctx->hwctx;
|
||||||
|
@ -295,12 +312,11 @@ static int qsv_init_child_ctx(AVHWFramesContext *ctx)
|
||||||
#if CONFIG_D3D11VA
|
#if CONFIG_D3D11VA
|
||||||
if (child_device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
|
if (child_device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
|
||||||
AVD3D11VAFramesContext *child_frames_hwctx = child_frames_ctx->hwctx;
|
AVD3D11VAFramesContext *child_frames_hwctx = child_frames_ctx->hwctx;
|
||||||
if (hwctx->frame_type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)
|
if (hwctx->frame_type == 0)
|
||||||
child_frames_hwctx->BindFlags = D3D11_BIND_RENDER_TARGET;
|
hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
|
||||||
else
|
|
||||||
child_frames_hwctx->BindFlags = D3D11_BIND_DECODER;
|
|
||||||
if (hwctx->frame_type & MFX_MEMTYPE_SHARED_RESOURCE)
|
if (hwctx->frame_type & MFX_MEMTYPE_SHARED_RESOURCE)
|
||||||
child_frames_hwctx->MiscFlags = D3D11_RESOURCE_MISC_SHARED;
|
child_frames_hwctx->MiscFlags = D3D11_RESOURCE_MISC_SHARED;
|
||||||
|
child_frames_hwctx->BindFlags = qsv_get_d3d11va_bind_flags(hwctx->frame_type);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if CONFIG_DXVA2
|
#if CONFIG_DXVA2
|
||||||
|
@ -334,11 +350,11 @@ static int qsv_init_child_ctx(AVHWFramesContext *ctx)
|
||||||
if (child_device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
|
if (child_device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
|
||||||
AVD3D11VAFramesContext *child_frames_hwctx = child_frames_ctx->hwctx;
|
AVD3D11VAFramesContext *child_frames_hwctx = child_frames_ctx->hwctx;
|
||||||
for (i = 0; i < ctx->initial_pool_size; i++) {
|
for (i = 0; i < ctx->initial_pool_size; i++) {
|
||||||
s->handle_pairs_internal[i].first = (mfxMemId)child_frames_hwctx->texture;
|
s->handle_pairs_internal[i].first = (mfxMemId)child_frames_hwctx->texture_infos[i].texture;
|
||||||
if(child_frames_hwctx->BindFlags & D3D11_BIND_RENDER_TARGET) {
|
if(child_frames_hwctx->BindFlags & D3D11_BIND_RENDER_TARGET) {
|
||||||
s->handle_pairs_internal[i].second = (mfxMemId)MFX_INFINITE;
|
s->handle_pairs_internal[i].second = (mfxMemId)MFX_INFINITE;
|
||||||
} else {
|
} else {
|
||||||
s->handle_pairs_internal[i].second = (mfxMemId)i;
|
s->handle_pairs_internal[i].second = (mfxMemId)child_frames_hwctx->texture_infos[i].index;
|
||||||
}
|
}
|
||||||
s->surfaces_internal[i].Data.MemId = (mfxMemId)&s->handle_pairs_internal[i];
|
s->surfaces_internal[i].Data.MemId = (mfxMemId)&s->handle_pairs_internal[i];
|
||||||
}
|
}
|
||||||
|
@ -714,10 +730,7 @@ static int qsv_frames_derive_from(AVHWFramesContext *dst_ctx,
|
||||||
dst_hwctx->texture = (ID3D11Texture2D*)pair->first;
|
dst_hwctx->texture = (ID3D11Texture2D*)pair->first;
|
||||||
if (src_hwctx->frame_type & MFX_MEMTYPE_SHARED_RESOURCE)
|
if (src_hwctx->frame_type & MFX_MEMTYPE_SHARED_RESOURCE)
|
||||||
dst_hwctx->MiscFlags = D3D11_RESOURCE_MISC_SHARED;
|
dst_hwctx->MiscFlags = D3D11_RESOURCE_MISC_SHARED;
|
||||||
if (src_hwctx->frame_type == MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET)
|
dst_hwctx->BindFlags = qsv_get_d3d11va_bind_flags(src_hwctx->frame_type);
|
||||||
dst_hwctx->BindFlags = D3D11_BIND_DECODER;
|
|
||||||
else
|
|
||||||
dst_hwctx->BindFlags = D3D11_BIND_RENDER_TARGET;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1137,11 +1150,11 @@ static int qsv_frames_derive_to(AVHWFramesContext *dst_ctx,
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
for (i = 0; i < src_ctx->initial_pool_size; i++) {
|
for (i = 0; i < src_ctx->initial_pool_size; i++) {
|
||||||
qsv_init_surface(dst_ctx, &s->surfaces_internal[i]);
|
qsv_init_surface(dst_ctx, &s->surfaces_internal[i]);
|
||||||
s->handle_pairs_internal[i].first = (mfxMemId)src_hwctx->texture;
|
s->handle_pairs_internal[i].first = (mfxMemId)src_hwctx->texture_infos[i].texture;
|
||||||
if (src_hwctx->BindFlags & D3D11_BIND_RENDER_TARGET) {
|
if (src_hwctx->BindFlags & D3D11_BIND_RENDER_TARGET) {
|
||||||
s->handle_pairs_internal[i].second = (mfxMemId)MFX_INFINITE;
|
s->handle_pairs_internal[i].second = (mfxMemId)MFX_INFINITE;
|
||||||
} else {
|
} else {
|
||||||
s->handle_pairs_internal[i].second = (mfxMemId)i;
|
s->handle_pairs_internal[i].second = (mfxMemId)src_hwctx->texture_infos[i].index;
|
||||||
}
|
}
|
||||||
s->surfaces_internal[i].Data.MemId = (mfxMemId)&s->handle_pairs_internal[i];
|
s->surfaces_internal[i].Data.MemId = (mfxMemId)&s->handle_pairs_internal[i];
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,8 +79,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define LIBAVUTIL_VERSION_MAJOR 57
|
#define LIBAVUTIL_VERSION_MAJOR 57
|
||||||
#define LIBAVUTIL_VERSION_MINOR 4
|
#define LIBAVUTIL_VERSION_MINOR 5
|
||||||
#define LIBAVUTIL_VERSION_MICRO 101
|
#define LIBAVUTIL_VERSION_MICRO 100
|
||||||
|
|
||||||
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
|
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
|
||||||
LIBAVUTIL_VERSION_MINOR, \
|
LIBAVUTIL_VERSION_MINOR, \
|
||||||
|
|
Loading…
Add table
Reference in a new issue