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