Commit 6c18ebc3 authored by Steve Lhomme's avatar Steve Lhomme Committed by Jean-Baptiste Kempf

dxva: create the context copy when calling va_pool_Get()

via a pf_new_surface_context callback
Signed-off-by: Jean-Baptiste Kempf's avatarJean-Baptiste Kempf <jb@videolan.org>
parent 14ca39de
......@@ -237,6 +237,35 @@ done:
return pic_ctx;
}
static picture_context_t* NewSurfacePicContext(vlc_va_t *va, vlc_va_surface_t *va_surface, ID3D11VideoDecoderOutputView *surface)
{
ID3D11ShaderResourceView *resourceView[D3D11_MAX_SHADER_VIEW];
ID3D11Resource *p_resource;
ID3D11VideoDecoderOutputView_GetResource(surface, &p_resource);
D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc;
ID3D11VideoDecoderOutputView_GetDesc(surface, &viewDesc);
for (int i=0; i<D3D11_MAX_SHADER_VIEW; i++)
resourceView[i] = va->sys->resourceView[viewDesc.Texture2D.ArraySlice*D3D11_MAX_SHADER_VIEW + i];
struct va_pic_context *pic_ctx = CreatePicContext(va_surface,
surface,
p_resource,
va->sys->d3dctx,
viewDesc.Texture2D.ArraySlice,
resourceView);
ID3D11Resource_Release(p_resource);
if (unlikely(pic_ctx==NULL))
return NULL;
/* all the resources are acquired during surfaces init, and a second time in
* CreatePicContext(), undo one of them otherwise we need an extra release
* when the pool is emptied */
ReleasePictureSys(&pic_ctx->picsys);
va_surface->decoderSurface = surface;
return &pic_ctx->s;
}
static int Get(vlc_va_t *va, picture_t *pic, uint8_t **data)
{
#if D3D11_DIRECT_DECODE
......@@ -276,34 +305,9 @@ static int Get(vlc_va_t *va, picture_t *pic, uint8_t **data)
else
#endif
{
ID3D11ShaderResourceView *resourceView[D3D11_MAX_SHADER_VIEW];
vlc_va_surface_t *va_surface = va_pool_Get(va, &va->sys->dx_sys.va_pool);
if (unlikely(va_surface==NULL))
return VLC_EGENERIC;
ID3D11Resource *p_resource;
ID3D11VideoDecoderOutputView_GetResource(va_surface->decoderSurface, &p_resource);
D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc;
ID3D11VideoDecoderOutputView_GetDesc(va_surface->decoderSurface, &viewDesc);
for (int i=0; i<D3D11_MAX_SHADER_VIEW; i++)
resourceView[i] = va->sys->resourceView[viewDesc.Texture2D.ArraySlice*D3D11_MAX_SHADER_VIEW + i];
struct va_pic_context *pic_ctx = CreatePicContext( va_surface,
va_surface->decoderSurface,
p_resource,
va->sys->d3dctx,
viewDesc.Texture2D.ArraySlice,
resourceView );
ID3D11Resource_Release(p_resource);
if (unlikely(pic_ctx==NULL))
{
va_surface_Release(va_surface);
return VLC_ENOMEM;
}
pic->context = &pic_ctx->s;
int res = va_pool_Get(va, pic, &va->sys->dx_sys.va_pool);
if (unlikely(res != VLC_SUCCESS))
return res;
}
*data = (uint8_t*)((struct va_pic_context *)pic->context)->picsys.decoder;
return VLC_SUCCESS;
......@@ -372,6 +376,7 @@ static int Open(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
dx_sys->va_pool.pf_create_decoder_surfaces = DxCreateDecoderSurfaces;
dx_sys->va_pool.pf_destroy_surfaces = DxDestroySurfaces;
dx_sys->va_pool.pf_setup_avcodec_ctx = SetupAVCodecContext;
dx_sys->va_pool.pf_new_surface_context = NewSurfacePicContext;
dx_sys->pf_get_input_list = DxGetInputList;
dx_sys->pf_setup_output = DxSetupOutput;
dx_sys->psz_decoder_dll = TEXT("D3D11.DLL");
......
......@@ -193,15 +193,18 @@ static void d3d9_pic_context_destroy(struct picture_context_t *opaque)
}
}
static struct picture_context_t *CreatePicContext(vlc_va_surface_t *);
static struct va_pic_context *CreatePicContext(vlc_va_surface_t *, IDirect3DSurface9 *);
static struct picture_context_t *d3d9_pic_context_copy(struct picture_context_t *ctx)
{
struct va_pic_context *src_ctx = (struct va_pic_context*)ctx;
return CreatePicContext(src_ctx->va_surface);
struct va_pic_context *pic_ctx = CreatePicContext(src_ctx->va_surface, src_ctx->picsys.surface);
if (unlikely(pic_ctx==NULL))
return NULL;
return &pic_ctx->s;
}
static struct picture_context_t *CreatePicContext(vlc_va_surface_t *va_surface)
static struct va_pic_context *CreatePicContext(vlc_va_surface_t *va_surface, IDirect3DSurface9 *surface)
{
struct va_pic_context *pic_ctx = calloc(1, sizeof(*pic_ctx));
if (unlikely(pic_ctx==NULL))
......@@ -210,8 +213,18 @@ static struct picture_context_t *CreatePicContext(vlc_va_surface_t *va_surface)
va_surface_AddRef(pic_ctx->va_surface);
pic_ctx->s.destroy = d3d9_pic_context_destroy;
pic_ctx->s.copy = d3d9_pic_context_copy;
pic_ctx->picsys.surface = va_surface->decoderSurface;
pic_ctx->picsys.surface = surface;
AcquirePictureSys(&pic_ctx->picsys);
return pic_ctx;
}
static picture_context_t* NewSurfacePicContext(vlc_va_t *va, vlc_va_surface_t *va_surface, IDirect3DSurface9 *surface)
{
VLC_UNUSED(va);
struct va_pic_context *pic_ctx = CreatePicContext(va_surface, surface);
if (unlikely(pic_ctx==NULL))
return NULL;
va_surface->decoderSurface = surface;
return &pic_ctx->s;
}
......@@ -229,15 +242,10 @@ static int Get(vlc_va_t *va, picture_t *pic, uint8_t **data)
return VLC_EGENERIC;
}
vlc_va_surface_t *va_surface = va_pool_Get(va, &sys->dx_sys.va_pool);
if (unlikely(va_surface==NULL))
return VLC_EGENERIC;
pic->context = CreatePicContext(va_surface);
va_surface_Release(va_surface);
if (unlikely(pic->context==NULL))
return VLC_EGENERIC;
*data = (uint8_t*)va_surface->decoderSurface;
return VLC_SUCCESS;
int res = va_pool_Get(va, pic, &sys->dx_sys.va_pool);
if (likely(res==VLC_SUCCESS))
*data = (uint8_t*)((struct va_pic_context*)pic->context)->picsys.surface;
return res;
}
static void Close(vlc_va_t *va, void **ctx)
......@@ -309,6 +317,7 @@ static int Open(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
dx_sys->va_pool.pf_create_decoder_surfaces = DxCreateVideoDecoder;
dx_sys->va_pool.pf_destroy_surfaces = DxDestroyVideoDecoder;
dx_sys->va_pool.pf_setup_avcodec_ctx = SetupAVCodecContext;
dx_sys->va_pool.pf_new_surface_context = NewSurfacePicContext;
dx_sys->pf_get_input_list = DxGetInputList;
dx_sys->pf_setup_output = DxSetupOutput;
dx_sys->psz_decoder_dll = TEXT("DXVA2.DLL");
......
......@@ -32,6 +32,7 @@
#include <vlc_common.h>
#include <vlc_codecs.h>
#include <vlc_codec.h>
#include <vlc_picture.h>
#define D3D_DecoderSurface void
......@@ -110,7 +111,7 @@ done:
return err;
}
static vlc_va_surface_t *GetSurface(va_pool_t *va_pool)
static picture_context_t *GetSurface(vlc_va_t *va, va_pool_t *va_pool)
{
for (unsigned i = 0; i < va_pool->surface_count; i++) {
vlc_va_surface_t *surface = va_pool->surface[i];
......@@ -118,28 +119,33 @@ static vlc_va_surface_t *GetSurface(va_pool_t *va_pool)
if (atomic_compare_exchange_strong(&surface->refcount, &expected, 2))
{
/* TODO do a copy to allow releasing locally and keep forward alive atomic_fetch_sub(&surface->refs, 1);*/
surface->decoderSurface = va_pool->hw_surface[i];
return surface;
picture_context_t *field = va_pool->pf_new_surface_context(va, surface, va_pool->hw_surface[i]);
if (!field)
{
atomic_fetch_sub(&surface->refcount, 1);
continue;
}
return field;
}
}
return NULL;
}
vlc_va_surface_t *va_pool_Get(vlc_va_t *va, va_pool_t *va_pool)
int va_pool_Get(vlc_va_t *va, picture_t *pic, va_pool_t *va_pool)
{
unsigned tries = (CLOCK_FREQ + VOUT_OUTMEM_SLEEP) / VOUT_OUTMEM_SLEEP;
vlc_va_surface_t *field;
picture_context_t *field;
while ((field = GetSurface(va_pool)) == NULL)
while ((field = GetSurface(va, va_pool)) == NULL)
{
if (--tries == 0)
return NULL;
return VLC_ENOITEM;
/* Pool empty. Wait for some time as in src/input/decoder.c.
* XXX: Both this and the core should use a semaphore or a CV. */
msleep(VOUT_OUTMEM_SLEEP);
}
return field;
pic->context = field;
return VLC_SUCCESS;
}
void va_surface_AddRef(vlc_va_surface_t *surface)
......
......@@ -71,12 +71,17 @@ typedef struct
*/
void (*pf_setup_avcodec_ctx)(vlc_va_t *);
/**
* Create a new context for the surface being acquired
*/
picture_context_t* (*pf_new_surface_context)(vlc_va_t *, vlc_va_surface_t *, D3D_DecoderSurface *);
} va_pool_t;
int va_pool_Open(vlc_va_t *, va_pool_t *, AVCodecContext *);
void va_pool_Close(vlc_va_t *va, va_pool_t *);
int va_pool_Setup(vlc_va_t *, va_pool_t *, AVCodecContext *, unsigned count, int alignment);
vlc_va_surface_t *va_pool_Get(vlc_va_t *, va_pool_t *);
int va_pool_Get(vlc_va_t *, picture_t *, va_pool_t *);
void va_surface_AddRef(vlc_va_surface_t *surface);
void va_surface_Release(vlc_va_surface_t *surface);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment