brillcodec: apply context management to DXVA 99/28099/1
authorgunsoo83.kim <gunsoo83.kim@samsung.com>
Fri, 26 Sep 2014 05:52:44 +0000 (14:52 +0900)
committergunsoo83.kim <gunsoo83.kim@samsung.com>
Fri, 26 Sep 2014 06:07:22 +0000 (15:07 +0900)
- implement plug-in context management in DXVA.

Change-Id: Iaa8642806483b9503d15cb5d6d2a300b04f1fe7d
Signed-off-by: gunsoo83.kim <gunsoo83.kim@samsung.com>
tizen/src/hw/pci/maru_dxva2_plugin.c

index 83b63b0..fca0064 100644 (file)
@@ -205,26 +205,13 @@ static const d3d_format_t d3d_formats[] = {
     { NULL, 0 }
 };
 
-/* */
-typedef struct {
-    LPDIRECT3DSURFACE9  d3d;
-    bool                is_occupied;
-} DXVAPluginSurface;
+struct DXVAPluginSurface;
+typedef struct DXVAPluginSurface DXVAPluginSurface;
 
 #define VA_DXVA2_MAX_SURFACE_COUNT (64)
 typedef struct DXVAPluginContext
 {
-    /* Direct3D */
-    D3DPRESENT_PARAMETERS   d3dpp;
-    LPDIRECT3D9             d3dobj;
-    LPDIRECT3DDEVICE9       d3ddev;
-
-    /* Device manager */
-    IDirect3DDeviceManager9 *devmng;
-    HANDLE                  hd3ddev;
-
     /* Video service */
-    IDirectXVideoDecoderService *vs;
     GUID                        guid_decdev;
     D3DFORMAT                   render_fmt;
 
@@ -235,26 +222,42 @@ typedef struct DXVAPluginContext
     /* Option conversion */
     D3DFORMAT   output;
 
-    /* */
+    /* Surfaces */
     unsigned     surface_count;
     int          surface_width;
     int          surface_height;
+    DXVAPluginSurface *surface;
+    LPDIRECT3DSURFACE9 hw_surface[VA_DXVA2_MAX_SURFACE_COUNT];
 
     int          thread_count;
 
-    DXVAPluginSurface surface[VA_DXVA2_MAX_SURFACE_COUNT];
-    LPDIRECT3DSURFACE9 hw_surface[VA_DXVA2_MAX_SURFACE_COUNT];
-
     struct dxva_context *hw_context;
 } DXVAPluginContext;
 
-// FIXME : modify dxva_ctx to multi instance for multi-thread decoding.
-static DXVAPluginContext *dxva_ctx = &(DXVAPluginContext) {};
+struct DXVAPluginSurface {
+    LPDIRECT3DSURFACE9  d3d;
+    bool                is_occupied;
+    DXVAPluginContext   *dxva_ctx;
+};
 
-/* DLL */
-static HINSTANCE hd3d9_dll;
-static HINSTANCE hdxva2_dll;
+typedef struct DXVADeviceHandle
+{
+    /* DLL */
+    HINSTANCE hd3d9_dll;
+    HINSTANCE hdxva2_dll;
 
+    /* Direct3D */
+    LPDIRECT3D9             d3dobj;
+    LPDIRECT3DDEVICE9       d3ddev;
+
+    /* Device manager */
+    IDirect3DDeviceManager9 *devmng;
+    HANDLE                  hd3ddev;
+
+    /* Video service */
+    IDirectXVideoDecoderService *vs;
+} DXVADeviceHandle;
+static DXVADeviceHandle *dxva_dev = &(DXVADeviceHandle) {};
 
 static const dxva2_mode_t *Dxva2FindMode(const GUID *guid)
 {
@@ -285,7 +288,7 @@ static int D3dCreateDevice(void)
 {
     /* */
     LPDIRECT3D9 (WINAPI *Create9)(UINT SDKVersion);
-    Create9 = (void *)GetProcAddress(hd3d9_dll, "Direct3DCreate9");
+    Create9 = (void *)GetProcAddress(dxva_dev->hd3d9_dll, "Direct3DCreate9");
     if (!Create9) {
         ERR("Cannot locate reference to Direct3DCreate9 ABI in DLL\n");
         return -1;
@@ -298,22 +301,22 @@ static int D3dCreateDevice(void)
         ERR("Direct3DCreate9 failed\n");
         return -1;
     }
-    dxva_ctx->d3dobj = d3dobj;
+    dxva_dev->d3dobj = d3dobj;
 
     /* */
-    D3DPRESENT_PARAMETERS *d3dpp = &dxva_ctx->d3dpp;
-    ZeroMemory(d3dpp, sizeof(*d3dpp));
-    d3dpp->Flags                  = D3DPRESENTFLAG_VIDEO;
-    d3dpp->Windowed               = TRUE;
-    d3dpp->hDeviceWindow          = NULL;
-    d3dpp->SwapEffect             = D3DSWAPEFFECT_DISCARD;
-    d3dpp->MultiSampleType        = D3DMULTISAMPLE_NONE;
-    d3dpp->PresentationInterval   = D3DPRESENT_INTERVAL_DEFAULT;
-    d3dpp->BackBufferCount        = 0;                  /* FIXME what to put here */
-    d3dpp->BackBufferFormat       = D3DFMT_X8R8G8B8;    /* FIXME what to put here */
-    d3dpp->BackBufferWidth        = 0;
-    d3dpp->BackBufferHeight       = 0;
-    d3dpp->EnableAutoDepthStencil = FALSE;
+    D3DPRESENT_PARAMETERS d3dpp;
+    ZeroMemory(&d3dpp, sizeof(d3dpp));
+    d3dpp.Flags                  = D3DPRESENTFLAG_VIDEO;
+    d3dpp.Windowed               = TRUE;
+    d3dpp.hDeviceWindow          = NULL;
+    d3dpp.SwapEffect             = D3DSWAPEFFECT_DISCARD;
+    d3dpp.MultiSampleType        = D3DMULTISAMPLE_NONE;
+    d3dpp.PresentationInterval   = D3DPRESENT_INTERVAL_DEFAULT;
+    d3dpp.BackBufferCount        = 0;                  /* FIXME what to put here */
+    d3dpp.BackBufferFormat       = D3DFMT_X8R8G8B8;    /* FIXME what to put here */
+    d3dpp.BackBufferWidth        = 0;
+    d3dpp.BackBufferHeight       = 0;
+    d3dpp.EnableAutoDepthStencil = FALSE;
 
     /* Direct3D needs a HWND to create a device, even without using ::Present
     this HWND is used to alert Direct3D when there's a change of focus window.
@@ -323,11 +326,11 @@ static int D3dCreateDevice(void)
                                        D3DDEVTYPE_HAL, GetDesktopWindow(),
                                        D3DCREATE_SOFTWARE_VERTEXPROCESSING |
                                        D3DCREATE_MULTITHREADED,
-                                       d3dpp, &d3ddev))) {
+                                       &d3dpp, &d3ddev))) {
         ERR("IDirect3D9_CreateDevice failed\n");
         return -1;
     }
-    dxva_ctx->d3ddev = d3ddev;
+    dxva_dev->d3ddev = d3ddev;
 
     return 0;
 }
@@ -340,7 +343,7 @@ static int D3dCreateDeviceManager(void)
     HRESULT (WINAPI *CreateDeviceManager9)(UINT *pResetToken,
                                            IDirect3DDeviceManager9 **);
     CreateDeviceManager9 =
-      (void *)GetProcAddress(hdxva2_dll,
+      (void *)GetProcAddress(dxva_dev->hdxva2_dll,
                              "DXVA2CreateDirect3DDeviceManager9");
 
     if (!CreateDeviceManager9) {
@@ -356,10 +359,10 @@ static int D3dCreateDeviceManager(void)
     }
     TRACE("OurDirect3DCreateDeviceManager9 Success!\n");
 
-    dxva_ctx->devmng = devmng;
+    dxva_dev->devmng = devmng;
     TRACE("obtained IDirect3DDeviceManager9\n");
 
-    HRESULT hr = IDirect3DDeviceManager9_ResetDevice(devmng, dxva_ctx->d3ddev, token);
+    HRESULT hr = IDirect3DDeviceManager9_ResetDevice(devmng, dxva_dev->d3ddev, token);
     if (FAILED(hr)) {
         ERR("IDirect3DDeviceManager9_ResetDevice failed: %08x\n", (unsigned)hr);
         return -1;
@@ -377,7 +380,7 @@ static int DxCreateVideoService(void)
                                          REFIID riid,
                                          void **ppService);
     CreateVideoService =
-      (void *)GetProcAddress(hdxva2_dll, "DXVA2CreateVideoService");
+      (void *)GetProcAddress(dxva_dev->hdxva2_dll, "DXVA2CreateVideoService");
 
     if (!CreateVideoService) {
         ERR("cannot load function\n");
@@ -388,21 +391,21 @@ static int DxCreateVideoService(void)
     HRESULT hr;
 
     HANDLE hd3ddev;
-    hr = IDirect3DDeviceManager9_OpenDeviceHandle(dxva_ctx->devmng, &hd3ddev);
+    hr = IDirect3DDeviceManager9_OpenDeviceHandle(dxva_dev->devmng, &hd3ddev);
     if (FAILED(hr)) {
         ERR("OpenDeviceHandle failed\n");
         return -1;
     }
-    dxva_ctx->hd3ddev = hd3ddev;
+    dxva_dev->hd3ddev = hd3ddev;
 
     void *pv;
-    hr = IDirect3DDeviceManager9_GetVideoService(dxva_ctx->devmng, hd3ddev,
+    hr = IDirect3DDeviceManager9_GetVideoService(dxva_dev->devmng, hd3ddev,
                                         &IID_IDirectXVideoDecoderService, &pv);
     if (FAILED(hr)) {
         ERR("GetVideoService failed\n");
         return -1;
     }
-    dxva_ctx->vs = pv;
+    dxva_dev->vs = pv;
 
     return 0;
 }
@@ -410,7 +413,7 @@ static int DxCreateVideoService(void)
 /**
  * Find the best suited decoder mode GUID and render format.
  */
-static int DxFindVideoServiceConversion(int codec_id)
+static int DxFindVideoServiceConversion(DXVAPluginContext *dxva_ctx, int codec_id)
 {
     unsigned i = 0;
     GUID *guid_decdev = &dxva_ctx->guid_decdev;
@@ -419,7 +422,7 @@ static int DxFindVideoServiceConversion(int codec_id)
     /* Retreive supported modes from the decoder service */
     UINT decdev_count = 0;
     GUID *guid_decdev_list = NULL;
-    if (FAILED(IDirectXVideoDecoderService_GetDecoderDeviceGuids(dxva_ctx->vs,
+    if (FAILED(IDirectXVideoDecoderService_GetDecoderDeviceGuids(dxva_dev->vs,
                                                                  &decdev_count,
                                                                  &guid_decdev_list))) {
         ERR("IDirectXVideoDecoderService_GetDecoderDeviceGuids failed\n");
@@ -459,7 +462,7 @@ static int DxFindVideoServiceConversion(int codec_id)
         INFO("Trying to use '%s' as input\n", mode->name);
         UINT      render_fmt_count = 0;
         D3DFORMAT *render_fmt_list = NULL;
-        if (FAILED(IDirectXVideoDecoderService_GetDecoderRenderTargets(dxva_ctx->vs, mode->guid,
+        if (FAILED(IDirectXVideoDecoderService_GetDecoderRenderTargets(dxva_dev->vs, mode->guid,
                                                                        &render_fmt_count,
                                                                        &render_fmt_list))) {
             ERR("IDirectXVideoDecoderService_GetDecoderRenderTargets failed\n");
@@ -504,7 +507,7 @@ static int DxFindVideoServiceConversion(int codec_id)
     return -1;
 }
 
-static void DxDestroyVideoDecoder(void)
+static void DxDestroyVideoDecoder(DXVAPluginContext *dxva_ctx)
 {
     unsigned i = 0;
 
@@ -522,7 +525,7 @@ static void DxDestroyVideoDecoder(void)
 /**
  * It creates a DXVA2 decoder using the given video format
  */
-static int DxCreateVideoDecoder(AVCodecContext *dec_ctx)
+static int DxCreateVideoDecoder(DXVAPluginContext *dxva_ctx, AVCodecContext *dec_ctx)
 {
     int surface_count = 0;
     unsigned i = 0;
@@ -556,7 +559,7 @@ static int DxCreateVideoDecoder(AVCodecContext *dec_ctx)
     if (surface_count > VA_DXVA2_MAX_SURFACE_COUNT)
         return -1;
     dxva_ctx->surface_count = surface_count;
-    if (FAILED(IDirectXVideoDecoderService_CreateSurface(dxva_ctx->vs,
+    if (FAILED(IDirectXVideoDecoderService_CreateSurface(dxva_dev->vs,
                                                          dxva_ctx->surface_width,
                                                          dxva_ctx->surface_height,
                                                          dxva_ctx->surface_count - 1,
@@ -570,10 +573,12 @@ static int DxCreateVideoDecoder(AVCodecContext *dec_ctx)
         dxva_ctx->surface_count = 0;
         return -1;
     }
+
+    dxva_ctx->surface = g_malloc_n(dxva_ctx->surface_count, sizeof(DXVAPluginSurface));
     for (i = 0; i < dxva_ctx->surface_count; i++) {
-        DXVAPluginSurface *surface = &dxva_ctx->surface[i];
-        surface->d3d = dxva_ctx->hw_surface[i];
-        surface->is_occupied = false;
+        dxva_ctx->surface[i].d3d = dxva_ctx->hw_surface[i];
+        dxva_ctx->surface[i].is_occupied = false;
+        dxva_ctx->surface[i].dxva_ctx = dxva_ctx;
     }
     TRACE("IDirectXVideoAccelerationService_CreateSurface succeed with %d surfaces (%dx%d)\n",
             dxva_ctx->surface_count, width, height);
@@ -603,7 +608,7 @@ static int DxCreateVideoDecoder(AVCodecContext *dec_ctx)
     /* List all configurations available for the decoder */
     UINT                      cfg_count = 0;
     DXVA2_ConfigPictureDecode *cfg_list = NULL;
-    if (FAILED(IDirectXVideoDecoderService_GetDecoderConfigurations(dxva_ctx->vs,
+    if (FAILED(IDirectXVideoDecoderService_GetDecoderConfigurations(dxva_dev->vs,
                                                                     &dxva_ctx->guid_decdev,
                                                                     &dsc,
                                                                     NULL,
@@ -647,7 +652,7 @@ static int DxCreateVideoDecoder(AVCodecContext *dec_ctx)
 
     /* Create the decoder */
     IDirectXVideoDecoder *decoder;
-    if (FAILED(IDirectXVideoDecoderService_CreateVideoDecoder(dxva_ctx->vs,
+    if (FAILED(IDirectXVideoDecoderService_CreateVideoDecoder(dxva_dev->vs,
                                                               &dxva_ctx->guid_decdev,
                                                               &dsc,
                                                               &dxva_ctx->cfg,
@@ -662,7 +667,7 @@ static int DxCreateVideoDecoder(AVCodecContext *dec_ctx)
     return 0;
 }
 
-static void DxCreateVideoConversion(void)
+static void DxCreateVideoConversion(DXVAPluginContext *dxva_ctx)
 {
     unsigned int output = dxva_ctx->render_fmt;
 
@@ -682,10 +687,10 @@ static void DxCreateVideoConversion(void)
  */
 static void DxDestroyVideoService(void)
 {
-    if (dxva_ctx->hd3ddev)
-        IDirect3DDeviceManager9_CloseDeviceHandle(dxva_ctx->devmng, dxva_ctx->hd3ddev);
-    if (dxva_ctx->vs)
-        IDirectXVideoDecoderService_Release(dxva_ctx->vs);
+    if (dxva_dev->hd3ddev)
+        IDirect3DDeviceManager9_CloseDeviceHandle(dxva_dev->devmng, dxva_dev->hd3ddev);
+    if (dxva_dev->vs)
+        IDirectXVideoDecoderService_Release(dxva_dev->vs);
 }
 
 /**
@@ -693,8 +698,8 @@ static void DxDestroyVideoService(void)
  */
 static void D3dDestroyDeviceManager(void)
 {
-    if (dxva_ctx->devmng)
-        IDirect3DDeviceManager9_Release(dxva_ctx->devmng);
+    if (dxva_dev->devmng)
+        IDirect3DDeviceManager9_Release(dxva_dev->devmng);
 }
 
 /**
@@ -702,10 +707,10 @@ static void D3dDestroyDeviceManager(void)
  */
 static void D3dDestroyDevice(void)
 {
-    if (dxva_ctx->d3ddev)
-        IDirect3DDevice9_Release(dxva_ctx->d3ddev);
-    if (dxva_ctx->d3dobj)
-        IDirect3D9_Release(dxva_ctx->d3dobj);
+    if (dxva_dev->d3ddev)
+        IDirect3DDevice9_Release(dxva_dev->d3ddev);
+    if (dxva_dev->d3dobj)
+        IDirect3D9_Release(dxva_dev->d3dobj);
 }
 
 #if 0
@@ -776,38 +781,30 @@ static void copy_nv12(uint8_t *dst[3], int linesizes[4],
 
 static void maru_dxva2_close(void)
 {
-    DxDestroyVideoDecoder();
     DxDestroyVideoService();
     D3dDestroyDeviceManager();
     D3dDestroyDevice();
 
-    if (hdxva2_dll) {
-        FreeLibrary(hdxva2_dll);
-        hdxva2_dll = NULL;
-    }
-    if (hd3d9_dll) {
-        FreeLibrary(hd3d9_dll);
-        hd3d9_dll = NULL;
+    if (dxva_dev->hdxva2_dll) {
+        FreeLibrary(dxva_dev->hdxva2_dll);
+        dxva_dev->hdxva2_dll = NULL;
     }
-
-    if (dxva_ctx->hw_context) {
-        free(dxva_ctx->hw_context);
-        dxva_ctx->hw_context = NULL;
+    if (dxva_dev->hd3d9_dll) {
+        FreeLibrary(dxva_dev->hd3d9_dll);
+        dxva_dev->hd3d9_dll = NULL;
     }
-
-    //free(dxva_ctx);
 }
 
 static bool probe(void)
 {
-    if (hd3d9_dll == NULL || hdxva2_dll == NULL) {
-        hd3d9_dll = LoadLibrary(TEXT("D3D9.DLL"));
-        if (!hd3d9_dll) {
+    if (dxva_dev->hd3d9_dll == NULL || dxva_dev->hdxva2_dll == NULL) {
+        dxva_dev->hd3d9_dll = LoadLibrary(TEXT("D3D9.DLL"));
+        if (!dxva_dev->hd3d9_dll) {
             ERR("cannot load d3d9.dll\n");
             goto error;
         }
-        hdxva2_dll = LoadLibrary(TEXT("DXVA2.DLL"));
-        if (!hdxva2_dll) {
+        dxva_dev->hdxva2_dll = LoadLibrary(TEXT("DXVA2.DLL"));
+        if (!dxva_dev->hdxva2_dll) {
             ERR("cannot load dxva2.dll\n");
             goto error;
         }
@@ -837,19 +834,32 @@ error:
     return false;
 }
 
+static void cleanup(void *opaque)
+{
+    DXVAPluginContext *dxva_ctx = (DXVAPluginContext *)opaque;
+
+    DxDestroyVideoDecoder(dxva_ctx);
+
+    if (dxva_ctx->hw_context) {
+        g_free(dxva_ctx->hw_context);
+    }
+
+    g_free(dxva_ctx);
+
+}
+
 static void *dxva_setup(AVCodecContext *dec_ctx, int width, int height)
 {
-    if (DxFindVideoServiceConversion(dec_ctx->codec_id)) {
+    DXVAPluginContext *dxva_ctx = g_malloc0(sizeof(DXVAPluginContext));
+
+    if (DxFindVideoServiceConversion(dxva_ctx, dec_ctx->codec_id)) {
         ERR("DxFindVideoServiceConversion failed\n");
         return NULL;
     }
 
     dxva_ctx->thread_count = dec_ctx->thread_count;
 
-    //TODO: destroy surface and decoder at avcontext deinit()
-    DxDestroyVideoDecoder();
-
-    if (DxCreateVideoDecoder(dec_ctx) < -1) {
+    if (DxCreateVideoDecoder(dxva_ctx, dec_ctx) < -1) {
         ERR("DxCreateVideoDecoder failed\n");
         return NULL;
     }
@@ -865,7 +875,7 @@ static void *dxva_setup(AVCodecContext *dec_ctx, int width, int height)
     dxva_ctx->hw_context->surface_count = dxva_ctx->surface_count;
     dxva_ctx->hw_context->surface = dxva_ctx->hw_surface;
 
-    DxCreateVideoConversion();
+    DxCreateVideoConversion(dxva_ctx);
 
     return dxva_ctx;
 }
@@ -874,10 +884,11 @@ static int dxva_get_surface(AVCodecContext *dec_ctx, AVFrame *frame)
 {
     unsigned i = 0;
     DXVAPluginSurface *surface = NULL;
+    DXVAPluginContext *dxva_ctx = (DXVAPluginContext *)get_plugin_context(dec_ctx);
 
     /* Check the device */
 #if 0
-    HRESULT hr = IDirect3DDeviceManager9_TestDevice(dxva_ctx->devmng, dxva_ctx->hd3ddev);
+    HRESULT hr = IDirect3DDeviceManager9_TestDevice(dxva_dev->devmng, dxva_dev->hd3ddev);
     if (hr == DXVA2_E_NEW_VIDEO_DEVICE) {
         if (DxResetVideoDecoder())
             return -1;
@@ -921,6 +932,7 @@ static void extract(void *dst, void *src)
 {
     AVFrame *frame = (AVFrame *)src;
     LPDIRECT3DSURFACE9 d3d = (LPDIRECT3DSURFACE9)(uintptr_t)frame->data[3];
+    DXVAPluginContext *dxva_ctx = (DXVAPluginContext *)((DXVAPluginSurface *)frame->opaque)->dxva_ctx;
 
     /* */
     assert(dxva_ctx->output == MAKEFOURCC('Y','V','1','2'));
@@ -990,6 +1002,7 @@ CodecPlugin dxva_plugin = {
     .output_pix_fmt = PIX_FMT_YUV420P,
     .probe = probe,
     .setup = dxva_setup,
+    .cleanup = cleanup,
     .get_buffer = dxva_get_surface,
     .release_buffer = dxva_release_surface,
     .get_picture = extract,