[release] version bump to 13.0 beta1
[vuplus_xbmc] / xbmc / cores / dvdplayer / DVDCodecs / Video / DXVA.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #ifdef HAS_DX
22
23 // setting that here because otherwise SampleFormat is defined to AVSampleFormat
24 // which we don't use here
25 #define FF_API_OLD_SAMPLE_FMT 0
26
27 #include <windows.h>
28 #include <d3d9.h>
29 #include <Initguid.h>
30 #include <dxva.h>
31 #include <dxva2api.h>
32 #include "libavcodec/dxva2.h"
33 #include "../DVDCodecUtils.h"
34
35 #include "DXVA.h"
36 #include "windowing/WindowingFactory.h"
37 #include "../../../VideoRenderers/WinRenderer.h"
38 #include "settings/Settings.h"
39 #include "settings/MediaSettings.h"
40 #include "boost/shared_ptr.hpp"
41 #include "utils/AutoPtrHandle.h"
42 #include "utils/StringUtils.h"
43 #include "settings/AdvancedSettings.h"
44 #include "settings/MediaSettings.h"
45 #include "cores/VideoRenderers/RenderManager.h"
46 #include "win32/WIN32Util.h"
47
48 #define ALLOW_ADDING_SURFACES 0
49
50 using namespace DXVA;
51 using namespace AUTOPTR;
52 using namespace std;
53
54 typedef HRESULT (__stdcall *DXVA2CreateVideoServicePtr)(IDirect3DDevice9* pDD, REFIID riid, void** ppService);
55 static DXVA2CreateVideoServicePtr g_DXVA2CreateVideoService;
56
57 static bool LoadDXVA()
58 {
59   static CCriticalSection g_section;
60   static HMODULE          g_handle;
61
62   CSingleLock lock(g_section);
63   if(g_handle == NULL)
64     g_handle = LoadLibraryEx("dxva2.dll", NULL, 0);
65   if(g_handle == NULL)
66     return false;
67   g_DXVA2CreateVideoService = (DXVA2CreateVideoServicePtr)GetProcAddress(g_handle, "DXVA2CreateVideoService");
68   if(g_DXVA2CreateVideoService == NULL)
69     return false;
70   return true;
71 }
72
73
74
75 static void RelBufferS(AVCodecContext *avctx, AVFrame *pic)
76 { ((CDecoder*)((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetHardware())->RelBuffer(avctx, pic); }
77
78 static int GetBufferS(AVCodecContext *avctx, AVFrame *pic) 
79 {  return ((CDecoder*)((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetHardware())->GetBuffer(avctx, pic); }
80
81
82 DEFINE_GUID(DXVADDI_Intel_ModeH264_A, 0x604F8E64,0x4951,0x4c54,0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6);
83 DEFINE_GUID(DXVADDI_Intel_ModeH264_C, 0x604F8E66,0x4951,0x4c54,0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6);
84 DEFINE_GUID(DXVADDI_Intel_ModeH264_E, 0x604F8E68,0x4951,0x4c54,0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6);
85 DEFINE_GUID(DXVADDI_Intel_ModeVC1_E , 0xBCC5DB6D,0xA2B6,0x4AF0,0xAC,0xE4,0xAD,0xB1,0xF7,0x87,0xBC,0x89);
86
87 #if _MSC_VER < 1700
88 DEFINE_GUID(DXVA_ModeMPEG2and1_VLD,   0x86695f12,0x340e,0x4f04,0x9f,0xd3,0x92,0x53,0xdd,0x32,0x74,0x60);
89 // When exposed by an accelerator, indicates compliance with the August 2010 spec update
90 DEFINE_GUID(DXVA_ModeVC1_D2010,       0x1b81beA4,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
91 #endif
92
93 typedef struct {
94     const char   *name;
95     const GUID   *guid;
96     int          codec;
97 } dxva2_mode_t;
98
99 /* XXX Prefered modes must come first */
100 static const dxva2_mode_t dxva2_modes[] = {
101     { "MPEG2 VLD",    &DXVA2_ModeMPEG2_VLD,     AV_CODEC_ID_MPEG2VIDEO },
102     { "MPEG1/2 VLD",  &DXVA_ModeMPEG2and1_VLD,  AV_CODEC_ID_MPEG2VIDEO },
103     { "MPEG2 MoComp", &DXVA2_ModeMPEG2_MoComp,  0 },
104     { "MPEG2 IDCT",   &DXVA2_ModeMPEG2_IDCT,    0 },
105
106     // Intel drivers return standard modes in addition to the Intel specific ones. Try the Intel specific first, they work better for Sandy Bridges.
107     { "Intel H.264 VLD, no FGT",                                      &DXVADDI_Intel_ModeH264_E, AV_CODEC_ID_H264 },
108     { "Intel H.264 inverse discrete cosine transform (IDCT), no FGT", &DXVADDI_Intel_ModeH264_C, 0 },
109     { "Intel H.264 motion compensation (MoComp), no FGT",             &DXVADDI_Intel_ModeH264_A, 0 },
110     { "Intel VC-1 VLD",                                               &DXVADDI_Intel_ModeVC1_E,  0 },
111
112     { "H.264 variable-length decoder (VLD), FGT",               &DXVA2_ModeH264_F, AV_CODEC_ID_H264 },
113     { "H.264 VLD, no FGT",                                      &DXVA2_ModeH264_E, AV_CODEC_ID_H264 },
114     { "H.264 IDCT, FGT",                                        &DXVA2_ModeH264_D, 0,            },
115     { "H.264 inverse discrete cosine transform (IDCT), no FGT", &DXVA2_ModeH264_C, 0,            },
116     { "H.264 MoComp, FGT",                                      &DXVA2_ModeH264_B, 0,            },
117     { "H.264 motion compensation (MoComp), no FGT",             &DXVA2_ModeH264_A, 0,            },
118
119     { "Windows Media Video 8 MoComp",           &DXVA2_ModeWMV8_B, 0 },
120     { "Windows Media Video 8 post processing",  &DXVA2_ModeWMV8_A, 0 },
121
122     { "Windows Media Video 9 IDCT",             &DXVA2_ModeWMV9_C, 0 },
123     { "Windows Media Video 9 MoComp",           &DXVA2_ModeWMV9_B, 0 },
124     { "Windows Media Video 9 post processing",  &DXVA2_ModeWMV9_A, 0 },
125
126     { "VC-1 VLD",             &DXVA2_ModeVC1_D,    AV_CODEC_ID_VC1 },
127     { "VC-1 VLD",             &DXVA2_ModeVC1_D,    AV_CODEC_ID_WMV3 },
128     { "VC-1 VLD 2010",        &DXVA_ModeVC1_D2010, AV_CODEC_ID_VC1 },
129     { "VC-1 VLD 2010",        &DXVA_ModeVC1_D2010, AV_CODEC_ID_WMV3 },
130     { "VC-1 IDCT",            &DXVA2_ModeVC1_C,    0 },
131     { "VC-1 MoComp",          &DXVA2_ModeVC1_B,    0 },
132     { "VC-1 post processing", &DXVA2_ModeVC1_A,    0 },
133
134     { NULL, NULL, 0 }
135 };
136
137 DEFINE_GUID(DXVA2_VideoProcATIVectorAdaptiveDevice,   0x3C5323C1,0x6fb7,0x44f5,0x90,0x81,0x05,0x6b,0xf2,0xee,0x44,0x9d);
138 DEFINE_GUID(DXVA2_VideoProcATIMotionAdaptiveDevice,   0x552C0DAD,0xccbc,0x420b,0x83,0xc8,0x74,0x94,0x3c,0xf9,0xf1,0xa6);
139 DEFINE_GUID(DXVA2_VideoProcATIAdaptiveDevice,         0x6E8329FF,0xb642,0x418b,0xbc,0xf0,0xbc,0xb6,0x59,0x1e,0x25,0x5f);
140 DEFINE_GUID(DXVA2_VideoProcNVidiaAdaptiveDevice,      0x6CB69578,0x7617,0x4637,0x91,0xE5,0x1C,0x02,0xDB,0x81,0x02,0x85);
141 DEFINE_GUID(DXVA2_VideoProcIntelEdgeDevice,           0xBF752EF6,0x8CC4,0x457A,0xBE,0x1B,0x08,0xBD,0x1C,0xAE,0xEE,0x9F);
142 DEFINE_GUID(DXVA2_VideoProcNVidiaUnknownDevice,       0xF9F19DA5,0x3B09,0x4B2F,0x9D,0x89,0xC6,0x47,0x53,0xE3,0xEA,0xAB);
143
144 typedef struct {
145     const char   *name;
146     const GUID   *guid;
147 } dxva2_device_t;
148
149 static const dxva2_device_t dxva2_devices[] = {
150   { "Progressive Device",           &DXVA2_VideoProcProgressiveDevice         },
151   { "Bob Device",                   &DXVA2_VideoProcBobDevice                 },
152   { "Vector Adaptative Device",     &DXVA2_VideoProcATIVectorAdaptiveDevice   },
153   { "Motion Adaptative Device",     &DXVA2_VideoProcATIMotionAdaptiveDevice   },
154   { "Adaptative Device",            &DXVA2_VideoProcATIAdaptiveDevice         },
155   { "Spatial-temporal device",      &DXVA2_VideoProcNVidiaAdaptiveDevice      },
156   { "Edge directed device",         &DXVA2_VideoProcIntelEdgeDevice           },
157   { "Unknown device (nVidia)",      &DXVA2_VideoProcNVidiaUnknownDevice       },
158   { NULL, NULL }
159 };
160
161 typedef struct {
162     const char   *name;
163     unsigned      flags;
164 } dxva2_deinterlacetech_t;
165
166 static const dxva2_deinterlacetech_t dxva2_deinterlacetechs[] = {
167   { "Inverse Telecine",                   DXVA2_DeinterlaceTech_InverseTelecine        },
168   { "Motion vector steered",              DXVA2_DeinterlaceTech_MotionVectorSteered    },
169   { "Pixel adaptive",                     DXVA2_DeinterlaceTech_PixelAdaptive          },
170   { "Field adaptive",                     DXVA2_DeinterlaceTech_FieldAdaptive          },
171   { "Edge filtering",                     DXVA2_DeinterlaceTech_EdgeFiltering          },
172   { "Median filtering",                   DXVA2_DeinterlaceTech_MedianFiltering        },
173   { "Bob vertical stretch 4-tap",         DXVA2_DeinterlaceTech_BOBVerticalStretch4Tap },
174   { "Bob vertical stretch",               DXVA2_DeinterlaceTech_BOBVerticalStretch     },
175   { "Bob line replicate",                 DXVA2_DeinterlaceTech_BOBLineReplicate       },
176   { "Unknown",                            DXVA2_DeinterlaceTech_Unknown                },
177   { NULL, 0 }
178 };
179
180
181 // Prefered targets must be first
182 static const D3DFORMAT render_targets[] = {
183     (D3DFORMAT)MAKEFOURCC('N','V','1','2'),
184     (D3DFORMAT)MAKEFOURCC('Y','V','1','2'),
185     D3DFMT_UNKNOWN
186 };
187
188 // List of PCI Device ID of ATI cards with UVD or UVD+ decoding block.
189 static DWORD UVDDeviceID [] = {
190   0x95C0, // ATI Radeon HD 3400 Series (and others)
191   0x95C5, // ATI Radeon HD 3400 Series (and others)
192   0x95C4, // ATI Radeon HD 3400 Series (and others)
193   0x94C3, // ATI Radeon HD 3410
194   0x9589, // ATI Radeon HD 3600 Series (and others)
195   0x9598, // ATI Radeon HD 3600 Series (and others)
196   0x9591, // ATI Radeon HD 3600 Series (and others)
197   0x9501, // ATI Radeon HD 3800 Series (and others)
198   0x9505, // ATI Radeon HD 3800 Series (and others)
199   0x9507, // ATI Radeon HD 3830
200   0x9513, // ATI Radeon HD 3850 X2
201   0x950F, // ATI Radeon HD 3850 X2
202   0x0000
203 };
204
205 // List of PCI Device ID of nVidia cards with the macroblock width issue. More or less the VP3 block.
206 // Per NVIDIA Accelerated Linux Graphics Driver, Appendix A Supported NVIDIA GPU Products, cards with note 1.
207 static DWORD VP3DeviceID [] = {
208   0x06E0, // GeForce 9300 GE
209   0x06E1, // GeForce 9300 GS
210   0x06E2, // GeForce 8400
211   0x06E4, // GeForce 8400 GS
212   0x06E5, // GeForce 9300M GS
213   0x06E6, // GeForce G100
214   0x06E8, // GeForce 9200M GS
215   0x06E9, // GeForce 9300M GS
216   0x06EC, // GeForce G 105M
217   0x06EF, // GeForce G 103M
218   0x06F1, // GeForce G105M
219   0x0844, // GeForce 9100M G
220   0x0845, // GeForce 8200M G
221   0x0846, // GeForce 9200
222   0x0847, // GeForce 9100
223   0x0848, // GeForce 8300
224   0x0849, // GeForce 8200
225   0x084A, // nForce 730a
226   0x084B, // GeForce 9200
227   0x084C, // nForce 980a/780a SLI
228   0x084D, // nForce 750a SLI
229   0x0860, // GeForce 9400
230   0x0861, // GeForce 9400
231   0x0862, // GeForce 9400M G
232   0x0863, // GeForce 9400M
233   0x0864, // GeForce 9300
234   0x0865, // ION
235   0x0866, // GeForce 9400M G
236   0x0867, // GeForce 9400
237   0x0868, // nForce 760i SLI
238   0x086A, // GeForce 9400
239   0x086C, // GeForce 9300 / nForce 730i
240   0x086D, // GeForce 9200
241   0x086E, // GeForce 9100M G
242   0x086F, // GeForce 8200M G
243   0x0870, // GeForce 9400M
244   0x0871, // GeForce 9200
245   0x0872, // GeForce G102M
246   0x0873, // GeForce G102M
247   0x0874, // ION
248   0x0876, // ION
249   0x087A, // GeForce 9400
250   0x087D, // ION
251   0x087E, // ION LE
252   0x087F, // ION LE
253   0x0000
254 };
255
256 typedef struct {
257     DWORD VendorID;
258     DWORD DeviceID;
259 } pci_device;
260
261 // List of devices that drop frames with a deinterlacing processor for progressive material.
262 static const pci_device NoDeintProcForProgDevices[] = {
263   { PCIV_nVidia, 0x0865 }, // ION
264   { PCIV_nVidia, 0x0874 }, // ION
265   { PCIV_nVidia, 0x0876 }, // ION
266   { PCIV_nVidia, 0x087D }, // ION
267   { PCIV_nVidia, 0x087E }, // ION LE
268   { PCIV_nVidia, 0x087F }, // ION LE
269   { 0          , 0x0000 }
270 };
271
272 static CStdString GUIDToString(const GUID& guid)
273 {
274   CStdString buffer = StringUtils::Format("%08X-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"
275               , guid.Data1, guid.Data2, guid.Data3
276               , guid.Data4[0], guid.Data4[1]
277               , guid.Data4[2], guid.Data4[3], guid.Data4[4]
278               , guid.Data4[5], guid.Data4[6], guid.Data4[7]);
279   return buffer;
280 }
281
282 static const dxva2_mode_t *dxva2_find_mode(const GUID *guid)
283 {
284     for (unsigned i = 0; dxva2_modes[i].name; i++) {
285         if (IsEqualGUID(*dxva2_modes[i].guid, *guid))
286             return &dxva2_modes[i];
287     }
288     return NULL;
289 }
290
291 static const dxva2_device_t *dxva2_find_device(const GUID *guid)
292 {
293     for (unsigned i = 0; dxva2_devices[i].name; i++) {
294         if (IsEqualGUID(*dxva2_devices[i].guid, *guid))
295             return &dxva2_devices[i];
296     }
297     return NULL;
298 }
299
300 static const dxva2_deinterlacetech_t *dxva2_find_deinterlacetech(unsigned flags)
301 {
302     for (unsigned i = 0; dxva2_deinterlacetechs[i].name; i++) {
303         if (dxva2_deinterlacetechs[i].flags == flags)
304             return &dxva2_deinterlacetechs[i];
305     }
306     return NULL;
307 }
308
309 #define SCOPE(type, var) boost::shared_ptr<type> var##_holder(var, CoTaskMemFree);
310
311 CSurfaceContext::CSurfaceContext()
312 {
313 }
314
315 CSurfaceContext::~CSurfaceContext()
316 {
317   for (vector<IDirect3DSurface9*>::iterator it = m_heldsurfaces.begin(); it != m_heldsurfaces.end(); ++it)
318     SAFE_RELEASE(*it);
319 }
320
321 void CSurfaceContext::HoldSurface(IDirect3DSurface9* surface)
322 {
323   surface->AddRef();
324   m_heldsurfaces.push_back(surface);
325 }
326
327 CDecoder::SVideoBuffer::SVideoBuffer()
328 {
329   surface = NULL;
330   Clear();
331 }
332
333 CDecoder::SVideoBuffer::~SVideoBuffer()
334 {
335   Clear();
336 }
337
338 void CDecoder::SVideoBuffer::Clear()
339 {
340   SAFE_RELEASE(surface);
341   age     = 0;
342   used    = 0;
343 }
344
345 CDecoder::CDecoder()
346  : m_event(true)
347 {
348   m_event.Set();
349   m_state     = DXVA_OPEN;
350   m_service   = NULL;
351   m_device    = NULL;
352   m_decoder   = NULL;
353   m_buffer_count = 0;
354   m_buffer_age   = 0;
355   m_refs         = 0;
356   m_shared       = 0;
357   m_surface_context = NULL;
358   memset(&m_format, 0, sizeof(m_format));
359   m_context          = (dxva_context*)calloc(1, sizeof(dxva_context));
360   m_context->cfg     = (DXVA2_ConfigPictureDecode*)calloc(1, sizeof(DXVA2_ConfigPictureDecode));
361   m_context->surface = (IDirect3DSurface9**)calloc(m_buffer_max, sizeof(IDirect3DSurface9*));
362   g_Windowing.Register(this);
363 }
364
365 CDecoder::~CDecoder()
366 {
367   g_Windowing.Unregister(this);
368   Close();
369   free(m_context->surface);
370   free(const_cast<DXVA2_ConfigPictureDecode*>(m_context->cfg)); // yes this is foobar
371   free(m_context);
372 }
373
374 void CDecoder::Close()
375 {
376   CSingleLock lock(m_section);
377   SAFE_RELEASE(m_decoder);
378   SAFE_RELEASE(m_service);
379   SAFE_RELEASE(m_surface_context);
380   for(unsigned i = 0; i < m_buffer_count; i++)
381     m_buffer[i].Clear();
382   m_buffer_count = 0;
383   memset(&m_format, 0, sizeof(m_format));
384 }
385
386 #define CHECK(a) \
387 do { \
388   HRESULT res = a; \
389   if(FAILED(res)) \
390   { \
391     CLog::Log(LOGERROR, "DXVA - failed executing "#a" at line %d with error %x", __LINE__, res); \
392     return false; \
393   } \
394 } while(0);
395
396 static bool CheckH264L41(AVCodecContext *avctx)
397 {
398     unsigned widthmbs  = (avctx->coded_width + 15) / 16;  // width in macroblocks
399     unsigned heightmbs = (avctx->coded_height + 15) / 16; // height in macroblocks
400     unsigned maxdpbmbs = 32768;                     // Decoded Picture Buffer (DPB) capacity in macroblocks for L4.1
401
402     return (avctx->refs * widthmbs * heightmbs <= maxdpbmbs);
403 }
404
405 static bool IsL41LimitedATI()
406 {
407   D3DADAPTER_IDENTIFIER9 AIdentifier = g_Windowing.GetAIdentifier();
408
409   if(AIdentifier.VendorId == PCIV_ATI)
410   {
411     for (unsigned idx = 0; UVDDeviceID[idx] != 0; idx++)
412     {
413       if (UVDDeviceID[idx] == AIdentifier.DeviceId)
414         return true;
415     }
416   }
417   return false;
418 }
419
420 static bool HasVP3WidthBug(AVCodecContext *avctx)
421 {
422   // Some nVidia VP3 hardware cannot do certain macroblock widths
423
424   D3DADAPTER_IDENTIFIER9 AIdentifier = g_Windowing.GetAIdentifier();
425
426   if(AIdentifier.VendorId == PCIV_nVidia
427   && !CDVDCodecUtils::IsVP3CompatibleWidth(avctx->coded_width))
428   {
429     // Find the card in a known list of problematic VP3 hardware
430     for (unsigned idx = 0; VP3DeviceID[idx] != 0; idx++)
431       if (VP3DeviceID[idx] == AIdentifier.DeviceId)
432         return true;
433   }
434   return false;
435 }
436
437 static bool CheckCompatibility(AVCodecContext *avctx)
438 {
439   // The incompatibilities are all for H264
440   if(avctx->codec_id != AV_CODEC_ID_H264)
441     return true;
442
443   // Macroblock width incompatibility
444   if (HasVP3WidthBug(avctx))
445   {
446     CLog::Log(LOGWARNING,"DXVA - width %i is not supported with nVidia VP3 hardware. DXVA will not be used", avctx->coded_width);
447     return false;
448   }
449
450   // there are many corrupt mpeg2 rips from dvd's which don't
451   // follow profile spec properly, they go corrupt on hw, so
452   // keep those running in software for the time being.
453   if (avctx->codec_id  == AV_CODEC_ID_MPEG2VIDEO
454   &&  avctx->height    <= 576
455   &&  avctx->width     <= 720)
456     return false;
457
458   // Check for hardware limited to H264 L4.1 (ie Bluray).
459
460   // No advanced settings: autodetect.
461   // The advanced setting lets the user override the autodetection (in case of false positive or negative)
462
463   bool checkcompat;
464   if (!g_advancedSettings.m_DXVACheckCompatibilityPresent)
465     checkcompat = IsL41LimitedATI();  // ATI UVD and UVD+ cards can only do L4.1 - corresponds roughly to series 3xxx
466   else
467     checkcompat = g_advancedSettings.m_DXVACheckCompatibility;
468
469   if (checkcompat && !CheckH264L41(avctx))
470   {
471       CLog::Log(LOGWARNING, "DXVA - compatibility check: video exceeds L4.1. DXVA will not be used.");
472       return false;
473   }
474
475   return true;
476 }
477
478 bool CDecoder::Open(AVCodecContext *avctx, enum PixelFormat fmt, unsigned int surfaces)
479 {
480   if (!CheckCompatibility(avctx))
481     return false;
482
483   if(!LoadDXVA())
484     return false;
485
486   CSingleLock lock(m_section);
487   Close();
488
489   if(m_state == DXVA_LOST)
490   {
491     CLog::Log(LOGDEBUG, "DXVA - device is in lost state, we can't start");
492     return false;
493   }
494
495   CHECK(g_DXVA2CreateVideoService(g_Windowing.Get3DDevice(), IID_IDirectXVideoDecoderService, (void**)&m_service))
496
497   UINT  input_count;
498   GUID *input_list;
499
500   CHECK(m_service->GetDecoderDeviceGuids(&input_count, &input_list))
501   SCOPE(GUID, input_list);
502
503   for(unsigned i = 0; i < input_count; i++)
504   {
505     const GUID *g            = &input_list[i];
506     const dxva2_mode_t *mode = dxva2_find_mode(g);
507     if(mode)
508       CLog::Log(LOGDEBUG, "DXVA - supports '%s'", mode->name);
509     else
510       CLog::Log(LOGDEBUG, "DXVA - supports %s", GUIDToString(*g).c_str());
511   }
512
513   m_format.Format = D3DFMT_UNKNOWN;
514   for(const dxva2_mode_t* mode = dxva2_modes; mode->name && m_format.Format == D3DFMT_UNKNOWN; mode++)
515   {
516     if(mode->codec != avctx->codec_id)
517       continue;
518
519     for(unsigned j = 0; j < input_count; j++)
520     {
521       if(!IsEqualGUID(input_list[j], *mode->guid))
522         continue;
523
524       CLog::Log(LOGDEBUG, "DXVA - trying '%s'", mode->name);
525       if(OpenTarget(input_list[j]))
526         break;
527     }
528   }
529
530   if(m_format.Format == D3DFMT_UNKNOWN)
531   {
532     CLog::Log(LOGDEBUG, "DXVA - unable to find an input/output format combination");
533     return false;
534   }
535
536   m_format.SampleWidth  = avctx->coded_width;
537   m_format.SampleHeight = avctx->coded_height;
538   m_format.SampleFormat.SampleFormat           = DXVA2_SampleProgressiveFrame;
539   m_format.SampleFormat.VideoLighting          = DXVA2_VideoLighting_dim;
540
541   if     (avctx->color_range == AVCOL_RANGE_JPEG)
542     m_format.SampleFormat.NominalRange = DXVA2_NominalRange_0_255;
543   else if(avctx->color_range == AVCOL_RANGE_MPEG)
544     m_format.SampleFormat.NominalRange = DXVA2_NominalRange_16_235;
545   else
546     m_format.SampleFormat.NominalRange = DXVA2_NominalRange_Unknown;
547
548   switch(avctx->chroma_sample_location)
549   {
550     case AVCHROMA_LOC_LEFT:
551       m_format.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Horizontally_Cosited 
552                                                    | DXVA2_VideoChromaSubsampling_Vertically_AlignedChromaPlanes;
553       break;
554     case AVCHROMA_LOC_CENTER:
555       m_format.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Vertically_AlignedChromaPlanes;
556       break;
557     case AVCHROMA_LOC_TOPLEFT:
558       m_format.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Horizontally_Cosited 
559                                                    | DXVA2_VideoChromaSubsampling_Vertically_Cosited;
560       break;
561     default:
562       m_format.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Unknown;      
563   }
564
565   switch(avctx->colorspace)
566   {
567     case AVCOL_SPC_BT709:
568       m_format.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT709;
569       break;
570     case AVCOL_SPC_BT470BG:
571     case AVCOL_SPC_SMPTE170M:
572       m_format.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT601;
573       break;
574     case AVCOL_SPC_SMPTE240M:
575       m_format.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_SMPTE240M;
576       break;
577     case AVCOL_SPC_FCC:
578     case AVCOL_SPC_UNSPECIFIED:
579     case AVCOL_SPC_RGB:
580     default:
581       m_format.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_Unknown;
582   }
583
584   switch(avctx->color_primaries)
585   {
586     case AVCOL_PRI_BT709:
587       m_format.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT709;
588       break;
589     case AVCOL_PRI_BT470M:
590       m_format.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT470_2_SysM;
591       break;
592     case AVCOL_PRI_BT470BG:
593       m_format.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT470_2_SysBG;
594       break;
595     case AVCOL_PRI_SMPTE170M:
596       m_format.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_SMPTE170M;
597       break;
598     case AVCOL_PRI_SMPTE240M:
599       m_format.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_SMPTE240M;
600       break;
601     case AVCOL_PRI_FILM:
602     case AVCOL_PRI_UNSPECIFIED:
603     default:
604       m_format.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_Unknown;
605   }
606
607   switch(avctx->color_trc)
608   {
609     case AVCOL_TRC_BT709:
610       m_format.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_709;
611       break;
612     case AVCOL_TRC_GAMMA22:
613       m_format.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_22;
614       break;
615     case AVCOL_TRC_GAMMA28:
616       m_format.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_28;
617       break;
618     default:
619       m_format.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_Unknown;
620   }
621
622   if (avctx->time_base.den > 0 && avctx->time_base.num > 0)
623   {
624     m_format.InputSampleFreq.Numerator   = avctx->time_base.num;
625     m_format.InputSampleFreq.Denominator = avctx->time_base.den;
626   } 
627   m_format.OutputFrameFreq = m_format.InputSampleFreq;
628   m_format.UABProtectionLevel = FALSE;
629   m_format.Reserved = 0;
630
631   if (surfaces > m_shared)
632     m_shared = surfaces;
633
634   if(avctx->refs > m_refs)
635     m_refs = avctx->refs;
636
637   if(m_refs == 0)
638   {
639     if(avctx->codec_id == AV_CODEC_ID_H264)
640       m_refs = 16;
641     else
642       m_refs = 2;
643   }
644   CLog::Log(LOGDEBUG, "DXVA - source requires %d references", avctx->refs);
645
646   // find what decode configs are available
647   UINT                       cfg_count = 0;
648   DXVA2_ConfigPictureDecode *cfg_list  = NULL;
649   CHECK(m_service->GetDecoderConfigurations(m_input
650                                           , &m_format
651                                           , NULL
652                                           , &cfg_count
653                                           , &cfg_list))
654   SCOPE(DXVA2_ConfigPictureDecode, cfg_list);
655
656   DXVA2_ConfigPictureDecode config = {};
657
658   unsigned bitstream = 2; // ConfigBitstreamRaw = 2 is required for Poulsbo and handles skipping better with nVidia
659   for(unsigned i = 0; i< cfg_count; i++)
660   {
661     CLog::Log(LOGDEBUG,
662               "DXVA - config %d: bitstream type %d%s",
663               i,
664               cfg_list[i].ConfigBitstreamRaw,
665               IsEqualGUID(cfg_list[i].guidConfigBitstreamEncryption, DXVA_NoEncrypt) ? "" : ", encrypted");
666
667     // select first available
668     if(config.ConfigBitstreamRaw == 0 && cfg_list[i].ConfigBitstreamRaw != 0)
669       config = cfg_list[i];
670
671     // overide with preferred if found
672     if(config.ConfigBitstreamRaw != bitstream && cfg_list[i].ConfigBitstreamRaw == bitstream)
673       config = cfg_list[i];
674   }
675
676   if(!config.ConfigBitstreamRaw)
677   {
678     CLog::Log(LOGDEBUG, "DXVA - failed to find a raw input bitstream");
679     return false;
680   }
681   *const_cast<DXVA2_ConfigPictureDecode*>(m_context->cfg) = config;
682
683   m_surface_context = new CSurfaceContext();
684
685   if(!OpenDecoder())
686     return false;
687
688   avctx->get_buffer      = GetBufferS;
689   avctx->release_buffer  = RelBufferS;
690   avctx->hwaccel_context = m_context;
691
692   if (IsL41LimitedATI())
693   {
694 #ifdef FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG
695     m_context->workaround |= FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG;
696 #else
697     CLog::Log(LOGWARNING, "DXVA - video card with different scaling list zigzag order detected, but no support in libavcodec");
698 #endif
699   }
700
701   m_state = DXVA_OPEN;
702   return true;
703 }
704
705 int CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame)
706 {
707   CSingleLock lock(m_section);
708   int result = Check(avctx);
709   if(result)
710     return result;
711
712   if(frame)
713   {
714     for(unsigned i = 0; i < m_buffer_count; i++)
715     {
716       if(m_buffer[i].surface == (IDirect3DSurface9*)frame->data[3])
717         return VC_BUFFER | VC_PICTURE;
718     }
719     CLog::Log(LOGWARNING, "DXVA - ignoring invalid surface");
720     return VC_BUFFER;
721   }
722   else
723     return 0;
724 }
725
726 bool CDecoder::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture)
727 {
728   ((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(picture);
729   CSingleLock lock(m_section);
730   picture->format = RENDER_FMT_DXVA;
731   picture->extended_format = (unsigned int)m_format.Format;
732   picture->context = m_surface_context;
733   picture->data[3]= frame->data[3];
734   return true;
735 }
736
737 int CDecoder::Check(AVCodecContext* avctx)
738 {
739   CSingleLock lock(m_section);
740
741   if(m_state == DXVA_RESET)
742     Close();
743
744   if(m_state == DXVA_LOST)
745   {
746     Close();
747     lock.Leave();
748     m_event.WaitMSec(2000);
749     lock.Enter();
750     if(m_state == DXVA_LOST)
751     {
752       CLog::Log(LOGERROR, "CDecoder::Check - device didn't reset in reasonable time");
753       return VC_ERROR;
754     }
755   }
756
757   if(m_format.SampleWidth  == 0
758   || m_format.SampleHeight == 0)
759   {
760     if(!Open(avctx, avctx->pix_fmt, m_shared))
761     {
762       CLog::Log(LOGERROR, "CDecoder::Check - decoder was not able to reset");
763       Close();
764       return VC_ERROR;
765     }
766     return VC_FLUSHED;
767   }
768   else
769   {
770     if(avctx->refs > m_refs)
771     {
772       CLog::Log(LOGWARNING, "CDecoder::Check - number of required reference frames increased, recreating decoder");
773 #if ALLOW_ADDING_SURFACES
774       if(!OpenDecoder())
775         return VC_ERROR;
776 #else
777       Close();
778       return VC_FLUSHED;
779 #endif
780     }
781   }
782
783   // Status reports are available only for the DXVA2_ModeH264 and DXVA2_ModeVC1 modes
784   if(avctx->codec_id != AV_CODEC_ID_H264
785   && avctx->codec_id != AV_CODEC_ID_VC1
786   && avctx->codec_id != AV_CODEC_ID_WMV3)
787     return 0;
788
789   DXVA2_DecodeExecuteParams params = {};
790   DXVA2_DecodeExtensionData data   = {};
791   union {
792     DXVA_Status_H264 h264;
793     DXVA_Status_VC1  vc1;
794   } status = {};
795
796   params.pExtensionData = &data;
797   data.Function = DXVA_STATUS_REPORTING_FUNCTION;
798   data.pPrivateOutputData    = &status;
799   data.PrivateOutputDataSize = avctx->codec_id == AV_CODEC_ID_H264 ? sizeof(DXVA_Status_H264) : sizeof(DXVA_Status_VC1);
800   HRESULT hr;
801   if(FAILED( hr = m_decoder->Execute(&params)))
802   {
803     CLog::Log(LOGWARNING, "DXVA - failed to get decoder status - 0x%08X", hr);
804     return VC_ERROR;
805   }
806
807   if(avctx->codec_id == AV_CODEC_ID_H264)
808   {
809     if(status.h264.bStatus)
810       CLog::Log(LOGWARNING, "DXVA - decoder problem of status %d with %d", status.h264.bStatus, status.h264.bBufType);
811   }
812   else
813   {
814     if(status.vc1.bStatus)
815       CLog::Log(LOGWARNING, "DXVA - decoder problem of status %d with %d", status.vc1.bStatus, status.vc1.bBufType);
816   }
817   return 0;
818 }
819
820 bool CDecoder::OpenTarget(const GUID &guid)
821 {
822   UINT       output_count = 0;
823   D3DFORMAT *output_list  = NULL;
824   CHECK(m_service->GetDecoderRenderTargets(guid, &output_count, &output_list))
825   SCOPE(D3DFORMAT, output_list);
826
827   for (unsigned i = 0; render_targets[i] != D3DFMT_UNKNOWN; i++)
828       for(unsigned k = 0; k < output_count; k++)
829           if (output_list[k] == render_targets[i])
830           {
831               m_input = guid;
832               m_format.Format = output_list[k];
833               return true;
834           }
835
836   return false;
837 }
838
839 bool CDecoder::OpenDecoder()
840 {
841   SAFE_RELEASE(m_decoder);
842   m_context->decoder = NULL;
843
844   m_context->surface_count = m_refs + 1 + 1 + m_shared; // refs + 1 decode + 1 libavcodec safety + processor buffer
845
846   if(m_context->surface_count > m_buffer_count)
847   {
848     CLog::Log(LOGDEBUG, "DXVA - allocating %d surfaces", m_context->surface_count - m_buffer_count);
849
850     CHECK(m_service->CreateSurface( (m_format.SampleWidth  + 15) & ~15
851                                   , (m_format.SampleHeight + 15) & ~15
852                                   , m_context->surface_count - 1 - m_buffer_count
853                                   , m_format.Format
854                                   , D3DPOOL_DEFAULT
855                                   , 0
856                                   , DXVA2_VideoDecoderRenderTarget
857                                   , m_context->surface + m_buffer_count, NULL ));
858
859     for(unsigned i = m_buffer_count; i < m_context->surface_count; i++)
860     {
861       m_buffer[i].surface = m_context->surface[i];
862       m_surface_context->HoldSurface(m_context->surface[i]);
863     }
864
865     m_buffer_count = m_context->surface_count;
866   }
867
868   CHECK(m_service->CreateVideoDecoder(m_input, &m_format
869                                     , m_context->cfg
870                                     , m_context->surface
871                                     , m_context->surface_count
872                                     , &m_decoder))
873
874   m_context->decoder = m_decoder;
875
876   return true;
877 }
878
879 bool CDecoder::Supports(enum PixelFormat fmt)
880 {
881   if(fmt == PIX_FMT_DXVA2_VLD)
882     return true;
883   return false;
884 }
885
886 void CDecoder::RelBuffer(AVCodecContext *avctx, AVFrame *pic)
887 {
888   CSingleLock lock(m_section);
889   IDirect3DSurface9* surface = (IDirect3DSurface9*)pic->data[3];
890
891   for(unsigned i = 0; i < m_buffer_count; i++)
892   {
893     if(m_buffer[i].surface == surface)
894     {
895       m_buffer[i].used = false;
896       m_buffer[i].age  = ++m_buffer_age;
897       break;
898     }
899   }
900   for(unsigned i = 0; i < 4; i++)
901     pic->data[i] = NULL;
902 }
903
904 int CDecoder::GetBuffer(AVCodecContext *avctx, AVFrame *pic)
905 {
906   CSingleLock lock(m_section);
907   if(avctx->coded_width  != m_format.SampleWidth
908   || avctx->coded_height != m_format.SampleHeight)
909   {
910     Close();
911     if(!Open(avctx, avctx->pix_fmt, m_shared))
912     {
913       Close();
914       return -1;
915     }
916   }
917
918   int           count = 0;
919   SVideoBuffer* buf   = NULL;
920   for(unsigned i = 0; i < m_buffer_count; i++)
921   {
922     if(m_buffer[i].used)
923       count++;
924     else
925     {
926       if(!buf || buf->age > m_buffer[i].age)
927         buf = m_buffer+i;
928     }
929   }
930
931   if(count >= m_refs+2)
932   {
933     m_refs++;
934 #if ALLOW_ADDING_SURFACES
935     if(!OpenDecoder())
936       return -1;
937     return GetBuffer(avctx, pic);
938 #else
939     Close();
940     return -1;
941 #endif
942   }
943
944   if(!buf)
945   {
946     CLog::Log(LOGERROR, "DXVA - unable to find new unused buffer");
947     return -1;
948   }
949
950   pic->reordered_opaque = avctx->reordered_opaque;
951   pic->type = FF_BUFFER_TYPE_USER;
952
953   for(unsigned i = 0; i < 4; i++)
954   {
955     pic->data[i] = NULL;
956     pic->linesize[i] = 0;
957   }
958
959   pic->data[0] = (uint8_t*)buf->surface;
960   pic->data[3] = (uint8_t*)buf->surface;
961   buf->used = true;
962
963   return 0;
964 }
965
966 unsigned CDecoder::GetAllowedReferences()
967 {
968   return m_shared;
969 }
970
971
972 //---------------------------------------------------------------------------
973 //---------------------------------------------------------------------------
974 //------------------------ PROCESSING SERVICE -------------------------------
975 //---------------------------------------------------------------------------
976 //---------------------------------------------------------------------------
977
978 CProcessor::CProcessor()
979 {
980   m_service = NULL;
981   m_process = NULL;
982   m_time    = 0;
983   g_Windowing.Register(this);
984
985   m_surfaces = NULL;
986   m_context = NULL;
987   m_index = 0;
988   m_progressive = true;
989 }
990
991 CProcessor::~CProcessor()
992 {
993   g_Windowing.Unregister(this);
994   UnInit();
995 }
996
997 void CProcessor::UnInit()
998 {
999   CSingleLock lock(m_section);
1000   Close();
1001   SAFE_RELEASE(m_service);
1002 }
1003
1004 void CProcessor::Close()
1005 {
1006   CSingleLock lock(m_section);
1007   SAFE_RELEASE(m_process);
1008   for(unsigned i = 0; i < m_sample.size(); i++)
1009   {
1010     SAFE_RELEASE(m_sample[i].context);
1011     SAFE_RELEASE(m_sample[i].sample.SrcSurface);
1012   }
1013   m_sample.clear();
1014
1015   SAFE_RELEASE(m_context);
1016   if (m_surfaces)
1017   {
1018     for (unsigned i = 0; i < m_size; i++)
1019       SAFE_RELEASE(m_surfaces[i]);
1020     free(m_surfaces);
1021     m_surfaces = NULL;
1022   }
1023 }
1024
1025 bool CProcessor::UpdateSize(const DXVA2_VideoDesc& dsc)
1026 {
1027   // TODO: print the D3FORMAT text version in log
1028   CLog::Log(LOGDEBUG, "DXVA - cheking samples array size using %d render target", dsc.Format);
1029
1030   GUID* deint_guid_list = NULL;
1031   unsigned guid_count = 0;
1032   if (FAILED(m_service->GetVideoProcessorDeviceGuids(&dsc, &guid_count, &deint_guid_list)))
1033     return false;
1034
1035   SCOPE(GUID, deint_guid_list);
1036   
1037   for (unsigned i = 0; i < guid_count; i++)
1038   {
1039     DXVA2_VideoProcessorCaps caps;
1040     CHECK(m_service->GetVideoProcessorCaps(deint_guid_list[i], &dsc, D3DFMT_X8R8G8B8, &caps));
1041     if (caps.NumBackwardRefSamples + caps.NumForwardRefSamples > m_size)
1042     {
1043       m_size = caps.NumBackwardRefSamples + caps.NumForwardRefSamples;
1044       CLog::Log(LOGDEBUG, "DXVA - updated maximum samples count to %d", m_size);
1045     }
1046     m_max_back_refs = std::max(caps.NumBackwardRefSamples, m_max_back_refs);
1047     m_max_fwd_refs = std::max(caps.NumForwardRefSamples, m_max_fwd_refs);
1048   }
1049
1050   return true;
1051 }
1052
1053 bool CProcessor::PreInit()
1054 {
1055   if (!LoadDXVA())
1056     return false;
1057
1058   UnInit();
1059
1060   CSingleLock lock(m_section);
1061
1062   if (FAILED(g_DXVA2CreateVideoService(g_Windowing.Get3DDevice(), IID_IDirectXVideoProcessorService, (void**)&m_service)))
1063     return false;
1064
1065   m_size = 0;
1066
1067   // We try to find the maximum count of reference frames using a standard resolution and all known render target formats
1068   DXVA2_VideoDesc dsc = {};
1069   dsc.SampleWidth = 640;
1070   dsc.SampleHeight = 480;
1071   dsc.SampleFormat.SampleFormat = DXVA2_SampleFieldInterleavedOddFirst;
1072
1073   m_max_back_refs = 0;
1074   m_max_fwd_refs = 0;
1075
1076   for (unsigned i = 0; render_targets[i] != D3DFMT_UNKNOWN; i++)
1077   {
1078     dsc.Format = render_targets[i];
1079     if (!UpdateSize(dsc))
1080       CLog::Log(LOGDEBUG, "DXVA - render target not supported by processor");
1081   }
1082
1083   m_size = m_max_back_refs + 1 + m_max_fwd_refs + 2;  // refs + 1 display + 2 safety frames
1084
1085   return true;
1086 }
1087
1088 bool CProcessor::Open(UINT width, UINT height, unsigned int flags, unsigned int format, unsigned int extended_format)
1089 {
1090   Close();
1091
1092   CSingleLock lock(m_section);
1093
1094   if (!m_service)
1095     return false;
1096
1097   DXVA2_VideoDesc dsc;
1098   memset(&dsc, 0, sizeof(DXVA2_VideoDesc));
1099
1100   dsc.SampleWidth = width;
1101   dsc.SampleHeight = height;
1102   dsc.SampleFormat.VideoLighting = DXVA2_VideoLighting_dim;
1103
1104   switch (CONF_FLAGS_CHROMA_MASK(flags))
1105   {
1106     case CONF_FLAGS_CHROMA_LEFT:
1107       dsc.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Horizontally_Cosited
1108                                               | DXVA2_VideoChromaSubsampling_Vertically_AlignedChromaPlanes;
1109       break;
1110     case CONF_FLAGS_CHROMA_CENTER:
1111       dsc.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Vertically_AlignedChromaPlanes;
1112       break;
1113     case CONF_FLAGS_CHROMA_TOPLEFT:
1114       dsc.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Horizontally_Cosited
1115                                               | DXVA2_VideoChromaSubsampling_Vertically_Cosited;
1116       break;
1117     default:
1118       dsc.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Unknown;
1119   }
1120
1121   if (flags & CONF_FLAGS_YUV_FULLRANGE)
1122     dsc.SampleFormat.NominalRange = DXVA2_NominalRange_0_255;
1123   else
1124     dsc.SampleFormat.NominalRange = DXVA2_NominalRange_16_235;
1125
1126   switch (CONF_FLAGS_YUVCOEF_MASK(flags))
1127   {
1128     case CONF_FLAGS_YUVCOEF_240M:
1129       dsc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_SMPTE240M;
1130       break;
1131     case CONF_FLAGS_YUVCOEF_BT601:
1132       dsc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT601;
1133       break;
1134     case CONF_FLAGS_YUVCOEF_BT709:
1135       dsc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT709;
1136       break;
1137     default:
1138       dsc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_Unknown;
1139   }
1140
1141   switch (CONF_FLAGS_COLPRI_MASK(flags))
1142   {
1143     case CONF_FLAGS_COLPRI_BT709:
1144       dsc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT709;
1145       break;
1146     case CONF_FLAGS_COLPRI_BT470M:
1147       dsc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT470_2_SysM;
1148       break;
1149     case CONF_FLAGS_COLPRI_BT470BG:
1150       dsc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT470_2_SysBG;
1151       break;
1152     case CONF_FLAGS_COLPRI_170M:
1153       dsc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_SMPTE170M;
1154       break;
1155     case CONF_FLAGS_COLPRI_240M:
1156       dsc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_SMPTE240M;
1157       break;
1158     default:
1159       dsc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_Unknown;
1160   }
1161
1162   switch (CONF_FLAGS_TRC_MASK(flags))
1163   {
1164     case CONF_FLAGS_TRC_BT709:
1165       dsc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_709;
1166       break;
1167     case CONF_FLAGS_TRC_GAMMA22:
1168       dsc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_22;
1169       break;
1170     case CONF_FLAGS_TRC_GAMMA28:
1171       dsc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_28;
1172       break;
1173     default:
1174       dsc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_Unknown;
1175   }
1176
1177   m_desc = dsc;
1178
1179   if (format == RENDER_FMT_DXVA)
1180     m_desc.Format = (D3DFORMAT)extended_format;
1181   else
1182   {
1183     // Only NV12 software colorspace conversion is implemented for now
1184     m_desc.Format = (D3DFORMAT)MAKEFOURCC('N','V','1','2');
1185     if (!CreateSurfaces())
1186       return false;
1187   }
1188
1189   // frame flags are not available to do the complete calculation of the deinterlacing mode, as done in Render()
1190   // It's OK, as it doesn't make any difference for all hardware except the few GPUs on the quirk list.
1191   // And for those GPUs, the correct values will be calculated with the first Render() and the correct processor
1192   // will replace the one allocated here, before the user sees anything.
1193   // It's a bit inefficient, that's all.
1194   m_deinterlace_mode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode;
1195   m_interlace_method = g_renderManager.AutoInterlaceMethod(CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod);;
1196
1197   EvaluateQuirkNoDeintProcForProg();
1198
1199   if (g_advancedSettings.m_DXVANoDeintProcForProgressive || m_quirk_nodeintprocforprog)
1200     CLog::Log(LOGNOTICE, "DXVA: Auto deinterlacing mode workaround activated. Deinterlacing processor will be used only for interlaced frames.");
1201
1202   if (!OpenProcessor())
1203     return false;
1204
1205   m_time = 0;
1206
1207   return true;
1208 }
1209
1210 void CProcessor::EvaluateQuirkNoDeintProcForProg()
1211 {
1212   D3DADAPTER_IDENTIFIER9 AIdentifier = g_Windowing.GetAIdentifier();
1213
1214   for (unsigned idx = 0; NoDeintProcForProgDevices[idx].VendorID != 0; idx++)
1215   {
1216     if(NoDeintProcForProgDevices[idx].VendorID == AIdentifier.VendorId
1217     && NoDeintProcForProgDevices[idx].DeviceID == AIdentifier.DeviceId)
1218     {
1219       m_quirk_nodeintprocforprog = true;
1220       return;
1221     }
1222   }
1223   m_quirk_nodeintprocforprog = false;
1224 }
1225
1226 bool CProcessor::SelectProcessor()
1227 {
1228   // The CProcessor can be run after dxva or software decoding, possibly after software deinterlacing.
1229
1230   // Deinterlace mode off: force progressive
1231   // Deinterlace mode auto or force, with a dxva deinterlacing method: create an deinterlacing capable processor. The frame flags will tell it to deinterlace or not.
1232   m_progressive = m_deinterlace_mode == VS_DEINTERLACEMODE_OFF
1233                   || (   m_interlace_method != VS_INTERLACEMETHOD_DXVA_BOB
1234                       && m_interlace_method != VS_INTERLACEMETHOD_DXVA_BEST);
1235
1236   if (m_progressive)
1237     m_desc.SampleFormat.SampleFormat = DXVA2_SampleProgressiveFrame;
1238   else
1239     m_desc.SampleFormat.SampleFormat = DXVA2_SampleFieldInterleavedEvenFirst;
1240
1241   GUID*    guid_list;
1242   unsigned guid_count;
1243   CHECK(m_service->GetVideoProcessorDeviceGuids(&m_desc, &guid_count, &guid_list));
1244   SCOPE(GUID, guid_list);
1245
1246   if(guid_count == 0)
1247   {
1248     CLog::Log(LOGDEBUG, "DXVA - unable to find any processors");
1249     return false;
1250   }
1251
1252   for(unsigned i = 0; i < guid_count; i++)
1253   {
1254     const GUID* g = &guid_list[i];
1255     const dxva2_device_t* device = dxva2_find_device(g);
1256
1257     if (device)
1258     {
1259       CLog::Log(LOGDEBUG, "DXVA - processor found %s", device->name);
1260     }
1261     else
1262     {
1263       CHECK(m_service->GetVideoProcessorCaps(*g, &m_desc, D3DFMT_X8R8G8B8, &m_caps));
1264       const dxva2_deinterlacetech_t* tech = dxva2_find_deinterlacetech(m_caps.DeinterlaceTechnology);
1265       if (tech != NULL)
1266         CLog::Log(LOGDEBUG, "DXVA - unknown processor %s found, deinterlace technology %s", GUIDToString(*g).c_str(), tech->name);
1267       else
1268         CLog::Log(LOGDEBUG, "DXVA - unknown processor %s found, unknown technology", GUIDToString(*g).c_str());
1269     }
1270   }
1271
1272   if (m_progressive)
1273     m_device = DXVA2_VideoProcProgressiveDevice;
1274   else if(m_interlace_method == VS_INTERLACEMETHOD_DXVA_BEST)
1275     m_device = guid_list[0];
1276   else
1277     m_device = DXVA2_VideoProcBobDevice;
1278
1279   return true;
1280 }
1281
1282 bool CProcessor::OpenProcessor()
1283 {
1284   if (!SelectProcessor())
1285     return false;
1286
1287   SAFE_RELEASE(m_process);
1288
1289   const dxva2_device_t* device = dxva2_find_device(&m_device);
1290   if (device)
1291     CLog::Log(LOGDEBUG, "DXVA - processor selected %s", device->name);
1292   else
1293     CLog::Log(LOGDEBUG, "DXVA - processor selected %s", GUIDToString(m_device).c_str());
1294
1295   D3DFORMAT rtFormat = D3DFMT_X8R8G8B8;
1296   CHECK(m_service->GetVideoProcessorCaps(m_device, &m_desc, rtFormat, &m_caps))
1297
1298   /* HACK for Intel Egde Device. 
1299    * won't work if backward refs is equals value from the capabilities *
1300    * Possible reasons are:                                             *
1301    * 1) The device capabilities are incorrectly reported               *
1302    * 2) The device is broken                                           */
1303   if (IsEqualGUID(m_device, DXVA2_VideoProcIntelEdgeDevice))
1304     m_caps.NumBackwardRefSamples = 0;
1305
1306   if (m_caps.DeviceCaps & DXVA2_VPDev_SoftwareDevice)
1307     CLog::Log(LOGDEBUG, "DXVA - processor is software device");
1308
1309   if (m_caps.DeviceCaps & DXVA2_VPDev_EmulatedDXVA1)
1310     CLog::Log(LOGDEBUG, "DXVA - processor is emulated dxva1");
1311
1312   CLog::Log(LOGDEBUG, "DXVA - processor requires %d past frames and %d future frames", m_caps.NumBackwardRefSamples, m_caps.NumForwardRefSamples);
1313
1314   if (m_caps.NumBackwardRefSamples + m_caps.NumForwardRefSamples + 3 > m_size)
1315   {
1316     CLog::Log(LOGERROR, "DXVA - used an incorrect number of reference frames creating processor");
1317     return false;
1318   }
1319
1320   CHECK(m_service->CreateVideoProcessor(m_device, &m_desc, rtFormat, 0, &m_process));
1321
1322   CHECK(m_service->GetProcAmpRange(m_device, &m_desc, rtFormat, DXVA2_ProcAmp_Brightness, &m_brightness));
1323   CHECK(m_service->GetProcAmpRange(m_device, &m_desc, rtFormat, DXVA2_ProcAmp_Contrast  , &m_contrast));
1324   CHECK(m_service->GetProcAmpRange(m_device, &m_desc, rtFormat, DXVA2_ProcAmp_Hue       , &m_hue));
1325   CHECK(m_service->GetProcAmpRange(m_device, &m_desc, rtFormat, DXVA2_ProcAmp_Saturation, &m_saturation));
1326
1327   return true;
1328 }
1329
1330 bool CProcessor::CreateSurfaces()
1331 {
1332   LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
1333   m_surfaces = (LPDIRECT3DSURFACE9*)calloc(m_size, sizeof(LPDIRECT3DSURFACE9));
1334   for (unsigned idx = 0; idx < m_size; idx++)
1335     CHECK(pD3DDevice->CreateOffscreenPlainSurface(
1336                                 (m_desc.SampleWidth + 15) & ~15,
1337                                 (m_desc.SampleHeight + 15) & ~15,
1338                                 m_desc.Format,
1339                                 D3DPOOL_DEFAULT,
1340                                 &m_surfaces[idx],
1341                                 NULL));
1342
1343   m_context = new CSurfaceContext();
1344
1345   return true;
1346 }
1347
1348 REFERENCE_TIME CProcessor::Add(DVDVideoPicture* picture)
1349 {
1350   CSingleLock lock(m_section);
1351
1352   IDirect3DSurface9* surface = NULL;
1353   CSurfaceContext* context = NULL;
1354
1355   if (picture->iFlags & DVP_FLAG_DROPPED)
1356     return 0;
1357
1358   switch (picture->format)
1359   {
1360     case RENDER_FMT_DXVA:
1361     {
1362       surface = (IDirect3DSurface9*)picture->data[3];
1363       context = picture->context;
1364       break;
1365     }
1366
1367     case RENDER_FMT_YUV420P:
1368     {
1369       surface = m_surfaces[m_index];
1370       m_index = (m_index + 1) % m_size;
1371
1372       context = m_context;
1373   
1374       D3DLOCKED_RECT rectangle;
1375       if (FAILED(surface->LockRect(&rectangle, NULL, 0)))
1376         return 0;
1377
1378       // Convert to NV12 - Luma
1379       // TODO: Optimize this later using shaders/swscale/etc.
1380       uint8_t *s = picture->data[0];
1381       uint8_t* bits = (uint8_t*)(rectangle.pBits);
1382       for (unsigned y = 0; y < picture->iHeight; y++)
1383       {
1384         memcpy(bits, s, picture->iWidth);
1385         s += picture->iLineSize[0];
1386         bits += rectangle.Pitch;
1387       }
1388
1389       D3DSURFACE_DESC desc;
1390       if (FAILED(surface->GetDesc(&desc)))
1391         return 0;
1392
1393       // Convert to NV12 - Chroma
1394       for (unsigned y = 0; y < picture->iHeight/2; y++)
1395       {
1396         uint8_t *s_u = picture->data[1] + (y * picture->iLineSize[1]);
1397         uint8_t *s_v = picture->data[2] + (y * picture->iLineSize[2]);
1398         uint8_t *d_uv = ((uint8_t*)(rectangle.pBits)) + (desc.Height + y) * rectangle.Pitch;
1399         for (unsigned x = 0; x < picture->iWidth/2; x++)
1400         {
1401           *d_uv++ = *s_u++;
1402           *d_uv++ = *s_v++;
1403         }
1404       }
1405   
1406       if (FAILED(surface->UnlockRect()))
1407         return 0;
1408
1409       break;
1410     }
1411     
1412     default:
1413     {
1414       CLog::Log(LOGWARNING, "DXVA - colorspace not supported by processor, skipping frame");
1415       return 0;
1416     }
1417   }
1418
1419   if (!surface || !context)
1420     return 0;
1421
1422   m_time += 2;
1423
1424   surface->AddRef();
1425   context->Acquire();
1426
1427   SVideoSample vs = {};
1428   vs.sample.Start          = m_time;
1429   vs.sample.End            = 0; 
1430   vs.sample.SampleFormat   = m_desc.SampleFormat;
1431
1432   if (picture->iFlags & DVP_FLAG_INTERLACED)
1433   {
1434     if (picture->iFlags & DVP_FLAG_TOP_FIELD_FIRST)
1435       vs.sample.SampleFormat.SampleFormat = DXVA2_SampleFieldInterleavedEvenFirst;
1436     else
1437       vs.sample.SampleFormat.SampleFormat = DXVA2_SampleFieldInterleavedOddFirst;
1438   }
1439   else
1440   {
1441     vs.sample.SampleFormat.SampleFormat = DXVA2_SampleProgressiveFrame;
1442   }
1443
1444   vs.sample.PlanarAlpha    = DXVA2_Fixed32OpaqueAlpha();
1445   vs.sample.SampleData     = 0;
1446   vs.sample.SrcSurface     = surface;
1447
1448
1449   vs.context = context;
1450
1451   if(!m_sample.empty())
1452     m_sample.back().sample.End = vs.sample.Start;
1453
1454   m_sample.push_back(vs);
1455   if (m_sample.size() > m_size)
1456   {
1457     SAFE_RELEASE(m_sample.front().context);
1458     SAFE_RELEASE(m_sample.front().sample.SrcSurface);
1459     m_sample.pop_front();
1460   }
1461
1462   return m_time;
1463 }
1464
1465 static DXVA2_Fixed32 ConvertRange(const DXVA2_ValueRange& range, int value, int min, int max, int def)
1466 {
1467   if(value > def)
1468     return DXVA2FloatToFixed( DXVA2FixedToFloat(range.DefaultValue)
1469                             + (DXVA2FixedToFloat(range.MaxValue) - DXVA2FixedToFloat(range.DefaultValue))
1470                             * (value - def) / (max - def) );
1471   else if(value < def)
1472     return DXVA2FloatToFixed( DXVA2FixedToFloat(range.DefaultValue)
1473                             + (DXVA2FixedToFloat(range.MinValue) - DXVA2FixedToFloat(range.DefaultValue)) 
1474                             * (value - def) / (min - def) );
1475   else
1476     return range.DefaultValue;
1477 }
1478
1479 bool CProcessor::Render(CRect src, CRect dst, IDirect3DSurface9* target, REFERENCE_TIME time, DWORD flags)
1480 {
1481   CSingleLock lock(m_section);
1482
1483   // With auto deinterlacing, the Ion Gen. 1 drops some frames with deinterlacing processor + progressive flags for progressive material.
1484   // For that GPU (or when specified by an advanced setting), use the progressive processor.
1485   // This is at the expense of the switch speed when video interlacing flags change and a deinterlacing processor is actually required.
1486   EDEINTERLACEMODE mode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode;
1487   if (g_advancedSettings.m_DXVANoDeintProcForProgressive || m_quirk_nodeintprocforprog)
1488     mode = (flags & RENDER_FLAG_FIELD0 || flags & RENDER_FLAG_FIELD1) ? VS_DEINTERLACEMODE_FORCE : VS_DEINTERLACEMODE_OFF;
1489   EINTERLACEMETHOD method = g_renderManager.AutoInterlaceMethod(CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod);
1490   if(m_interlace_method != method
1491   || m_deinterlace_mode != mode
1492   || !m_process)
1493   {
1494     m_deinterlace_mode = mode;
1495     m_interlace_method = method;
1496
1497     if (!OpenProcessor())
1498       return false;
1499   }
1500   
1501   // MinTime and MaxTime are the first and last samples to keep. Delete the rest.
1502   REFERENCE_TIME MinTime = time - m_max_back_refs*2;
1503   REFERENCE_TIME MaxTime = time + m_max_fwd_refs*2;
1504
1505   SSamples::iterator it = m_sample.begin();
1506   while (it != m_sample.end())
1507   {
1508     if (it->sample.Start < MinTime)
1509     {
1510       SAFE_RELEASE(it->context);
1511       SAFE_RELEASE(it->sample.SrcSurface);
1512       it = m_sample.erase(it);
1513     }
1514     else
1515       ++it;
1516   }
1517
1518   if(m_sample.empty())
1519     return false;
1520
1521   // MinTime and MaxTime are now the first and last samples to feed the processor.
1522   MinTime = time - m_caps.NumBackwardRefSamples*2;
1523   MaxTime = time + m_caps.NumForwardRefSamples*2;
1524
1525   D3DSURFACE_DESC desc;
1526   CHECK(target->GetDesc(&desc));
1527   CRect rectTarget(0, 0, desc.Width, desc.Height);
1528   CWIN32Util::CropSource(src, dst, rectTarget);
1529   RECT sourceRECT = { src.x1, src.y1, src.x2, src.y2 };
1530   RECT dstRECT    = { dst.x1, dst.y1, dst.x2, dst.y2 };
1531
1532
1533   // How to prepare the samples array for VideoProcessBlt
1534   // - always provide current picture + the number of forward and backward references required by the current processor.
1535   // - provide the surfaces in the array in increasing temporal order
1536   // - at the start of playback, there may not be enough samples available. Use SampleFormat.SampleFormat = DXVA2_SampleUnknown for the missing samples.
1537
1538   int count = 1 + m_caps.NumBackwardRefSamples + m_caps.NumForwardRefSamples;
1539   int valid = 0;
1540   auto_aptr<DXVA2_VideoSample> samp(new DXVA2_VideoSample[count]);
1541
1542   for (int i = 0; i < count; i++)
1543     samp[i].SampleFormat.SampleFormat = DXVA2_SampleUnknown;
1544
1545   for(it = m_sample.begin(); it != m_sample.end() && valid < count; ++it)
1546   {
1547     if (it->sample.Start >= MinTime && it->sample.Start <= MaxTime)
1548     {
1549       DXVA2_VideoSample& vs = samp[(it->sample.Start - MinTime) / 2];
1550       vs = it->sample;
1551       vs.SrcRect = sourceRECT;
1552       vs.DstRect = dstRECT;
1553       if(vs.End == 0)
1554         vs.End = vs.Start + 2;
1555
1556       // Override the sample format when the processor doesn't need to deinterlace or when deinterlacing is forced and flags are missing.
1557       if (m_progressive)
1558         vs.SampleFormat.SampleFormat = DXVA2_SampleProgressiveFrame;
1559       else if (m_deinterlace_mode == VS_DEINTERLACEMODE_FORCE && vs.SampleFormat.SampleFormat == DXVA2_SampleProgressiveFrame)
1560         vs.SampleFormat.SampleFormat = DXVA2_SampleFieldInterleavedEvenFirst;
1561
1562       valid++;
1563     }
1564   }
1565   
1566   // MS' guidelines above don't work. The blit fails when the processor is given DXVA2_SampleUnknown samples (with ATI at least).
1567   // The ATI driver works with a reduced number of samples though, support that for now.
1568   // Problem is an ambiguity if there are future refs requested by the processor. There are no such implementations at the moment.
1569   int offset = 0;
1570   if(valid < count)
1571   {
1572     CLog::Log(LOGWARNING, __FUNCTION__" - did not find all required samples, adjusting the sample array.");
1573
1574     for (int i = 0; i < count; i++)
1575     {
1576       if (samp[i].SampleFormat.SampleFormat == DXVA2_SampleUnknown)
1577         offset = i+1;
1578     }
1579     count -= offset;
1580     if (count == 0)
1581     {
1582       CLog::Log(LOGWARNING, __FUNCTION__" - no usable samples.");
1583       return false;
1584     }
1585   }
1586
1587   DXVA2_VideoProcessBltParams blt = {};
1588   blt.TargetFrame = time;
1589   if (flags & RENDER_FLAG_FIELD1)
1590     blt.TargetFrame += 1;
1591   blt.TargetRect  = dstRECT;
1592   blt.ConstrictionSize.cx = 0;
1593   blt.ConstrictionSize.cy = 0;
1594
1595   blt.DestFormat.VideoTransferFunction = DXVA2_VideoTransFunc_sRGB;
1596   blt.DestFormat.SampleFormat          = DXVA2_SampleProgressiveFrame;
1597   if(g_Windowing.UseLimitedColor())
1598     blt.DestFormat.NominalRange          = DXVA2_NominalRange_16_235;
1599   else
1600     blt.DestFormat.NominalRange          = DXVA2_NominalRange_0_255;
1601   blt.Alpha = DXVA2_Fixed32OpaqueAlpha();
1602
1603   blt.ProcAmpValues.Brightness = ConvertRange( m_brightness, CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness
1604                                              , 0, 100, 50);
1605   blt.ProcAmpValues.Contrast   = ConvertRange( m_contrast, CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast
1606                                              , 0, 100, 50);
1607   blt.ProcAmpValues.Hue        = m_hue.DefaultValue;
1608   blt.ProcAmpValues.Saturation = m_saturation.DefaultValue;
1609
1610   blt.BackgroundColor.Y     = 0x1000;
1611   blt.BackgroundColor.Cb    = 0x8000;
1612   blt.BackgroundColor.Cr    = 0x8000;
1613   blt.BackgroundColor.Alpha = 0xffff;
1614
1615   /* HACK to kickstart certain DXVA drivers (poulsbo) which oddly  *
1616    * won't render anything until someting else have been rendered. */
1617   g_Windowing.Get3DDevice()->SetFVF( D3DFVF_XYZ );
1618   float verts[2][3]= {};
1619   g_Windowing.Get3DDevice()->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 1, verts, 3*sizeof(float));
1620
1621   CHECK(m_process->VideoProcessBlt(target, &blt, &samp[offset], count, NULL));
1622   return true;
1623 }
1624
1625 #endif