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