2 * Copyright (C) 2005-2013 Team XBMC
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)
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.
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/>.
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
32 #include "libavcodec/dxva2.h"
33 #include "../DVDCodecUtils.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"
48 #define ALLOW_ADDING_SURFACES 0
51 using namespace AUTOPTR;
54 typedef HRESULT (__stdcall *DXVA2CreateVideoServicePtr)(IDirect3DDevice9* pDD, REFIID riid, void** ppService);
55 static DXVA2CreateVideoServicePtr g_DXVA2CreateVideoService;
57 static bool LoadDXVA()
59 static CCriticalSection g_section;
60 static HMODULE g_handle;
62 CSingleLock lock(g_section);
64 g_handle = LoadLibraryEx("dxva2.dll", NULL, 0);
67 g_DXVA2CreateVideoService = (DXVA2CreateVideoServicePtr)GetProcAddress(g_handle, "DXVA2CreateVideoService");
68 if(g_DXVA2CreateVideoService == NULL)
75 static void RelBufferS(AVCodecContext *avctx, AVFrame *pic)
76 { ((CDecoder*)((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetHardware())->RelBuffer(avctx, pic); }
78 static int GetBufferS(AVCodecContext *avctx, AVFrame *pic)
79 { return ((CDecoder*)((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetHardware())->GetBuffer(avctx, pic); }
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);
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);
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 },
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 },
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, },
119 { "Windows Media Video 8 MoComp", &DXVA2_ModeWMV8_B, 0 },
120 { "Windows Media Video 8 post processing", &DXVA2_ModeWMV8_A, 0 },
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 },
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 },
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);
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 },
164 } dxva2_deinterlacetech_t;
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 },
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'),
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
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
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
249 0x087A, // GeForce 9400
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
272 static CStdString GUIDToString(const GUID& guid)
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]);
282 static const dxva2_mode_t *dxva2_find_mode(const GUID *guid)
284 for (unsigned i = 0; dxva2_modes[i].name; i++) {
285 if (IsEqualGUID(*dxva2_modes[i].guid, *guid))
286 return &dxva2_modes[i];
291 static const dxva2_device_t *dxva2_find_device(const GUID *guid)
293 for (unsigned i = 0; dxva2_devices[i].name; i++) {
294 if (IsEqualGUID(*dxva2_devices[i].guid, *guid))
295 return &dxva2_devices[i];
300 static const dxva2_deinterlacetech_t *dxva2_find_deinterlacetech(unsigned flags)
302 for (unsigned i = 0; dxva2_deinterlacetechs[i].name; i++) {
303 if (dxva2_deinterlacetechs[i].flags == flags)
304 return &dxva2_deinterlacetechs[i];
309 #define SCOPE(type, var) boost::shared_ptr<type> var##_holder(var, CoTaskMemFree);
311 CSurfaceContext::CSurfaceContext()
315 CSurfaceContext::~CSurfaceContext()
317 for (vector<IDirect3DSurface9*>::iterator it = m_heldsurfaces.begin(); it != m_heldsurfaces.end(); ++it)
321 void CSurfaceContext::HoldSurface(IDirect3DSurface9* surface)
324 m_heldsurfaces.push_back(surface);
327 CDecoder::SVideoBuffer::SVideoBuffer()
333 CDecoder::SVideoBuffer::~SVideoBuffer()
338 void CDecoder::SVideoBuffer::Clear()
340 SAFE_RELEASE(surface);
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);
365 CDecoder::~CDecoder()
367 g_Windowing.Unregister(this);
369 free(m_context->surface);
370 free(const_cast<DXVA2_ConfigPictureDecode*>(m_context->cfg)); // yes this is foobar
374 void CDecoder::Close()
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++)
383 memset(&m_format, 0, sizeof(m_format));
391 CLog::Log(LOGERROR, "DXVA - failed executing "#a" at line %d with error %x", __LINE__, res); \
396 static bool CheckH264L41(AVCodecContext *avctx)
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
402 return (avctx->refs * widthmbs * heightmbs <= maxdpbmbs);
405 static bool IsL41LimitedATI()
407 D3DADAPTER_IDENTIFIER9 AIdentifier = g_Windowing.GetAIdentifier();
409 if(AIdentifier.VendorId == PCIV_ATI)
411 for (unsigned idx = 0; UVDDeviceID[idx] != 0; idx++)
413 if (UVDDeviceID[idx] == AIdentifier.DeviceId)
420 static bool HasVP3WidthBug(AVCodecContext *avctx)
422 // Some nVidia VP3 hardware cannot do certain macroblock widths
424 D3DADAPTER_IDENTIFIER9 AIdentifier = g_Windowing.GetAIdentifier();
426 if(AIdentifier.VendorId == PCIV_nVidia
427 && !CDVDCodecUtils::IsVP3CompatibleWidth(avctx->coded_width))
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)
437 static bool CheckCompatibility(AVCodecContext *avctx)
439 // The incompatibilities are all for H264
440 if(avctx->codec_id != AV_CODEC_ID_H264)
443 // Macroblock width incompatibility
444 if (HasVP3WidthBug(avctx))
446 CLog::Log(LOGWARNING,"DXVA - width %i is not supported with nVidia VP3 hardware. DXVA will not be used", avctx->coded_width);
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)
458 // Check for hardware limited to H264 L4.1 (ie Bluray).
460 // No advanced settings: autodetect.
461 // The advanced setting lets the user override the autodetection (in case of false positive or negative)
464 if (!g_advancedSettings.m_DXVACheckCompatibilityPresent)
465 checkcompat = IsL41LimitedATI(); // ATI UVD and UVD+ cards can only do L4.1 - corresponds roughly to series 3xxx
467 checkcompat = g_advancedSettings.m_DXVACheckCompatibility;
469 if (checkcompat && !CheckH264L41(avctx))
471 CLog::Log(LOGWARNING, "DXVA - compatibility check: video exceeds L4.1. DXVA will not be used.");
478 bool CDecoder::Open(AVCodecContext *avctx, enum PixelFormat fmt, unsigned int surfaces)
480 if (!CheckCompatibility(avctx))
486 CSingleLock lock(m_section);
489 if(m_state == DXVA_LOST)
491 CLog::Log(LOGDEBUG, "DXVA - device is in lost state, we can't start");
495 CHECK(g_DXVA2CreateVideoService(g_Windowing.Get3DDevice(), IID_IDirectXVideoDecoderService, (void**)&m_service))
500 CHECK(m_service->GetDecoderDeviceGuids(&input_count, &input_list))
501 SCOPE(GUID, input_list);
503 for(unsigned i = 0; i < input_count; i++)
505 const GUID *g = &input_list[i];
506 const dxva2_mode_t *mode = dxva2_find_mode(g);
508 CLog::Log(LOGDEBUG, "DXVA - supports '%s'", mode->name);
510 CLog::Log(LOGDEBUG, "DXVA - supports %s", GUIDToString(*g).c_str());
513 m_format.Format = D3DFMT_UNKNOWN;
514 for(const dxva2_mode_t* mode = dxva2_modes; mode->name && m_format.Format == D3DFMT_UNKNOWN; mode++)
516 if(mode->codec != avctx->codec_id)
519 for(unsigned j = 0; j < input_count; j++)
521 if(!IsEqualGUID(input_list[j], *mode->guid))
524 CLog::Log(LOGDEBUG, "DXVA - trying '%s'", mode->name);
525 if(OpenTarget(input_list[j]))
530 if(m_format.Format == D3DFMT_UNKNOWN)
532 CLog::Log(LOGDEBUG, "DXVA - unable to find an input/output format combination");
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;
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;
546 m_format.SampleFormat.NominalRange = DXVA2_NominalRange_Unknown;
548 switch(avctx->chroma_sample_location)
550 case AVCHROMA_LOC_LEFT:
551 m_format.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Horizontally_Cosited
552 | DXVA2_VideoChromaSubsampling_Vertically_AlignedChromaPlanes;
554 case AVCHROMA_LOC_CENTER:
555 m_format.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Vertically_AlignedChromaPlanes;
557 case AVCHROMA_LOC_TOPLEFT:
558 m_format.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Horizontally_Cosited
559 | DXVA2_VideoChromaSubsampling_Vertically_Cosited;
562 m_format.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Unknown;
565 switch(avctx->colorspace)
567 case AVCOL_SPC_BT709:
568 m_format.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT709;
570 case AVCOL_SPC_BT470BG:
571 case AVCOL_SPC_SMPTE170M:
572 m_format.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT601;
574 case AVCOL_SPC_SMPTE240M:
575 m_format.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_SMPTE240M;
578 case AVCOL_SPC_UNSPECIFIED:
581 m_format.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_Unknown;
584 switch(avctx->color_primaries)
586 case AVCOL_PRI_BT709:
587 m_format.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT709;
589 case AVCOL_PRI_BT470M:
590 m_format.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT470_2_SysM;
592 case AVCOL_PRI_BT470BG:
593 m_format.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT470_2_SysBG;
595 case AVCOL_PRI_SMPTE170M:
596 m_format.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_SMPTE170M;
598 case AVCOL_PRI_SMPTE240M:
599 m_format.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_SMPTE240M;
602 case AVCOL_PRI_UNSPECIFIED:
604 m_format.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_Unknown;
607 switch(avctx->color_trc)
609 case AVCOL_TRC_BT709:
610 m_format.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_709;
612 case AVCOL_TRC_GAMMA22:
613 m_format.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_22;
615 case AVCOL_TRC_GAMMA28:
616 m_format.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_28;
619 m_format.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_Unknown;
622 if (avctx->time_base.den > 0 && avctx->time_base.num > 0)
624 m_format.InputSampleFreq.Numerator = avctx->time_base.num;
625 m_format.InputSampleFreq.Denominator = avctx->time_base.den;
627 m_format.OutputFrameFreq = m_format.InputSampleFreq;
628 m_format.UABProtectionLevel = FALSE;
629 m_format.Reserved = 0;
631 if (surfaces > m_shared)
634 if(avctx->refs > m_refs)
635 m_refs = avctx->refs;
639 if(avctx->codec_id == AV_CODEC_ID_H264)
644 CLog::Log(LOGDEBUG, "DXVA - source requires %d references", avctx->refs);
646 // find what decode configs are available
648 DXVA2_ConfigPictureDecode *cfg_list = NULL;
649 CHECK(m_service->GetDecoderConfigurations(m_input
654 SCOPE(DXVA2_ConfigPictureDecode, cfg_list);
656 DXVA2_ConfigPictureDecode config = {};
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++)
662 "DXVA - config %d: bitstream type %d%s",
664 cfg_list[i].ConfigBitstreamRaw,
665 IsEqualGUID(cfg_list[i].guidConfigBitstreamEncryption, DXVA_NoEncrypt) ? "" : ", encrypted");
667 // select first available
668 if(config.ConfigBitstreamRaw == 0 && cfg_list[i].ConfigBitstreamRaw != 0)
669 config = cfg_list[i];
671 // overide with preferred if found
672 if(config.ConfigBitstreamRaw != bitstream && cfg_list[i].ConfigBitstreamRaw == bitstream)
673 config = cfg_list[i];
676 if(!config.ConfigBitstreamRaw)
678 CLog::Log(LOGDEBUG, "DXVA - failed to find a raw input bitstream");
681 *const_cast<DXVA2_ConfigPictureDecode*>(m_context->cfg) = config;
683 m_surface_context = new CSurfaceContext();
688 avctx->get_buffer = GetBufferS;
689 avctx->release_buffer = RelBufferS;
690 avctx->hwaccel_context = m_context;
692 if (IsL41LimitedATI())
694 #ifdef FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG
695 m_context->workaround |= FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG;
697 CLog::Log(LOGWARNING, "DXVA - video card with different scaling list zigzag order detected, but no support in libavcodec");
705 int CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame)
707 CSingleLock lock(m_section);
708 int result = Check(avctx);
714 for(unsigned i = 0; i < m_buffer_count; i++)
716 if(m_buffer[i].surface == (IDirect3DSurface9*)frame->data[3])
717 return VC_BUFFER | VC_PICTURE;
719 CLog::Log(LOGWARNING, "DXVA - ignoring invalid surface");
726 bool CDecoder::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture)
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];
737 int CDecoder::Check(AVCodecContext* avctx)
739 CSingleLock lock(m_section);
741 if(m_state == DXVA_RESET)
744 if(m_state == DXVA_LOST)
748 m_event.WaitMSec(2000);
750 if(m_state == DXVA_LOST)
752 CLog::Log(LOGERROR, "CDecoder::Check - device didn't reset in reasonable time");
757 if(m_format.SampleWidth == 0
758 || m_format.SampleHeight == 0)
760 if(!Open(avctx, avctx->pix_fmt, m_shared))
762 CLog::Log(LOGERROR, "CDecoder::Check - decoder was not able to reset");
770 if(avctx->refs > m_refs)
772 CLog::Log(LOGWARNING, "CDecoder::Check - number of required reference frames increased, recreating decoder");
773 #if ALLOW_ADDING_SURFACES
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)
789 DXVA2_DecodeExecuteParams params = {};
790 DXVA2_DecodeExtensionData data = {};
792 DXVA_Status_H264 h264;
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);
801 if(FAILED( hr = m_decoder->Execute(¶ms)))
803 CLog::Log(LOGWARNING, "DXVA - failed to get decoder status - 0x%08X", hr);
807 if(avctx->codec_id == AV_CODEC_ID_H264)
809 if(status.h264.bStatus)
810 CLog::Log(LOGWARNING, "DXVA - decoder problem of status %d with %d", status.h264.bStatus, status.h264.bBufType);
814 if(status.vc1.bStatus)
815 CLog::Log(LOGWARNING, "DXVA - decoder problem of status %d with %d", status.vc1.bStatus, status.vc1.bBufType);
820 bool CDecoder::OpenTarget(const GUID &guid)
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);
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])
832 m_format.Format = output_list[k];
839 bool CDecoder::OpenDecoder()
841 SAFE_RELEASE(m_decoder);
842 m_context->decoder = NULL;
844 m_context->surface_count = m_refs + 1 + 1 + m_shared; // refs + 1 decode + 1 libavcodec safety + processor buffer
846 if(m_context->surface_count > m_buffer_count)
848 CLog::Log(LOGDEBUG, "DXVA - allocating %d surfaces", m_context->surface_count - m_buffer_count);
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
856 , DXVA2_VideoDecoderRenderTarget
857 , m_context->surface + m_buffer_count, NULL ));
859 for(unsigned i = m_buffer_count; i < m_context->surface_count; i++)
861 m_buffer[i].surface = m_context->surface[i];
862 m_surface_context->HoldSurface(m_context->surface[i]);
865 m_buffer_count = m_context->surface_count;
868 CHECK(m_service->CreateVideoDecoder(m_input, &m_format
871 , m_context->surface_count
874 m_context->decoder = m_decoder;
879 bool CDecoder::Supports(enum PixelFormat fmt)
881 if(fmt == PIX_FMT_DXVA2_VLD)
886 void CDecoder::RelBuffer(AVCodecContext *avctx, AVFrame *pic)
888 CSingleLock lock(m_section);
889 IDirect3DSurface9* surface = (IDirect3DSurface9*)pic->data[3];
891 for(unsigned i = 0; i < m_buffer_count; i++)
893 if(m_buffer[i].surface == surface)
895 m_buffer[i].used = false;
896 m_buffer[i].age = ++m_buffer_age;
900 for(unsigned i = 0; i < 4; i++)
904 int CDecoder::GetBuffer(AVCodecContext *avctx, AVFrame *pic)
906 CSingleLock lock(m_section);
907 if(avctx->coded_width != m_format.SampleWidth
908 || avctx->coded_height != m_format.SampleHeight)
911 if(!Open(avctx, avctx->pix_fmt, m_shared))
919 SVideoBuffer* buf = NULL;
920 for(unsigned i = 0; i < m_buffer_count; i++)
926 if(!buf || buf->age > m_buffer[i].age)
931 if(count >= m_refs+2)
934 #if ALLOW_ADDING_SURFACES
937 return GetBuffer(avctx, pic);
946 CLog::Log(LOGERROR, "DXVA - unable to find new unused buffer");
950 pic->reordered_opaque = avctx->reordered_opaque;
951 pic->type = FF_BUFFER_TYPE_USER;
953 for(unsigned i = 0; i < 4; i++)
956 pic->linesize[i] = 0;
959 pic->data[0] = (uint8_t*)buf->surface;
960 pic->data[3] = (uint8_t*)buf->surface;
966 unsigned CDecoder::GetAllowedReferences()
972 //---------------------------------------------------------------------------
973 //---------------------------------------------------------------------------
974 //------------------------ PROCESSING SERVICE -------------------------------
975 //---------------------------------------------------------------------------
976 //---------------------------------------------------------------------------
978 CProcessor::CProcessor()
983 g_Windowing.Register(this);
988 m_progressive = true;
991 CProcessor::~CProcessor()
993 g_Windowing.Unregister(this);
997 void CProcessor::UnInit()
999 CSingleLock lock(m_section);
1001 SAFE_RELEASE(m_service);
1004 void CProcessor::Close()
1006 CSingleLock lock(m_section);
1007 SAFE_RELEASE(m_process);
1008 for(unsigned i = 0; i < m_sample.size(); i++)
1010 SAFE_RELEASE(m_sample[i].context);
1011 SAFE_RELEASE(m_sample[i].sample.SrcSurface);
1015 SAFE_RELEASE(m_context);
1018 for (unsigned i = 0; i < m_size; i++)
1019 SAFE_RELEASE(m_surfaces[i]);
1025 bool CProcessor::UpdateSize(const DXVA2_VideoDesc& dsc)
1027 // TODO: print the D3FORMAT text version in log
1028 CLog::Log(LOGDEBUG, "DXVA - checking samples array size using %d render target", dsc.Format);
1030 GUID* deint_guid_list = NULL;
1031 unsigned guid_count = 0;
1032 if (FAILED(m_service->GetVideoProcessorDeviceGuids(&dsc, &guid_count, &deint_guid_list)))
1035 SCOPE(GUID, deint_guid_list);
1037 for (unsigned i = 0; i < guid_count; i++)
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)
1043 m_size = caps.NumBackwardRefSamples + caps.NumForwardRefSamples;
1044 CLog::Log(LOGDEBUG, "DXVA - updated maximum samples count to %d", m_size);
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);
1053 bool CProcessor::PreInit()
1060 CSingleLock lock(m_section);
1062 if (FAILED(g_DXVA2CreateVideoService(g_Windowing.Get3DDevice(), IID_IDirectXVideoProcessorService, (void**)&m_service)))
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;
1073 m_max_back_refs = 0;
1076 for (unsigned i = 0; render_targets[i] != D3DFMT_UNKNOWN; i++)
1078 dsc.Format = render_targets[i];
1079 if (!UpdateSize(dsc))
1080 CLog::Log(LOGDEBUG, "DXVA - render target not supported by processor");
1083 m_size = m_max_back_refs + 1 + m_max_fwd_refs + 2; // refs + 1 display + 2 safety frames
1088 bool CProcessor::Open(UINT width, UINT height, unsigned int flags, unsigned int format, unsigned int extended_format)
1092 CSingleLock lock(m_section);
1097 DXVA2_VideoDesc dsc;
1098 memset(&dsc, 0, sizeof(DXVA2_VideoDesc));
1100 dsc.SampleWidth = width;
1101 dsc.SampleHeight = height;
1102 dsc.SampleFormat.VideoLighting = DXVA2_VideoLighting_dim;
1104 switch (CONF_FLAGS_CHROMA_MASK(flags))
1106 case CONF_FLAGS_CHROMA_LEFT:
1107 dsc.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Horizontally_Cosited
1108 | DXVA2_VideoChromaSubsampling_Vertically_AlignedChromaPlanes;
1110 case CONF_FLAGS_CHROMA_CENTER:
1111 dsc.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Vertically_AlignedChromaPlanes;
1113 case CONF_FLAGS_CHROMA_TOPLEFT:
1114 dsc.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Horizontally_Cosited
1115 | DXVA2_VideoChromaSubsampling_Vertically_Cosited;
1118 dsc.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Unknown;
1121 if (flags & CONF_FLAGS_YUV_FULLRANGE)
1122 dsc.SampleFormat.NominalRange = DXVA2_NominalRange_0_255;
1124 dsc.SampleFormat.NominalRange = DXVA2_NominalRange_16_235;
1126 switch (CONF_FLAGS_YUVCOEF_MASK(flags))
1128 case CONF_FLAGS_YUVCOEF_240M:
1129 dsc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_SMPTE240M;
1131 case CONF_FLAGS_YUVCOEF_BT601:
1132 dsc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT601;
1134 case CONF_FLAGS_YUVCOEF_BT709:
1135 dsc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT709;
1138 dsc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_Unknown;
1141 switch (CONF_FLAGS_COLPRI_MASK(flags))
1143 case CONF_FLAGS_COLPRI_BT709:
1144 dsc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT709;
1146 case CONF_FLAGS_COLPRI_BT470M:
1147 dsc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT470_2_SysM;
1149 case CONF_FLAGS_COLPRI_BT470BG:
1150 dsc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT470_2_SysBG;
1152 case CONF_FLAGS_COLPRI_170M:
1153 dsc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_SMPTE170M;
1155 case CONF_FLAGS_COLPRI_240M:
1156 dsc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_SMPTE240M;
1159 dsc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_Unknown;
1162 switch (CONF_FLAGS_TRC_MASK(flags))
1164 case CONF_FLAGS_TRC_BT709:
1165 dsc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_709;
1167 case CONF_FLAGS_TRC_GAMMA22:
1168 dsc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_22;
1170 case CONF_FLAGS_TRC_GAMMA28:
1171 dsc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_28;
1174 dsc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_Unknown;
1179 if (format == RENDER_FMT_DXVA)
1180 m_desc.Format = (D3DFORMAT)extended_format;
1183 // Only NV12 software colorspace conversion is implemented for now
1184 m_desc.Format = (D3DFORMAT)MAKEFOURCC('N','V','1','2');
1185 if (!CreateSurfaces())
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);;
1197 EvaluateQuirkNoDeintProcForProg();
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.");
1202 if (!OpenProcessor())
1210 void CProcessor::EvaluateQuirkNoDeintProcForProg()
1212 D3DADAPTER_IDENTIFIER9 AIdentifier = g_Windowing.GetAIdentifier();
1214 for (unsigned idx = 0; NoDeintProcForProgDevices[idx].VendorID != 0; idx++)
1216 if(NoDeintProcForProgDevices[idx].VendorID == AIdentifier.VendorId
1217 && NoDeintProcForProgDevices[idx].DeviceID == AIdentifier.DeviceId)
1219 m_quirk_nodeintprocforprog = true;
1223 m_quirk_nodeintprocforprog = false;
1226 bool CProcessor::SelectProcessor()
1228 // The CProcessor can be run after dxva or software decoding, possibly after software deinterlacing.
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);
1237 m_desc.SampleFormat.SampleFormat = DXVA2_SampleProgressiveFrame;
1239 m_desc.SampleFormat.SampleFormat = DXVA2_SampleFieldInterleavedEvenFirst;
1242 unsigned guid_count;
1243 CHECK(m_service->GetVideoProcessorDeviceGuids(&m_desc, &guid_count, &guid_list));
1244 SCOPE(GUID, guid_list);
1248 CLog::Log(LOGDEBUG, "DXVA - unable to find any processors");
1252 for(unsigned i = 0; i < guid_count; i++)
1254 const GUID* g = &guid_list[i];
1255 const dxva2_device_t* device = dxva2_find_device(g);
1259 CLog::Log(LOGDEBUG, "DXVA - processor found %s", device->name);
1263 CHECK(m_service->GetVideoProcessorCaps(*g, &m_desc, D3DFMT_X8R8G8B8, &m_caps));
1264 const dxva2_deinterlacetech_t* tech = dxva2_find_deinterlacetech(m_caps.DeinterlaceTechnology);
1266 CLog::Log(LOGDEBUG, "DXVA - unknown processor %s found, deinterlace technology %s", GUIDToString(*g).c_str(), tech->name);
1268 CLog::Log(LOGDEBUG, "DXVA - unknown processor %s found, unknown technology", GUIDToString(*g).c_str());
1273 m_device = DXVA2_VideoProcProgressiveDevice;
1274 else if(m_interlace_method == VS_INTERLACEMETHOD_DXVA_BEST)
1275 m_device = guid_list[0];
1277 m_device = DXVA2_VideoProcBobDevice;
1282 bool CProcessor::OpenProcessor()
1284 if (!SelectProcessor())
1287 SAFE_RELEASE(m_process);
1289 const dxva2_device_t* device = dxva2_find_device(&m_device);
1291 CLog::Log(LOGDEBUG, "DXVA - processor selected %s", device->name);
1293 CLog::Log(LOGDEBUG, "DXVA - processor selected %s", GUIDToString(m_device).c_str());
1295 D3DFORMAT rtFormat = D3DFMT_X8R8G8B8;
1296 CHECK(m_service->GetVideoProcessorCaps(m_device, &m_desc, rtFormat, &m_caps))
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;
1306 if (m_caps.DeviceCaps & DXVA2_VPDev_SoftwareDevice)
1307 CLog::Log(LOGDEBUG, "DXVA - processor is software device");
1309 if (m_caps.DeviceCaps & DXVA2_VPDev_EmulatedDXVA1)
1310 CLog::Log(LOGDEBUG, "DXVA - processor is emulated dxva1");
1312 CLog::Log(LOGDEBUG, "DXVA - processor requires %d past frames and %d future frames", m_caps.NumBackwardRefSamples, m_caps.NumForwardRefSamples);
1314 if (m_caps.NumBackwardRefSamples + m_caps.NumForwardRefSamples + 3 > m_size)
1316 CLog::Log(LOGERROR, "DXVA - used an incorrect number of reference frames creating processor");
1320 CHECK(m_service->CreateVideoProcessor(m_device, &m_desc, rtFormat, 0, &m_process));
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));
1330 bool CProcessor::CreateSurfaces()
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,
1343 m_context = new CSurfaceContext();
1348 REFERENCE_TIME CProcessor::Add(DVDVideoPicture* picture)
1350 CSingleLock lock(m_section);
1352 IDirect3DSurface9* surface = NULL;
1353 CSurfaceContext* context = NULL;
1355 if (picture->iFlags & DVP_FLAG_DROPPED)
1358 switch (picture->format)
1360 case RENDER_FMT_DXVA:
1362 surface = (IDirect3DSurface9*)picture->data[3];
1363 context = picture->context;
1367 case RENDER_FMT_YUV420P:
1369 surface = m_surfaces[m_index];
1370 m_index = (m_index + 1) % m_size;
1372 context = m_context;
1374 D3DLOCKED_RECT rectangle;
1375 if (FAILED(surface->LockRect(&rectangle, NULL, 0)))
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++)
1384 memcpy(bits, s, picture->iWidth);
1385 s += picture->iLineSize[0];
1386 bits += rectangle.Pitch;
1389 D3DSURFACE_DESC desc;
1390 if (FAILED(surface->GetDesc(&desc)))
1393 // Convert to NV12 - Chroma
1394 for (unsigned y = 0; y < picture->iHeight/2; y++)
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++)
1406 if (FAILED(surface->UnlockRect()))
1414 CLog::Log(LOGWARNING, "DXVA - colorspace not supported by processor, skipping frame");
1419 if (!surface || !context)
1427 SVideoSample vs = {};
1428 vs.sample.Start = m_time;
1430 vs.sample.SampleFormat = m_desc.SampleFormat;
1432 if (picture->iFlags & DVP_FLAG_INTERLACED)
1434 if (picture->iFlags & DVP_FLAG_TOP_FIELD_FIRST)
1435 vs.sample.SampleFormat.SampleFormat = DXVA2_SampleFieldInterleavedEvenFirst;
1437 vs.sample.SampleFormat.SampleFormat = DXVA2_SampleFieldInterleavedOddFirst;
1441 vs.sample.SampleFormat.SampleFormat = DXVA2_SampleProgressiveFrame;
1444 vs.sample.PlanarAlpha = DXVA2_Fixed32OpaqueAlpha();
1445 vs.sample.SampleData = 0;
1446 vs.sample.SrcSurface = surface;
1449 vs.context = context;
1451 if(!m_sample.empty())
1452 m_sample.back().sample.End = vs.sample.Start;
1454 m_sample.push_back(vs);
1455 if (m_sample.size() > m_size)
1457 SAFE_RELEASE(m_sample.front().context);
1458 SAFE_RELEASE(m_sample.front().sample.SrcSurface);
1459 m_sample.pop_front();
1465 static DXVA2_Fixed32 ConvertRange(const DXVA2_ValueRange& range, int value, int min, int max, int 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) );
1476 return range.DefaultValue;
1479 bool CProcessor::Render(CRect src, CRect dst, IDirect3DSurface9* target, REFERENCE_TIME time, DWORD flags)
1481 CSingleLock lock(m_section);
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
1494 m_deinterlace_mode = mode;
1495 m_interlace_method = method;
1497 if (!OpenProcessor())
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;
1505 SSamples::iterator it = m_sample.begin();
1506 while (it != m_sample.end())
1508 if (it->sample.Start < MinTime)
1510 SAFE_RELEASE(it->context);
1511 SAFE_RELEASE(it->sample.SrcSurface);
1512 it = m_sample.erase(it);
1518 if(m_sample.empty())
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;
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 };
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.
1538 int count = 1 + m_caps.NumBackwardRefSamples + m_caps.NumForwardRefSamples;
1540 auto_aptr<DXVA2_VideoSample> samp(new DXVA2_VideoSample[count]);
1542 for (int i = 0; i < count; i++)
1543 samp[i].SampleFormat.SampleFormat = DXVA2_SampleUnknown;
1545 for(it = m_sample.begin(); it != m_sample.end() && valid < count; ++it)
1547 if (it->sample.Start >= MinTime && it->sample.Start <= MaxTime)
1549 DXVA2_VideoSample& vs = samp[(it->sample.Start - MinTime) / 2];
1551 vs.SrcRect = sourceRECT;
1552 vs.DstRect = dstRECT;
1554 vs.End = vs.Start + 2;
1556 // Override the sample format when the processor doesn't need to deinterlace or when deinterlacing is forced and flags are missing.
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;
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.
1572 CLog::Log(LOGWARNING, __FUNCTION__" - did not find all required samples, adjusting the sample array.");
1574 for (int i = 0; i < count; i++)
1576 if (samp[i].SampleFormat.SampleFormat == DXVA2_SampleUnknown)
1582 CLog::Log(LOGWARNING, __FUNCTION__" - no usable samples.");
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;
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;
1600 blt.DestFormat.NominalRange = DXVA2_NominalRange_0_255;
1601 blt.Alpha = DXVA2_Fixed32OpaqueAlpha();
1603 blt.ProcAmpValues.Brightness = ConvertRange( m_brightness, CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness
1605 blt.ProcAmpValues.Contrast = ConvertRange( m_contrast, CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast
1607 blt.ProcAmpValues.Hue = m_hue.DefaultValue;
1608 blt.ProcAmpValues.Saturation = m_saturation.DefaultValue;
1610 blt.BackgroundColor.Y = 0x1000;
1611 blt.BackgroundColor.Cb = 0x8000;
1612 blt.BackgroundColor.Cr = 0x8000;
1613 blt.BackgroundColor.Alpha = 0xffff;
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));
1621 CHECK(m_process->VideoProcessBlt(target, &blt, &samp[offset], count, NULL));