[vlc-devel] [PATCH 04/17] dxva: split the directx related parts from the pool/va parts

Steve Lhomme robux4 at videolabs.io
Tue Jun 20 17:45:36 CEST 2017


---
 modules/codec/Makefile.am                   |   2 +
 modules/codec/avcodec/d3d11va.c             |  89 ++++++-------
 modules/codec/avcodec/directx_va.c          | 151 +--------------------
 modules/codec/avcodec/directx_va.h          |  49 +------
 modules/codec/avcodec/dxva2.c               |  76 +++++------
 modules/codec/avcodec/va_surface.c          | 198 ++++++++++++++++++++++++++++
 modules/codec/avcodec/va_surface.h          |  41 ++++++
 modules/codec/avcodec/va_surface_internal.h |  91 +++++++++++++
 8 files changed, 423 insertions(+), 274 deletions(-)
 create mode 100644 modules/codec/avcodec/va_surface.c
 create mode 100644 modules/codec/avcodec/va_surface.h
 create mode 100644 modules/codec/avcodec/va_surface_internal.h

diff --git a/modules/codec/Makefile.am b/modules/codec/Makefile.am
index 27e0270fa3..c3bb6d207a 100644
--- a/modules/codec/Makefile.am
+++ b/modules/codec/Makefile.am
@@ -404,6 +404,7 @@ endif
 
 libdxva2_plugin_la_SOURCES = \
 	codec/avcodec/dxva2.c codec/avcodec/directx_va.c codec/avcodec/directx_va.h \
+        codec/avcodec/va_surface.c codec/avcodec/va_surface.h codec/avcodec/va_surface_internal.h \
 	packetizer/h264_nal.c packetizer/h264_nal.h \
 	packetizer/hevc_nal.c packetizer/hevc_nal.h \
 	video_chroma/d3d9_fmt.h
@@ -414,6 +415,7 @@ endif
 
 libd3d11va_plugin_la_SOURCES = \
 	codec/avcodec/d3d11va.c codec/avcodec/directx_va.c codec/avcodec/directx_va.h \
+        codec/avcodec/va_surface.c codec/avcodec/va_surface.h codec/avcodec/va_surface_internal.h \
 	video_chroma/d3d11_fmt.h video_chroma/dxgi_fmt.c video_chroma/dxgi_fmt.h \
 	packetizer/h264_nal.c packetizer/h264_nal.h \
 	packetizer/hevc_nal.c packetizer/hevc_nal.h
diff --git a/modules/codec/avcodec/d3d11va.c b/modules/codec/avcodec/d3d11va.c
index 7b63890a98..58bb7059ad 100644
--- a/modules/codec/avcodec/d3d11va.c
+++ b/modules/codec/avcodec/d3d11va.c
@@ -164,8 +164,8 @@ void SetupAVCodecContext(vlc_va_t *va)
     sys->hw.video_context = sys->d3dvidctx;
     sys->hw.decoder = dx_sys->decoder;
     sys->hw.cfg = &sys->cfg;
-    sys->hw.surface_count = dx_sys->surface_count;
-    sys->hw.surface = dx_sys->hw_surface;
+    sys->hw.surface_count = dx_sys->va_pool.surface_count;
+    sys->hw.surface = dx_sys->va_pool.hw_surface;
     sys->hw.context_mutex = sys->context_mutex;
 
     if (IsEqualGUID(&dx_sys->input, &DXVA_Intel_H264_NoFGT_ClearVideo))
@@ -177,7 +177,7 @@ static int Extract(vlc_va_t *va, picture_t *output, uint8_t *data)
     VLC_UNUSED(va); VLC_UNUSED(data);
     struct va_pic_context *pic_ctx = (struct va_pic_context*)output->context;
     if (!va->sys->b_extern_pool)
-        directx_va_AddRef(pic_ctx->va_surface);
+        va_surface_AddRef(pic_ctx->va_surface);
     assert(data == (void*)pic_ctx->picsys.decoder);
     return VLC_SUCCESS;
 }
@@ -204,7 +204,7 @@ static void d3d11_pic_context_destroy(struct picture_context_t *opaque)
 {
     struct va_pic_context *pic_ctx = (struct va_pic_context*)opaque;
     if (pic_ctx->va_surface)
-        directx_va_Release(pic_ctx->va_surface);
+        va_surface_Release(pic_ctx->va_surface);
     ReleasePictureSys(&pic_ctx->picsys);
     free(pic_ctx);
 }
@@ -294,7 +294,7 @@ static int Get(vlc_va_t *va, picture_t *pic, uint8_t **data)
 #endif
     {
         ID3D11ShaderResourceView *resourceView[D3D11_MAX_SHADER_VIEW];
-        vlc_va_surface_t *va_surface = directx_va_Get(va, &va->sys->dx_sys);
+        vlc_va_surface_t *va_surface = va_pool_Get(va, &va->sys->dx_sys.va_pool);
         if (unlikely(va_surface==NULL))
             return VLC_EGENERIC;
 
@@ -317,7 +317,7 @@ static int Get(vlc_va_t *va, picture_t *pic, uint8_t **data)
         ID3D11Resource_Release(p_resource);
         if (unlikely(pic_ctx==NULL))
         {
-            directx_va_Release(va_surface);
+            va_surface_Release(va_surface);
             return VLC_ENOMEM;
         }
         pic->context = &pic_ctx->s;
@@ -359,7 +359,7 @@ static void ReleasePic(void *opaque, uint8_t *data)
     (void)data;
     picture_t *pic = opaque;
     struct va_pic_context *pic_ctx = (struct va_pic_context*)pic->context;
-    directx_va_Release(pic_ctx->va_surface);
+    va_surface_Release(pic_ctx->va_surface);
     picture_Release(pic);
 }
 
@@ -382,14 +382,14 @@ static int Open(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
 
     dx_sys = &sys->dx_sys;
 
-    dx_sys->pf_check_device            = CheckDevice;
-    dx_sys->pf_create_device           = D3dCreateDevice;
-    dx_sys->pf_destroy_device          = D3dDestroyDevice;
-    dx_sys->pf_create_video_service    = DxCreateVideoService;
-    dx_sys->pf_destroy_video_service   = DxDestroyVideoService;
-    dx_sys->pf_create_decoder_surfaces = DxCreateDecoderSurfaces;
-    dx_sys->pf_destroy_surfaces        = DxDestroySurfaces;
-    dx_sys->pf_setup_avcodec_ctx       = SetupAVCodecContext;
+    dx_sys->va_pool.pf_check_device            = CheckDevice;
+    dx_sys->va_pool.pf_create_device           = D3dCreateDevice;
+    dx_sys->va_pool.pf_destroy_device          = D3dDestroyDevice;
+    dx_sys->va_pool.pf_create_video_service    = DxCreateVideoService;
+    dx_sys->va_pool.pf_destroy_video_service   = DxDestroyVideoService;
+    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->pf_get_input_list          = DxGetInputList;
     dx_sys->pf_setup_output            = DxSetupOutput;
     dx_sys->psz_decoder_dll            = TEXT("D3D11.DLL");
@@ -768,7 +768,7 @@ static int DxCreateDecoderSurfaces(vlc_va_t *va, int codec_id, const video_forma
         isXboxHardware(dx_sys->d3ddev))
     {
         msg_Warn(va, "%dx%d resolution not supported by your hardware", dx_sys->surface_width, dx_sys->surface_height);
-        dx_sys->surface_count = 0;
+        dx_sys->va_pool.surface_count = 0;
         return VLC_EGENERIC;
     }
 #endif
@@ -798,26 +798,26 @@ static int DxCreateDecoderSurfaces(vlc_va_t *va, int codec_id, const video_forma
     if (sys->b_extern_pool)
     {
 #if D3D11_DIRECT_DECODE
-        dx_sys->surface_count = 0;
+        dx_sys->va_pool.surface_count = 0;
 #else
         size_t surface_idx;
-        for (surface_idx = 0; surface_idx < dx_sys->surface_count; surface_idx++) {
+        for (surface_idx = 0; surface_idx < dx_sys->va_pool.surface_count; surface_idx++) {
             picture_t *pic = decoder_NewPicture( (decoder_t*) va->obj.parent );
             sys->extern_pics[surface_idx] = pic;
-            dx_sys->hw_surface[surface_idx] = NULL;
+            dx_sys->va_pool.hw_surface[surface_idx] = NULL;
             if (pic==NULL)
             {
-                msg_Warn(va, "not enough decoder pictures %d out of %d", surface_idx, dx_sys->surface_count);
+                msg_Warn(va, "not enough decoder pictures %d out of %d", surface_idx, dx_sys->va_pool.surface_count);
                 sys->b_extern_pool = false;
                 break;
             }
 
             D3D11_TEXTURE2D_DESC texDesc;
             ID3D11Texture2D_GetDesc(pic->p_sys->texture[KNOWN_DXGI_INDEX], &texDesc);
-            if (texDesc.ArraySize < dx_sys->surface_count)
+            if (texDesc.ArraySize < dx_sys->va_pool.surface_count)
             {
                 msg_Warn(va, "not enough decoding slices in the texture (%d/%d)",
-                         texDesc.ArraySize, dx_sys->surface_count);
+                         texDesc.ArraySize, dx_sys->va_pool.surface_count);
                 sys->b_extern_pool = false;
                 break;
             }
@@ -847,17 +847,17 @@ static int DxCreateDecoderSurfaces(vlc_va_t *va, int codec_id, const video_forma
 
             AllocateShaderView(VLC_OBJECT(va), dx_sys->d3ddev, textureFmt, pic->p_sys->texture, pic->p_sys->slice_index, pic->p_sys->resourceView);
 
-            dx_sys->hw_surface[surface_idx] = pic->p_sys->decoder;
+            dx_sys->va_pool.hw_surface[surface_idx] = pic->p_sys->decoder;
         }
 
         if (!sys->b_extern_pool)
         {
             for (size_t i = 0; i < surface_idx; ++i)
             {
-                if (dx_sys->hw_surface[i])
+                if (dx_sys->va_pool.hw_surface[i])
                 {
-                    ID3D11VideoDecoderOutputView_Release(dx_sys->hw_surface[i]);
-                    dx_sys->hw_surface[i] = NULL;
+                    ID3D11VideoDecoderOutputView_Release(dx_sys->va_pool.hw_surface[i]);
+                    dx_sys->va_pool.hw_surface[i] = NULL;
                 }
                 if (sys->extern_pics[i])
                 {
@@ -876,13 +876,13 @@ static int DxCreateDecoderSurfaces(vlc_va_t *va, int codec_id, const video_forma
     {
         D3D11_TEXTURE2D_DESC texDesc;
         ZeroMemory(&texDesc, sizeof(texDesc));
-        texDesc.Width = dx_sys->surface_width;
-        texDesc.Height = dx_sys->surface_height;
+        texDesc.Width = dx_sys->va_pool.surface_width;
+        texDesc.Height = dx_sys->va_pool.surface_height;
         texDesc.MipLevels = 1;
         texDesc.Format = sys->render;
         texDesc.SampleDesc.Count = 1;
         texDesc.MiscFlags = 0;
-        texDesc.ArraySize = dx_sys->surface_count;
+        texDesc.ArraySize = dx_sys->va_pool.surface_count;
         texDesc.Usage = D3D11_USAGE_DEFAULT;
         texDesc.BindFlags = D3D11_BIND_DECODER;
         texDesc.CPUAccessFlags = 0;
@@ -893,35 +893,36 @@ static int DxCreateDecoderSurfaces(vlc_va_t *va, int codec_id, const video_forma
         ID3D11Texture2D *p_texture;
         hr = ID3D11Device_CreateTexture2D( dx_sys->d3ddev, &texDesc, NULL, &p_texture );
         if (FAILED(hr)) {
-            msg_Err(va, "CreateTexture2D %d failed. (hr=0x%0lx)", dx_sys->surface_count, hr);
-            dx_sys->surface_count = 0;
+            msg_Err(va, "CreateTexture2D %d failed. (hr=0x%0lx)", dx_sys->va_pool.surface_count, hr);
+            dx_sys->va_pool.surface_count = 0;
             return VLC_EGENERIC;
         }
 
-        int surface_count = dx_sys->surface_count;
-        for (dx_sys->surface_count = 0; dx_sys->surface_count < surface_count; dx_sys->surface_count++) {
-            sys->extern_pics[dx_sys->surface_count] = NULL;
-            viewDesc.Texture2D.ArraySlice = dx_sys->surface_count;
+        int surface_count = dx_sys->va_pool.surface_count;
+        for (dx_sys->va_pool.surface_count = 0; dx_sys->va_pool.surface_count < surface_count; dx_sys->va_pool.surface_count++) {
+            sys->extern_pics[dx_sys->va_pool.surface_count] = NULL;
+            viewDesc.Texture2D.ArraySlice = dx_sys->va_pool.surface_count;
 
             hr = ID3D11VideoDevice_CreateVideoDecoderOutputView( dx_sys->d3ddec,
                                                                  (ID3D11Resource*) p_texture,
                                                                  &viewDesc,
-                                                                 &dx_sys->hw_surface[dx_sys->surface_count] );
+                                                                 &dx_sys->va_pool.hw_surface[dx_sys->va_pool.surface_count] );
             if (FAILED(hr)) {
-                msg_Err(va, "CreateVideoDecoderOutputView %d failed. (hr=0x%0lx)", dx_sys->surface_count, hr);
+                msg_Err(va, "CreateVideoDecoderOutputView %d failed. (hr=0x%0lx)", dx_sys->va_pool.surface_count, hr);
                 ID3D11Texture2D_Release(p_texture);
                 return VLC_EGENERIC;
             }
 
             if (texDesc.BindFlags & D3D11_BIND_SHADER_RESOURCE)
             {
-                ID3D11Texture2D *textures[D3D11_MAX_SHADER_VIEW] = {p_texture, p_texture, p_texture};
-                AllocateShaderView(VLC_OBJECT(va), dx_sys->d3ddev, textureFmt, textures, dx_sys->surface_count, &sys->resourceView[dx_sys->surface_count * D3D11_MAX_SHADER_VIEW]);
+                ID3D11Texture2D *textures[D3D11_MAX_SHADER_VIEW] = {p_texture, p_texture};
+                AllocateShaderView(VLC_OBJECT(va), dx_sys->d3ddev, textureFmt, textures, dx_sys->va_pool.surface_count,
+                                   &sys->resourceView[dx_sys->va_pool.surface_count * D3D11_MAX_SHADER_VIEW]);
             }
         }
     }
     msg_Dbg(va, "ID3D11VideoDecoderOutputView succeed with %d surfaces (%dx%d)",
-            dx_sys->surface_count, dx_sys->surface_width, dx_sys->surface_height);
+            dx_sys->va_pool.surface_count, dx_sys->va_pool.surface_width, dx_sys->va_pool.surface_height);
 
     D3D11_VIDEO_DECODER_DESC decoderDesc;
     ZeroMemory(&decoderDesc, sizeof(decoderDesc));
@@ -996,15 +997,15 @@ static int DxCreateDecoderSurfaces(vlc_va_t *va, int codec_id, const video_forma
 static void DxDestroySurfaces(vlc_va_t *va)
 {
     directx_sys_t *dx_sys = &va->sys->dx_sys;
-    if (dx_sys->surface_count && !va->sys->b_extern_pool) {
+    if (dx_sys->va_pool.surface_count && !va->sys->b_extern_pool) {
         ID3D11Resource *p_texture;
-        ID3D11VideoDecoderOutputView_GetResource( dx_sys->hw_surface[0], &p_texture );
+        ID3D11VideoDecoderOutputView_GetResource( dx_sys->va_pool.hw_surface[0], &p_texture );
         ID3D11Resource_Release(p_texture);
         ID3D11Resource_Release(p_texture);
     }
-    for (int i = 0; i < dx_sys->surface_count; i++)
+    for (int i = 0; i < dx_sys->va_pool.surface_count; i++)
     {
-        ID3D11VideoDecoderOutputView_Release( dx_sys->hw_surface[i] );
+        ID3D11VideoDecoderOutputView_Release( dx_sys->va_pool.hw_surface[i] );
         for (int j = 0; j < D3D11_MAX_SHADER_VIEW; j++)
         {
             if (va->sys->resourceView[i*D3D11_MAX_SHADER_VIEW + j])
diff --git a/modules/codec/avcodec/directx_va.c b/modules/codec/avcodec/directx_va.c
index ac4d11a0f3..2e1a262d32 100644
--- a/modules/codec/avcodec/directx_va.c
+++ b/modules/codec/avcodec/directx_va.c
@@ -262,7 +262,6 @@ static const directx_va_mode_t DXVA_MODES[] = {
 };
 
 static int FindVideoServiceConversion(vlc_va_t *, directx_sys_t *, const es_format_t *fmt);
-static void DestroyVideoDecoder(vlc_va_t *, directx_sys_t *);
 
 char *directx_va_GetDecoderName(const GUID *guid)
 {
@@ -283,21 +282,7 @@ int directx_va_Setup(vlc_va_t *va, directx_sys_t *dx_sys, AVCodecContext *avctx)
     int surface_alignment = 16;
     int surface_count = 2;
 
-    if (dx_sys->width == avctx->coded_width && dx_sys->height == avctx->coded_height
-     && dx_sys->decoder != NULL)
-        goto ok;
-
-    /* */
-    DestroyVideoDecoder(va, dx_sys);
-
-    avctx->hwaccel_context = NULL;
-    if (avctx->coded_width <= 0 || avctx->coded_height <= 0)
-        return VLC_EGENERIC;
-
-    /* */
-    msg_Dbg(va, "directx_va_Setup id %d %dx%d", dx_sys->codec_id, avctx->coded_width, avctx->coded_height);
-
-    switch ( dx_sys->codec_id )
+    switch ( dx_sys->va_pool.codec_id )
     {
     case AV_CODEC_ID_MPEG2VIDEO:
         /* decoding MPEG-2 requires additional alignment on some Intel GPUs,
@@ -321,120 +306,13 @@ int directx_va_Setup(vlc_va_t *va, directx_sys_t *dx_sys, AVCodecContext *avctx)
     if ( avctx->active_thread_type & FF_THREAD_FRAME )
         surface_count += avctx->thread_count;
 
-    if (surface_count > MAX_SURFACE_COUNT)
-        return VLC_EGENERIC;
-
-    dx_sys->surface_count = surface_count;
-
-#define ALIGN(x, y) (((x) + ((y) - 1)) & ~((y) - 1))
-    dx_sys->width  = avctx->coded_width;
-    dx_sys->height = avctx->coded_height;
-    dx_sys->surface_width  = ALIGN(dx_sys->width, surface_alignment);
-    dx_sys->surface_height = ALIGN(dx_sys->height, surface_alignment);
-
-    /* FIXME transmit a video_format_t by VaSetup directly */
-    video_format_t fmt;
-    memset(&fmt, 0, sizeof(fmt));
-    fmt.i_width = dx_sys->width;
-    fmt.i_height = dx_sys->height;
-    fmt.i_frame_rate = avctx->framerate.num;
-    fmt.i_frame_rate_base = avctx->framerate.den;
-
-    if (dx_sys->pf_create_decoder_surfaces(va, dx_sys->codec_id, &fmt))
-        return VLC_EGENERIC;
-
-    if (avctx->coded_width != dx_sys->surface_width ||
-        avctx->coded_height != dx_sys->surface_height)
-        msg_Warn( va, "surface dimensions (%dx%d) differ from avcodec dimensions (%dx%d)",
-                  dx_sys->surface_width, dx_sys->surface_height,
-                  avctx->coded_width, avctx->coded_height);
-
-    for (int i = 0; i < dx_sys->surface_count; i++) {
-        vlc_va_surface_t *surface = malloc(sizeof(*surface));
-        if (unlikely(surface==NULL))
-        {
-            dx_sys->surface_count = i;
-            return VLC_ENOMEM;
-        }
-        atomic_init(&surface->refcount, 1);
-        dx_sys->surface[i] = surface;
-    }
-
-    dx_sys->pf_setup_avcodec_ctx(va);
-
-ok:
-    return VLC_SUCCESS;
-}
-
-void DestroyVideoDecoder(vlc_va_t *va, directx_sys_t *dx_sys)
-{
-    dx_sys->pf_destroy_surfaces(va);
-
-    for (int i = 0; i < dx_sys->surface_count; i++)
-    {
-        IUnknown_Release( dx_sys->hw_surface[i] );
-        directx_va_Release(dx_sys->surface[i]);
-    }
-
-    dx_sys->surface_count = 0;
-}
-
-static vlc_va_surface_t *GetSurface(directx_sys_t *dx_sys)
-{
-    for (int i = 0; i < dx_sys->surface_count; i++) {
-        vlc_va_surface_t *surface = dx_sys->surface[i];
-        uintptr_t expected = 1;
-
-        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 = dx_sys->hw_surface[i];
-            return surface;
-        }
-    }
-    return NULL;
-}
-
-vlc_va_surface_t *directx_va_Get(vlc_va_t *va, directx_sys_t *dx_sys)
-{
-    /* Check the device */
-    if (dx_sys->pf_check_device(va)!=VLC_SUCCESS)
-        return NULL;
-
-    unsigned tries = (CLOCK_FREQ + VOUT_OUTMEM_SLEEP) / VOUT_OUTMEM_SLEEP;
-    vlc_va_surface_t *field;
-
-    while ((field = GetSurface(dx_sys)) == NULL)
-    {
-        if (--tries == 0)
-            return NULL;
-        /* 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;
-}
-
-void directx_va_AddRef(vlc_va_surface_t *surface)
-{
-    atomic_fetch_add(&surface->refcount, 1);
-}
-
-void directx_va_Release(vlc_va_surface_t *surface)
-{
-    if (atomic_fetch_sub(&surface->refcount, 1) != 1)
-        return;
-    free(surface);
+    return va_pool_Setup(va, &dx_sys->va_pool, avctx,
+                         surface_count, surface_alignment);
 }
 
 void directx_va_Close(vlc_va_t *va, directx_sys_t *dx_sys)
 {
-    DestroyVideoDecoder(va, dx_sys);
-    dx_sys->pf_destroy_video_service(va);
-    if (dx_sys->pf_destroy_device_manager)
-        dx_sys->pf_destroy_device_manager(va);
-    dx_sys->pf_destroy_device(va);
-
+    va_pool_Close(va, &dx_sys->va_pool);
     if (dx_sys->hdecoder_dll)
         FreeLibrary(dx_sys->hdecoder_dll);
 }
@@ -442,8 +320,6 @@ void directx_va_Close(vlc_va_t *va, directx_sys_t *dx_sys)
 int directx_va_Open(vlc_va_t *va, directx_sys_t *dx_sys,
                     AVCodecContext *ctx, const es_format_t *fmt, bool b_dll)
 {
-    dx_sys->codec_id = ctx->codec_id;
-
     if (b_dll) {
         /* Load dll*/
         dx_sys->hdecoder_dll = LoadLibrary(dx_sys->psz_decoder_dll);
@@ -454,23 +330,8 @@ int directx_va_Open(vlc_va_t *va, directx_sys_t *dx_sys,
         msg_Dbg(va, "DLLs loaded");
     }
 
-    /* */
-    if (dx_sys->pf_create_device(va)) {
-        msg_Err(va, "Failed to create DirectX device");
-        goto error;
-    }
-    msg_Dbg(va, "CreateDevice succeed");
-
-    if (dx_sys->pf_create_device_manager &&
-        dx_sys->pf_create_device_manager(va) != VLC_SUCCESS) {
-        msg_Err(va, "CreateDeviceManager failed");
+    if (va_pool_Open(va, &dx_sys->va_pool, ctx, fmt) != VLC_SUCCESS)
         goto error;
-    }
-
-    if (dx_sys->pf_create_video_service(va)) {
-        msg_Err(va, "CreateVideoService failed");
-        goto error;
-    }
 
     /* */
     if (FindVideoServiceConversion(va, dx_sys, fmt)) {
@@ -543,7 +404,7 @@ static int FindVideoServiceConversion(vlc_va_t *va, directx_sys_t *dx_sys, const
     /* Try all supported mode by our priority */
     const directx_va_mode_t *mode = DXVA_MODES;
     for (; mode->name; ++mode) {
-        if (!mode->codec || mode->codec != dx_sys->codec_id)
+        if (!mode->codec || mode->codec != dx_sys->va_pool.codec_id)
             continue;
 
         /* */
diff --git a/modules/codec/avcodec/directx_va.h b/modules/codec/avcodec/directx_va.h
index 65e53c78f7..43a40a1af8 100644
--- a/modules/codec/avcodec/directx_va.h
+++ b/modules/codec/avcodec/directx_va.h
@@ -42,11 +42,7 @@
 #include <unknwn.h>
 #include <stdatomic.h>
 
-/* */
-struct vlc_va_surface_t {
-    atomic_uintptr_t     refcount;
-    D3D_DecoderSurface *decoderSurface;
-};
+#include "va_surface_internal.h"
 
 typedef struct input_list_t {
     void (*pf_release)(struct input_list_t *);
@@ -57,9 +53,7 @@ typedef struct input_list_t {
 #define MAX_SURFACE_COUNT (64)
 typedef struct
 {
-    int          codec_id;
-    int          width;
-    int          height;
+    va_pool_t             va_pool;
 
     /* DLL */
     HINSTANCE             hdecoder_dll;
@@ -75,28 +69,6 @@ typedef struct
     /* Video decoder */
     D3D_DecoderType        *decoder;
 
-    /* */
-    int          surface_count;
-    int          surface_width;
-    int          surface_height;
-
-    vlc_va_surface_t     *surface[MAX_SURFACE_COUNT];
-    D3D_DecoderSurface  *hw_surface[MAX_SURFACE_COUNT];
-
-    /**
-     * Check that the decoder device is still available
-     */
-    int (*pf_check_device)(vlc_va_t *);
-
-    int (*pf_create_device)(vlc_va_t *);
-    void (*pf_destroy_device)(vlc_va_t *);
-
-    int (*pf_create_device_manager)(vlc_va_t *);
-    void (*pf_destroy_device_manager)(vlc_va_t *);
-
-    int (*pf_create_video_service)(vlc_va_t *);
-    void (*pf_destroy_video_service)(vlc_va_t *);
-
     /**
      * Read the list of possible input GUIDs
      */
@@ -107,28 +79,11 @@ typedef struct
      */
     int (*pf_setup_output)(vlc_va_t *, const GUID *input, const video_format_t *fmt);
 
-    /**
-     * Create the DirectX surfaces in hw_surface and the decoder in decoder
-     */
-    int (*pf_create_decoder_surfaces)(vlc_va_t *, int codec_id,
-                                      const video_format_t *fmt);
-    /**
-     * Destroy resources allocated with the surfaces and the associated decoder
-     */
-    void (*pf_destroy_surfaces)(vlc_va_t *);
-    /**
-     * Set the avcodec hw context after the decoder is created
-     */
-    void (*pf_setup_avcodec_ctx)(vlc_va_t *);
-
 } directx_sys_t;
 
 int directx_va_Open(vlc_va_t *, directx_sys_t *, AVCodecContext *ctx, const es_format_t *fmt, bool b_dll);
 void directx_va_Close(vlc_va_t *, directx_sys_t *);
 int directx_va_Setup(vlc_va_t *, directx_sys_t *, AVCodecContext *avctx);
-vlc_va_surface_t *directx_va_Get(vlc_va_t *, directx_sys_t *);
-void directx_va_AddRef(vlc_va_surface_t *surface);
-void directx_va_Release(vlc_va_surface_t *surface);
 char *directx_va_GetDecoderName(const GUID *guid);
 
 #endif /* AVCODEC_DIRECTX_VA_H */
diff --git a/modules/codec/avcodec/dxva2.c b/modules/codec/avcodec/dxva2.c
index 85acfb1747..d13bae1915 100644
--- a/modules/codec/avcodec/dxva2.c
+++ b/modules/codec/avcodec/dxva2.c
@@ -167,8 +167,8 @@ void SetupAVCodecContext(vlc_va_t *va)
 
     sys->hw.decoder = dx_sys->decoder;
     sys->hw.cfg = &sys->cfg;
-    sys->hw.surface_count = dx_sys->surface_count;
-    sys->hw.surface = dx_sys->hw_surface;
+    sys->hw.surface_count = dx_sys->va_pool.surface_count;
+    sys->hw.surface = dx_sys->va_pool.hw_surface;
 
     if (IsEqualGUID(&dx_sys->input, &DXVA_Intel_H264_NoFGT_ClearVideo))
         sys->hw.workaround |= FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO;
@@ -178,7 +178,7 @@ static int Extract(vlc_va_t *va, picture_t *picture, uint8_t *data)
 {
     VLC_UNUSED(va); VLC_UNUSED(data);
     struct va_pic_context *pic_ctx = (struct va_pic_context*)picture->context;
-    directx_va_AddRef(pic_ctx->va_surface);
+    va_surface_AddRef(pic_ctx->va_surface);
     return VLC_SUCCESS;
 }
 
@@ -204,7 +204,7 @@ static void d3d9_pic_context_destroy(struct picture_context_t *opaque)
     if (pic_ctx->va_surface)
     {
         ReleasePictureSys(&pic_ctx->picsys);
-        directx_va_Release(pic_ctx->va_surface);
+        va_surface_Release(pic_ctx->va_surface);
         free(pic_ctx);
     }
 }
@@ -223,7 +223,7 @@ static struct picture_context_t *CreatePicContext(vlc_va_surface_t *va_surface)
     if (unlikely(pic_ctx==NULL))
         return NULL;
     pic_ctx->va_surface = va_surface;
-    directx_va_AddRef(pic_ctx->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;
@@ -233,11 +233,11 @@ static struct picture_context_t *CreatePicContext(vlc_va_surface_t *va_surface)
 
 static int Get(vlc_va_t *va, picture_t *pic, uint8_t **data)
 {
-    vlc_va_surface_t *va_surface = directx_va_Get(va, &va->sys->dx_sys);
+    vlc_va_surface_t *va_surface = va_pool_Get(va, &va->sys->dx_sys.va_pool);
     if (unlikely(va_surface==NULL))
         return VLC_EGENERIC;
     pic->context = CreatePicContext(va_surface);
-    directx_va_Release(va_surface);
+    va_surface_Release(va_surface);
     if (unlikely(pic->context==NULL))
         return VLC_EGENERIC;
     *data = (uint8_t*)va_surface->decoderSurface;
@@ -278,7 +278,7 @@ static void ReleasePic(void *opaque, uint8_t *data)
     (void)data;
     picture_t *pic = opaque;
     struct va_pic_context *pic_ctx = (struct va_pic_context*)pic->context;
-    directx_va_Release(pic_ctx->va_surface);
+    va_surface_Release(pic_ctx->va_surface);
     picture_Release(pic);
 }
 
@@ -304,16 +304,16 @@ static int Open(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
 
     dx_sys = &sys->dx_sys;
 
-    dx_sys->pf_check_device            = CheckDevice;
-    dx_sys->pf_create_device           = D3dCreateDevice;
-    dx_sys->pf_destroy_device          = D3dDestroyDevice;
-    dx_sys->pf_create_device_manager   = D3dCreateDeviceManager;
-    dx_sys->pf_destroy_device_manager  = D3dDestroyDeviceManager;
-    dx_sys->pf_create_video_service    = DxCreateVideoService;
-    dx_sys->pf_destroy_video_service   = DxDestroyVideoService;
-    dx_sys->pf_create_decoder_surfaces = DxCreateVideoDecoder;
-    dx_sys->pf_destroy_surfaces        = DxDestroyVideoDecoder;
-    dx_sys->pf_setup_avcodec_ctx       = SetupAVCodecContext;
+    dx_sys->va_pool.pf_check_device            = CheckDevice;
+    dx_sys->va_pool.pf_create_device           = D3dCreateDevice;
+    dx_sys->va_pool.pf_destroy_device          = D3dDestroyDevice;
+    dx_sys->va_pool.pf_create_device_manager   = D3dCreateDeviceManager;
+    dx_sys->va_pool.pf_destroy_device_manager  = D3dDestroyDeviceManager;
+    dx_sys->va_pool.pf_create_video_service    = DxCreateVideoService;
+    dx_sys->va_pool.pf_destroy_video_service   = DxDestroyVideoService;
+    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->pf_get_input_list          = DxGetInputList;
     dx_sys->pf_setup_output            = DxSetupOutput;
     dx_sys->psz_decoder_dll            = TEXT("DXVA2.DLL");
@@ -653,27 +653,27 @@ static int DxCreateVideoDecoder(vlc_va_t *va, int codec_id, const video_format_t
     HRESULT hr;
 
     hr = IDirectXVideoDecoderService_CreateSurface(sys->d3ddec,
-                                                         sys->surface_width,
-                                                         sys->surface_height,
-                                                         sys->surface_count - 1,
+                                                         sys->va_pool.surface_width,
+                                                         sys->va_pool.surface_height,
+                                                         sys->va_pool.surface_count - 1,
                                                          p_sys->render,
                                                          D3DPOOL_DEFAULT,
                                                          0,
                                                          DXVA2_VideoDecoderRenderTarget,
-                                                         sys->hw_surface,
+                                                         sys->va_pool.hw_surface,
                                                          NULL);
     if (FAILED(hr)) {
-        msg_Err(va, "IDirectXVideoAccelerationService_CreateSurface %d failed (hr=0x%0lx)", sys->surface_count - 1, hr);
-        sys->surface_count = 0;
+        msg_Err(va, "IDirectXVideoAccelerationService_CreateSurface %d failed (hr=0x%0lx)", sys->va_pool.surface_count - 1, hr);
+        sys->va_pool.surface_count = 0;
         return VLC_EGENERIC;
     }
     msg_Dbg(va, "IDirectXVideoAccelerationService_CreateSurface succeed with %d surfaces (%dx%d)",
-            sys->surface_count, sys->surface_width, sys->surface_height);
+            sys->va_pool.surface_count, sys->va_pool.surface_width, sys->va_pool.surface_height);
 
     IDirect3DSurface9 *tstCrash;
     hr = IDirectXVideoDecoderService_CreateSurface(sys->d3ddec,
-                                                         sys->surface_width,
-                                                         sys->surface_height,
+                                                         sys->va_pool.surface_width,
+                                                         sys->va_pool.surface_height,
                                                          0,
                                                          p_sys->render,
                                                          D3DPOOL_DEFAULT,
@@ -683,9 +683,9 @@ static int DxCreateVideoDecoder(vlc_va_t *va, int codec_id, const video_format_t
                                                          NULL);
     if (FAILED(hr)) {
         msg_Err(va, "extra buffer impossible, avoid a crash (hr=0x%0lx)", hr);
-        for (int i = 0; i < sys->surface_count; i++)
-            IDirect3DSurface9_Release( sys->hw_surface[i] );
-        sys->surface_count = 0;
+        for (int i = 0; i < sys->va_pool.surface_count; i++)
+            IDirect3DSurface9_Release( sys->va_pool.hw_surface[i] );
+        sys->va_pool.surface_count = 0;
         return VLC_EGENERIC;
     }
     IDirect3DSurface9_Release(tstCrash);
@@ -727,9 +727,9 @@ static int DxCreateVideoDecoder(vlc_va_t *va, int codec_id, const video_format_t
                                                                     &cfg_count,
                                                                     &cfg_list))) {
         msg_Err(va, "IDirectXVideoDecoderService_GetDecoderConfigurations failed");
-        for (int i = 0; i < sys->surface_count; i++)
-            IDirect3DSurface9_Release( sys->hw_surface[i] );
-        sys->surface_count = 0;
+        for (int i = 0; i < sys->va_pool.surface_count; i++)
+            IDirect3DSurface9_Release( sys->va_pool.hw_surface[i] );
+        sys->va_pool.surface_count = 0;
         return VLC_EGENERIC;
     }
     msg_Dbg(va, "we got %d decoder configurations", cfg_count);
@@ -771,13 +771,13 @@ static int DxCreateVideoDecoder(vlc_va_t *va, int codec_id, const video_format_t
                                                               &sys->input,
                                                               &dsc,
                                                               &p_sys->cfg,
-                                                              sys->hw_surface,
-                                                              sys->surface_count,
+                                                              sys->va_pool.hw_surface,
+                                                              sys->va_pool.surface_count,
                                                               &decoder))) {
         msg_Err(va, "IDirectXVideoDecoderService_CreateVideoDecoder failed");
-        for (int i = 0; i < sys->surface_count; i++)
-            IDirect3DSurface9_Release( sys->hw_surface[i] );
-        sys->surface_count = 0;
+        for (int i = 0; i < sys->va_pool.surface_count; i++)
+            IDirect3DSurface9_Release( sys->va_pool.hw_surface[i] );
+        sys->va_pool.surface_count = 0;
         return VLC_EGENERIC;
     }
     sys->decoder = decoder;
diff --git a/modules/codec/avcodec/va_surface.c b/modules/codec/avcodec/va_surface.c
new file mode 100644
index 0000000000..c8c015676d
--- /dev/null
+++ b/modules/codec/avcodec/va_surface.c
@@ -0,0 +1,198 @@
+/*****************************************************************************
+ * va_surface.c: libavcodec Generic Video Acceleration helpers
+ *****************************************************************************
+ * Copyright (C) 2009 Geoffroy Couprie
+ * Copyright (C) 2009 Laurent Aimar
+ * Copyright (C) 2015 Steve Lhomme
+ * $Id$
+ *
+ * Authors: Geoffroy Couprie <geal at videolan.org>
+ *          Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
+ *          Steve Lhomme <robux4 at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+
+#include <vlc_common.h>
+#include <vlc_codecs.h>
+#include <vlc_codec.h>
+
+
+#define D3D_DecoderType     void
+#define D3D_DecoderSurface  void
+typedef struct vlc_va_surface_t vlc_va_surface_t;
+#include "va_surface_internal.h"
+
+#include "avcodec.h"
+
+static void DestroyVideoDecoder(vlc_va_t *va, va_pool_t *va_pool)
+{
+    va_pool->pf_destroy_surfaces(va);
+    va_pool->surface_count = 0;
+}
+
+/* */
+int va_pool_Setup(vlc_va_t *va, va_pool_t *va_pool, AVCodecContext *avctx, int count, int alignment)
+{
+    if (va_pool->width == avctx->coded_width && va_pool->height == avctx->coded_height
+     && va_pool->decoder != NULL)
+        goto ok;
+
+    /* */
+    DestroyVideoDecoder(va, va_pool);
+
+    avctx->hwaccel_context = NULL;
+    if (avctx->coded_width <= 0 || avctx->coded_height <= 0)
+        return VLC_EGENERIC;
+
+    /* */
+    msg_Dbg(va, "va_pool_Setup id %d %dx%d", va_pool->codec_id, avctx->coded_width, avctx->coded_height);
+
+    if (count > MAX_SURFACE_COUNT)
+        return VLC_EGENERIC;
+
+    va_pool->surface_count = count;
+
+#define ALIGN(x, y) (((x) + ((y) - 1)) & ~((y) - 1))
+    va_pool->width  = avctx->coded_width;
+    va_pool->height = avctx->coded_height;
+    va_pool->surface_width  = ALIGN(va_pool->width, alignment);
+    va_pool->surface_height = ALIGN(va_pool->height, alignment);
+
+    /* FIXME transmit a video_format_t by VaSetup directly */
+    video_format_t fmt;
+    memset(&fmt, 0, sizeof(fmt));
+    fmt.i_width = va_pool->width;
+    fmt.i_height = va_pool->height;
+    fmt.i_frame_rate = avctx->framerate.num;
+    fmt.i_frame_rate_base = avctx->framerate.den;
+
+    if (va_pool->pf_create_decoder_surfaces(va, va_pool->codec_id, &fmt))
+        return VLC_EGENERIC;
+
+    if (avctx->coded_width != va_pool->surface_width ||
+        avctx->coded_height != va_pool->surface_height)
+        msg_Warn( va, "surface dimensions (%dx%d) differ from avcodec dimensions (%dx%d)",
+                  va_pool->surface_width, va_pool->surface_height,
+                  avctx->coded_width, avctx->coded_height);
+
+    for (int i = 0; i < va_pool->surface_count; i++) {
+        vlc_va_surface_t *surface = malloc(sizeof(*surface));
+        if (unlikely(surface==NULL))
+        {
+            va_pool->surface_count = i;
+            return VLC_ENOMEM;
+        }
+        atomic_init(&surface->refcount, 1);
+        va_pool->surface[i] = surface;
+    }
+
+    va_pool->pf_setup_avcodec_ctx(va);
+
+ok:
+    return VLC_SUCCESS;
+}
+
+static vlc_va_surface_t *GetSurface(va_pool_t *va_pool)
+{
+    for (int i = 0; i < va_pool->surface_count; i++) {
+        vlc_va_surface_t *surface = va_pool->surface[i];
+        uintptr_t expected = 1;
+
+        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;
+        }
+    }
+    return NULL;
+}
+
+vlc_va_surface_t *va_pool_Get(vlc_va_t *va, va_pool_t *va_pool)
+{
+    /* Check the device */
+    if (va_pool->pf_check_device(va)!=VLC_SUCCESS)
+        return NULL;
+
+    unsigned tries = (CLOCK_FREQ + VOUT_OUTMEM_SLEEP) / VOUT_OUTMEM_SLEEP;
+    vlc_va_surface_t *field;
+
+    while ((field = GetSurface(va_pool)) == NULL)
+    {
+        if (--tries == 0)
+            return NULL;
+        /* 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;
+}
+
+void va_surface_AddRef(vlc_va_surface_t *surface)
+{
+    atomic_fetch_add(&surface->refcount, 1);
+}
+
+void va_surface_Release(vlc_va_surface_t *surface)
+{
+    if (atomic_fetch_sub(&surface->refcount, 1) != 1)
+        return;
+    free(surface);
+}
+
+void va_pool_Close(vlc_va_t *va, va_pool_t *va_pool)
+{
+    DestroyVideoDecoder(va, va_pool);
+    va_pool->pf_destroy_video_service(va);
+    if (va_pool->pf_destroy_device_manager)
+        va_pool->pf_destroy_device_manager(va);
+    va_pool->pf_destroy_device(va);
+}
+
+int va_pool_Open(vlc_va_t *va, va_pool_t *va_pool,
+                    AVCodecContext *ctx, const es_format_t *fmt)
+{
+    va_pool->codec_id = ctx->codec_id;
+
+    /* */
+    if (va_pool->pf_create_device(va)) {
+        msg_Err(va, "Failed to create device");
+        goto error;
+    }
+    msg_Dbg(va, "CreateDevice succeed");
+
+    if (va_pool->pf_create_device_manager &&
+        va_pool->pf_create_device_manager(va) != VLC_SUCCESS) {
+        msg_Err(va, "CreateDeviceManager failed");
+        goto error;
+    }
+
+    if (va_pool->pf_create_video_service(va)) {
+        msg_Err(va, "CreateVideoService failed");
+        goto error;
+    }
+
+    return VLC_SUCCESS;
+
+error:
+    return VLC_EGENERIC;
+}
+
diff --git a/modules/codec/avcodec/va_surface.h b/modules/codec/avcodec/va_surface.h
new file mode 100644
index 0000000000..b89b420403
--- /dev/null
+++ b/modules/codec/avcodec/va_surface.h
@@ -0,0 +1,41 @@
+/*****************************************************************************
+ * directx_va.h: DirectX Generic Video Acceleration helpers
+ *****************************************************************************
+ * Copyright (C) 2009 Geoffroy Couprie
+ * Copyright (C) 2009 Laurent Aimar
+ * Copyright (C) 2015 Steve Lhomme
+ * $Id$
+ *
+ * Authors: Geoffroy Couprie <geal at videolan.org>
+ *          Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
+ *          Steve Lhomme <robux4 at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef AVCODEC_VA_SURFACE_H
+#define AVCODEC_VA_SURFACE_H
+
+#include <vlc_common.h>
+
+#include <stdatomic.h>
+
+/* */
+struct vlc_va_surface_t {
+    atomic_uintptr_t     refcount;
+    D3D_DecoderSurface  *decoderSurface;
+};
+
+#endif /* AVCODEC_VA_SURFACE_H */
diff --git a/modules/codec/avcodec/va_surface_internal.h b/modules/codec/avcodec/va_surface_internal.h
new file mode 100644
index 0000000000..92881ac018
--- /dev/null
+++ b/modules/codec/avcodec/va_surface_internal.h
@@ -0,0 +1,91 @@
+/*****************************************************************************
+ * va_surface_internal.h: libavcodec Generic Video Acceleration helpers
+ *****************************************************************************
+ * Copyright (C) 2009 Geoffroy Couprie
+ * Copyright (C) 2009 Laurent Aimar
+ * Copyright (C) 2015 Steve Lhomme
+ * $Id$
+ *
+ * Authors: Geoffroy Couprie <geal at videolan.org>
+ *          Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
+ *          Steve Lhomme <robux4 at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef AVCODEC_VA_SURFACE_INTERNAL_H
+#define AVCODEC_VA_SURFACE_INTERNAL_H
+
+#include "va_surface.h"
+
+#include <libavcodec/avcodec.h>
+#include "va.h"
+
+#define MAX_SURFACE_COUNT (64)
+typedef struct
+{
+    int          codec_id;
+    int          width;
+    int          height;
+
+    /* Video decoder */
+    D3D_DecoderType    *decoder;
+
+    /* */
+    int          surface_count;
+    int          surface_width;
+    int          surface_height;
+
+    vlc_va_surface_t    *surface[MAX_SURFACE_COUNT];
+    D3D_DecoderSurface  *hw_surface[MAX_SURFACE_COUNT];
+
+    /**
+     * Check that the decoder device is still available
+     */
+    int (*pf_check_device)(vlc_va_t *);
+
+    int (*pf_create_device)(vlc_va_t *);
+    void (*pf_destroy_device)(vlc_va_t *);
+
+    int (*pf_create_device_manager)(vlc_va_t *);
+    void (*pf_destroy_device_manager)(vlc_va_t *);
+
+    int (*pf_create_video_service)(vlc_va_t *);
+    void (*pf_destroy_video_service)(vlc_va_t *);
+
+    /**
+     * Create the DirectX surfaces in hw_surface and the decoder in decoder
+     */
+    int (*pf_create_decoder_surfaces)(vlc_va_t *, int codec_id,
+                                      const video_format_t *fmt);
+    /**
+     * Destroy resources allocated with the surfaces and the associated decoder
+     */
+    void (*pf_destroy_surfaces)(vlc_va_t *);
+    /**
+     * Set the avcodec hw context after the decoder is created
+     */
+    void (*pf_setup_avcodec_ctx)(vlc_va_t *);
+
+} va_pool_t;
+
+int va_pool_Open(vlc_va_t *, va_pool_t *, AVCodecContext *, const es_format_t *);
+void va_pool_Close(vlc_va_t *va, va_pool_t *);
+int va_pool_Setup(vlc_va_t *, va_pool_t *, AVCodecContext *, int count, int alignment);
+vlc_va_surface_t *va_pool_Get(vlc_va_t *, va_pool_t *);
+void va_surface_AddRef(vlc_va_surface_t *surface);
+void va_surface_Release(vlc_va_surface_t *surface);
+
+#endif /* AVCODEC_VA_SURFACE_INTERNAL_H */
-- 
2.12.1




More information about the vlc-devel mailing list