MythTV master
mythvdpauhelper.cpp
Go to the documentation of this file.
1// MythTV
4#include "mythvdpauhelper.h"
5#include "libmythui/platforms/mythxdisplay.h" // always last
6
7// Std
8#include <cmath>
9
10#define LOC QString("VDPAUHelp: ")
11
12#define INIT_ST \
13VdpStatus status; \
14bool ok = true;
15
16// NOLINTBEGIN(cppcoreguidelines-macro-usage)
17#define CHECK_ST \
18ok &= (status == VDP_STATUS_OK); \
19if (!ok) \
20{ \
21 LOG(VB_PLAYBACK, LOG_ERR, LOC + QString("Error at %1:%2 (#%3, %4)") \
22 .arg(__FILE__).arg( __LINE__).arg(status) \
23 .arg(m_vdpGetErrorString(status))); \
24}
25
26#define GET_PROC(FUNC_ID, PROC) \
27status = m_vdpGetProcAddress(m_device, FUNC_ID, reinterpret_cast<void **>(&(PROC))); CHECK_ST
28// NOLINTEND(cppcoreguidelines-macro-usage)
29
30VDPAUCodec::VDPAUCodec(MythCodecContext::CodecProfile Profile, QSize Size, uint32_t Macroblocks, uint32_t Level)
31 : m_maxSize(Size),
32 m_maxMacroBlocks(Macroblocks),
33 m_maxLevel(Level)
34{
35 // Levels don't work for MPEG1/2
36 if (MythCodecContext::MPEG1 <= Profile && Profile <= MythCodecContext::MPEG2SNR)
37 m_maxLevel = 1000;
38}
39
40bool VDPAUCodec::Supported(int Width, int Height, int Level) const
41{
42 // Note - level checks are now ignored here and in FFmpeg
43 uint32_t macros = static_cast<uint32_t>(((Width + 15) & ~15) * ((Height + 15) & ~15)) / 256;
44 bool result = (Width <= m_maxSize.width()) && (Height <= m_maxSize.height()) &&
45 (macros <= m_maxMacroBlocks) /*&& (static_cast<uint32_t>(Level) <= m_maxLevel)*/;
46 if (!result)
47 {
48 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Not supported: Size %1x%2 > %3x%4, MBs %5 > %6, Level %7 > %8")
49 .arg(Width).arg(Height).arg(m_maxSize.width()).arg(m_maxSize.height())
50 .arg(macros).arg(m_maxMacroBlocks).arg(Level).arg(m_maxLevel));
51 }
52 return result;
53}
54
55bool MythVDPAUHelper::HaveVDPAU(bool Reinit /*=false*/)
56{
57 static QMutex s_mutex;
58 static bool s_checked = false;
59 static bool s_available = false;
60
61 QMutexLocker locker(&s_mutex);
62 if (s_checked && !Reinit)
63 return s_available;
64
65 {
66 MythVDPAUHelper vdpau;
67 s_available = vdpau.IsValid();
68 }
69
70 s_checked = true;
71 if (s_available)
72 {
73 LOG(VB_GENERAL, LOG_INFO, LOC + "Supported/available VDPAU decoders:");
75 for (const auto& profile : std::as_const(profiles))
76 LOG(VB_GENERAL, LOG_INFO, LOC +
78 }
79 else
80 {
81 LOG(VB_GENERAL, LOG_INFO, LOC + "VDPAU is NOT available");
82 }
83 return s_available;
84}
85
86bool MythVDPAUHelper::ProfileCheck(VdpDecoderProfile Profile, uint32_t &Level,
87 uint32_t &Macros, uint32_t &Width, uint32_t &Height)
88{
89 if (!m_device)
90 return false;
91
93 VdpBool supported = VDP_FALSE;
94 status = m_vdpDecoderQueryCapabilities(m_device, Profile, &supported,
95 &Level, &Macros, &Width, &Height);
97
98 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("ProfileCheck: Prof %1 Supp %2 Level %3 Macros %4 Width %5 Height %6 Status %7")
99 .arg(Profile).arg(supported).arg(Level).arg(Macros).arg(Width).arg(Height).arg(status));
100
101 if (((supported != VDP_TRUE) || (status != VDP_STATUS_OK)) &&
102 (Profile == VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE ||
103 Profile == VDP_DECODER_PROFILE_H264_BASELINE))
104 {
105 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Driver does not report support for H264 %1Baseline")
106 .arg(Profile == VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE ? "Constrained " : ""));
107
108 // H264 Constrained baseline is reported as not supported on older chipsets but
109 // works due to support for H264 Main. Test for H264 main if constrained baseline
110 // fails - which mimics the fallback in FFmpeg.
111 // Updated to included baseline... not so sure about that:)
112 status = m_vdpDecoderQueryCapabilities(m_device, VDP_DECODER_PROFILE_H264_MAIN, &supported,
113 &Level, &Macros, &Width, &Height);
115 if (supported == VDP_TRUE)
116 LOG(VB_GENERAL, LOG_INFO, LOC + "... but assuming available as H264 Main is supported");
117 }
118
119 return supported == VDP_TRUE;
120}
121
123{
124 static const std::array<const VdpDecoderProfile,15> MainProfiles
125 {
126 VDP_DECODER_PROFILE_MPEG1, VDP_DECODER_PROFILE_MPEG2_SIMPLE, VDP_DECODER_PROFILE_MPEG2_MAIN,
127 VDP_DECODER_PROFILE_MPEG4_PART2_SP, VDP_DECODER_PROFILE_MPEG4_PART2_ASP,
128 VDP_DECODER_PROFILE_VC1_SIMPLE, VDP_DECODER_PROFILE_VC1_MAIN, VDP_DECODER_PROFILE_VC1_ADVANCED,
129 VDP_DECODER_PROFILE_H264_BASELINE, VDP_DECODER_PROFILE_H264_MAIN, VDP_DECODER_PROFILE_H264_HIGH,
130 VDP_DECODER_PROFILE_H264_EXTENDED, VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE,
131 VDP_DECODER_PROFILE_H264_CONSTRAINED_HIGH, VDP_DECODER_PROFILE_H264_HIGH_444_PREDICTIVE
132 };
133
134 static const std::array<const VdpDecoderProfile,4> HEVCProfiles
135 {
136 VDP_DECODER_PROFILE_HEVC_MAIN, VDP_DECODER_PROFILE_HEVC_MAIN_10,
137 VDP_DECODER_PROFILE_HEVC_MAIN_STILL, VDP_DECODER_PROFILE_HEVC_MAIN_444
138 };
139
140 auto VDPAUToMythProfile = [](VdpDecoderProfile Profile)
141 {
142 switch (Profile)
143 {
144 case VDP_DECODER_PROFILE_MPEG1: return MythCodecContext::MPEG1;
145 case VDP_DECODER_PROFILE_MPEG2_SIMPLE: return MythCodecContext::MPEG2Simple;
146 case VDP_DECODER_PROFILE_MPEG2_MAIN: return MythCodecContext::MPEG2Main;
147
148 case VDP_DECODER_PROFILE_MPEG4_PART2_SP: return MythCodecContext::MPEG4Simple;
149 case VDP_DECODER_PROFILE_MPEG4_PART2_ASP: return MythCodecContext::MPEG4AdvancedSimple;
150
151 case VDP_DECODER_PROFILE_VC1_SIMPLE: return MythCodecContext::VC1Simple;
152 case VDP_DECODER_PROFILE_VC1_MAIN: return MythCodecContext::VC1Main;
153 case VDP_DECODER_PROFILE_VC1_ADVANCED: return MythCodecContext::VC1Advanced;
154
155 case VDP_DECODER_PROFILE_H264_BASELINE: return MythCodecContext::H264Baseline;
156 case VDP_DECODER_PROFILE_H264_MAIN: return MythCodecContext::H264Main;
157 case VDP_DECODER_PROFILE_H264_HIGH: return MythCodecContext::H264High;
158 case VDP_DECODER_PROFILE_H264_EXTENDED: return MythCodecContext::H264Extended;
159 case VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE: return MythCodecContext::H264ConstrainedBaseline;
160 case VDP_DECODER_PROFILE_H264_CONSTRAINED_HIGH: return MythCodecContext::H264ConstrainedHigh;
161 case VDP_DECODER_PROFILE_H264_HIGH_444_PREDICTIVE: return MythCodecContext::H264High444; // ?
162
163 case VDP_DECODER_PROFILE_HEVC_MAIN: return MythCodecContext::HEVCMain;
164 case VDP_DECODER_PROFILE_HEVC_MAIN_10: return MythCodecContext::HEVCMain10;
165 case VDP_DECODER_PROFILE_HEVC_MAIN_STILL: return MythCodecContext::HEVCMainStill;
166 case VDP_DECODER_PROFILE_HEVC_MAIN_444: return MythCodecContext::HEVCRext;
167 }
169 };
170
171 static QRecursiveMutex lock;
172 static bool s_initialised = false;
173 static VDPAUProfiles s_profiles;
174
175 QMutexLocker locker(&lock);
176 if (s_initialised)
177 return s_profiles;
178 s_initialised = true;
179
180 MythVDPAUHelper helper;
181 if (!helper.IsValid())
182 return s_profiles;
183
184 uint32_t level = 0;
185 uint32_t macros = 0;
186 uint32_t width = 0;
187 uint32_t height = 0;
188 for (VdpDecoderProfile profile : MainProfiles)
189 {
190 if (helper.ProfileCheck(profile, level, macros, width, height))
191 {
192 MythCodecContext::CodecProfile prof = VDPAUToMythProfile(profile);
193 s_profiles.emplace_back(prof,
194 VDPAUCodec(prof, QSize(static_cast<int>(width), static_cast<int>(height)), macros, level));
195 }
196 }
197
198 if (helper.HEVCSupported())
199 {
200 for (VdpDecoderProfile profile : HEVCProfiles)
201 {
202 if (helper.ProfileCheck(profile, level, macros, width, height))
203 {
204 MythCodecContext::CodecProfile prof = VDPAUToMythProfile(profile);
205 s_profiles.emplace_back(prof,
206 VDPAUCodec(prof, QSize(static_cast<int>(width), static_cast<int>(height)), macros, level));
207 }
208 }
209 }
210
211 return s_profiles;
212}
213
214void MythVDPAUHelper::GetDecoderList(QStringList &Decoders)
215{
217 if (profiles.empty())
218 return;
219
220 Decoders.append("VDPAU:");
221 for (const auto& profile : std::as_const(profiles))
222 if (profile.first != MythCodecContext::MJPEG)
223 Decoders.append(MythCodecContext::GetProfileDescription(profile.first, profile.second.m_maxSize));
224}
225
226static void vdpau_preemption_callback(VdpDevice /*unused*/, void* Opaque)
227{
228 auto* helper = static_cast<MythVDPAUHelper*>(Opaque);
229 if (helper)
230 helper->SetPreempted();
231}
232
236MythVDPAUHelper::MythVDPAUHelper(AVVDPAUDeviceContext* Context)
237 : m_device(Context->device),
238 m_vdpGetProcAddress(Context->get_proc_address),
239 m_valid(InitProcs())
240{
241 if (m_valid)
242 {
243 INIT_ST
246 if (!ok)
247 LOG(VB_PLAYBACK, LOG_ERR, LOC + "Failed to register preemption callback");
248 }
249}
250
251static const char* DummyGetError(VdpStatus /*status*/)
252{
253 return "Unknown";
254}
255
257 : m_display(MythXDisplay::OpenMythXDisplay(false)),
258 m_createdDevice(true)
259{
260 if (!m_display)
261 return;
262
263 INIT_ST
265 m_display->Lock();
266 status = vdp_device_create_x11(m_display->GetDisplay(),
269 m_display->Unlock();
271 if (!ok)
272 {
273 LOG(VB_PLAYBACK, LOG_ERR, LOC + "Failed to create VDPAU device.");
274 return;
275 }
276 m_valid = InitProcs();
277}
278
280{
282 m_vdpPreemptionCallbackRegister(m_device, nullptr, nullptr);
285 delete m_display;
286}
287
289{
290 INIT_ST
291 GET_PROC(VDP_FUNC_ID_GET_ERROR_STRING, m_vdpGetErrorString)
292 if (!ok)
293 {
295 ok = true;
296 }
297 GET_PROC(VDP_FUNC_ID_GET_INFORMATION_STRING, m_vdpGetInformationString)
298 GET_PROC(VDP_FUNC_ID_DEVICE_DESTROY, m_vdpDeviceDestroy)
299 GET_PROC(VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES, m_vdpDecoderQueryCapabilities)
300 GET_PROC(VDP_FUNC_ID_DECODER_CREATE, m_vdpDecoderCreate)
301 GET_PROC(VDP_FUNC_ID_DECODER_DESTROY, m_vdpDecoderDestroy)
302 GET_PROC(VDP_FUNC_ID_VIDEO_MIXER_CREATE, m_vdpVideoMixerCreate)
303 GET_PROC(VDP_FUNC_ID_VIDEO_MIXER_DESTROY, m_vdpVideoMixerDestroy)
304 GET_PROC(VDP_FUNC_ID_VIDEO_MIXER_RENDER, m_vdpVideoMixerRender)
305 GET_PROC(VDP_FUNC_ID_VIDEO_MIXER_SET_ATTRIBUTE_VALUES, m_vdpVideoMixerSetAttributeValues)
306 GET_PROC(VDP_FUNC_ID_VIDEO_MIXER_SET_FEATURE_ENABLES, m_vdpVideoMixerSetFeatureEnables)
307 GET_PROC(VDP_FUNC_ID_VIDEO_MIXER_QUERY_FEATURE_SUPPORT, m_vdpVideoMixerQueryFeatureSupport)
308 GET_PROC(VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_SUPPORT, m_vdpVideoMixerQueryAttributeSupport)
309 GET_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_CREATE, m_vdpOutputSurfaceCreate)
310 GET_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY, m_vdpOutputSurfaceDestroy)
311 GET_PROC(VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS, m_vdpVideoSurfaceGetParameters)
312 GET_PROC(VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER, m_vdpPreemptionCallbackRegister)
313
314 return ok;
315}
316
318{
319 return m_valid;
320}
321
323{
324 emit DisplayPreempted();
325}
326
328{
329 if (!m_valid)
330 return false;
331
332 // FFmpeg will disallow HEVC VDPAU for driver versions < 410
333 const char* infostring = nullptr;
334 INIT_ST
335 status = m_vdpGetInformationString(&infostring);
337 if (!ok || !infostring)
338 return false;
339
340 if (!QString(infostring).contains("NVIDIA", Qt::CaseInsensitive))
341 return true;
342
343 int driver = 0;
344 sscanf(infostring, "NVIDIA VDPAU Driver Shared Library %d", &driver);
345 return !(driver < 410);
346}
347
348bool MythVDPAUHelper::CheckH264Decode(AVCodecContext *Context)
349{
350 if (!Context)
351 return false;
352
353 int mbs = static_cast<int>(ceil(static_cast<double>(Context->width) / 16.0));
354 if (mbs != 49 && mbs != 54 && mbs != 59 && mbs != 64 &&
355 mbs != 113 && mbs != 118 &&mbs != 123 && mbs != 128)
356 {
357 return true;
358 }
359
360 VdpDecoderProfile profile = 0;
361 switch (Context->profile & ~FF_PROFILE_H264_INTRA)
362 {
363 case FF_PROFILE_H264_BASELINE: profile = VDP_DECODER_PROFILE_H264_BASELINE; break;
364 case FF_PROFILE_H264_CONSTRAINED_BASELINE: profile = VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE; break;
365 case FF_PROFILE_H264_MAIN: profile = VDP_DECODER_PROFILE_H264_MAIN; break;
366 case FF_PROFILE_H264_HIGH: profile = VDP_DECODER_PROFILE_H264_HIGH; break;
367#ifdef VDP_DECODER_PROFILE_H264_EXTENDED
368 case FF_PROFILE_H264_EXTENDED: profile = VDP_DECODER_PROFILE_H264_EXTENDED; break;
369#endif
370 case FF_PROFILE_H264_HIGH_10: profile = VDP_DECODER_PROFILE_H264_HIGH; break;
371#ifdef VDP_DECODER_PROFILE_H264_HIGH_444_PREDICTIVE
372 case FF_PROFILE_H264_HIGH_422:
373 case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
374 case FF_PROFILE_H264_CAVLC_444: profile = VDP_DECODER_PROFILE_H264_HIGH_444_PREDICTIVE; break;
375#endif
376 default: return false;
377 }
378
379 // Create an instance
380 MythVDPAUHelper helper;
381 if (helper.IsValid())
382 return helper.H264DecodeCheck(profile, Context);
383 return false;
384}
385
386bool MythVDPAUHelper::H264DecodeCheck(VdpDecoderProfile Profile, AVCodecContext *Context)
387{
388 if (!m_valid || !Context)
389 return false;
390
391 INIT_ST
392 VdpDecoder tmp = 0;
393 status = m_vdpDecoderCreate(m_device, Profile, static_cast<uint>(Context->width),
394 static_cast<uint>(Context->height), 2, &tmp);
396 if (tmp)
398 if (!ok)
399 {
400 LOG(VB_GENERAL, LOG_INFO, LOC + QString("No H264 decoder support for %1x%2")
401 .arg(Context->width).arg(Context->height));
402 }
403 return ok;
404}
405
406VdpOutputSurface MythVDPAUHelper::CreateOutputSurface(QSize Size)
407{
408 if (!m_valid)
409 return 0;
410
411 VdpOutputSurface result = 0;
412 INIT_ST
413 status = m_vdpOutputSurfaceCreate(m_device, VDP_RGBA_FORMAT_B8G8R8A8,
414 static_cast<uint>(Size.width()),
415 static_cast<uint>(Size.height()), &result);
417 return result;
418}
419
421{
422 if (!Surface)
423 return;
424
425 INIT_ST
428}
429
430VdpVideoMixer MythVDPAUHelper::CreateMixer(QSize Size, VdpChromaType ChromaType,
431 MythDeintType Deinterlacer)
432{
433 if (!m_valid || Size.isEmpty())
434 return 0;
435
436 VdpVideoMixer result = 0;
437
438 static const std::array<const VdpVideoMixerParameter,3> parameters {
439 VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH,
440 VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT,
441 VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE
442 };
443
444
445 uint width = static_cast<uint>(Size.width());
446 uint height = static_cast<uint>(Size.height());
447 std::array<void const *,3> parametervalues { &width, &height, &ChromaType};
448
449 uint32_t featurecount = 0;
450 std::array<VdpVideoMixerFeature,2> features {};
451 VdpBool enable = VDP_TRUE;
452 const std::array<VdpBool,2> enables = { enable, enable };
453
454 if (DEINT_MEDIUM == Deinterlacer || DEINT_HIGH == Deinterlacer)
455 {
456 features[featurecount] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL;
457 featurecount++;
458 }
459
460 if (DEINT_HIGH== Deinterlacer)
461 {
462 features[featurecount] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL;
463 featurecount++;
464 }
465
466 INIT_ST
467 status = m_vdpVideoMixerCreate(m_device, featurecount, featurecount ? features.data() : nullptr,
468 3, parameters.data(), parametervalues.data(), &result);
470
471 if (!ok || !result)
472 {
473 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create video mixer");
474 return result;
475 }
476
477 if (featurecount)
478 {
479 status = m_vdpVideoMixerSetFeatureEnables(result, featurecount, features.data(), enables.data());
481 }
482 return result;
483}
484
485void MythVDPAUHelper::MixerRender(VdpVideoMixer Mixer, VdpVideoSurface Source,
486 VdpOutputSurface Dest, FrameScanType Scan, int TopFieldFirst,
487 QVector<AVBufferRef*>& Frames)
488{
489 if (!m_valid || !Mixer || !Source || !Dest)
490 return;
491
492 VdpVideoMixerPictureStructure field = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
493 if (kScan_Interlaced == Scan)
494 {
495 field = TopFieldFirst ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD :
496 VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
497 }
498 else if (kScan_Intr2ndField == Scan)
499 {
500 field = TopFieldFirst ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD :
501 VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
502 }
503
504 int count = Frames.size();
505 if ((count < 1) || (field == VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME))
506 {
507 INIT_ST
508 status = m_vdpVideoMixerRender(Mixer, VDP_INVALID_HANDLE, nullptr, field,
509 0, nullptr, Source, 0, nullptr, nullptr, Dest, nullptr, nullptr, 0, nullptr);
511 }
512 else
513 {
514 std::array<VdpVideoSurface,2> past = { VDP_INVALID_HANDLE, VDP_INVALID_HANDLE };
515 std::array<VdpVideoSurface,1> future = { VDP_INVALID_HANDLE };
516
517 auto next = static_cast<VdpVideoSurface>(reinterpret_cast<uintptr_t>(Frames[0]->data));
518 auto current = static_cast<VdpVideoSurface>(reinterpret_cast<uintptr_t>(Frames[count > 1 ? 1 : 0]->data));
519 auto last = static_cast<VdpVideoSurface>(reinterpret_cast<uintptr_t>(Frames[count > 2 ? 2 : 0]->data));
520
521 if (field == VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD)
522 {
523 future[0] = current;
524 past[0] = past[1] = last;
525 }
526 else
527 {
528 future[0] = next;
529 past[0] = current;
530 past[1] = last;
531 }
532
533 INIT_ST
534 status = m_vdpVideoMixerRender(Mixer, VDP_INVALID_HANDLE, nullptr, field,
535 2, past.data(), current, 1, future.data(),
536 nullptr, Dest, nullptr, nullptr, 0, nullptr);
538 }
539}
540
541void MythVDPAUHelper::DeleteMixer(VdpVideoMixer Mixer)
542{
543 if (!Mixer)
544 return;
545
546 INIT_ST
547 status = m_vdpVideoMixerDestroy(Mixer);
549}
550
551void MythVDPAUHelper::SetCSCMatrix(VdpVideoMixer Mixer, MythVideoColourSpace *ColourSpace)
552{
553 if (!Mixer || !ColourSpace)
554 return;
555
556 VdpVideoMixerAttribute attr = { VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX };
557 void const* val = { ColourSpace->data() };
558
559 INIT_ST
560 status = m_vdpVideoMixerSetAttributeValues(Mixer, 1, &attr, &val);
562}
563
565{
566 if (!m_valid)
567 return false;
568
569 INIT_ST
570 auto supported = static_cast<VdpBool>(false);
571 status = m_vdpVideoMixerQueryFeatureSupport(m_device, Feature, &supported);
573 return ok && static_cast<bool>(supported);
574}
575
577{
578 if (!m_valid)
579 return false;
580
581 INIT_ST
582 auto supported = static_cast<VdpBool>(false);
583 status = m_vdpVideoMixerQueryAttributeSupport(m_device, Attribute, &supported);
585 return ok && static_cast<bool>(supported);
586}
587
588QSize MythVDPAUHelper::GetSurfaceParameters(VdpVideoSurface Surface, VdpChromaType &Chroma)
589{
590 if (!Surface)
591 return {};
592
593 uint width = 0;
594 uint height = 0;
595 INIT_ST
596 status = m_vdpVideoSurfaceGetParameters(Surface, &Chroma, &width, &height);
598
599 return {static_cast<int>(width), static_cast<int>(height)};
600}
static QString GetProfileDescription(CodecProfile Profile, QSize Size, VideoFrameType Format=FMT_NONE, uint ColorDepth=0)
A simple wrapper around VDPAU functionality.
void DeleteOutputSurface(VdpOutputSurface Surface)
VdpOutputSurface CreateOutputSurface(QSize Size)
VdpVideoMixerDestroy * m_vdpVideoMixerDestroy
VdpVideoMixerSetFeatureEnables * m_vdpVideoMixerSetFeatureEnables
bool HEVCSupported(void)
void MixerRender(VdpVideoMixer Mixer, VdpVideoSurface Source, VdpOutputSurface Dest, FrameScanType Scan, int TopFieldFirst, QVector< AVBufferRef * > &Frames)
bool IsValid(void) const
VdpOutputSurfaceDestroy * m_vdpOutputSurfaceDestroy
static bool CheckH264Decode(AVCodecContext *Context)
VdpVideoMixerCreate * m_vdpVideoMixerCreate
QSize GetSurfaceParameters(VdpVideoSurface Surface, VdpChromaType &Chroma)
VdpDecoderQueryCapabilities * m_vdpDecoderQueryCapabilities
void DeleteMixer(VdpVideoMixer Mixer)
~MythVDPAUHelper(void) override
MythXDisplay * m_display
static bool HaveVDPAU(bool Reinit=false)
VdpDecoderDestroy * m_vdpDecoderDestroy
bool IsFeatureAvailable(uint Feature)
VdpVideoMixerQueryAttributeSupport * m_vdpVideoMixerQueryAttributeSupport
void SetCSCMatrix(VdpVideoMixer Mixer, MythVideoColourSpace *ColourSpace)
static void GetDecoderList(QStringList &Decoders)
VdpGetErrorString * m_vdpGetErrorString
VdpVideoMixerSetAttributeValues * m_vdpVideoMixerSetAttributeValues
VdpVideoMixer CreateMixer(QSize Size, VdpChromaType ChromaType=VDP_CHROMA_TYPE_420, MythDeintType Deinterlacer=DEINT_BASIC)
VdpDeviceDestroy * m_vdpDeviceDestroy
void DisplayPreempted(void)
VdpVideoMixerRender * m_vdpVideoMixerRender
VdpDecoderCreate * m_vdpDecoderCreate
static const VDPAUProfiles & GetProfiles(void)
VdpVideoSurfaceGetParameters * m_vdpVideoSurfaceGetParameters
void SetPreempted(void)
bool H264DecodeCheck(VdpDecoderProfile Profile, AVCodecContext *Context)
VdpVideoMixerQueryFeatureSupport * m_vdpVideoMixerQueryFeatureSupport
bool ProfileCheck(VdpDecoderProfile Profile, uint32_t &Level, uint32_t &Macros, uint32_t &Width, uint32_t &Height)
bool IsAttributeAvailable(uint Attribute)
VdpOutputSurfaceCreate * m_vdpOutputSurfaceCreate
VdpGetProcAddress * m_vdpGetProcAddress
VdpGetInformationString * m_vdpGetInformationString
VdpPreemptionCallbackRegister * m_vdpPreemptionCallbackRegister
MythVideoColourSpace contains a QMatrix4x4 that can convert YCbCr data to RGB.
int GetScreen() const
Definition: mythxdisplay.h:27
void Unlock()
Definition: mythxdisplay.h:29
Display * GetDisplay()
Definition: mythxdisplay.h:25
uint32_t m_maxMacroBlocks
uint32_t m_maxLevel
bool Supported(int Width, int Height, int Level) const
VDPAUCodec(MythCodecContext::CodecProfile Profile, QSize Size, uint32_t Macroblocks, uint32_t Level)
unsigned int uint
Definition: freesurround.h:24
static guint32 * tmp
Definition: goom_core.cpp:26
MythDeintType
Definition: mythframe.h:67
@ DEINT_HIGH
Definition: mythframe.h:71
@ DEINT_MEDIUM
Definition: mythframe.h:70
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
#define LOC
#define GET_PROC(FUNC_ID, PROC)
#define CHECK_ST
static const char * DummyGetError(VdpStatus)
static void vdpau_preemption_callback(VdpDevice, void *Opaque)
#define INIT_ST
std::vector< VDPAUProfile > VDPAUProfiles
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15
Definition: surface.h:4
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:95
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:89
FrameScanType
Definition: videoouttypes.h:95
@ kScan_Intr2ndField
Definition: videoouttypes.h:99
@ kScan_Interlaced
Definition: videoouttypes.h:98