Guest User

Untitled

a guest
Nov 21st, 2011
1,183
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <cstdio>
  2.  
  3. #define COBJMACROS
  4. #include <windows.h>
  5. #include <d3d9.h>
  6. #include <dxva2api.h>
  7.  
  8. extern "C" {
  9. #include <libavformat/avformat.h>
  10. #include <libavcodec/avcodec.h>
  11. #include <libavcodec/dxva2.h>
  12. }
  13.  
  14. #define VA_DXVA2_MAX_SURFACE_COUNT (64)
  15.  
  16. typedef struct {
  17.     LPDIRECT3DSURFACE9 d3d;
  18.     int                refcount;
  19.     unsigned int       order;
  20. } vlc_va_surface_t;
  21.  
  22. typedef struct
  23. {
  24.     int          codec_id;
  25.     int          width;
  26.     int          height;
  27.  
  28.     /* DLL */
  29.     HINSTANCE             hd3d9_dll;
  30.     HINSTANCE             hdxva2_dll;
  31.  
  32.     /* Direct3D */
  33.     D3DPRESENT_PARAMETERS  d3dpp;
  34.     LPDIRECT3D9            d3dobj;
  35.     D3DADAPTER_IDENTIFIER9 d3dai;
  36.     LPDIRECT3DDEVICE9      d3ddev;
  37.  
  38.     /* Device manager */
  39.     UINT                     token;
  40.     IDirect3DDeviceManager9  *devmng;
  41.     HANDLE                   device;
  42.  
  43.     /* Video service */
  44.     IDirectXVideoDecoderService  *vs;
  45.     GUID                         input;
  46.     D3DFORMAT                    render;
  47.  
  48.     /* Video decoder */
  49.     DXVA2_ConfigPictureDecode    cfg;
  50.     IDirectXVideoDecoder         *decoder;
  51.  
  52.     /* Option conversion */
  53.     D3DFORMAT                    output;
  54.  
  55.     /* */
  56.     struct dxva_context hw;
  57.  
  58.     /* */
  59.     unsigned     surface_count;
  60.     unsigned     surface_order;
  61.     int          surface_width;
  62.     int          surface_height;
  63.  
  64.     vlc_va_surface_t surface[VA_DXVA2_MAX_SURFACE_COUNT];
  65.     LPDIRECT3DSURFACE9 hw_surface[VA_DXVA2_MAX_SURFACE_COUNT];
  66. } vlc_va_dxva2_t;
  67.  
  68.  
  69. typedef struct {
  70.     const char   *name;
  71.     D3DFORMAT    format;
  72.     PixelFormat  codec;
  73. } d3d_format_t;
  74.  
  75. /* XXX Prefered format must come first */
  76. static const d3d_format_t d3d_formats[] = {
  77.     { "YV12",   (D3DFORMAT)MAKEFOURCC('Y','V','1','2'),    PIX_FMT_YUV420P },
  78.     { "NV12",   (D3DFORMAT)MAKEFOURCC('N','V','1','2'),    PIX_FMT_NV12 },
  79.  
  80.     { NULL, (D3DFORMAT)0, PIX_FMT_NONE }
  81. };
  82.  
  83. /**
  84.  * video format description
  85.  */
  86. struct video_format_t
  87. {
  88.     PixelFormat  i_chroma;                               /**< picture chroma */
  89.  
  90.     unsigned int i_width;                                 /**< picture width */
  91.     unsigned int i_height;                               /**< picture height */
  92.     unsigned int i_x_offset;               /**< start offset of visible area */
  93.     unsigned int i_y_offset;               /**< start offset of visible area */
  94.     unsigned int i_visible_width;                 /**< width of visible area */
  95.     unsigned int i_visible_height;               /**< height of visible area */
  96.  
  97.     unsigned int i_bits_per_pixel;             /**< number of bits per pixel */
  98.  
  99.     unsigned int i_sar_num;                   /**< sample/pixel aspect ratio */
  100.     unsigned int i_sar_den;
  101.  
  102.     unsigned int i_frame_rate;                     /**< frame rate numerator */
  103.     unsigned int i_frame_rate_base;              /**< frame rate denominator */
  104.  
  105.     uint32_t i_rmask, i_gmask, i_bmask;          /**< color masks for RGB chroma */
  106.     int i_rrshift, i_lrshift;
  107.     int i_rgshift, i_lgshift;
  108.     int i_rbshift, i_lbshift;
  109. };
  110.  
  111. static const d3d_format_t *D3dFindFormat(D3DFORMAT format)
  112. {
  113.     for (unsigned i = 0; d3d_formats[i].name; i++) {
  114.         if (d3d_formats[i].format == format)
  115.             return &d3d_formats[i];
  116.     }
  117.     return NULL;
  118. }
  119.  
  120. static const GUID DXVA2_ModeMPEG2_MoComp = {
  121.     0xe6a9f44b, 0x61b0,0x4563, {0x9e,0xa4,0x63,0xd2,0xa3,0xc6,0xfe,0x66}
  122. };
  123. static const GUID DXVA2_ModeMPEG2_IDCT = {
  124.     0xbf22ad00, 0x03ea,0x4690, {0x80,0x77,0x47,0x33,0x46,0x20,0x9b,0x7e}
  125. };
  126. static const GUID DXVA2_ModeMPEG2_VLD = {
  127.     0xee27417f, 0x5e28,0x4e65, {0xbe,0xea,0x1d,0x26,0xb5,0x08,0xad,0xc9}
  128. };
  129. static const GUID DXVA2_ModeMPEG2and1_VLD = {
  130.     0x86695f12, 0x340e,0x4f04, {0x9f,0xd3,0x92,0x53,0xdd,0x32,0x74,0x60}
  131. };
  132. static const GUID DXVA2_ModeMPEG1_VLD = {
  133.     0x6f3ec719, 0x3735,0x42cc, {0x80,0x63,0x65,0xcc,0x3c,0xb3,0x66,0x16}
  134. };
  135.  
  136. static const GUID DXVA2_ModeH264_A = {
  137.     0x1b81be64, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
  138. };
  139. static const GUID DXVA2_ModeH264_B = {
  140.     0x1b81be65, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
  141. };
  142. static const GUID DXVA2_ModeH264_C = {
  143.     0x1b81be66, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
  144. };
  145. static const GUID DXVA2_ModeH264_D = {
  146.     0x1b81be67, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
  147. };
  148. static const GUID DXVA2_ModeH264_E = {
  149.     0x1b81be68, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
  150. };
  151. static const GUID DXVA2_ModeH264_F = {
  152.     0x1b81be69, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
  153. };
  154. static const GUID DXVA_ModeH264_VLD_WithFMOASO_NoFGT = {
  155.     0xd5f04ff9, 0x3418,0x45d8, {0x95,0x61,0x32,0xa7,0x6a,0xae,0x2d,0xdd}
  156. };
  157. static const GUID DXVADDI_Intel_ModeH264_A = {
  158.     0x604F8E64, 0x4951,0x4c54, {0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6}
  159. };
  160. static const GUID DXVADDI_Intel_ModeH264_C = {
  161.     0x604F8E66, 0x4951,0x4c54, {0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6}
  162. };
  163. static const GUID DXVADDI_Intel_ModeH264_E = { // DXVA_Intel_H264_ClearVideo
  164.     0x604F8E68, 0x4951,0x4c54, {0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6}
  165. };
  166. static const GUID DXVA2_ModeWMV8_A = {
  167.     0x1b81be80, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
  168. };
  169. static const GUID DXVA2_ModeWMV8_B = {
  170.     0x1b81be81, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
  171. };
  172. static const GUID DXVA2_ModeWMV9_A = {
  173.     0x1b81be90, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
  174. };
  175. static const GUID DXVA2_ModeWMV9_B = {
  176.     0x1b81be91, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
  177. };
  178. static const GUID DXVA2_ModeWMV9_C = {
  179.     0x1b81be94, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
  180. };
  181.  
  182. static const GUID DXVA2_ModeVC1_A = {
  183.     0x1b81beA0, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
  184. };
  185. static const GUID DXVA2_ModeVC1_B = {
  186.     0x1b81beA1, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
  187. };
  188. static const GUID DXVA2_ModeVC1_C = {
  189.     0x1b81beA2, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
  190. };
  191. static const GUID DXVA2_ModeVC1_D = {
  192.     0x1b81beA3, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
  193. };
  194. /* Conformity to the August 2010 update of the specification, ModeVC1_VLD2010 */
  195. static const GUID DXVA2_ModeVC1_D2010 = {
  196.     0x1b81beA4, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
  197. };
  198.  
  199. static const GUID DXVA_NoEncrypt = {
  200.     0x1b81bed0, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
  201. };
  202.  
  203. static const GUID DXVA_Intel_VC1_ClearVideo = {
  204.     0xBCC5DB6D, 0xA2B6,0x4AF0, {0xAC,0xE4,0xAD,0xB1,0xF7,0x87,0xBC,0x89}
  205. };
  206.  
  207. static const GUID DXVA_nVidia_MPEG4_ASP = {
  208.     0x9947EC6F, 0x689B,0x11DC, {0xA3,0x20,0x00,0x19,0xDB,0xBC,0x41,0x84}
  209. };
  210. static const GUID DXVA_ModeMPEG4pt2_VLD_Simple = {
  211.     0xefd64d74, 0xc9e8,0x41d7, {0xa5,0xe9,0xe9,0xb0,0xe3,0x9f,0xa3,0x19}
  212. };
  213. static const GUID DXVA_ModeMPEG4pt2_VLD_AdvSimple_NoGMC = {
  214.     0xed418a9f, 0x10d,0x4eda,  {0x9a,0xe3,0x9a,0x65,0x35,0x8d,0x8d,0x2e}
  215. };
  216. static const GUID DXVA_ModeMPEG4pt2_VLD_AdvSimple_GMC = {
  217.     0xab998b5b, 0x4258,0x44a9, {0x9f,0xeb,0x94,0xe5,0x97,0xa6,0xba,0xae}
  218. };
  219.  
  220.  
  221. static const GUID IID_IDirectXVideoDecoderService = {
  222.     0xfc51a551, 0xd5e7, 0x11d9, {0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02}
  223. };
  224. static const GUID IID_IDirectXVideoAccelerationService = {
  225.     0xfc51a550, 0xd5e7, 0x11d9, {0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02}
  226. };
  227.  
  228. typedef struct {
  229.     const char   *name;
  230.     const GUID&  guid;
  231.     int          codec;
  232. } dxva2_mode_t;
  233.  
  234. /* XXX Prefered modes must come first */
  235. static const dxva2_mode_t dxva2_modes[] = {
  236.     { "MPEG-2 variable-length decoder",            DXVA2_ModeMPEG2_VLD,     CODEC_ID_MPEG2VIDEO },
  237.     { "MPEG-2 & MPEG-1 variable-length decoder",   DXVA2_ModeMPEG2and1_VLD, CODEC_ID_MPEG2VIDEO },
  238.     { "MPEG-2 motion compensation",                DXVA2_ModeMPEG2_MoComp,  0 },
  239.     { "MPEG-2 inverse discrete cosine transform",  DXVA2_ModeMPEG2_IDCT,    0 },
  240.  
  241.     { "MPEG-1 variable-length decoder",            DXVA2_ModeMPEG1_VLD,     0 },
  242.  
  243.     { "H.264 variable-length decoder, film grain technology",                      DXVA2_ModeH264_F,                   CODEC_ID_H264 },
  244.     { "H.264 variable-length decoder, no film grain technology",                   DXVA2_ModeH264_E,                   CODEC_ID_H264 },
  245.     { "H.264 variable-length decoder, no film grain technology (Intel ClearVideo)",DXVADDI_Intel_ModeH264_E,           CODEC_ID_H264 },
  246.     { "H.264 variable-length decoder, no film grain technology, FMO/ASO",          DXVA_ModeH264_VLD_WithFMOASO_NoFGT, CODEC_ID_H264 },
  247.     { "H.264 inverse discrete cosine transform, film grain technology",            DXVA2_ModeH264_D,                   0             },
  248.     { "H.264 inverse discrete cosine transform, no film grain technology",         DXVA2_ModeH264_C,                   0             },
  249.     { "H.264 inverse discrete cosine transform, no film grain technology (Intel)", DXVADDI_Intel_ModeH264_C,           0             },
  250.     { "H.264 motion compensation, film grain technology",                          DXVA2_ModeH264_B,                   0             },
  251.     { "H.264 motion compensation, no film grain technology",                       DXVA2_ModeH264_A,                   0             },
  252.     { "H.264 motion compensation, no film grain technology (Intel)",               DXVADDI_Intel_ModeH264_A,           0             },
  253.  
  254.     { "Windows Media Video 8 motion compensation", DXVA2_ModeWMV8_B, 0 },
  255.     { "Windows Media Video 8 post processing",     DXVA2_ModeWMV8_A, 0 },
  256.  
  257.     { "Windows Media Video 9 IDCT",                DXVA2_ModeWMV9_C, 0 },
  258.     { "Windows Media Video 9 motion compensation", DXVA2_ModeWMV9_B, 0 },
  259.     { "Windows Media Video 9 post processing",     DXVA2_ModeWMV9_A, 0 },
  260.  
  261.     { "VC-1 variable-length decoder",              DXVA2_ModeVC1_D, CODEC_ID_VC1 },
  262.     { "VC-1 variable-length decoder",              DXVA2_ModeVC1_D, CODEC_ID_WMV3 },
  263.     { "VC-1 variable-length decoder",              DXVA2_ModeVC1_D2010, CODEC_ID_VC1 },
  264.     { "VC-1 variable-length decoder",              DXVA2_ModeVC1_D2010, CODEC_ID_WMV3 },
  265.     { "VC-1 inverse discrete cosine transform",    DXVA2_ModeVC1_C, 0 },
  266.     { "VC-1 motion compensation",                  DXVA2_ModeVC1_B, 0 },
  267.     { "VC-1 post processing",                      DXVA2_ModeVC1_A, 0 },
  268.  
  269.     { "VC-1 variable-length decoder (Intel)",      DXVA_Intel_VC1_ClearVideo, 0 },
  270.  
  271.     { "MPEG-4 Part 2 nVidia bitstream decoder",                                                         DXVA_nVidia_MPEG4_ASP,                 0 },
  272.     { "MPEG-4 Part 2 variable-length decoder, Simple Profile",                                          DXVA_ModeMPEG4pt2_VLD_Simple,          0 },
  273.     { "MPEG-4 Part 2 variable-length decoder, Simple&Advanced Profile, no global motion compensation",  DXVA_ModeMPEG4pt2_VLD_AdvSimple_NoGMC, 0 },
  274.     { "MPEG-4 Part 2 variable-length decoder, Simple&Advanced Profile, global motion compensation",     DXVA_ModeMPEG4pt2_VLD_AdvSimple_GMC,   0 },
  275.  
  276.     { NULL, GUID_NULL, 0 }
  277. };
  278.  
  279. static const dxva2_mode_t *Dxva2FindMode(const GUID& guid)
  280. {
  281.     for (unsigned i = 0; dxva2_modes[i].name; i++) {
  282.         if (IsEqualGUID(dxva2_modes[i].guid, guid))
  283.             return &dxva2_modes[i];
  284.     }
  285.     return NULL;
  286. }
  287.  
  288. static int D3dCreateDevice(vlc_va_dxva2_t *);
  289. static void D3dDestroyDevice(vlc_va_dxva2_t *);
  290. //static char *DxDescribe(vlc_va_dxva2_t *);
  291.  
  292. static int D3dCreateDeviceManager(vlc_va_dxva2_t *);
  293. static void D3dDestroyDeviceManager(vlc_va_dxva2_t *);
  294.  
  295. static int DxCreateVideoService(vlc_va_dxva2_t *);
  296. static void DxDestroyVideoService(vlc_va_dxva2_t *);
  297. static int DxFindVideoServiceConversion(vlc_va_dxva2_t *, GUID *input, D3DFORMAT *output);
  298.  
  299. static int DxCreateVideoDecoder(vlc_va_dxva2_t *, int codec_id, const video_format_t *fmt);
  300. static void DxDestroyVideoDecoder(vlc_va_dxva2_t *);
  301. static int DxResetVideoDecoder(vlc_va_dxva2_t *);
  302.  
  303. static void DxCreateVideoConversion(vlc_va_dxva2_t *);
  304. static void DxDestroyVideoConversion(vlc_va_dxva2_t *);
  305.  
  306. static void Close(vlc_va_dxva2_t *external)
  307. {
  308.     vlc_va_dxva2_t *va = external;
  309.  
  310.     DxDestroyVideoConversion(va);
  311.     DxDestroyVideoDecoder(va);
  312.     DxDestroyVideoService(va);
  313.     D3dDestroyDeviceManager(va);
  314.     D3dDestroyDevice(va);
  315.  
  316.     if (va->hdxva2_dll)
  317.         FreeLibrary(va->hdxva2_dll);
  318.     if (va->hd3d9_dll)
  319.         FreeLibrary(va->hd3d9_dll);
  320.     free(va);
  321. }
  322.  
  323. vlc_va_dxva2_t *vlc_va_NewDxva2(int codec_id)
  324. {
  325.     vlc_va_dxva2_t *va = (vlc_va_dxva2_t *)calloc(1, sizeof(*va));
  326.     if (!va)
  327.         return NULL;
  328.  
  329.     va->codec_id = codec_id;
  330.  
  331.     /* Load dll*/
  332.     va->hd3d9_dll = LoadLibrary(TEXT("D3D9.DLL"));
  333.     if (!va->hd3d9_dll) {
  334.         av_log(NULL, AV_LOG_ERROR, "cannot load d3d9.dll\n");
  335.         goto error;
  336.     }
  337.     va->hdxva2_dll = LoadLibrary(TEXT("DXVA2.DLL"));
  338.     if (!va->hdxva2_dll) {
  339.         av_log(NULL, AV_LOG_ERROR, "cannot load dxva2.dll\n");
  340.         goto error;
  341.     }
  342.     av_log(NULL, AV_LOG_INFO, "DLLs loaded\n");
  343.  
  344.     /* */
  345.     if (D3dCreateDevice(va)) {
  346.         av_log(NULL, AV_LOG_ERROR, "Failed to create Direct3D device\n");
  347.         goto error;
  348.     }
  349.     av_log(NULL, AV_LOG_INFO, "D3dCreateDevice succeed\n");
  350.  
  351.     if (D3dCreateDeviceManager(va)) {
  352.         av_log(NULL, AV_LOG_ERROR, "D3dCreateDeviceManager failed\n");
  353.         goto error;
  354.     }
  355.  
  356.     if (DxCreateVideoService(va)) {
  357.         av_log(NULL, AV_LOG_ERROR, "DxCreateVideoService failed\n");
  358.         goto error;
  359.     }
  360.  
  361.     /* */
  362.     if (DxFindVideoServiceConversion(va, &va->input, &va->render)) {
  363.         av_log(NULL, AV_LOG_ERROR, "DxFindVideoServiceConversion failed\n");
  364.         goto error;
  365.     }
  366.  
  367.     /* TODO print the hardware name/vendor for debugging purposes */
  368.     return va;
  369.  
  370. error:
  371.     Close(va);
  372.     return NULL;
  373. }
  374.  
  375. /**
  376.  * It creates a Direct3D device usable for DXVA 2
  377.  */
  378. static int D3dCreateDevice(vlc_va_dxva2_t *va)
  379. {
  380.     /* */
  381.     typedef LPDIRECT3D9 (WINAPI *Create9func)(UINT SDKVersion);
  382.     Create9func Create9 = (Create9func )GetProcAddress(va->hd3d9_dll, TEXT("Direct3DCreate9"));
  383.  
  384.     if (!Create9) {
  385.         av_log(NULL, AV_LOG_ERROR, "Cannot locate reference to Direct3DCreate9 ABI in DLL");
  386.         return -1;
  387.     }
  388.  
  389.     /* */
  390.     LPDIRECT3D9 d3dobj;
  391.     d3dobj = Create9(D3D_SDK_VERSION);
  392.     if (!d3dobj) {
  393.         av_log(NULL, AV_LOG_ERROR, "Direct3DCreate9 failed");
  394.         return -1;
  395.     }
  396.     va->d3dobj = d3dobj;
  397.  
  398.     /* */
  399.     D3DADAPTER_IDENTIFIER9 *d3dai = &va->d3dai;
  400.     if (FAILED(IDirect3D9_GetAdapterIdentifier(va->d3dobj,
  401.                                                D3DADAPTER_DEFAULT, 0, d3dai))) {
  402.         av_log(NULL, AV_LOG_WARNING, "IDirect3D9_GetAdapterIdentifier failed");
  403.         ZeroMemory(d3dai, sizeof(*d3dai));
  404.     }
  405.  
  406.     /* */
  407.     D3DPRESENT_PARAMETERS *d3dpp = &va->d3dpp;
  408.     ZeroMemory(d3dpp, sizeof(*d3dpp));
  409.     d3dpp->Flags                  = D3DPRESENTFLAG_VIDEO;
  410.     d3dpp->Windowed               = TRUE;
  411.     d3dpp->hDeviceWindow          = NULL;
  412.     d3dpp->SwapEffect             = D3DSWAPEFFECT_DISCARD;
  413.     d3dpp->MultiSampleType        = D3DMULTISAMPLE_NONE;
  414.     d3dpp->PresentationInterval   = D3DPRESENT_INTERVAL_DEFAULT;
  415.     d3dpp->BackBufferCount        = 0;                  /* FIXME what to put here */
  416.     d3dpp->BackBufferFormat       = D3DFMT_X8R8G8B8;    /* FIXME what to put here */
  417.     d3dpp->BackBufferWidth        = 0;
  418.     d3dpp->BackBufferHeight       = 0;
  419.     d3dpp->EnableAutoDepthStencil = FALSE;
  420.  
  421.     /* Direct3D needs a HWND to create a device, even without using ::Present
  422.     this HWND is used to alert Direct3D when there's a change of focus window.
  423.     For now, use GetShellWindow, as it looks harmless */
  424.     LPDIRECT3DDEVICE9 d3ddev;
  425.     if (FAILED(IDirect3D9_CreateDevice(d3dobj, D3DADAPTER_DEFAULT,
  426.                                        D3DDEVTYPE_HAL, GetShellWindow(),
  427.                                        D3DCREATE_SOFTWARE_VERTEXPROCESSING |
  428.                                        D3DCREATE_MULTITHREADED,
  429.                                        d3dpp, &d3ddev))) {
  430.         av_log(NULL, AV_LOG_ERROR, "IDirect3D9_CreateDevice failed\n");
  431.         return -1;
  432.     }
  433.     va->d3ddev = d3ddev;
  434.  
  435.     return 0;
  436. }
  437.  
  438. /**
  439.  * It releases a Direct3D device and its resources.
  440.  */
  441. static void D3dDestroyDevice(vlc_va_dxva2_t *va)
  442. {
  443.     if (va->d3ddev)
  444.         IDirect3DDevice9_Release(va->d3ddev);
  445.     if (va->d3dobj)
  446.         IDirect3D9_Release(va->d3dobj);
  447. }
  448.  
  449. /**
  450.  * It describes our Direct3D object
  451.  
  452. static char *DxDescribe(vlc_va_dxva2_t *va)
  453. {
  454.     static const struct {
  455.         unsigned id;
  456.         char     name[32];
  457.     } vendors [] = {
  458.         { 0x1002, "ATI" },
  459.         { 0x10DE, "NVIDIA" },
  460.         { 0x8086, "Intel" },
  461.         { 0x5333, "S3 Graphics" },
  462.         { 0, "" }
  463.     };
  464.     D3DADAPTER_IDENTIFIER9 *id = &va->d3dai;
  465.  
  466.     const char *vendor = "Unknown";
  467.     for (int i = 0; vendors[i].id != 0; i++) {
  468.         if (vendors[i].id == id->VendorId) {
  469.             vendor = vendors[i].name;
  470.             break;
  471.         }
  472.     }
  473.  
  474.     char *description;
  475.     if (asprintf(&description, "DXVA2 (%.*s, vendor %d(%s), device %d, revision %d)",
  476.                  sizeof(id->Description), id->Description,
  477.                  id->VendorId, vendor, id->DeviceId, id->Revision) < 0)
  478.         return NULL;
  479.     return description;
  480. }
  481. */
  482. /**
  483.  * It creates a Direct3D device manager
  484.  */
  485. static int D3dCreateDeviceManager(vlc_va_dxva2_t *va)
  486. {
  487.     typedef HRESULT (WINAPI *CreateDeviceManager9_func)(UINT *pResetToken, IDirect3DDeviceManager9 **);
  488.     CreateDeviceManager9_func CreateDeviceManager9 =
  489.         (CreateDeviceManager9_func)GetProcAddress(va->hdxva2_dll, TEXT("DXVA2CreateDirect3DDeviceManager9"));
  490.  
  491.     if (!CreateDeviceManager9) {
  492.         av_log(NULL, AV_LOG_ERROR, "cannot load function\n");
  493.         return -1;
  494.     }
  495.     av_log(NULL, AV_LOG_INFO, "OurDirect3DCreateDeviceManager9 Success!\n");
  496.  
  497.     UINT token;
  498.     IDirect3DDeviceManager9 *devmng;
  499.     if (FAILED(CreateDeviceManager9(&token, &devmng))) {
  500.         av_log(NULL, AV_LOG_ERROR, " OurDirect3DCreateDeviceManager9 failed\n");
  501.         return -1;
  502.     }
  503.    
  504.     HRESULT hr = devmng->ResetDevice(va->d3ddev, token);
  505.     if (FAILED(hr)) {
  506.         av_log(NULL, AV_LOG_ERROR, "IDirect3DDeviceManager9_ResetDevice failed: %08x", (unsigned)hr);
  507.         return -1;
  508.     }
  509.  
  510.     devmng->AddRef();
  511.     va->token  = token;
  512.     va->devmng = devmng;
  513.     av_log(NULL, AV_LOG_INFO, "obtained IDirect3DDeviceManager9\n");
  514.  
  515.     return 0;
  516. }
  517. /**
  518.  * It destroys a Direct3D device manager
  519.  */
  520. static void D3dDestroyDeviceManager(vlc_va_dxva2_t *va)
  521. {
  522.     if (va->devmng)
  523.         va->devmng->Release();
  524. }
  525.  
  526. /**
  527.  * It creates a DirectX video service
  528.  */
  529. static int DxCreateVideoService(vlc_va_dxva2_t *va)
  530. {
  531.     typedef HRESULT (WINAPI *CreateVideoService_func)(IDirect3DDevice9 *,
  532.                                          REFIID riid,
  533.                                          void **ppService);
  534.     CreateVideoService_func CreateVideoService =
  535.       (CreateVideoService_func)GetProcAddress(va->hdxva2_dll,
  536.                              TEXT("DXVA2CreateVideoService"));
  537.  
  538.     if (!CreateVideoService) {
  539.         av_log(NULL, AV_LOG_ERROR, "cannot load function\n");
  540.         return 4;
  541.     }
  542.     av_log(NULL, AV_LOG_INFO, "DXVA2CreateVideoService Success!\n");
  543.  
  544.     HRESULT hr;
  545.  
  546.     HANDLE device;
  547.     hr = va->devmng->OpenDeviceHandle(&device);
  548.     if (FAILED(hr)) {
  549.         av_log(NULL, AV_LOG_ERROR, "OpenDeviceHandle failed\n");
  550.         return -1;
  551.     }
  552.     va->device = device;
  553.  
  554.     IDirectXVideoDecoderService *vs;
  555.     hr = va->devmng->GetVideoService(device,
  556.                                      IID_IDirectXVideoDecoderService,
  557.                                      (void **)&vs);
  558.     if (FAILED(hr)) {
  559.         av_log(NULL, AV_LOG_ERROR, "GetVideoService failed\n");
  560.         return -1;
  561.     }
  562.     va->vs = vs;
  563.  
  564.     return 0;
  565. }
  566. /**
  567.  * It destroys a DirectX video service
  568.  */
  569. static void DxDestroyVideoService(vlc_va_dxva2_t *va)
  570. {
  571.     if (va->device)
  572.         va->devmng->CloseDeviceHandle(va->device);
  573.     if (va->vs)
  574.         va->vs->Release();
  575. }
  576. /**
  577.  * Find the best suited decoder mode GUID and render format.
  578.  */
  579. static int DxFindVideoServiceConversion(vlc_va_dxva2_t *va, GUID *input, D3DFORMAT *output)
  580. {
  581.     /* Retrieve supported modes from the decoder service */
  582.     UINT input_count = 0;
  583.     GUID *input_list = NULL;
  584.     if (FAILED(va->vs->GetDecoderDeviceGuids(&input_count, &input_list))) {
  585.         av_log(NULL, AV_LOG_ERROR, "IDirectXVideoDecoderService_GetDecoderDeviceGuids failed\n");
  586.         return -1;
  587.     }
  588.     for (unsigned i = 0; i < input_count; i++) {
  589.         const GUID &g = input_list[i];
  590.         const dxva2_mode_t *mode = Dxva2FindMode(g);
  591.         if (mode) {
  592.             av_log(NULL, AV_LOG_INFO, "- '%s' is supported by hardware\n", mode->name);
  593.         } else {
  594.             av_log(NULL, AV_LOG_WARNING, "- Unknown GUID = %08X-%04x-%04x-XXXX\n",
  595.                      (unsigned)g.Data1, g.Data2, g.Data3);
  596.         }
  597.     }
  598.  
  599.     /* Try all supported mode by our priority */
  600.     for (unsigned i = 0; dxva2_modes[i].name; i++) {
  601.         const dxva2_mode_t *mode = &dxva2_modes[i];
  602.         if (!mode->codec || mode->codec != va->codec_id)
  603.             continue;
  604.  
  605.         /* */
  606.         bool is_suported = false;
  607.         for (unsigned count = 0; !is_suported && count < input_count; count++) {
  608.             const GUID &g = input_list[count];
  609.             is_suported = IsEqualGUID(mode->guid, g) == 0;
  610.         }
  611.         if (!is_suported)
  612.             continue;
  613.  
  614.         /* */
  615.         av_log(NULL, AV_LOG_DEBUG, "Trying to use '%s' as input\n", mode->name);
  616.         UINT      output_count = 0;
  617.         D3DFORMAT *output_list = NULL;
  618.         if (FAILED(va->vs->GetDecoderRenderTargets( mode->guid,
  619.                                                     &output_count,
  620.                                                     &output_list))) {
  621.             av_log(NULL, AV_LOG_ERROR, "IDirectXVideoDecoderService_GetDecoderRenderTargets failed\n");
  622.             continue;
  623.         }
  624.         for (unsigned j = 0; j < output_count; j++) {
  625.             const D3DFORMAT f = output_list[j];
  626.             const d3d_format_t *format = D3dFindFormat(f);
  627.             if (format) {
  628.                 av_log(NULL, AV_LOG_DEBUG, "%s is supported for output\n", format->name);
  629.             } else {
  630.                 av_log(NULL, AV_LOG_DEBUG, "%d is supported for output (%4.4s)\n", f, (const char*)&f);
  631.             }
  632.         }
  633.  
  634.         /* */
  635.         for (unsigned j = 0; d3d_formats[j].name; j++) {
  636.             const d3d_format_t *format = &d3d_formats[j];
  637.  
  638.             /* */
  639.             bool is_suported = false;
  640.             for (unsigned k = 0; !is_suported && k < output_count; k++) {
  641.                 is_suported = format->format == output_list[k];
  642.             }
  643.             if (!is_suported)
  644.                 continue;
  645.  
  646.             /* We have our solution */
  647.             av_log(NULL, AV_LOG_DEBUG, "Using '%s' to decode to '%s'\n", mode->name, format->name);
  648.             *input  = mode->guid;
  649.             *output = format->format;
  650.             CoTaskMemFree(output_list);
  651.             CoTaskMemFree(input_list);
  652.             return 0;
  653.         }
  654.         CoTaskMemFree(output_list);
  655.     }
  656.     CoTaskMemFree(input_list);
  657.     return -1;
  658. }
  659.  
  660. /**
  661.  * It creates a DXVA2 decoder using the given video format
  662.  */
  663. static int DxCreateVideoDecoder(vlc_va_dxva2_t *va,
  664.                                 int codec_id, const video_format_t *fmt)
  665. {
  666.     /* */
  667.     av_log(NULL, AV_LOG_DEBUG, "DxCreateVideoDecoder id %d %dx%d\n",
  668.             codec_id, fmt->i_width, fmt->i_height);
  669.  
  670.     va->width  = fmt->i_width;
  671.     va->height = fmt->i_height;
  672.  
  673.     /* Allocates all surfaces needed for the decoder */
  674.     va->surface_width  = (fmt->i_width  + 15) & ~15;
  675.     va->surface_height = (fmt->i_height + 15) & ~15;
  676.     switch (codec_id) {
  677.     case CODEC_ID_H264:
  678.         va->surface_count = 16 + 1;
  679.         break;
  680.     default:
  681.         va->surface_count = 2 + 1;
  682.         break;
  683.     }
  684.     LPDIRECT3DSURFACE9 surface_list[VA_DXVA2_MAX_SURFACE_COUNT];
  685.     if (FAILED(va->vs->CreateSurface(va->surface_width,
  686.                                      va->surface_height,
  687.                                      va->surface_count - 1,
  688.                                      va->render,
  689.                                      D3DPOOL_DEFAULT,
  690.                                      0,
  691.                                      DXVA2_VideoDecoderRenderTarget,
  692.                                      surface_list,
  693.                                      NULL))) {
  694.         av_log(NULL, AV_LOG_ERROR, "IDirectXVideoAccelerationService_CreateSurface failed\n");
  695.         va->surface_count = 0;
  696.         return -1;
  697.     }
  698.     for (unsigned i = 0; i < va->surface_count; i++) {
  699.         vlc_va_surface_t *surface = &va->surface[i];
  700.         surface->d3d = surface_list[i];
  701.         surface->refcount = 0;
  702.         surface->order = 0;
  703.     }
  704.     av_log(NULL, AV_LOG_DEBUG, "IDirectXVideoAccelerationService_CreateSurface succeed with %d surfaces (%dx%d)\n",
  705.             va->surface_count, fmt->i_width, fmt->i_height);
  706.  
  707.     /* */
  708.     DXVA2_VideoDesc dsc;
  709.     ZeroMemory(&dsc, sizeof(dsc));
  710.     dsc.SampleWidth     = fmt->i_width;
  711.     dsc.SampleHeight    = fmt->i_height;
  712.     dsc.Format          = va->render;
  713.     if (fmt->i_frame_rate > 0 && fmt->i_frame_rate_base > 0) {
  714.         dsc.InputSampleFreq.Numerator   = fmt->i_frame_rate;
  715.         dsc.InputSampleFreq.Denominator = fmt->i_frame_rate_base;
  716.     } else {
  717.         dsc.InputSampleFreq.Numerator   = 0;
  718.         dsc.InputSampleFreq.Denominator = 0;
  719.     }
  720.     dsc.OutputFrameFreq = dsc.InputSampleFreq;
  721.     dsc.UABProtectionLevel = FALSE;
  722.     dsc.Reserved = 0;
  723.  
  724.     /* FIXME I am unsure we can let unknown everywhere */
  725.     DXVA2_ExtendedFormat *ext = &dsc.SampleFormat;
  726.     ext->SampleFormat = 0;//DXVA2_SampleUnknown;
  727.     ext->VideoChromaSubsampling = 0;//DXVA2_VideoChromaSubsampling_Unknown;
  728.     ext->NominalRange = 0;//DXVA2_NominalRange_Unknown;
  729.     ext->VideoTransferMatrix = 0;//DXVA2_VideoTransferMatrix_Unknown;
  730.     ext->VideoLighting = 0;//DXVA2_VideoLighting_Unknown;
  731.     ext->VideoPrimaries = 0;//DXVA2_VideoPrimaries_Unknown;
  732.     ext->VideoTransferFunction = 0;//DXVA2_VideoTransFunc_Unknown;
  733.  
  734.     /* List all configurations available for the decoder */
  735.     UINT                      cfg_count = 0;
  736.     DXVA2_ConfigPictureDecode *cfg_list = NULL;
  737.     if (FAILED(va->vs->GetDecoderConfigurations(va->input,
  738.                                                 &dsc,  
  739.                                                 NULL,
  740.                                                 &cfg_count,
  741.                                                 &cfg_list))) {
  742.         av_log(NULL, AV_LOG_ERROR, "IDirectXVideoDecoderService_GetDecoderConfigurations failed\n");
  743.         return -1;
  744.     }
  745.     av_log(NULL, AV_LOG_DEBUG, "we got %d decoder configurations\n", cfg_count);
  746.  
  747.     /* Select the best decoder configuration */
  748.     int cfg_score = 0;
  749.     for (unsigned i = 0; i < cfg_count; i++) {
  750.         const DXVA2_ConfigPictureDecode *cfg = &cfg_list[i];
  751.  
  752.         /* */
  753.         av_log(NULL, AV_LOG_DEBUG, "configuration[%d] ConfigBitstreamRaw %d\n",
  754.                 i, cfg->ConfigBitstreamRaw);
  755.  
  756.         /* */
  757.         int score;
  758.         if (cfg->ConfigBitstreamRaw == 1)
  759.             score = 1;
  760.         else if (codec_id == CODEC_ID_H264 && cfg->ConfigBitstreamRaw == 2)
  761.             score = 2;
  762.         else
  763.             continue;
  764.         if (IsEqualGUID(cfg->guidConfigBitstreamEncryption, DXVA_NoEncrypt))
  765.             score += 16;
  766.  
  767.         if (cfg_score < score) {
  768.             va->cfg = *cfg;
  769.             cfg_score = score;
  770.         }
  771.     }
  772.     CoTaskMemFree(cfg_list);
  773.     if (cfg_score <= 0) {
  774.         av_log(NULL, AV_LOG_ERROR, "Failed to find a supported decoder configuration\n");
  775.         return -1;
  776.     }
  777.  
  778.     /* Create the decoder */
  779.     IDirectXVideoDecoder *decoder;
  780.     if (FAILED(va->vs->CreateVideoDecoder(va->input,
  781.                                           &dsc,
  782.                                           &va->cfg,
  783.                                           surface_list,
  784.                                           va->surface_count,
  785.                                           &decoder))) {
  786.         av_log(NULL, AV_LOG_ERROR, "IDirectXVideoDecoderService_CreateVideoDecoder failed\n");
  787.         return -1;
  788.     }
  789.     va->decoder = decoder;
  790.     av_log(NULL, AV_LOG_DEBUG, "IDirectXVideoDecoderService_CreateVideoDecoder succeed\n");
  791.     return 0;
  792. }
  793. static void DxDestroyVideoDecoder(vlc_va_dxva2_t *va)
  794. {
  795.     if (va->decoder)
  796.         va->decoder->Release();
  797.     va->decoder = NULL;
  798.  
  799.     for (unsigned i = 0; i < va->surface_count; i++)
  800.         va->surface[i].d3d->Release();
  801.     va->surface_count = 0;
  802. }
  803.  
  804. static int DxResetVideoDecoder(vlc_va_dxva2_t *va)
  805. {
  806.     av_log(NULL, AV_LOG_ERROR, "DxResetVideoDecoder unimplemented\n");
  807.     return -1;
  808. }
  809.  
  810. static void DxCreateVideoConversion(vlc_va_dxva2_t *va)
  811. {
  812.     switch (va->render) {
  813.     case MAKEFOURCC('N','V','1','2'):
  814.         va->output = (D3DFORMAT)MAKEFOURCC('Y','V','1','2');
  815.         break;
  816.     default:
  817.         va->output = va->render;
  818.         break;
  819.     }
  820. //    CopyInitCache(&va->surface_cache, va->surface_width);
  821. }
  822. static void DxDestroyVideoConversion(vlc_va_dxva2_t *va)
  823. {
  824. //    CopyCleanCache(&va->surface_cache);
  825. }
  826.  
  827. static int Setup(vlc_va_dxva2_t *external, void **hw, PixelFormat *chroma,
  828.     int width, int height)
  829. {
  830.     vlc_va_dxva2_t *va = external;
  831.  
  832.     if (va->width == width && va->height == height && va->decoder)
  833.         goto ok;
  834.  
  835.     /* */
  836.     DxDestroyVideoConversion(va);
  837.     DxDestroyVideoDecoder(va);
  838.  
  839.     *chroma = PIX_FMT_NONE;
  840.     if (width <= 0 || height <= 0)
  841.         return -1;
  842.  
  843.     /* FIXME transmit a video_format_t by VaSetup directly */
  844.     video_format_t fmt;
  845.     memset(&fmt, 0, sizeof(fmt));
  846.     fmt.i_width = width;
  847.     fmt.i_height = height;
  848.  
  849.     if (DxCreateVideoDecoder(va, va->codec_id, &fmt))
  850.         return -1;
  851.     /* */
  852.     va->hw.decoder = va->decoder;
  853.     va->hw.cfg = &va->cfg;
  854.     va->hw.surface_count = va->surface_count;
  855.     va->hw.surface = va->hw_surface;
  856.     for (unsigned i = 0; i < va->surface_count; i++)
  857.         va->hw.surface[i] = va->surface[i].d3d;
  858.  
  859.     /* */
  860.     DxCreateVideoConversion(va);
  861.  
  862.     /* */
  863. ok:
  864.     *hw = &va->hw;
  865.     const d3d_format_t *output = D3dFindFormat(va->output);
  866.     *chroma = output->codec;
  867.  
  868.     return 0;
  869. }
  870.  
  871. static int Get(vlc_va_dxva2_t *external, AVFrame *ff)
  872. {
  873.     vlc_va_dxva2_t *va = external;
  874.  
  875.     /* Check the device */
  876.     HRESULT hr = va->devmng->TestDevice(va->device);
  877.     if (hr == DXVA2_E_NEW_VIDEO_DEVICE) {
  878.         if (DxResetVideoDecoder(va))
  879.             return -1;
  880.     } else if (FAILED(hr)) {
  881.         av_log(NULL, AV_LOG_ERROR, "IDirect3DDeviceManager9_TestDevice %u", (unsigned)hr);
  882.         return -1;
  883.     }
  884.  
  885.     /* Grab an unused surface, in case none are, try the oldest
  886.      * XXX using the oldest is a workaround in case a problem happens with ffmpeg */
  887.     unsigned i, old;
  888.     for (i = 0, old = 0; i < va->surface_count; i++) {
  889.         vlc_va_surface_t *surface = &va->surface[i];
  890.  
  891.         if (!surface->refcount)
  892.             break;
  893.  
  894.         if (surface->order < va->surface[old].order)
  895.             old = i;
  896.     }
  897.     if (i >= va->surface_count)
  898.         i = old;
  899.  
  900.     vlc_va_surface_t *surface = &va->surface[i];
  901.  
  902.     surface->refcount = 1;
  903.     surface->order = va->surface_order++;
  904.  
  905.     /* */
  906.     for (int i = 0; i < 4; i++) {
  907.         ff->data[i] = NULL;
  908.         ff->linesize[i] = 0;
  909.  
  910.         if (i == 0 || i == 3)
  911.             ff->data[i] = (uint8_t *)surface->d3d;/* Yummie */
  912.     }
  913.     return 0;
  914. }
  915.  
  916. static void Release(vlc_va_dxva2_t *external, AVFrame *ff)
  917. {
  918.     vlc_va_dxva2_t *va = external;
  919.     LPDIRECT3DSURFACE9 d3d = (LPDIRECT3DSURFACE9)(uintptr_t)ff->data[3];
  920.  
  921.     for (unsigned i = 0; i < va->surface_count; i++) {
  922.         vlc_va_surface_t *surface = &va->surface[i];
  923.  
  924.         if (surface->d3d == d3d)
  925.             surface->refcount--;
  926.     }
  927. }
  928.  
  929. /*****************************************************************************
  930.  * ffmpeg_GetFrameBuf: callback used by ffmpeg to get a frame buffer.
  931.  *****************************************************************************
  932.  * It is used for direct rendering as well as to get the right PTS for each
  933.  * decoded picture (even in indirect rendering mode).
  934.  *****************************************************************************/
  935. static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
  936.                                AVFrame *p_ff_pic )
  937. {
  938.     vlc_va_dxva2_t *va = (vlc_va_dxva2_t *)p_context->opaque;
  939.  
  940.     /* */
  941.     p_ff_pic->reordered_opaque = p_context->reordered_opaque;
  942.     p_ff_pic->opaque = NULL;
  943.  
  944.     PixelFormat chroma;
  945.     if( va )
  946.     {
  947.         /* hwaccel_context is not present in old ffmpeg version */
  948.         if( Setup( va,
  949.                    &p_context->hwaccel_context, &chroma,
  950.                     p_context->width, p_context->height ) )
  951.         {
  952.             av_log(NULL, AV_LOG_ERROR, "vlc_va_Setup failed" );
  953.             return -1;
  954.         }
  955.  
  956.         /* */
  957.         p_ff_pic->type = FF_BUFFER_TYPE_USER;
  958.  
  959.         /* FIXME what is that, should give good value */
  960.         p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg
  961.  
  962.         if( Get( va, p_ff_pic ) )
  963.         {
  964.             av_log(NULL, AV_LOG_ERROR, "VaGrabSurface failed" );
  965.             return -1;
  966.         }
  967.         return 0;
  968.     }
  969.     else if( /*!p_sys->b_direct_rendering*/ 1 )
  970.     {
  971.         /* Not much to do in indirect rendering mode. */
  972.         return avcodec_default_get_buffer( p_context, p_ff_pic );
  973.     }
  974. }
  975.  
  976. static int  ffmpeg_ReGetFrameBuf( struct AVCodecContext *p_context, AVFrame *p_ff_pic )
  977. {
  978.     p_ff_pic->reordered_opaque = p_context->reordered_opaque;
  979.  
  980.     /* We always use default reget function, it works perfectly fine */
  981.     return avcodec_default_reget_buffer( p_context, p_ff_pic );
  982. }
  983.  
  984. static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context,
  985.                                     AVFrame *p_ff_pic )
  986. {
  987.     vlc_va_dxva2_t *va = (vlc_va_dxva2_t *)p_context->opaque;
  988.  
  989.     if( va )
  990.     {
  991.         Release( va, p_ff_pic );
  992.     }
  993.     else if( !p_ff_pic->opaque )
  994.     {
  995.         /* We can end up here without the AVFrame being allocated by
  996.          * avcodec_default_get_buffer() if VA is used and the frame is
  997.          * released when the decoder is closed
  998.          */
  999.         if( p_ff_pic->type == FF_BUFFER_TYPE_INTERNAL )
  1000.             avcodec_default_release_buffer( p_context, p_ff_pic );
  1001.     }
  1002.     for( int i = 0; i < 4; i++ )
  1003.         p_ff_pic->data[i] = NULL;
  1004. }
  1005.  
  1006. static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *p_context,
  1007.                                           const enum PixelFormat *pi_fmt )
  1008. {
  1009.     vlc_va_dxva2_t *va = (vlc_va_dxva2_t *)p_context->opaque;
  1010.  
  1011.     if( va )
  1012.     {
  1013.         Close( va );
  1014.         va = NULL;
  1015.     }
  1016.  
  1017.     /* Try too look for a supported hw acceleration */
  1018.     for( int i = 0; pi_fmt[i] != PIX_FMT_NONE; i++ )
  1019.     {
  1020.         static const char *ppsz_name[PIX_FMT_NB] = {NULL};
  1021.         ppsz_name[PIX_FMT_VDPAU_H264] = "PIX_FMT_VDPAU_H264";
  1022.         ppsz_name[PIX_FMT_VAAPI_IDCT] = "PIX_FMT_VAAPI_IDCT";
  1023.         ppsz_name[PIX_FMT_VAAPI_VLD] = "PIX_FMT_VAAPI_VLD";
  1024.         ppsz_name[PIX_FMT_VAAPI_MOCO] = "PIX_FMT_VAAPI_MOCO";
  1025.         ppsz_name[PIX_FMT_DXVA2_VLD] = "PIX_FMT_DXVA2_VLD";
  1026.         ppsz_name[PIX_FMT_YUYV422] = "PIX_FMT_YUYV422";
  1027.         ppsz_name[PIX_FMT_YUV420P] = "PIX_FMT_YUV420P";
  1028.  
  1029.         av_log(p_context, AV_LOG_DEBUG, "Available decoder output format %d (%s)\n", pi_fmt[i], ppsz_name[pi_fmt[i]] ? ppsz_name[pi_fmt[i]] : "Unknown" );
  1030.  
  1031.         /* Only VLD supported */
  1032.         if( pi_fmt[i] == PIX_FMT_DXVA2_VLD )
  1033.         {
  1034.             av_log(p_context, AV_LOG_DEBUG, "Trying DXVA2\n" );
  1035.             va = vlc_va_NewDxva2( p_context->codec_id );
  1036.             if( !va )
  1037.                 av_log(NULL, AV_LOG_ERROR, "Failed to open DXVA2\n" );
  1038.         }
  1039.  
  1040.         if( va &&
  1041.             p_context->width > 0 && p_context->height > 0 )
  1042.         {
  1043.             /* We try to call vlc_va_Setup when possible to detect errors when
  1044.              * possible (later is too late) */
  1045.             if( Setup( va,
  1046.                        &p_context->hwaccel_context,
  1047.                        &p_context->pix_fmt,
  1048.                         p_context->width, p_context->height ) )
  1049.             {
  1050.                 av_log(NULL, AV_LOG_ERROR, "vlc_va_Setup failed\n" );
  1051.                 Close( va );
  1052.                 va = NULL;
  1053.             }
  1054.         }
  1055.  
  1056.         if( va )
  1057.         {
  1058. //             if( va->description )
  1059. //                 msg_Info( p_dec, "Using %s for hardware decoding.", p_sys->p_va->description );
  1060.  
  1061.             /* FIXME this will disabled direct rendering
  1062.              * even if a new pixel format is renegotiated
  1063.              */
  1064.             p_context->draw_horiz_band = NULL;
  1065.             p_context->opaque = va;
  1066.             return pi_fmt[i];
  1067.         }
  1068.     }
  1069.  
  1070.     /* Fallback to default behaviour */
  1071.     return avcodec_default_get_format( p_context, pi_fmt );
  1072. }
  1073.  
  1074. int main(void)
  1075. {const char *filename = "D:\\wl\\SOBG\\hwdecode\\rec1.mov";
  1076.  int setup_hwdecode = 0;
  1077.  
  1078.     av_register_all();
  1079.     av_log_set_level(AV_LOG_DEBUG);
  1080.    
  1081.     AVFormatContext *fc = NULL;
  1082.     int res = avformat_open_input(&fc, filename, NULL, NULL);
  1083.     if (res < 0) {
  1084.         printf("error %x in avformat_open_input\n", res);
  1085.         return 1;
  1086.     }
  1087.  
  1088.     res = avformat_find_stream_info(fc, NULL);
  1089.     if (res < 0) {
  1090.         printf("error %x in avformat_find_stream_info\n", res);
  1091.         return 1;
  1092.     }
  1093.  
  1094.     av_dump_format(fc, 0, filename, 0);
  1095.  
  1096.     AVCodec *codec = avcodec_find_decoder(fc->streams[0]->codec->codec_id);
  1097.     if(!codec) {
  1098.         printf("decoder not found\n");
  1099.         return 1;
  1100.     }
  1101.  
  1102.     AVCodecContext *codecctx = fc->streams[0]->codec;
  1103.  
  1104.     vlc_va_dxva2_t *dxva = vlc_va_NewDxva2(codecctx->codec_id);
  1105.     res = Setup(dxva, &codecctx->hwaccel_context, &codecctx->pix_fmt, codecctx->width, codecctx->height);
  1106.  
  1107.     if (res < 0) {
  1108.         printf("error DXVA setup\n", res);
  1109.         return 1;
  1110.     }
  1111.     codecctx->opaque = dxva;
  1112.     codecctx->get_format = ffmpeg_GetFormat;
  1113.     codecctx->get_buffer = ffmpeg_GetFrameBuf;
  1114.     codecctx->reget_buffer = ffmpeg_ReGetFrameBuf;
  1115.     codecctx->release_buffer = ffmpeg_ReleaseFrameBuf;
  1116.  
  1117.     res = avcodec_open2(codecctx, codec, NULL);
  1118.     if (res < 0) {
  1119.         printf("error %x in avcodec_open2\n", res);
  1120.         return 1;
  1121.     }
  1122.  
  1123.     AVPacket pkt;
  1124.     AVFrame *picture = avcodec_alloc_frame();
  1125.     int packet_number = 0;
  1126.     DWORD start_time = timeGetTime();
  1127.     printf("start decoding, time = %d\n", start_time);
  1128.     while(av_read_frame(fc, &pkt) == 0) {
  1129.         int got_picture = 0;
  1130.         int bytes_used = avcodec_decode_video2(codecctx, picture, &got_picture, &pkt);
  1131.         av_free_packet(&pkt);
  1132.         if((++packet_number % 1000) == 0)
  1133.             printf("decoded_packet # %d\n", packet_number);
  1134. //      Sleep(40);
  1135.     }
  1136.     DWORD stop_time = timeGetTime();
  1137.     printf("end decoding time = %d\n", stop_time);
  1138.     printf("time difference = %d\n", stop_time - start_time);
  1139.  
  1140.     av_free(picture);
  1141.  
  1142.     av_close_input_file(fc);
  1143.    
  1144.  
  1145.     return 0;
  1146. }
  1147.    
  1148.  
RAW Paste Data