Enabled VC-1/WMV3 DXVA2 support in VLC.
[vlc.git] / modules / codec / avcodec / dxva2.c
index 7d3391a..054d6ea 100644 (file)
@@ -36,6 +36,7 @@
 #ifdef HAVE_LIBAVCODEC_AVCODEC_H
 #   include <libavcodec/avcodec.h>
 #   ifdef HAVE_AVCODEC_DXVA2
+#       define DXVA2API_USE_BITFIELDS
 #       include <libavcodec/dxva2.h>
 #   endif
 #elif defined(HAVE_FFMPEG_AVCODEC_H)
@@ -93,6 +94,15 @@ static const GUID DXVA2_ModeH264_E = {
 static const GUID DXVA2_ModeH264_F = {
     0x1b81be69, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
 };
+static const GUID DXVADDI_Intel_ModeH264_A = {
+    0x604F8E64, 0x4951,0x4c54, {0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6}
+};
+static const GUID DXVADDI_Intel_ModeH264_C = {
+    0x604F8E66,0x4951, 0x4c54, {0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6}
+};
+static const GUID DXVADDI_Intel_ModeH264_E = {
+    0x604F8E68,0x4951, 0x4c54, {0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6}
+};
 static const GUID DXVA2_ModeWMV8_A = {
     0x1b81be80, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
 };
@@ -134,12 +144,15 @@ static const dxva2_mode_t dxva2_modes[] = {
     { "DXVA2_ModeMPEG2_MoComp", &DXVA2_ModeMPEG2_MoComp,  0 },
     { "DXVA2_ModeMPEG2_IDCT",   &DXVA2_ModeMPEG2_IDCT,    0 },
 
-    { "H.264 variable-length decoder (VLD), FGT",               &DXVA2_ModeH264_F, CODEC_ID_H264 },
-    { "H.264 VLD, no FGT",                                      &DXVA2_ModeH264_E, CODEC_ID_H264 },
-    { "H.264 IDCT, FGT",                                        &DXVA2_ModeH264_D, 0,            },
-    { "H.264 inverse discrete cosine transform (IDCT), no FGT", &DXVA2_ModeH264_C, 0,            },
-    { "H.264 MoComp, FGT",                                      &DXVA2_ModeH264_B, 0,            },
-    { "H.264 motion compensation (MoComp), no FGT",             &DXVA2_ModeH264_A, 0,            },
+    { "H.264 variable-length decoder (VLD), FGT",               &DXVA2_ModeH264_F,         CODEC_ID_H264 },
+    { "H.264 VLD, no FGT",                                      &DXVA2_ModeH264_E,         CODEC_ID_H264 },
+    { "H.264 VLD, no FGT (Intel)",                              &DXVADDI_Intel_ModeH264_E, CODEC_ID_H264 },
+    { "H.264 IDCT, FGT",                                        &DXVA2_ModeH264_D,         0             },
+    { "H.264 inverse discrete cosine transform (IDCT), no FGT", &DXVA2_ModeH264_C,         0             },
+    { "H.264 inverse discrete cosine transform (IDCT), no FGT (Intel)", &DXVADDI_Intel_ModeH264_C, 0     },
+    { "H.264 MoComp, FGT",                                      &DXVA2_ModeH264_B,         0             },
+    { "H.264 motion compensation (MoComp), no FGT",             &DXVA2_ModeH264_A,         0             },
+    { "H.264 motion compensation (MoComp), no FGT (Intel)",     &DXVADDI_Intel_ModeH264_A, 0             },
 
     { "Windows Media Video 8 MoComp",           &DXVA2_ModeWMV8_B, 0 },
     { "Windows Media Video 8 post processing",  &DXVA2_ModeWMV8_A, 0 },
@@ -148,7 +161,8 @@ static const dxva2_mode_t dxva2_modes[] = {
     {  "Windows Media Video 9 MoComp",          &DXVA2_ModeWMV9_B, 0 },
     {  "Windows Media Video 9 post processing", &DXVA2_ModeWMV9_A, 0 },
 
-    { "VC-1 VLD",             &DXVA2_ModeVC1_D, 0 },
+    { "VC-1 VLD",             &DXVA2_ModeVC1_D, CODEC_ID_VC1 },
+    { "VC-1 VLD",             &DXVA2_ModeVC1_D, CODEC_ID_WMV3 },
     { "VC-1 IDCT",            &DXVA2_ModeVC1_C, 0 },
     { "VC-1 MoComp",          &DXVA2_ModeVC1_B, 0 },
     { "VC-1 post processing", &DXVA2_ModeVC1_A, 0 },
@@ -218,23 +232,24 @@ typedef struct
     HINSTANCE             hdxva2_dll;
 
     /* Direct3D */
-       D3DPRESENT_PARAMETERS d3dpp;
-       LPDIRECT3D9           d3dobj;
-       LPDIRECT3DDEVICE9     d3ddev;
+    D3DPRESENT_PARAMETERS  d3dpp;
+    LPDIRECT3D9            d3dobj;
+    D3DADAPTER_IDENTIFIER9 d3dai;
+    LPDIRECT3DDEVICE9      d3ddev;
 
     /* Device manager */
     UINT                     token;
-    LPDIRECT3DDEVICEMANAGER9 devmng;
+    IDirect3DDeviceManager9  *devmng;
     HANDLE                   device;
 
     /* Video service */
-    LPDIRECTXVIDEODECODERSERVICE vs;
+    IDirectXVideoDecoderService  *vs;
     GUID                         input;
     D3DFORMAT                    render;
 
     /* Video decoder */
     DXVA2_ConfigPictureDecode    cfg;
-    LPDIRECTXVIDEODECODER        decoder;
+    IDirectXVideoDecoder         *decoder;
 
     /* Option conversion */
     D3DFORMAT                    output;
@@ -319,8 +334,7 @@ static int Setup(vlc_va_t *external, void **hw, vlc_fourcc_t *chroma,
         return VLC_EGENERIC;
     /* */
     va->hw.decoder = va->decoder;
-    if (va->codec_id == CODEC_ID_H264)
-        va->hw.cfg = &va->cfg;
+    va->hw.cfg = &va->cfg;
     va->hw.surface_count = va->surface_count;
     va->hw.surface = va->hw_surface;
     for (unsigned i = 0; i < va->surface_count; i++)
@@ -531,6 +545,14 @@ static int D3dCreateDevice(vlc_va_dxva2_t *va)
     }
     va->d3dobj = d3dobj;
 
+    /* */
+    D3DADAPTER_IDENTIFIER9 *d3dai = &va->d3dai;
+    if (FAILED(IDirect3D9_GetAdapterIdentifier(va->d3dobj,
+                                               D3DADAPTER_DEFAULT, 0, d3dai))) {
+        msg_Warn(va->log, "IDirect3D9_GetAdapterIdentifier failed");
+        ZeroMemory(d3dai, sizeof(*d3dai));
+    }
+
     /* */
     D3DPRESENT_PARAMETERS *d3dpp = &va->d3dpp;
     ZeroMemory(d3dpp, sizeof(*d3dpp));
@@ -577,17 +599,30 @@ static void D3dDestroyDevice(vlc_va_dxva2_t *va)
  */
 static char *DxDescribe(vlc_va_dxva2_t *va)
 {
-    D3DADAPTER_IDENTIFIER9 id;
-    ZeroMemory(&id, sizeof(id));
-
-    if (FAILED(IDirect3D9_GetAdapterIdentifier(va->d3dobj,
-                                               D3DADAPTER_DEFAULT, 0, &id)))
-        return strdup("DXVA2 (unknown)");
+    static const struct {
+        unsigned id;
+        char     name[32];
+    } vendors [] = {
+        { 0x1002, "ATI" },
+        { 0x10DE, "NVIDIA" },
+        { 0x8086, "Intel" },
+        { 0x5333, "S3 Graphics" },
+        { 0, "" }
+    };
+    D3DADAPTER_IDENTIFIER9 *id = &va->d3dai;
+
+    const char *vendor = "Unknown";
+    for (int i = 0; vendors[i].id != 0; i++) {
+        if (vendors[i].id == id->VendorId) {
+            vendor = vendors[i].name;
+            break;
+        }
+    }
 
     char *description;
-    if (asprintf(&description, "DXVA2 (%.*s, vendor %d, device %d, revision %d)",
-                 sizeof(id.Description), id.Description,
-                 id.VendorId, id.DeviceId, id.Revision) < 0)
+    if (asprintf(&description, "DXVA2 (%.*s, vendor %d(%s), device %d, revision %d)",
+                 sizeof(id->Description), id->Description,
+                 id->VendorId, vendor, id->DeviceId, id->Revision) < 0)
         return NULL;
     return description;
 }
@@ -610,7 +645,7 @@ static int D3dCreateDeviceManager(vlc_va_dxva2_t *va)
     msg_Dbg(va->log, "OurDirect3DCreateDeviceManager9 Success!");
 
     UINT token;
-    LPDIRECT3DDEVICEMANAGER9 devmng;
+    IDirect3DDeviceManager9 *devmng;
     if (FAILED(CreateDeviceManager9(&token, &devmng))) {
         msg_Err(va->log, " OurDirect3DCreateDeviceManager9 failed");
         return VLC_EGENERIC;
@@ -663,7 +698,7 @@ static int DxCreateVideoService(vlc_va_dxva2_t *va)
     }
     va->device = device;
 
-    LPDIRECTXVIDEODECODERSERVICE vs;
+    IDirectXVideoDecoderService *vs;
     hr = IDirect3DDeviceManager9_GetVideoService(va->devmng, device,
                                                  &IID_IDirectXVideoDecoderService,
                                                  &vs);
@@ -705,7 +740,7 @@ static int DxFindVideoServiceConversion(vlc_va_dxva2_t *va, GUID *input, D3DFORM
         if (mode) {
             msg_Dbg(va->log, "- '%s' is supported by hardware", mode->name);
         } else {
-            msg_Warn(va->log, "- Unknown GUID = %08X-%04x-%04x-XXXX\n",
+            msg_Warn(va->log, "- Unknown GUID = %08X-%04x-%04x-XXXX",
                      (unsigned)g->Data1, g->Data2, g->Data3);
         }
     }
@@ -879,7 +914,7 @@ static int DxCreateVideoDecoder(vlc_va_dxva2_t *va,
     }
 
     /* Create the decoder */
-    LPDIRECTXVIDEODECODER decoder;
+    IDirectXVideoDecoder *decoder;
     if (FAILED(IDirectXVideoDecoderService_CreateVideoDecoder(va->vs,
                                                               &va->input,
                                                               &dsc,