Merge pull request #4539 from Matricom/amcodec
[vuplus_xbmc] / xbmc / cores / dvdplayer / DVDCodecs / Video / DXVAHD.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 "DXVAHD.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 *DXVAHDCreateVideoServicePtr)(IDirect3DDevice9Ex *pD3DDevice, const DXVAHD_CONTENT_DESC *pContentDesc, DXVAHD_DEVICE_USAGE Usage, PDXVAHDSW_Plugin pPlugin, IDXVAHD_Device **ppDevice);
55 static DXVAHDCreateVideoServicePtr g_DXVAHDCreateVideoService;
56
57 #define CHECK(a) \
58 do { \
59   HRESULT res = a; \
60   if(FAILED(res)) \
61   { \
62     CLog::Log(LOGERROR, __FUNCTION__" - failed executing "#a" at line %d with error %x", __LINE__, res); \
63     return false; \
64   } \
65 } while(0);
66
67 #define LOGIFERROR(a) \
68 do { \
69   HRESULT res = a; \
70   if(FAILED(res)) \
71   { \
72     CLog::Log(LOGERROR, __FUNCTION__" - failed executing "#a" at line %d with error %x", __LINE__, res); \
73   } \
74 } while(0);
75
76 static bool LoadDXVAHD()
77 {
78   static CCriticalSection g_section;
79   static HMODULE          g_handle;
80
81   CSingleLock lock(g_section);
82   if(g_handle == NULL)
83   {
84     g_handle = LoadLibraryEx("dxva2.dll", NULL, 0);
85   }
86   if(g_handle == NULL)
87   {
88     return false;
89   }
90   g_DXVAHDCreateVideoService = (DXVAHDCreateVideoServicePtr)GetProcAddress(g_handle, "DXVAHD_CreateDevice");
91   if(g_DXVAHDCreateVideoService == NULL)
92   {
93     return false;
94   }
95   return true;
96 }
97
98 static std::string GUIDToString(const GUID& guid)
99 {
100   std::string buffer = StringUtils::Format("%08X-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"
101                                           , guid.Data1, guid.Data2, guid.Data3
102                                           , guid.Data4[0], guid.Data4[1]
103                                           , guid.Data4[2], guid.Data4[3], guid.Data4[4]
104                                           , guid.Data4[5], guid.Data4[6], guid.Data4[7]);
105   return buffer;
106 }
107
108 CProcessorHD::CProcessorHD()
109 {
110   m_pDXVAHD = NULL;
111   m_pDXVAVP = NULL;
112   m_index   = 0;
113   m_frame   = 0;
114   g_Windowing.Register(this);
115
116   m_surfaces = NULL;
117   m_context  = NULL;
118 }
119
120 CProcessorHD::~CProcessorHD()
121 {
122   g_Windowing.Unregister(this);
123   UnInit();
124 }
125
126 void CProcessorHD::UnInit()
127 {
128   CSingleLock lock(m_section);
129   Close();
130   SAFE_RELEASE(m_pDXVAHD);
131 }
132
133 void CProcessorHD::Close()
134 {
135   CSingleLock lock(m_section);
136   SAFE_RELEASE(m_pDXVAVP);
137
138   for(unsigned i = 0; i < m_frames.size(); i++)
139   {
140     SAFE_RELEASE(m_frames[i].context);
141     SAFE_RELEASE(m_frames[i].pSurface);
142   }
143   m_frames.clear();
144
145   SAFE_RELEASE(m_context);
146   if (m_surfaces)
147   {
148     for (unsigned i = 0; i < m_size; i++)
149     {
150       SAFE_RELEASE(m_surfaces[i]);
151     }
152     free(m_surfaces);
153     m_surfaces = NULL;
154   }
155 }
156
157 bool CProcessorHD::UpdateSize(const DXVA2_VideoDesc& dsc)
158 {
159   return true;
160 }
161
162 bool CProcessorHD::PreInit()
163 {
164   if (!LoadDXVAHD())
165   {
166     CLog::Log(LOGWARNING, __FUNCTION__" - DXVAHD not loaded.");
167     return false;
168   }
169
170   UnInit();
171
172   CSingleLock lock(m_section);
173
174   DXVAHD_RATIONAL fps = { 60, 1 }; 
175   DXVAHD_CONTENT_DESC desc;
176   desc.InputFrameFormat = DXVAHD_FRAME_FORMAT_PROGRESSIVE;
177   desc.InputFrameRate = fps;
178   desc.InputWidth = 640;
179   desc.InputHeight = 480;
180   desc.OutputFrameRate = fps;
181   desc.OutputWidth = 640;
182   desc.OutputHeight = 480;
183
184   HRESULT cvres = g_DXVAHDCreateVideoService( (IDirect3DDevice9Ex*)g_Windowing.Get3DDevice()
185                                               , &desc
186                                               , DXVAHD_DEVICE_USAGE_OPTIMAL_QUALITY
187                                               , NULL
188                                               , &m_pDXVAHD );
189
190   if(FAILED(cvres))
191   {
192     if(cvres == E_NOINTERFACE)
193       CLog::Log(LOGNOTICE, __FUNCTION__" - The Direct3d device doesn't support DXVA-HD.");
194     else
195       CLog::Log(LOGERROR, __FUNCTION__" - failed to create DXVAHD device %x", cvres);
196
197     return false;
198   }
199
200   CHECK(m_pDXVAHD->GetVideoProcessorDeviceCaps( &m_VPDevCaps ));
201
202   if (m_VPDevCaps.VideoProcessorCount == 0)
203   {
204     CLog::Log(LOGWARNING, __FUNCTION__" - unable to find any video processor. GPU drivers doesn't support DXVA-HD.");
205     return false;
206   }
207
208   // Create the array of video processor caps. 
209   DXVAHD_VPCAPS* pVPCaps = new (std::nothrow) DXVAHD_VPCAPS[ m_VPDevCaps.VideoProcessorCount ];
210   if (pVPCaps == NULL)
211   {
212     CLog::Log(LOGERROR, __FUNCTION__" - unable to create video processor caps array. Out of memory.");
213     return false;
214   }
215
216   HRESULT hr = m_pDXVAHD->GetVideoProcessorCaps( m_VPDevCaps.VideoProcessorCount, pVPCaps );
217   if(FAILED(hr))
218   {
219     CLog::Log(LOGERROR, __FUNCTION__" - failed get processor caps with error %x.", hr);
220
221     delete [] pVPCaps;
222     return false;
223   }
224
225   m_max_back_refs = 0;
226   m_max_fwd_refs = 0;
227
228   for (unsigned int i = 0; i < m_VPDevCaps.VideoProcessorCount; i++)
229   {
230     if (pVPCaps[i].FutureFrames > m_max_fwd_refs)
231     {
232       m_max_fwd_refs = pVPCaps[i].FutureFrames;
233     }
234
235     if (pVPCaps[i].PastFrames > m_max_back_refs)
236     {
237       m_max_back_refs = pVPCaps[i].PastFrames;
238     }
239   }
240
241   m_size = m_max_back_refs + 1 + m_max_fwd_refs + 2;  // refs + 1 display + 2 safety frames
242
243   // Get the image filtering capabilities.
244   for (long i = 0; i < NUM_FILTERS; i++)
245   {
246     if (m_VPDevCaps.FilterCaps & (1 << i))
247     {
248       m_pDXVAHD->GetVideoProcessorFilterRange(PROCAMP_FILTERS[i], &m_Filters[i].Range);
249       m_Filters[i].bSupported = true;
250     }
251     else
252     {
253       m_Filters[i].bSupported = false;
254     }
255   }
256
257   m_VPCaps = pVPCaps[0];
258   m_device = m_VPCaps.VPGuid;
259
260   delete [] pVPCaps;
261
262   return true;
263 }
264
265 bool CProcessorHD::Open(UINT width, UINT height, unsigned int flags, unsigned int format, unsigned int extended_format)
266 {
267   Close();
268
269   CSingleLock lock(m_section);
270
271   if (!m_pDXVAHD)
272   {
273     return false;
274   }
275
276   m_width = width;
277   m_height = height;
278   m_flags = flags;
279   m_renderFormat = format;
280
281   if (g_advancedSettings.m_DXVANoDeintProcForProgressive)
282   {
283     CLog::Log(LOGNOTICE, __FUNCTION__" - Auto deinterlacing mode workaround activated. Deinterlacing processor will be used only for interlaced frames.");
284   }
285
286   if (format == RENDER_FMT_DXVA)
287   {
288     m_format = (D3DFORMAT)extended_format;
289   }
290   else
291   {
292     // Only NV12 software colorspace conversion is implemented for now
293     m_format = (D3DFORMAT)MAKEFOURCC('N','V','1','2');
294     if (!CreateSurfaces())
295       return false;
296   }
297
298   if (!OpenProcessor())
299   {
300     return false;
301   }
302
303   m_frame = 0;
304
305   return true;
306 }
307
308 bool CProcessorHD::ReInit()
309 {
310   return PreInit() && (m_renderFormat == RENDER_FMT_DXVA || CreateSurfaces());
311 }
312
313 bool CProcessorHD::OpenProcessor()
314 {
315   // restore the device if it was lost
316   if (!m_pDXVAHD && !ReInit())
317   {
318     return false;
319   }
320
321   SAFE_RELEASE(m_pDXVAVP);
322
323   CLog::Log(LOGDEBUG, __FUNCTION__" - processor selected %s.", GUIDToString(m_device).c_str());
324
325   CHECK(m_pDXVAHD->CreateVideoProcessor(&m_device, &m_pDXVAVP));
326
327   DXVAHD_STREAM_STATE_D3DFORMAT_DATA d3dformat = { m_format };
328   LOGIFERROR(m_pDXVAVP->SetVideoProcessStreamState( 0, DXVAHD_STREAM_STATE_D3DFORMAT
329                                                   , sizeof(d3dformat), &d3dformat ));
330
331   DXVAHD_STREAM_STATE_INPUT_COLOR_SPACE_DATA data =
332   {
333     0,                                          // Type: 0=Video, 1=Graphics
334     0,                                          // RGB_Range: 0=Full, 1=Limited
335     m_flags & CONF_FLAGS_YUVCOEF_BT709 ? 1 : 0, // YCbCr_Matrix: 0=BT.601, 1=BT.709
336     m_flags & CONF_FLAGS_YUV_FULLRANGE ? 1 : 0  // YCbCr_xvYCC: 0=Conventional YCbCr, 1=xvYCC
337   };
338   LOGIFERROR(m_pDXVAVP->SetVideoProcessStreamState( 0, DXVAHD_STREAM_STATE_INPUT_COLOR_SPACE
339                                                   , sizeof(data), &data ));
340
341   DXVAHD_COLOR_YCbCrA bgColor = { 0.0625f, 0.5f, 0.5f, 1.0f }; // black color
342   DXVAHD_COLOR backgroundColor;
343   backgroundColor.YCbCr = bgColor; 
344   DXVAHD_BLT_STATE_BACKGROUND_COLOR_DATA backgroundData = { true, backgroundColor }; // {YCbCr, DXVAHD_COLOR}
345   LOGIFERROR(m_pDXVAVP->SetVideoProcessBltState( DXVAHD_BLT_STATE_BACKGROUND_COLOR
346                                                , sizeof (backgroundData), &backgroundData ));
347
348   DXVAHD_STREAM_STATE_ALPHA_DATA alpha = { true, 1.0f };
349   LOGIFERROR(m_pDXVAVP->SetVideoProcessStreamState( 0, DXVAHD_STREAM_STATE_ALPHA
350                                                   , sizeof(alpha), &alpha ));
351
352   return true;
353 }
354
355 bool CProcessorHD::CreateSurfaces()
356 {
357   LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
358   m_surfaces = (LPDIRECT3DSURFACE9*)calloc(m_size, sizeof(LPDIRECT3DSURFACE9));
359   for (unsigned idx = 0; idx < m_size; idx++)
360     CHECK(pD3DDevice->CreateOffscreenPlainSurface(
361                                 (m_width + 15) & ~15,
362                                 (m_height + 15) & ~15,
363                                 m_format,
364                                 m_VPDevCaps.InputPool,
365                                 &m_surfaces[idx],
366                                 NULL));
367
368   m_context = new CSurfaceContext();
369
370   return true;
371 }
372
373 REFERENCE_TIME CProcessorHD::Add(DVDVideoPicture* picture)
374 {
375   CSingleLock lock(m_section);
376
377   IDirect3DSurface9* surface = NULL;
378   CSurfaceContext* context = NULL;
379
380   if (picture->iFlags & DVP_FLAG_DROPPED)
381   {
382     return 0;
383   }
384
385   switch (picture->format)
386   {
387     case RENDER_FMT_DXVA:
388     {
389       surface = (IDirect3DSurface9*)picture->data[3];
390       context = picture->context;
391       break;
392     }
393
394     case RENDER_FMT_YUV420P:
395     {
396       if (!m_surfaces)
397       {
398         CLog::Log(LOGWARNING, __FUNCTION__" - not initialized.");
399         return 0;
400       }
401
402       surface = m_surfaces[m_index];
403       m_index = (m_index + 1) % m_size;
404
405       context = m_context;
406   
407       D3DLOCKED_RECT rectangle;
408       if (FAILED(surface->LockRect(&rectangle, NULL, 0)))
409       {
410         return 0;
411       }
412
413       // Convert to NV12 - Luma
414       // TODO: Optimize this later using shaders/swscale/etc.
415       uint8_t *s = picture->data[0];
416       uint8_t* bits = (uint8_t*)(rectangle.pBits);
417       for (unsigned y = 0; y < picture->iHeight; y++)
418       {
419         memcpy(bits, s, picture->iWidth);
420         s += picture->iLineSize[0];
421         bits += rectangle.Pitch;
422       }
423
424       D3DSURFACE_DESC desc;
425       if (FAILED(surface->GetDesc(&desc)))
426       {
427         return 0;
428       }
429
430       // Convert to NV12 - Chroma
431       uint8_t *s_u, *s_v, *d_uv;
432       for (unsigned y = 0; y < picture->iHeight/2; y++)
433       {
434         s_u = picture->data[1] + (y * picture->iLineSize[1]);
435         s_v = picture->data[2] + (y * picture->iLineSize[2]);
436         d_uv = ((uint8_t*)(rectangle.pBits)) + (desc.Height + y) * rectangle.Pitch;
437         for (unsigned x = 0; x < picture->iWidth/2; x++)
438         {
439           *d_uv++ = *s_u++;
440           *d_uv++ = *s_v++;
441         }
442       }
443   
444       if (FAILED(surface->UnlockRect()))
445       {
446         return 0;
447       }
448       break;
449     }
450     
451     default:
452     {
453       CLog::Log(LOGWARNING, __FUNCTION__" - colorspace not supported by processor, skipping frame.");
454       return 0;
455     }
456   }
457
458   if (!surface || !context)
459   {
460     return 0;
461   }
462   m_frame += 2;
463
464   surface->AddRef();
465   context->Acquire();
466
467   SFrame frame = {};
468   frame.index       = m_frame;
469   frame.pSurface    = surface; 
470   frame.context     = context;
471   frame.format      = DXVAHD_FRAME_FORMAT_PROGRESSIVE;
472
473   if (picture->iFlags & DVP_FLAG_INTERLACED)
474   {
475     frame.format = picture->iFlags & DVP_FLAG_TOP_FIELD_FIRST
476                      ? DXVAHD_FRAME_FORMAT_INTERLACED_TOP_FIELD_FIRST
477                      : DXVAHD_FRAME_FORMAT_INTERLACED_BOTTOM_FIELD_FIRST;
478   }
479
480   m_frames.push_back(frame);
481
482   if (m_frames.size() > m_size)
483   {
484     SAFE_RELEASE(m_frames.front().context);
485     SAFE_RELEASE(m_frames.front().pSurface);
486
487     m_frames.pop_front();
488   }
489
490   return m_frame;
491 }
492
493 bool CProcessorHD::ApplyFilter(DXVAHD_FILTER filter, int value, int min, int max, int def)
494 {
495   if (filter > NUM_FILTERS)
496   {
497     return false;
498   }
499   // Unsupported filter. Ignore.
500   if (!m_Filters[filter].bSupported)
501   {
502     return false;
503   }
504
505   DXVAHD_FILTER_RANGE_DATA range = m_Filters[filter].Range;
506   int val;
507
508   if(value > def)
509   {
510     val = range.Default + (range.Maximum - range.Default) * (value - def) / (max - def);
511   }
512   else if(value < def)
513   {
514     val = range.Default + (range.Minimum - range.Default) * (value - def) / (min - def);
515   }
516   else
517   {
518     val = range.Default;
519   }
520
521   DXVAHD_STREAM_STATE_FILTER_DATA data = { true, val };
522   DXVAHD_STREAM_STATE state = static_cast<DXVAHD_STREAM_STATE>(DXVAHD_STREAM_STATE_FILTER_BRIGHTNESS + filter);
523
524   return !FAILED( m_pDXVAVP->SetVideoProcessStreamState( 0, state, sizeof(data), &data ) );
525 }
526
527 bool CProcessorHD::Render(CRect src, CRect dst, IDirect3DSurface9* target, REFERENCE_TIME frame, DWORD flags)
528 {
529   CSingleLock lock(m_section);
530
531   // restore processor if it was lost
532   if(!m_pDXVAVP && !OpenProcessor())
533   {
534     return false;
535   }
536   
537   EDEINTERLACEMODE deinterlace_mode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode;
538   if (g_advancedSettings.m_DXVANoDeintProcForProgressive)
539     deinterlace_mode = (flags & RENDER_FLAG_FIELD0 || flags & RENDER_FLAG_FIELD1) ? VS_DEINTERLACEMODE_FORCE : VS_DEINTERLACEMODE_OFF;
540   EINTERLACEMETHOD interlace_method = g_renderManager.AutoInterlaceMethod(CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod);
541
542   bool progressive = deinterlace_mode == VS_DEINTERLACEMODE_OFF
543                   || (   interlace_method != VS_INTERLACEMETHOD_DXVA_BOB
544                       && interlace_method != VS_INTERLACEMETHOD_DXVA_BEST);
545
546   // minFrame is the first samples to keep. Delete the rest.
547   REFERENCE_TIME minFrame = frame - m_max_back_refs * 2;
548
549   SFrames::iterator it = m_frames.begin();
550   while (it != m_frames.end())
551   {
552     if (it->index < minFrame)
553     {
554       SAFE_RELEASE(it->context);
555       SAFE_RELEASE(it->pSurface);
556       it = m_frames.erase(it);
557     }
558     else
559       ++it;
560   }
561
562   if(m_frames.empty())
563   {
564     return false;
565   }
566
567   D3DSURFACE_DESC desc;
568   CHECK(target->GetDesc(&desc));
569   CRect rectTarget(0, 0, desc.Width, desc.Height);
570   CWIN32Util::CropSource(src, dst, rectTarget);
571   RECT sourceRECT = { src.x1, src.y1, src.x2, src.y2 };
572   RECT dstRECT    = { dst.x1, dst.y1, dst.x2, dst.y2 };
573
574   // MinTime and MaxTime are now the first and last samples to feed the processor.
575   minFrame = frame - m_VPCaps.PastFrames * 2;
576   REFERENCE_TIME maxFrame = frame + m_VPCaps.FutureFrames * 2;
577
578   bool isValid(false);
579   DXVAHD_FRAME_FORMAT dxvaFrameFormat = DXVAHD_FRAME_FORMAT_PROGRESSIVE;
580
581   DXVAHD_STREAM_DATA stream_data = { 0 };
582   stream_data.Enable = TRUE;
583   stream_data.PastFrames = 0;
584   stream_data.FutureFrames = 0;
585   stream_data.ppPastSurfaces = new IDirect3DSurface9*[m_VPCaps.PastFrames];
586   stream_data.ppFutureSurfaces = new IDirect3DSurface9*[m_VPCaps.FutureFrames];
587
588   for(it = m_frames.begin(); it != m_frames.end(); ++it)
589   {
590     if (it->index >= minFrame && it->index <= maxFrame)
591     {
592       if (it->index < frame)
593       {
594         // frames order should be { .., T-1, T-2, T-3 }
595         stream_data.ppPastSurfaces[(frame - it->index)/2 - 1] = it->pSurface;
596         stream_data.PastFrames++;
597       }
598       else if (it->index == frame)
599       {
600         stream_data.pInputSurface = it->pSurface;
601         dxvaFrameFormat = (DXVAHD_FRAME_FORMAT) it->format;
602         isValid = true;
603       }
604       else if (it->index > frame)
605       {
606         // frames order should be { T+1, T+2, T+3, .. }
607         stream_data.ppFutureSurfaces[(it->index - frame)/2 - 1] = it->pSurface;
608         stream_data.FutureFrames++;
609       }
610     }
611   }
612
613   // no present frame, skip
614   if (!isValid)
615   {
616     CLog::Log(LOGWARNING, __FUNCTION__" - uncomplete stream data, skipping frame.");
617     return false;
618   }
619
620   // Override the sample format when the processor doesn't need to deinterlace or when deinterlacing is forced and flags are missing.
621   if (progressive)
622   {
623     dxvaFrameFormat = DXVAHD_FRAME_FORMAT_PROGRESSIVE;
624   }
625   else if (deinterlace_mode == VS_DEINTERLACEMODE_FORCE 
626         && dxvaFrameFormat  == DXVAHD_FRAME_FORMAT_PROGRESSIVE)
627   {
628     dxvaFrameFormat = DXVAHD_FRAME_FORMAT_INTERLACED_TOP_FIELD_FIRST;
629   }
630
631   bool frameProgressive = dxvaFrameFormat == DXVAHD_FRAME_FORMAT_PROGRESSIVE;
632
633   // Progressive or Interlaced video at normal rate.
634   stream_data.InputFrameOrField = frame + (flags & RENDER_FLAG_FIELD1 ? 1 : 0);
635   stream_data.OutputIndex = flags & RENDER_FLAG_FIELD1 && !frameProgressive ? 1 : 0;
636
637   DXVAHD_STREAM_STATE_FRAME_FORMAT_DATA frame_format = { dxvaFrameFormat };
638   LOGIFERROR( m_pDXVAVP->SetVideoProcessStreamState( 0, DXVAHD_STREAM_STATE_FRAME_FORMAT
639                                                    , sizeof(frame_format), &frame_format ) );
640
641   DXVAHD_STREAM_STATE_DESTINATION_RECT_DATA dstRect = { true, dstRECT };
642   LOGIFERROR( m_pDXVAVP->SetVideoProcessStreamState( 0, DXVAHD_STREAM_STATE_DESTINATION_RECT
643                                                    , sizeof(dstRect), &dstRect));
644
645   DXVAHD_STREAM_STATE_SOURCE_RECT_DATA srcRect = { true, sourceRECT };
646   LOGIFERROR( m_pDXVAVP->SetVideoProcessStreamState( 0, DXVAHD_STREAM_STATE_SOURCE_RECT
647                                                    , sizeof(srcRect), &srcRect));
648
649   ApplyFilter( DXVAHD_FILTER_BRIGHTNESS, CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness
650                                              , 0, 100, 50);
651   ApplyFilter( DXVAHD_FILTER_CONTRAST, CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast
652                                              , 0, 100, 50);
653
654   unsigned int uiRange = g_Windowing.UseLimitedColor() ? 1 : 0;
655   DXVAHD_BLT_STATE_OUTPUT_COLOR_SPACE_DATA colorData = 
656   {
657     0,        // 0 = playback, 1 = video processing
658     uiRange,  // 0 = 0-255, 1 = 16-235
659     1,        // 0 = BT.601, 1 = BT.709
660     1         // 0 = Conventional YCbCr, 1 = xvYCC
661   };
662
663   LOGIFERROR( m_pDXVAVP->SetVideoProcessBltState( DXVAHD_BLT_STATE_OUTPUT_COLOR_SPACE
664                                                 , sizeof(colorData), &colorData ));
665
666   DXVAHD_BLT_STATE_TARGET_RECT_DATA targetRect = { true, dstRECT };
667   LOGIFERROR( m_pDXVAVP->SetVideoProcessBltState( DXVAHD_BLT_STATE_TARGET_RECT
668                                                 , sizeof(targetRect), &targetRect ) );
669
670   HRESULT hr = m_pDXVAVP->VideoProcessBltHD(target, frame, 1, &stream_data);
671   if(FAILED(hr))
672   {
673     CLog::Log(LOGERROR, __FUNCTION__" - failed executing VideoProcessBltHD with error %x", hr);
674   }
675
676   delete [] stream_data.ppPastSurfaces;
677   delete [] stream_data.ppFutureSurfaces;
678
679   return !FAILED(hr);
680 }
681
682 #endif