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 "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"
45 #define ALLOW_ADDING_SURFACES 0
48 using namespace AUTOPTR;
51 typedef HRESULT (__stdcall *DXVA2CreateVideoServicePtr)(IDirect3DDevice9* pDD, REFIID riid, void** ppService);
52 static DXVA2CreateVideoServicePtr g_DXVA2CreateVideoService;
54 static bool LoadDXVA()
56 static CCriticalSection g_section;
57 static HMODULE g_handle;
59 CSingleLock lock(g_section);
61 g_handle = LoadLibraryEx("dxva2.dll", NULL, 0);
64 g_DXVA2CreateVideoService = (DXVA2CreateVideoServicePtr)GetProcAddress(g_handle, "DXVA2CreateVideoService");
65 if(g_DXVA2CreateVideoService == NULL)
72 static void RelBufferS(AVCodecContext *avctx, AVFrame *pic)
73 { ((CDecoder*)((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetHardware())->RelBuffer(avctx, pic); }
75 static int GetBufferS(AVCodecContext *avctx, AVFrame *pic)
76 { return ((CDecoder*)((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetHardware())->GetBuffer(avctx, pic); }
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);
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);
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 },
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 },
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, },
116 { "Windows Media Video 8 MoComp", &DXVA2_ModeWMV8_B, 0 },
117 { "Windows Media Video 8 post processing", &DXVA2_ModeWMV8_A, 0 },
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 },
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 },
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);
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 },
161 } dxva2_deinterlacetech_t;
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 },
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'),
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
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
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
246 0x087A, // GeForce 9400
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
269 static CStdString GUIDToString(const GUID& guid)
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]);
280 static const dxva2_mode_t *dxva2_find_mode(const GUID *guid)
282 for (unsigned i = 0; dxva2_modes[i].name; i++) {
283 if (IsEqualGUID(*dxva2_modes[i].guid, *guid))
284 return &dxva2_modes[i];
289 static const dxva2_device_t *dxva2_find_device(const GUID *guid)
291 for (unsigned i = 0; dxva2_devices[i].name; i++) {
292 if (IsEqualGUID(*dxva2_devices[i].guid, *guid))
293 return &dxva2_devices[i];
298 static const dxva2_deinterlacetech_t *dxva2_find_deinterlacetech(unsigned flags)
300 for (unsigned i = 0; dxva2_deinterlacetechs[i].name; i++) {
301 if (dxva2_deinterlacetechs[i].flags == flags)
302 return &dxva2_deinterlacetechs[i];
307 #define SCOPE(type, var) boost::shared_ptr<type> var##_holder(var, CoTaskMemFree);
309 CSurfaceContext::CSurfaceContext()
313 CSurfaceContext::~CSurfaceContext()
315 for (vector<IDirect3DSurface9*>::iterator it = m_heldsurfaces.begin(); it != m_heldsurfaces.end(); it++)
319 void CSurfaceContext::HoldSurface(IDirect3DSurface9* surface)
322 m_heldsurfaces.push_back(surface);
325 CDecoder::SVideoBuffer::SVideoBuffer()
331 CDecoder::SVideoBuffer::~SVideoBuffer()
336 void CDecoder::SVideoBuffer::Clear()
338 SAFE_RELEASE(surface);
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);
363 CDecoder::~CDecoder()
365 g_Windowing.Unregister(this);
367 free(m_context->surface);
368 free(const_cast<DXVA2_ConfigPictureDecode*>(m_context->cfg)); // yes this is foobar
372 void CDecoder::Close()
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++)
381 memset(&m_format, 0, sizeof(m_format));
389 CLog::Log(LOGERROR, "DXVA - failed executing "#a" at line %d with error %x", __LINE__, res); \
394 static bool CheckH264L41(AVCodecContext *avctx)
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
400 return (avctx->refs * widthmbs * heightmbs <= maxdpbmbs);
403 static bool IsL41LimitedATI()
405 D3DADAPTER_IDENTIFIER9 AIdentifier = g_Windowing.GetAIdentifier();
407 if(AIdentifier.VendorId == PCIV_ATI)
409 for (unsigned idx = 0; UVDDeviceID[idx] != 0; idx++)
411 if (UVDDeviceID[idx] == AIdentifier.DeviceId)
418 static bool HasVP3WidthBug(AVCodecContext *avctx)
420 // Some nVidia VP3 hardware cannot do certain macroblock widths
422 D3DADAPTER_IDENTIFIER9 AIdentifier = g_Windowing.GetAIdentifier();
424 if(AIdentifier.VendorId == PCIV_nVidia
425 && !CDVDCodecUtils::IsVP3CompatibleWidth(avctx->coded_width))
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)
435 static bool CheckCompatibility(AVCodecContext *avctx)
437 // The incompatibilities are all for H264
438 if(avctx->codec_id != CODEC_ID_H264)
441 // Macroblock width incompatibility
442 if (HasVP3WidthBug(avctx))
444 CLog::Log(LOGWARNING,"DXVA - width %i is not supported with nVidia VP3 hardware. DXVA will not be used", avctx->coded_width);
448 // Check for hardware limited to H264 L4.1 (ie Bluray).
450 // No advanced settings: autodetect.
451 // The advanced setting lets the user override the autodetection (in case of false positive or negative)
454 if (!g_advancedSettings.m_DXVACheckCompatibilityPresent)
455 checkcompat = IsL41LimitedATI(); // ATI UVD and UVD+ cards can only do L4.1 - corresponds roughly to series 3xxx
457 checkcompat = g_advancedSettings.m_DXVACheckCompatibility;
459 if (checkcompat && !CheckH264L41(avctx))
461 CLog::Log(LOGWARNING, "DXVA - compatibility check: video exceeds L4.1. DXVA will not be used.");
468 bool CDecoder::Open(AVCodecContext *avctx, enum PixelFormat fmt, unsigned int surfaces)
470 if (!CheckCompatibility(avctx))
476 CSingleLock lock(m_section);
479 if(m_state == DXVA_LOST)
481 CLog::Log(LOGDEBUG, "DXVA - device is in lost state, we can't start");
485 CHECK(g_DXVA2CreateVideoService(g_Windowing.Get3DDevice(), IID_IDirectXVideoDecoderService, (void**)&m_service))
490 CHECK(m_service->GetDecoderDeviceGuids(&input_count, &input_list))
491 SCOPE(GUID, input_list);
493 for(unsigned i = 0; i < input_count; i++)
495 const GUID *g = &input_list[i];
496 const dxva2_mode_t *mode = dxva2_find_mode(g);
498 CLog::Log(LOGDEBUG, "DXVA - supports '%s'", mode->name);
500 CLog::Log(LOGDEBUG, "DXVA - supports %s", GUIDToString(*g).c_str());
503 m_format.Format = D3DFMT_UNKNOWN;
504 for(const dxva2_mode_t* mode = dxva2_modes; mode->name && m_format.Format == D3DFMT_UNKNOWN; mode++)
506 if(mode->codec != avctx->codec_id)
509 for(unsigned j = 0; j < input_count; j++)
511 if(!IsEqualGUID(input_list[j], *mode->guid))
514 CLog::Log(LOGDEBUG, "DXVA - trying '%s'", mode->name);
515 if(OpenTarget(input_list[j]))
520 if(m_format.Format == D3DFMT_UNKNOWN)
522 CLog::Log(LOGDEBUG, "DXVA - unable to find an input/output format combination");
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;
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;
536 m_format.SampleFormat.NominalRange = DXVA2_NominalRange_Unknown;
538 switch(avctx->chroma_sample_location)
540 case AVCHROMA_LOC_LEFT:
541 m_format.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Horizontally_Cosited
542 | DXVA2_VideoChromaSubsampling_Vertically_AlignedChromaPlanes;
544 case AVCHROMA_LOC_CENTER:
545 m_format.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Vertically_AlignedChromaPlanes;
547 case AVCHROMA_LOC_TOPLEFT:
548 m_format.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Horizontally_Cosited
549 | DXVA2_VideoChromaSubsampling_Vertically_Cosited;
552 m_format.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Unknown;
555 switch(avctx->colorspace)
557 case AVCOL_SPC_BT709:
558 m_format.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT709;
560 case AVCOL_SPC_BT470BG:
561 case AVCOL_SPC_SMPTE170M:
562 m_format.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT601;
564 case AVCOL_SPC_SMPTE240M:
565 m_format.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_SMPTE240M;
568 case AVCOL_SPC_UNSPECIFIED:
571 m_format.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_Unknown;
574 switch(avctx->color_primaries)
576 case AVCOL_PRI_BT709:
577 m_format.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT709;
579 case AVCOL_PRI_BT470M:
580 m_format.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT470_2_SysM;
582 case AVCOL_PRI_BT470BG:
583 m_format.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT470_2_SysBG;
585 case AVCOL_PRI_SMPTE170M:
586 m_format.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_SMPTE170M;
588 case AVCOL_PRI_SMPTE240M:
589 m_format.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_SMPTE240M;
592 case AVCOL_PRI_UNSPECIFIED:
594 m_format.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_Unknown;
597 switch(avctx->color_trc)
599 case AVCOL_TRC_BT709:
600 m_format.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_709;
602 case AVCOL_TRC_GAMMA22:
603 m_format.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_22;
605 case AVCOL_TRC_GAMMA28:
606 m_format.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_28;
609 m_format.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_Unknown;
612 if (avctx->time_base.den > 0 && avctx->time_base.num > 0)
614 m_format.InputSampleFreq.Numerator = avctx->time_base.num;
615 m_format.InputSampleFreq.Denominator = avctx->time_base.den;
617 m_format.OutputFrameFreq = m_format.InputSampleFreq;
618 m_format.UABProtectionLevel = FALSE;
619 m_format.Reserved = 0;
621 if (surfaces > m_shared)
624 if(avctx->refs > m_refs)
625 m_refs = avctx->refs;
629 if(avctx->codec_id == CODEC_ID_H264)
634 CLog::Log(LOGDEBUG, "DXVA - source requires %d references", avctx->refs);
636 // find what decode configs are available
638 DXVA2_ConfigPictureDecode *cfg_list = NULL;
639 CHECK(m_service->GetDecoderConfigurations(m_input
644 SCOPE(DXVA2_ConfigPictureDecode, cfg_list);
646 DXVA2_ConfigPictureDecode config = {};
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++)
652 "DXVA - config %d: bitstream type %d%s",
654 cfg_list[i].ConfigBitstreamRaw,
655 IsEqualGUID(cfg_list[i].guidConfigBitstreamEncryption, DXVA_NoEncrypt) ? "" : ", encrypted");
657 // select first available
658 if(config.ConfigBitstreamRaw == 0 && cfg_list[i].ConfigBitstreamRaw != 0)
659 config = cfg_list[i];
661 // overide with preferred if found
662 if(config.ConfigBitstreamRaw != bitstream && cfg_list[i].ConfigBitstreamRaw == bitstream)
663 config = cfg_list[i];
666 if(!config.ConfigBitstreamRaw)
668 CLog::Log(LOGDEBUG, "DXVA - failed to find a raw input bitstream");
671 *const_cast<DXVA2_ConfigPictureDecode*>(m_context->cfg) = config;
673 m_surface_context = new CSurfaceContext();
678 avctx->get_buffer = GetBufferS;
679 avctx->release_buffer = RelBufferS;
680 avctx->hwaccel_context = m_context;
682 if (IsL41LimitedATI())
684 #ifdef FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG
685 m_context->workaround |= FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG;
687 CLog::Log(LOGWARNING, "DXVA - video card with different scaling list zigzag order detected, but no support in libavcodec");
695 int CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame)
697 CSingleLock lock(m_section);
698 int result = Check(avctx);
704 for(unsigned i = 0; i < m_buffer_count; i++)
706 if(m_buffer[i].surface == (IDirect3DSurface9*)frame->data[3])
707 return VC_BUFFER | VC_PICTURE;
709 CLog::Log(LOGWARNING, "DXVA - ignoring invalid surface");
716 bool CDecoder::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture)
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];
727 int CDecoder::Check(AVCodecContext* avctx)
729 CSingleLock lock(m_section);
731 if(m_state == DXVA_RESET)
734 if(m_state == DXVA_LOST)
738 m_event.WaitMSec(2000);
740 if(m_state == DXVA_LOST)
742 CLog::Log(LOGERROR, "CDecoder::Check - device didn't reset in reasonable time");
747 if(m_format.SampleWidth == 0
748 || m_format.SampleHeight == 0)
750 if(!Open(avctx, avctx->pix_fmt, m_shared))
752 CLog::Log(LOGERROR, "CDecoder::Check - decoder was not able to reset");
760 if(avctx->refs > m_refs)
762 CLog::Log(LOGWARNING, "CDecoder::Check - number of required reference frames increased, recreating decoder");
763 #if ALLOW_ADDING_SURFACES
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)
779 DXVA2_DecodeExecuteParams params = {};
780 DXVA2_DecodeExtensionData data = {};
782 DXVA_Status_H264 h264;
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);
791 if(FAILED( hr = m_decoder->Execute(¶ms)))
793 CLog::Log(LOGWARNING, "DXVA - failed to get decoder status - 0x%08X", hr);
797 if(avctx->codec_id == CODEC_ID_H264)
799 if(status.h264.bStatus)
800 CLog::Log(LOGWARNING, "DXVA - decoder problem of status %d with %d", status.h264.bStatus, status.h264.bBufType);
804 if(status.vc1.bStatus)
805 CLog::Log(LOGWARNING, "DXVA - decoder problem of status %d with %d", status.vc1.bStatus, status.vc1.bBufType);
810 bool CDecoder::OpenTarget(const GUID &guid)
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);
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])
822 m_format.Format = output_list[k];
829 bool CDecoder::OpenDecoder()
831 SAFE_RELEASE(m_decoder);
832 m_context->decoder = NULL;
834 m_context->surface_count = m_refs + 1 + 1 + m_shared; // refs + 1 decode + 1 libavcodec safety + processor buffer
836 if(m_context->surface_count > m_buffer_count)
838 CLog::Log(LOGDEBUG, "DXVA - allocating %d surfaces", m_context->surface_count - m_buffer_count);
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
846 , DXVA2_VideoDecoderRenderTarget
847 , m_context->surface + m_buffer_count, NULL ));
849 for(unsigned i = m_buffer_count; i < m_context->surface_count; i++)
851 m_buffer[i].surface = m_context->surface[i];
852 m_surface_context->HoldSurface(m_context->surface[i]);
855 m_buffer_count = m_context->surface_count;
858 CHECK(m_service->CreateVideoDecoder(m_input, &m_format
861 , m_context->surface_count
864 m_context->decoder = m_decoder;
869 bool CDecoder::Supports(enum PixelFormat fmt)
871 if(fmt == PIX_FMT_DXVA2_VLD)
876 void CDecoder::RelBuffer(AVCodecContext *avctx, AVFrame *pic)
878 CSingleLock lock(m_section);
879 IDirect3DSurface9* surface = (IDirect3DSurface9*)pic->data[3];
881 for(unsigned i = 0; i < m_buffer_count; i++)
883 if(m_buffer[i].surface == surface)
885 m_buffer[i].used = false;
886 m_buffer[i].age = ++m_buffer_age;
890 for(unsigned i = 0; i < 4; i++)
894 int CDecoder::GetBuffer(AVCodecContext *avctx, AVFrame *pic)
896 CSingleLock lock(m_section);
897 if(avctx->coded_width != m_format.SampleWidth
898 || avctx->coded_height != m_format.SampleHeight)
901 if(!Open(avctx, avctx->pix_fmt, m_shared))
909 SVideoBuffer* buf = NULL;
910 for(unsigned i = 0; i < m_buffer_count; i++)
916 if(!buf || buf->age > m_buffer[i].age)
921 if(count >= m_refs+2)
924 #if ALLOW_ADDING_SURFACES
927 return GetBuffer(avctx, pic);
936 CLog::Log(LOGERROR, "DXVA - unable to find new unused buffer");
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++)
946 pic->linesize[i] = 0;
949 pic->data[0] = (uint8_t*)buf->surface;
950 pic->data[3] = (uint8_t*)buf->surface;
956 //---------------------------------------------------------------------------
957 //---------------------------------------------------------------------------
958 //------------------------ PROCESSING SERVICE -------------------------------
959 //---------------------------------------------------------------------------
960 //---------------------------------------------------------------------------
962 CProcessor::CProcessor()
967 g_Windowing.Register(this);
972 m_progressive = true;
975 CProcessor::~CProcessor()
977 g_Windowing.Unregister(this);
981 void CProcessor::UnInit()
983 CSingleLock lock(m_section);
985 SAFE_RELEASE(m_service);
988 void CProcessor::Close()
990 CSingleLock lock(m_section);
991 SAFE_RELEASE(m_process);
992 for(unsigned i = 0; i < m_sample.size(); i++)
994 SAFE_RELEASE(m_sample[i].context);
995 SAFE_RELEASE(m_sample[i].sample.SrcSurface);
999 SAFE_RELEASE(m_context);
1002 for (unsigned i = 0; i < m_size; i++)
1003 SAFE_RELEASE(m_surfaces[i]);
1009 bool CProcessor::UpdateSize(const DXVA2_VideoDesc& dsc)
1011 // TODO: print the D3FORMAT text version in log
1012 CLog::Log(LOGDEBUG, "DXVA - cheking samples array size using %d render target", dsc.Format);
1014 GUID* deint_guid_list = NULL;
1015 unsigned guid_count = 0;
1016 if (FAILED(m_service->GetVideoProcessorDeviceGuids(&dsc, &guid_count, &deint_guid_list)))
1019 SCOPE(GUID, deint_guid_list);
1021 for (unsigned i = 0; i < guid_count; i++)
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)
1027 m_size = caps.NumBackwardRefSamples + caps.NumForwardRefSamples;
1028 CLog::Log(LOGDEBUG, "DXVA - updated maximum samples count to %d", m_size);
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);
1037 bool CProcessor::PreInit()
1044 CSingleLock lock(m_section);
1046 if (FAILED(g_DXVA2CreateVideoService(g_Windowing.Get3DDevice(), IID_IDirectXVideoProcessorService, (void**)&m_service)))
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;
1057 m_max_back_refs = 0;
1060 for (unsigned i = 0; render_targets[i] != D3DFMT_UNKNOWN; i++)
1062 dsc.Format = render_targets[i];
1063 if (!UpdateSize(dsc))
1064 CLog::Log(LOGDEBUG, "DXVA - render target not supported by processor");
1067 m_size = m_max_back_refs + 1 + m_max_fwd_refs + 2; // refs + 1 display + 2 safety frames
1072 bool CProcessor::Open(UINT width, UINT height, unsigned int flags, unsigned int format, unsigned int extended_format)
1076 CSingleLock lock(m_section);
1081 DXVA2_VideoDesc dsc;
1082 memset(&dsc, 0, sizeof(DXVA2_VideoDesc));
1084 dsc.SampleWidth = width;
1085 dsc.SampleHeight = height;
1086 dsc.SampleFormat.VideoLighting = DXVA2_VideoLighting_dim;
1088 switch (CONF_FLAGS_CHROMA_MASK(flags))
1090 case CONF_FLAGS_CHROMA_LEFT:
1091 dsc.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Horizontally_Cosited
1092 | DXVA2_VideoChromaSubsampling_Vertically_AlignedChromaPlanes;
1094 case CONF_FLAGS_CHROMA_CENTER:
1095 dsc.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Vertically_AlignedChromaPlanes;
1097 case CONF_FLAGS_CHROMA_TOPLEFT:
1098 dsc.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Horizontally_Cosited
1099 | DXVA2_VideoChromaSubsampling_Vertically_Cosited;
1102 dsc.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Unknown;
1105 if (flags & CONF_FLAGS_YUV_FULLRANGE)
1106 dsc.SampleFormat.NominalRange = DXVA2_NominalRange_0_255;
1108 dsc.SampleFormat.NominalRange = DXVA2_NominalRange_16_235;
1110 switch (CONF_FLAGS_YUVCOEF_MASK(flags))
1112 case CONF_FLAGS_YUVCOEF_240M:
1113 dsc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_SMPTE240M;
1115 case CONF_FLAGS_YUVCOEF_BT601:
1116 dsc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT601;
1118 case CONF_FLAGS_YUVCOEF_BT709:
1119 dsc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT709;
1122 dsc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_Unknown;
1125 switch (CONF_FLAGS_COLPRI_MASK(flags))
1127 case CONF_FLAGS_COLPRI_BT709:
1128 dsc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT709;
1130 case CONF_FLAGS_COLPRI_BT470M:
1131 dsc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT470_2_SysM;
1133 case CONF_FLAGS_COLPRI_BT470BG:
1134 dsc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT470_2_SysBG;
1136 case CONF_FLAGS_COLPRI_170M:
1137 dsc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_SMPTE170M;
1139 case CONF_FLAGS_COLPRI_240M:
1140 dsc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_SMPTE240M;
1143 dsc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_Unknown;
1146 switch (CONF_FLAGS_TRC_MASK(flags))
1148 case CONF_FLAGS_TRC_BT709:
1149 dsc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_709;
1151 case CONF_FLAGS_TRC_GAMMA22:
1152 dsc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_22;
1154 case CONF_FLAGS_TRC_GAMMA28:
1155 dsc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_28;
1158 dsc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_Unknown;
1163 if (format == RENDER_FMT_DXVA)
1164 m_desc.Format = (D3DFORMAT)extended_format;
1167 // Only NV12 software colorspace conversion is implemented for now
1168 m_desc.Format = (D3DFORMAT)MAKEFOURCC('N','V','1','2');
1169 if (!CreateSurfaces())
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);;
1181 EvaluateQuirkNoDeintProcForProg();
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.");
1186 if (!OpenProcessor())
1194 void CProcessor::EvaluateQuirkNoDeintProcForProg()
1196 D3DADAPTER_IDENTIFIER9 AIdentifier = g_Windowing.GetAIdentifier();
1198 for (unsigned idx = 0; NoDeintProcForProgDevices[idx].VendorID != 0; idx++)
1200 if(NoDeintProcForProgDevices[idx].VendorID == AIdentifier.VendorId
1201 && NoDeintProcForProgDevices[idx].DeviceID == AIdentifier.DeviceId)
1203 m_quirk_nodeintprocforprog = true;
1207 m_quirk_nodeintprocforprog = false;
1210 bool CProcessor::SelectProcessor()
1212 // The CProcessor can be run after dxva or software decoding, possibly after software deinterlacing.
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);
1221 m_desc.SampleFormat.SampleFormat = DXVA2_SampleProgressiveFrame;
1223 m_desc.SampleFormat.SampleFormat = DXVA2_SampleFieldInterleavedEvenFirst;
1226 unsigned guid_count;
1227 CHECK(m_service->GetVideoProcessorDeviceGuids(&m_desc, &guid_count, &guid_list));
1228 SCOPE(GUID, guid_list);
1232 CLog::Log(LOGDEBUG, "DXVA - unable to find any processors");
1236 for(unsigned i = 0; i < guid_count; i++)
1238 const GUID* g = &guid_list[i];
1239 const dxva2_device_t* device = dxva2_find_device(g);
1243 CLog::Log(LOGDEBUG, "DXVA - processor found %s", device->name);
1247 CHECK(m_service->GetVideoProcessorCaps(*g, &m_desc, D3DFMT_X8R8G8B8, &m_caps));
1248 const dxva2_deinterlacetech_t* tech = dxva2_find_deinterlacetech(m_caps.DeinterlaceTechnology);
1250 CLog::Log(LOGDEBUG, "DXVA - unknown processor %s found, deinterlace technology %s", GUIDToString(*g).c_str(), tech->name);
1252 CLog::Log(LOGDEBUG, "DXVA - unknown processor %s found, unknown technology", GUIDToString(*g).c_str());
1257 m_device = DXVA2_VideoProcProgressiveDevice;
1258 else if(m_interlace_method == VS_INTERLACEMETHOD_DXVA_BEST)
1259 m_device = guid_list[0];
1261 m_device = DXVA2_VideoProcBobDevice;
1266 bool CProcessor::OpenProcessor()
1268 if (!SelectProcessor())
1271 SAFE_RELEASE(m_process);
1273 const dxva2_device_t* device = dxva2_find_device(&m_device);
1275 CLog::Log(LOGDEBUG, "DXVA - processor selected %s", device->name);
1277 CLog::Log(LOGDEBUG, "DXVA - processor selected %s", GUIDToString(m_device).c_str());
1279 D3DFORMAT rtFormat = D3DFMT_X8R8G8B8;
1280 CHECK(m_service->GetVideoProcessorCaps(m_device, &m_desc, rtFormat, &m_caps))
1282 if (m_caps.DeviceCaps & DXVA2_VPDev_SoftwareDevice)
1283 CLog::Log(LOGDEBUG, "DXVA - processor is software device");
1285 if (m_caps.DeviceCaps & DXVA2_VPDev_EmulatedDXVA1)
1286 CLog::Log(LOGDEBUG, "DXVA - processor is emulated dxva1");
1288 CLog::Log(LOGDEBUG, "DXVA - processor requires %d past frames and %d future frames", m_caps.NumBackwardRefSamples, m_caps.NumForwardRefSamples);
1290 if (m_caps.NumBackwardRefSamples + m_caps.NumForwardRefSamples + 3 > m_size)
1292 CLog::Log(LOGERROR, "DXVA - used an incorrect number of reference frames creating processor");
1296 CHECK(m_service->CreateVideoProcessor(m_device, &m_desc, rtFormat, 0, &m_process));
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));
1306 bool CProcessor::CreateSurfaces()
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,
1319 m_context = new CSurfaceContext();
1324 REFERENCE_TIME CProcessor::Add(DVDVideoPicture* picture)
1326 CSingleLock lock(m_section);
1328 IDirect3DSurface9* surface = NULL;
1329 CSurfaceContext* context = NULL;
1331 if (picture->iFlags & DVP_FLAG_DROPPED)
1334 switch (picture->format)
1336 case RENDER_FMT_DXVA:
1338 surface = (IDirect3DSurface9*)picture->data[3];
1339 context = picture->context;
1343 case RENDER_FMT_YUV420P:
1345 surface = m_surfaces[m_index];
1346 m_index = (m_index + 1) % m_size;
1348 context = m_context;
1350 D3DLOCKED_RECT rectangle;
1351 if (FAILED(surface->LockRect(&rectangle, NULL, 0)))
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++)
1360 memcpy(bits, s, picture->iWidth);
1361 s += picture->iLineSize[0];
1362 bits += rectangle.Pitch;
1365 D3DSURFACE_DESC desc;
1366 if (FAILED(surface->GetDesc(&desc)))
1369 // Convert to NV12 - Chroma
1370 uint8_t *s_u, *s_v, *d_uv;
1371 for (unsigned y = 0; y < picture->iHeight/2; y++)
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++)
1383 if (FAILED(surface->UnlockRect()))
1391 CLog::Log(LOGWARNING, "DXVA - colorspace not supported by processor, skipping frame");
1396 if (!surface || !context)
1404 SVideoSample vs = {};
1405 vs.sample.Start = m_time;
1407 vs.sample.SampleFormat = m_desc.SampleFormat;
1409 if (picture->iFlags & DVP_FLAG_INTERLACED)
1411 if (picture->iFlags & DVP_FLAG_TOP_FIELD_FIRST)
1412 vs.sample.SampleFormat.SampleFormat = DXVA2_SampleFieldInterleavedEvenFirst;
1414 vs.sample.SampleFormat.SampleFormat = DXVA2_SampleFieldInterleavedOddFirst;
1418 vs.sample.SampleFormat.SampleFormat = DXVA2_SampleProgressiveFrame;
1421 vs.sample.PlanarAlpha = DXVA2_Fixed32OpaqueAlpha();
1422 vs.sample.SampleData = 0;
1423 vs.sample.SrcSurface = surface;
1426 vs.context = context;
1428 if(!m_sample.empty())
1429 m_sample.back().sample.End = vs.sample.Start;
1431 m_sample.push_back(vs);
1432 if (m_sample.size() > m_size)
1434 SAFE_RELEASE(m_sample.front().context);
1435 SAFE_RELEASE(m_sample.front().sample.SrcSurface);
1436 m_sample.pop_front();
1442 static DXVA2_Fixed32 ConvertRange(const DXVA2_ValueRange& range, int value, int min, int max, int 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) );
1453 return range.DefaultValue;
1456 bool CProcessor::Render(CRect src, CRect dst, IDirect3DSurface9* target, REFERENCE_TIME time, DWORD flags)
1458 CSingleLock lock(m_section);
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
1471 m_deinterlace_mode = mode;
1472 m_interlace_method = method;
1474 if (!OpenProcessor())
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;
1482 SSamples::iterator it = m_sample.begin();
1483 while (it != m_sample.end())
1485 if (it->sample.Start < MinTime)
1487 SAFE_RELEASE(it->context);
1488 SAFE_RELEASE(it->sample.SrcSurface);
1489 it = m_sample.erase(it);
1495 if(m_sample.empty())
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;
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 };
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.
1515 int count = 1 + m_caps.NumBackwardRefSamples + m_caps.NumForwardRefSamples;
1517 auto_aptr<DXVA2_VideoSample> samp(new DXVA2_VideoSample[count]);
1519 for (int i = 0; i < count; i++)
1520 samp[i].SampleFormat.SampleFormat = DXVA2_SampleUnknown;
1522 for(it = m_sample.begin(); it != m_sample.end() && valid < count; it++)
1524 if (it->sample.Start >= MinTime && it->sample.Start <= MaxTime)
1526 DXVA2_VideoSample& vs = samp[(it->sample.Start - MinTime) / 2];
1528 vs.SrcRect = sourceRECT;
1529 vs.DstRect = dstRECT;
1531 vs.End = vs.Start + 2;
1533 // Override the sample format when the processor doesn't need to deinterlace or when deinterlacing is forced and flags are missing.
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;
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.
1549 CLog::Log(LOGWARNING, __FUNCTION__" - did not find all required samples, adjusting the sample array.");
1551 for (int i = 0; i < count; i++)
1553 if (samp[i].SampleFormat.SampleFormat == DXVA2_SampleUnknown)
1559 CLog::Log(LOGWARNING, __FUNCTION__" - no usable samples.");
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;
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();
1577 blt.ProcAmpValues.Brightness = ConvertRange( m_brightness, g_settings.m_currentVideoSettings.m_Brightness
1579 blt.ProcAmpValues.Contrast = ConvertRange( m_contrast, g_settings.m_currentVideoSettings.m_Contrast
1581 blt.ProcAmpValues.Hue = m_hue.DefaultValue;
1582 blt.ProcAmpValues.Saturation = m_saturation.DefaultValue;
1584 blt.BackgroundColor.Y = 0x1000;
1585 blt.BackgroundColor.Cb = 0x8000;
1586 blt.BackgroundColor.Cr = 0x8000;
1587 blt.BackgroundColor.Alpha = 0xffff;
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));
1595 CHECK(m_process->VideoProcessBlt(target, &blt, &samp[offset], count, NULL));