MythTV master
mythvideooutgpu.cpp
Go to the documentation of this file.
1#include <QtGlobal>
2#if QT_VERSION >= QT_VERSION_CHECK(6,5,0)
3#include <QtSystemDetection>
4#endif
5
6// MythTV
7#include "libmythbase/mythconfig.h"
12
13#include "mythplayer.h"
14#include "mythvideogpu.h"
15#include "mythvideooutgpu.h"
16
17#ifdef Q_OS_WINDOWS
19#include "videoout_d3d.h"
20#endif
21#if CONFIG_OPENGL
24#endif
25#if CONFIG_VULKAN
28#endif
29
30#define LOC QString("VidOutGPU: ")
31
32void MythVideoOutputGPU::GetRenderOptions([[ maybe_unused ]] RenderOptions& Options,
33 [[ maybe_unused ]] MythRender* Render)
34{
35#if CONFIG_OPENGL
36 if (dynamic_cast<MythRenderOpenGL*>(Render) != nullptr)
38#endif
39
40#if CONFIG_VULKAN
41 if (dynamic_cast<MythRenderVulkan*>(Render) != nullptr)
43#endif
44}
45
47 MythPainter* Painter, MythDisplay* MDisplay,
48 const QString& Decoder,
49 MythCodecID CodecID, const QSize VideoDim,
50 const QSize VideoDispDim, float VideoAspect,
51 float FrameRate, uint PlayerFlags,
52 const QString& Codec, int ReferenceFrames,
53 const VideoFrameTypes*& RenderFormats)
54{
55 if (!(MainWindow && Render && Painter && MDisplay))
56 {
57 LOG(VB_GENERAL, LOG_ERR, LOC + "Fatal error");
58 return nullptr;
59 }
60
62 {
63 LOG(VB_GENERAL, LOG_ERR, LOC + "Cannot create null video output here");
64 return nullptr;
65 }
66
67 QStringList renderers;
68
69#ifdef Q_OS_WINDOWS
70// auto * d3drender = dynamic_cast<MythRenderD3D9*>(Render);
71// auto * d3dpainter = dynamic_cast<MythD3D9Painter*>(Painter);
72// if (Render->Type() == kRenderDirect3D9)
73// renderers += VideoOutputD3D::GetAllowedRenderers(CodecID, VideoDispDim);
74#endif
75
76#if CONFIG_OPENGL
77 auto * openglrender = dynamic_cast<MythRenderOpenGL*>(Render);
78 auto * openglpainter = dynamic_cast<MythOpenGLPainter*>(Painter);
79 if (openglrender && openglpainter && (Render->Type() == kRenderOpenGL))
80 renderers += MythVideoOutputOpenGL::GetAllowedRenderers(openglrender, CodecID, VideoDispDim);
81#endif
82
83#if CONFIG_VULKAN
84 auto * vulkanrender = dynamic_cast<MythRenderVulkan*>(Render);
85 auto * vulkanpainter = dynamic_cast<MythPainterVulkan*>(Painter);
86 if (vulkanrender && vulkanpainter && (Render->Type() == kRenderVulkan))
88#endif
89
90 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Allowed renderers for %1 %2 (Decoder: %3): '%4'")
91 .arg(get_encoding_type(CodecID),
92 get_decoder_name(CodecID),
93 Decoder,
94 renderers.join(",")));
95 renderers = MythVideoProfile::GetFilteredRenderers(Decoder, renderers);
96 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Allowed renderers (filt: %1): %2")
97 .arg(Decoder, renderers.join(",")));
98
99 QString renderer;
100
101 auto videoprofile = std::make_shared<MythVideoProfile>();
102
103 if (!renderers.empty())
104 {
105 videoprofile->SetInput(VideoDispDim, FrameRate, Codec);
106 QString tmp = videoprofile->GetVideoRenderer();
107 if (videoprofile->IsDecoderCompatible(Decoder) && renderers.contains(tmp))
108 {
109 renderer = tmp;
110 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Preferred renderer: " + renderer);
111 }
112 else
113 {
114 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("No preferred renderer for decoder '%1' - profile renderer: '%2'")
115 .arg(Decoder, tmp));
116 }
117 }
118
119 if (renderer.isEmpty())
120 renderer = MythVideoProfile::GetBestVideoRenderer(renderers);
121
122 if (renderer.isEmpty())
123 {
124 QString fallback;
125#if CONFIG_OPENGL
126 if (Render->Type() == kRenderOpenGL)
127 fallback = "opengl";
128#endif
129#if CONFIG_VULKAN
130 if (Render->Type() == kRenderVulkan)
131 fallback = VULKAN_RENDERER;
132#endif
133 LOG(VB_GENERAL, LOG_WARNING, LOC + "No renderer found. This should not happen!.");
134 LOG(VB_GENERAL, LOG_WARNING, LOC + QString("Falling back to '%1'").arg(fallback));
135 renderer = fallback;
136 }
137
138 while (!renderers.empty())
139 {
140 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Trying video renderer: '%1'").arg(renderer));
141 int index = renderers.indexOf(renderer);
142 if (index >= 0)
143 renderers.removeAt(index);
144 else
145 break;
146
147 MythVideoOutputGPU* video = nullptr;
148
149#ifdef Q_OS_WINDOWS
150// if (renderer == "direct3d")
151// video = new VideoOutputD3D(MainWindow, d3drender,
152// d3dpainter, MDisplay,
153// videoprofile, renderer);
154#endif
155#if CONFIG_OPENGL
156 // cppcheck-suppress knownConditionTrueFalse
157 if (!video && renderer.contains("opengl") && openglrender)
158 {
159 video = new MythVideoOutputOpenGL(MainWindow, openglrender,
160 openglpainter, MDisplay,
161 videoprofile, renderer);
162 }
163#endif
164#if CONFIG_VULKAN
165 if (!video && renderer.contains(VULKAN_RENDERER))
166 {
167 video = new MythVideoOutputVulkan(MainWindow, vulkanrender,
168 vulkanpainter, MDisplay,
169 videoprofile, renderer);
170 }
171#endif
172
173 if (video)
174 {
175 video->SetVideoFrameRate(FrameRate);
176 video->SetReferenceFrames(ReferenceFrames);
177 if (video->Init(VideoDim, VideoDispDim, VideoAspect, MainWindow->GetUIScreenRect(), CodecID))
178 {
179 video->SetVideoScalingAllowed(true);
180 RenderFormats = video->m_renderFormats;
181 return video;
182 }
183 delete video;
184 video = nullptr;
185 }
186 renderer = MythVideoProfile::GetBestVideoRenderer(renderers);
187 }
188
189 LOG(VB_GENERAL, LOG_ERR, LOC + "Not compiled with any useable video output method.");
190 return nullptr;
191}
192
194{
195 if (codec_is_vaapi(CodecId)) return FMT_VAAPI;
196 if (codec_is_vdpau(CodecId)) return FMT_VDPAU;
197 if (codec_is_nvdec(CodecId)) return FMT_NVDEC;
198 if (codec_is_vtb(CodecId)) return FMT_VTB;
199 if (codec_is_mmal(CodecId)) return FMT_MMAL;
200 if (codec_is_v4l2(CodecId) || codec_is_drmprime(CodecId)) return FMT_DRMPRIME;
201 if (codec_is_mediacodec(CodecId)) return FMT_MEDIACODEC;
202 return FMT_NONE;
203}
204
218 MythPainterGPU* Painter, MythDisplay* MDisplay,
219 MythVideoProfilePtr VideoProfile, QString& Profile)
220 : m_mainWindow(MainWindow),
221 m_render(Render),
222 m_painter(Painter),
223 m_profile(std::move(Profile))
224{
225 if (!(m_mainWindow && m_render && m_painter && MDisplay))
226 {
227 LOG(VB_GENERAL, LOG_ERR, "Fatal error");
228 return;
229 }
230
231 m_videoProfile = std::move(VideoProfile);
232 m_render->IncrRef();
233 SetDisplay(MDisplay);
235
236 // If our rendering context is overlaid on top of a video plane, we need transparency
237 // and we need to ensure we are clearing the entire framebuffer.
238 // Note: an alpha of zero is probably safe to use everywhere. tbc.
239 if (m_display->IsPlanar())
240 {
241 m_clearAlpha = 0;
242 m_needFullClear = true;
243 }
244
246
259}
260
262{
263 m_hdrTracker = nullptr;
264
266 delete m_video;
267 if (m_painter)
269 if (m_render)
270 m_render->DecrRef();
271}
272
274{
275 return GetDisplayVisibleRect();
276}
277
279{
281}
282
284{
285 SetWindowSize(Size);
287}
288
290{
291 if (!m_videoProfile)
292 return;
293
294 if (qFuzzyCompare(m_videoProfile->GetOutput() + 1.0F, NewRate + 1.0F))
295 return;
296
297 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Video frame rate changed: %1->%2")
298 .arg(static_cast<double>(m_videoProfile->GetOutput())).arg(static_cast<double>(NewRate)));
299 m_videoProfile->SetOutput(NewRate);
300 m_newFrameRate = true;
301}
302
303bool MythVideoOutputGPU::Init(const QSize VideoDim, const QSize VideoDispDim,
304 float Aspect, const QRect DisplayVisibleRect, MythCodecID CodecId)
305{
306 // if we are the main video player then free up as much video memory
307 // as possible at startup
310
311 // Default initialisation - mainly MythVideoBounds
312 if (!MythVideoOutput::Init(VideoDim, VideoDispDim, Aspect, DisplayVisibleRect, CodecId))
313 return false;
314
315 // Ensure any new profile preferences are handled after a stream change
316 if (m_videoProfile)
317 m_video->SetProfile(m_videoProfile->GetVideoRenderer());
318
319 // Set default support for picture attributes
321
322 // Setup display
323 QSize size = GetVideoDim();
324
325 // Set the display mode if required
327 ResizeForVideo(size);
329
330 // Create buffers
332 if (!m_buffersCreated)
333 return false;
334
335 // Adjust visible rect for embedding
336 QRect dvr = GetDisplayVisibleRectAdj();
338 {
339 m_render->SetViewPort(QRect(QPoint(), dvr.size()));
340 return true;
341 }
342
343 // Reset OpenGLVideo
344 if (m_video->IsValid())
346
347 return true;
348}
349
356void MythVideoOutputGPU::DiscardFrames(bool KeyFrame, bool Flushed)
357{
358 if (Flushed)
359 {
360 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("(%1): %2").arg(KeyFrame).arg(m_videoBuffers.GetStatus()));
362 }
363 MythVideoOutput::DiscardFrames(KeyFrame, Flushed);
364}
365
378{
379 if (!Frame)
380 return;
381
382 auto retain = MythVideoFrame::HardwareFormat(Frame->m_type);
383 QVector<MythVideoFrame*> release;
384
387 {
389 if (!retain || (frame != Frame))
390 release.append(frame);
391 }
392
393 if (retain)
394 {
398 }
399 else
400 {
401 release.append(Frame);
402 }
404
405 for (auto * frame : release)
407}
408
410{
412 return true;
413
414 if (codec_is_copyback(CodecID))
415 {
417 return m_videoBuffers.CreateBuffers(FMT_YV12, Size.width(), Size.height(), m_renderFormats);
418 }
419
420 if (codec_is_mediacodec(CodecID))
422 if (codec_is_vaapi(CodecID))
424 if (codec_is_vtb(CodecID))
425 return m_videoBuffers.CreateBuffers(FMT_VTB, m_renderFormats, Size, 1, 4, 2);
426 if (codec_is_vdpau(CodecID))
428 if (codec_is_nvdec(CodecID))
430 if (codec_is_mmal(CodecID))
432 if (codec_is_v4l2(CodecID) || codec_is_drmprime(CodecID))
434
436}
437
439{
442 m_buffersCreated = false;
443}
444
446{
447 m_maxReferenceFrames = ReferenceFrames;
448}
449
450bool MythVideoOutputGPU::InputChanged(QSize VideoDim, QSize VideoDispDim,
451 float VideoAspect, MythCodecID CodecId,
452 bool& AspectOnly, int ReferenceFrames,
453 bool ForceChange)
454{
455 QSize currentvideodim = GetVideoDim();
456 QSize currentvideodispdim = GetVideoDispDim();
457 MythCodecID currentcodec = m_videoCodecID;
458 float currentaspect = GetVideoAspect();
459
461 {
462 // InputChanged has been called twice in quick succession without a call to ProcessFrame
463 currentvideodim = m_newVideoDim;
464 currentvideodispdim = m_newVideoDispDim;
465 currentcodec = m_newCodecId;
466 currentaspect = m_newAspect;
467 }
468
469 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Video changed: %1x%2 (%3x%4) '%5' (Aspect %6 Refs %13)"
470 "-> %7x%8 (%9x%10) '%11' (Aspect %12 Refs %14)")
471 .arg(currentvideodispdim.width()).arg(currentvideodispdim.height())
472 .arg(currentvideodim.width()).arg(currentvideodim.height())
473 .arg(toString(currentcodec)).arg(static_cast<double>(currentaspect))
474 .arg(VideoDispDim.width()).arg(VideoDispDim.height())
475 .arg(VideoDim.width()).arg(VideoDim.height())
476 .arg(toString(CodecId)).arg(static_cast<double>(VideoAspect))
477 .arg(m_maxReferenceFrames).arg(ReferenceFrames));
478
479 bool cidchanged = (CodecId != currentcodec);
480 bool reschanged = (VideoDispDim != currentvideodispdim);
481 bool refschanged = m_maxReferenceFrames != ReferenceFrames;
482
483 // aspect ratio changes are a no-op as changes are handled at display time
484 if (!(cidchanged || reschanged || refschanged || ForceChange))
485 {
486 AspectOnly = true;
487 return true;
488 }
489
490 // N.B. We no longer check for interop support for the new codec as it is a
491 // poor substitute for a full check of decoder capabilities etc. Better to let
492 // hardware decoding fail if necessary - which should at least fallback to
493 // software decoding rather than bailing out here.
494
495 // delete and recreate the buffers and flag that the input has changed
496 m_maxReferenceFrames = ReferenceFrames;
498 if (!m_buffersCreated)
499 return false;
500
501 m_newCodecId= CodecId;
502 m_newVideoDim = VideoDim;
503 m_newVideoDispDim = VideoDispDim;
504 m_newAspect = VideoAspect;
505 return true;
506}
507
509{
511 {
512 // Ensure we don't lose embedding through program changes.
513 bool wasembedding = IsEmbedding();
514 QRect oldrect;
515 if (wasembedding)
516 {
517 oldrect = GetEmbeddingRect();
518 EmbedPlayback(false, {});
519 }
520
521 // Note - we don't call the default VideoOutput::InputChanged method as
522 // the OpenGL implementation is asynchronous.
523 // So we need to update the video display profile here. It is a little
524 // circular as we need to set the video dimensions first which are then
525 // reset in Init.
526 // All told needs a cleanup - not least because the use of codecName appears
527 // to be inconsistent.
529 AVCodecID avCodecId = myth2av_codecid(m_newCodecId);
530 const AVCodec* codec = avcodec_find_decoder(avCodecId);
531 QString codecName;
532 if (codec)
533 codecName = codec->name;
534 if (m_videoProfile)
535 m_videoProfile->SetInput(GetVideoDispDim(), 0 , codecName);
538 m_newVideoDim = QSize();
539 m_newVideoDispDim = QSize();
540 m_newAspect = 0.0F;
541 m_newFrameRate = false;
542
543 if (wasembedding && ok)
544 EmbedPlayback(true, oldrect);
545
546 // Update deinterlacers for any input change
548
549 if (!ok)
550 return false;
551 }
552 else if (m_newFrameRate)
553 {
554 // If we are switching mode purely for a refresh rate change, then there
555 // is no need to recreate buffers etc etc
557 m_newFrameRate = false;
558 }
559
560 return true;
561}
562
569{
570 if (!m_display)
571 return;
572
573 // Retrieve the display aspect ratio.
574 // This will be, in priority order:-
575 // - aspect ratio override when using resolution/mode switching (if not 'Default')
576 // - aspect ratio override for setups where detection does not work/is broken (multiscreen, broken EDID etc)
577 // - aspect ratio based on detected physical size (this should be the common/default value)
578 // - aspect ratio fallback using screen resolution
579 // - 16:9
580 QString source;
581 double displayaspect = m_display->GetAspectRatio(source);
582 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Display aspect ratio: %1 (%2)")
583 .arg(displayaspect).arg(source));
584
585 // Get the window and screen resolutions
586 QSize window = GetRawWindowRect().size();
587 QSize screen = m_display->GetResolution();
588
589 // If not running fullscreen, adjust for window size and ignore any video
590 // mode overrides as they do not apply when in a window
591 if (!window.isEmpty() && !screen.isEmpty() && window != screen)
592 {
593 displayaspect = m_display->GetAspectRatio(source, true);
594 double screenaspect = screen.width() / static_cast<double>(screen.height());
595 double windowaspect = window.width() / static_cast<double>(window.height());
596 displayaspect = displayaspect * (1.0 / screenaspect) * windowaspect;
597 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Window aspect ratio: %1").arg(displayaspect));
598 }
599
600 SetDisplayAspect(static_cast<float>(displayaspect));
601}
602
604{
605 // Process input changes
606 if (!ProcessInputChange())
607 return;
608
609 if (Frame)
610 {
611 SetRotation(Frame->m_rotation);
612
613 if (m_hdrTracker)
614 m_hdrTracker->Update(Frame);
615
616 if (MythVideoFrame::HardwareFormat(Frame->m_type) || Frame->m_dummy)
617 return;
618
619 // software deinterlacing
621
622 // update software textures
623 if (m_video)
624 m_video->PrepareFrame(Frame, Scan);
625 }
626}
627
629{
630 bool dummy = false;
631 bool topfieldfirst = false;
632 if (Frame)
633 {
634 m_framesPlayed = Frame->m_frameNumber + 1;
635 topfieldfirst = Frame->m_interlacedReverse ? !Frame->m_topFieldFirst : Frame->m_topFieldFirst;
636 dummy = Frame->m_dummy;
637 }
638 else
639 {
640 // see DoneDisplayingFrame
641 // we only retain pause frames for hardware formats
644 }
645
646 // Main UI when embedded
647 if (m_painter && IsEmbedding())
648 {
649 // If we are using high dpi, the painter needs to set the appropriate
650 // viewport and enable scaling of its images
652
654 {
655 m_mainWindow->GetPaintWindow()->clearMask();
657 }
659 }
660
661 // Video
662 // N.B. dummy streams need the viewport updated in case we have resized the window (i.e. LiveTV)
663 if (m_video && !dummy)
664 m_video->RenderFrame(Frame, topfieldfirst, Scan, GetStereoOverride());
665 else if (dummy)
667}
668
669void MythVideoOutputGPU::UpdatePauseFrame(std::chrono::milliseconds& DisplayTimecode, FrameScanType Scan)
670{
671 MythVideoFrame* release = nullptr;
674 if (used)
675 {
677 {
679 }
680 else
681 {
683 m_deinterlacer.Filter(used, Scan, m_videoProfile.get(), true);
684 if (m_video)
685 m_video->PrepareFrame(used, Scan);
686 }
687 DisplayTimecode = used->m_displayTimecode;
688 }
689 else
690 {
691 LOG(VB_PLAYBACK, LOG_WARNING, LOC + "Could not update pause frame");
692 }
694
695 if (release)
696 DoneDisplayingFrame(release);
697}
698
700{
701 m_video->EndFrame();
702}
703
705{
706 // Clear reference frames for GPU deinterlacing
707 if (m_video)
709 // Clear decoded frames
711}
712
725{
726 if (!m_display)
727 return;
729 return;
730
731 if (Size.isEmpty())
732 {
733 Size = GetVideoDispDim();
734 if (Size.isEmpty())
735 return;
736 }
737
738 float rate = m_videoProfile ? m_videoProfile->GetOutput() : 0.0F;
739
740 bool hide = m_display->NextModeIsLarger(Size);
741 if (hide)
742 m_mainWindow->hide();
743
744 if (m_display->SwitchToVideo(Size, static_cast<double>(rate)))
745 {
746 // Switching to custom display resolution succeeded
747 // Make a note of the new size
748 QString source;
749 double aspect = m_display->GetAspectRatio(source);
750 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Aspect ratio: %1 (%2)")
751 .arg(aspect).arg(source));
752 SetDisplayAspect(static_cast<float>(aspect));
754
755 bool fullscreen = !UsingGuiSize();
756
757 // if width && height are zero users expect fullscreen playback
758 if (!fullscreen)
759 {
760 int gui_width = 0;
761 int gui_height = 0;
762 gCoreContext->GetResolutionSetting("Gui", gui_width, gui_height);
763 fullscreen |= (0 == gui_width && 0 == gui_height);
764 }
765
766 if (fullscreen)
767 {
768 QSize size = m_display->GetResolution();
769 QRect display_visible_rect = QRect(m_mainWindow->geometry().topLeft(), size);
770 if (hide)
771 {
773 hide = false;
774 }
775 m_mainWindow->MoveResize(display_visible_rect);
776 }
777 }
778 if (hide)
780}
void GetResolutionSetting(const QString &type, int &width, int &height, double &forced_aspect, double &refresh_rate, int index=-1)
void Filter(MythVideoFrame *Frame, FrameScanType Scan, MythVideoProfile *Profile, bool Force=false)
Deinterlace Frame if needed.
double GetAspectRatio(QString &Source, bool IgnoreModeOverride=false)
Returns current screen aspect ratio.
bool SwitchToVideo(QSize Size, double Rate=0.0)
Switches to the resolution and refresh rate defined in the database for the specified video resolutio...
virtual bool UsingVideoModes()
Definition: mythdisplay.h:30
QSize GetResolution()
bool NextModeIsLarger(QSize Size)
Check whether the next mode is larger in size than the current mode.
virtual bool IsPlanar()
Definition: mythdisplay.h:31
static HDRTracker Create(class MythDisplay *MDisplay)
Create a tracker instance that looks for changes in the required EOTF.
QWidget * GetPaintWindow()
void MoveResize(QRect &Geometry)
void Draw(MythPainter *Painter=nullptr)
void SetViewControl(ViewControls Control)
virtual void FreeResources(void)
Definition: mythpainter.h:50
RenderType Type(void) const
virtual void SetViewPort(const QRect, bool=false)
QRect GetEmbeddingRect(void) const
void RefreshVideoBoundsState()
Send out latest state to listeners.
void SetRotation(int Rotation)
Set the rotation in degrees.
bool IsEmbedding(void) const
virtual void EmbedPlayback(bool Embed, QRect Rect)
QSize GetVideoDim(void) const
QSize GetVideoDispDim(void) const
void SourceChanged(QSize VideoDim, QSize VideoDispDim, float Aspect)
Update for new source video dimensions and aspect ratio.
MythDisplay * m_display
void SetDisplayAspect(float DisplayAspect)
void SetVideoScalingAllowed(bool Change)
Disable or enable underscan/overscan.
QRect GetDisplayVisibleRect(void) const
QRect GetRawWindowRect(void) const
float GetVideoAspect(void) const
void SetDisplay(MythDisplay *mDisplay)
QRect GetWindowRect(void) const
void SetWindowSize(QSize Size)
StereoscopicMode GetStereoOverride() const
bool UsingGuiSize(void) const
void PictureAttributeChanged(PictureAttribute Attribute, int Value)
void SetSupportedAttributes(PictureAttributeSupported Supported)
Enable the given set of picture attributes.
void SupportedAttributesChanged(PictureAttributeSupported Supported)
void PictureAttributesUpdated(const std::map< PictureAttribute, int > &Values)
int ChangePictureAttribute(PictureAttribute Attribute, bool Direction, int Value)
std::chrono::milliseconds m_displayTimecode
Definition: mythframe.h:131
VideoFrameType m_type
Definition: mythframe.h:118
bool m_alreadyDeinterlaced
Definition: mythframe.h:153
static bool HardwareFormat(VideoFrameType Type)
Definition: mythframe.h:424
virtual void RenderFrame(MythVideoFrame *Frame, bool TopFieldFirst, FrameScanType Scan, StereoscopicMode StereoOverride, bool DrawBorder=false)=0
bool IsValid() const
virtual void PrepareFrame(MythVideoFrame *Frame, FrameScanType Scan=kScan_Progressive)=0
virtual void EndFrame()=0
virtual void ResetTextures()=0
virtual void ResetFrameFormat()
void SetProfile(const QString &Profile)
Common code shared between GPU accelerated sub-classes (e.g. OpenGL)
virtual QRect GetDisplayVisibleRectAdj()
MythCodecID m_newCodecId
MythVideoOutputGPU(MythMainWindow *MainWindow, MythRender *Render, MythPainterGPU *Painter, MythDisplay *Display, MythVideoProfilePtr VideoProfile, QString &Profile)
HDRTracker m_hdrTracker
MythMainWindow * m_mainWindow
void PrepareFrame(MythVideoFrame *Frame, FrameScanType Scan) override
void WindowResized(QSize Size)
void PictureAttributesUpdated(const std::map< PictureAttribute, int > &Values)
void SetVideoFrameRate(float NewRate) override
MythRender * m_render
static MythVideoOutputGPU * Create(MythMainWindow *MainWindow, MythRender *Render, MythPainter *Painter, MythDisplay *Display, const QString &Decoder, MythCodecID CodecID, QSize VideoDim, QSize VideoDispDim, float VideoAspect, float FrameRate, uint PlayerFlags, const QString &Codec, int ReferenceFrames, const VideoFrameTypes *&RenderFormats)
void UpdatePauseFrame(std::chrono::milliseconds &DisplayTimecode, FrameScanType Scan=kScan_Progressive) override
void EndFrame() override
MythPainterGPU * m_painter
~MythVideoOutputGPU() override
void ChangePictureAttribute(PictureAttribute Attribute, bool Direction, int Value)
static VideoFrameType FrameTypeForCodec(MythCodecID CodecId)
bool CreateBuffers(MythCodecID CodecID, QSize Size)
bool InputChanged(QSize VideoDim, QSize VideoDispDim, float VideoAspect, MythCodecID CodecId, bool &AspectOnly, int ReferenceFrames, bool ForceChange) override
Tells video output to discard decoded frames and wait for new ones.
void ResizeForVideo(QSize Size=QSize())
static void GetRenderOptions(RenderOptions &Options, MythRender *Render)
void PictureAttributeChanged(PictureAttribute Attribute, int Value)
void DiscardFrames(bool KeyFrame, bool Flushed) override
Discard video frames.
bool Init(QSize VideoDim, QSize VideoDispDim, float Aspect, QRect DisplayVisibleRect, MythCodecID CodecId) override
void InitDisplayMeasurements()
Initialise display measurement.
void SupportedAttributesChanged(PictureAttributeSupported Supported)
void SetReferenceFrames(int ReferenceFrames)
void DoneDisplayingFrame(MythVideoFrame *Frame) override
Release a video frame back into the decoder pool.
void InitPictureAttributes() override
void RenderFrame(MythVideoFrame *Frame, FrameScanType Scan) override
void ClearAfterSeek() override
Tells video output to toss decoded buffers due to a seek.
MythVideoGPU * m_video
static void GetRenderOptions(RenderOptions &Options)
Generate the list of available OpenGL profiles.
static QStringList GetAllowedRenderers(MythRenderOpenGL *Render, MythCodecID CodecId, QSize VideoDim)
Generate a list of supported OpenGL profiles.
static void GetRenderOptions(RenderOptions &Options)
static QStringList GetAllowedRenderers(MythCodecID CodecId)
MythCodecID m_videoCodecID
Definition: mythvideoout.h:98
long long m_framesPlayed
Definition: mythvideoout.h:103
virtual void ClearAfterSeek()
Tells video output to toss decoded buffers due to a seek.
virtual void SetDeinterlacing(bool Enable, bool DoubleRate, MythDeintType Force=DEINT_NONE)
MythVideoColourSpace m_videoColourSpace
Definition: mythvideoout.h:94
virtual bool Init(QSize VideoDim, QSize VideoDispDim, float VideoAspect, QRect WindowRect, MythCodecID CodecID)
MythVideoProfilePtr m_videoProfile
Definition: mythvideoout.h:100
MythDeintType m_forcedDeinterlacer
Definition: mythvideoout.h:109
uint8_t m_clearAlpha
Definition: mythvideoout.h:97
VideoBuffers m_videoBuffers
Definition: mythvideoout.h:101
MythDeinterlacer m_deinterlacer
Definition: mythvideoout.h:105
const VideoFrameTypes * m_renderFormats
Definition: mythvideoout.h:106
virtual void DiscardFrames(bool KeyFrame, bool Flushed)
Releases all frames not being actively displayed from any queue onto the queue of frames ready for de...
int m_maxReferenceFrames
Definition: mythvideoout.h:99
static QStringList GetFilteredRenderers(const QString &Decoder, const QStringList &Renderers)
static QString GetBestVideoRenderer(const QStringList &Renderers)
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
virtual int IncrRef(void)
Increments reference count.
static uint GetNumBuffers(int PixelFormat, int MaxReferenceFrames=16, bool Decoder=false)
frame_queue_t::iterator BeginLock(BufferType Type)
Lock the video buffers.
MythVideoFrame * Tail(BufferType Type)
QString GetStatus(uint Num=0) const
bool CreateBuffers(VideoFrameType Type, const VideoFrameTypes *RenderFormats, QSize Size, uint NeedFree, uint NeedprebufferNormal, uint NeedPrebufferSmall, int MaxReferenceFrames=16)
void Reset(void)
Resets the class so that Init may be called again.
bool Contains(BufferType Type, MythVideoFrame *Frame) const
void Remove(BufferType Type, MythVideoFrame *Frame)
void DiscardPauseFrames(void)
void DoneDisplayingFrame(MythVideoFrame *Frame)
Removes frame from used queue and adds it to the available list.
MythVideoFrame * Dequeue(BufferType Type)
void Enqueue(BufferType Type, MythVideoFrame *Frame)
void Init(uint NumDecode, uint NeedFree, uint NeedprebufferNormal, uint NeedPrebufferSmall)
Creates buffers and sets various buffer management parameters.
bool DiscardAndRecreate(MythCodecID CodecID, QSize VideoDim, int References)
Discard all buffers and recreate.
uint Size(BufferType Type) const
MythVideoFrame * Head(BufferType Type)
unsigned int uint
Definition: compat.h:60
QString get_decoder_name(MythCodecID codec_id)
AVCodecID myth2av_codecid(MythCodecID codec_id)
QString get_encoding_type(MythCodecID codecid)
MythCodecID
Definition: mythcodecid.h:14
@ kCodec_NONE
Definition: mythcodecid.h:17
static bool codec_is_vdpau(MythCodecID id)
Definition: mythcodecid.h:304
static bool codec_is_mediacodec(MythCodecID id)
Definition: mythcodecid.h:337
static bool codec_is_drmprime(MythCodecID id)
Definition: mythcodecid.h:301
static bool codec_is_mmal(MythCodecID id)
Definition: mythcodecid.h:363
static bool codec_is_nvdec(MythCodecID id)
Definition: mythcodecid.h:344
static bool codec_is_vtb(MythCodecID id)
Definition: mythcodecid.h:351
static bool codec_is_v4l2(MythCodecID id)
Definition: mythcodecid.h:358
static bool codec_is_copyback(MythCodecID id)
Definition: mythcodecid.h:368
static bool codec_is_vaapi(MythCodecID id)
Definition: mythcodecid.h:321
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
std::vector< VideoFrameType > VideoFrameTypes
Definition: mythframe.h:82
VideoFrameType
Definition: mythframe.h:20
@ FMT_VAAPI
Definition: mythframe.h:57
@ FMT_VTB
Definition: mythframe.h:61
@ FMT_YV12
Definition: mythframe.h:23
@ FMT_DRMPRIME
Definition: mythframe.h:63
@ FMT_VDPAU
Definition: mythframe.h:56
@ FMT_NONE
Definition: mythframe.h:21
@ FMT_NVDEC
Definition: mythframe.h:62
@ FMT_MMAL
Definition: mythframe.h:59
@ FMT_MEDIACODEC
Definition: mythframe.h:60
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
PlayerFlags
Definition: mythplayer.h:64
@ kVideoIsNull
Definition: mythplayer.h:72
@ kRenderOpenGL
@ kRenderVulkan
std::shared_ptr< MythVideoProfile > MythVideoProfilePtr
Definition: mythvideogpu.h:18
#define LOC
#define VULKAN_RENDERER
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:93
STL namespace.
@ kVideoBuffer_used
Definition: videobuffers.h:30
@ kVideoBuffer_pause
Definition: videobuffers.h:31
FrameScanType
Definition: videoouttypes.h:95
@ kScan_Interlaced
Definition: videoouttypes.h:98
@ kScan_Progressive
bool is_interlaced(FrameScanType Scan)
#define ALL_PICTURE_ATTRIBUTES