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