9#include "libmythbase/mythconfig.h"
21#include "libavutil/stereo3d.h"
24#define LOC QString("GLVid: ")
39 :
MythVideoGPU(Render, ColourSpace, Bounds, VideoProfile, Profile),
40 m_openglRender(Render)
44 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Fatal error");
58 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Chroma upsampling filter %1")
80 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Primaries conversion changed - recreating shaders");
93 m_shaders[i]->setUniformValue(
"m_colourGamma", colourgamma);
94 m_shaders[i]->setUniformValue(
"m_displayGamma", displaygamma);
110 QVector4D parameters(lineheight,
112 maxheight - lineheight,
120 m_shaders[i]->setUniformValue(
"m_frameData", parameters);
123 QVector2D size { rect ? 1.0F :
static_cast<GLfloat
>(
m_videoDim.width()),
124 rect ? 1.0F :
static_cast<GLfloat
>(
m_videoDim.height()) };
125 m_shaders[i]->setUniformValue(
"m_textureSize", size);
148 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Removing single field textures");
162 bool CreateReferences )
191 deinterlacer =
Frame->GetSingleRateOption(Filter);
193 if (!deinterlacer || other)
231 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Forcing OpenGL YV12 for basic deinterlacer");
236 std::vector<QSize> sizes;
237 sizes.emplace_back(size);
243 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Created %1 single field textures")
251 uint refstocreate = ((deinterlacer ==
DEINT_HIGH) && CreateReferences) ? 2 : 0;
253 if (totaltextures > max)
256 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Insufficent texture units for deinterlacer '%1' (%2 < %3)")
259 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Falling back to '%1'")
270 std::vector<QSize> sizes;
287 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Created deinterlacer '%1' (%2->%3)")
322 for (
const QString& define : std::as_const(defines))
323 glsldefines += QString(
"#define MYTHTV_%1\n").arg(define);
328 vertex = MediaCodecVertexShader;
342 static const QString glsl300(
"#version 300 es\n");
346 glsldefines.append(glsl300);
367#if CONFIG_VIDEOTOOLBOX
386 if (topfield && !basic)
387 defines <<
"TOPFIELD";
395 defines <<
"ONEFIELD";
398 case DEINT_MEDIUM: cost *= 5; defines <<
"LINEARBLEND";
break;
399 case DEINT_HIGH: cost *= 15; defines <<
"KERNEL"; kernel =
true;
break;
410 for (
int i = (kernel ? 2 : 0); (i >= 0) && count; i--)
412 QString
find = QString(
"s_texture%1").arg(i);
413 QStringList replacelist;
414 for (
int j = (i * count); j < ((i + 1) * count); ++j)
415 replacelist << QString(
"s_texture%1").arg(j);
416 fragment.replace(
find, replacelist.join(
", "));
422 for (
int i = 1 ; i >= 0; i--)
424 QString find1 = QString(
"sampler2D kernelTex%1").arg(i);
425 QString find2 = QString(
"kernelTex%1").arg(i);
426 QStringList replacelist1;
427 QStringList replacelist2;
428 for (
int j = 0; j < count; ++j)
430 replacelist1 << QString(
"sampler2D kernelTexture%1%2").arg(i).arg(j);
431 replacelist2 << QString(
"kernelTexture%1%2").arg(i).arg(j);
433 fragment.replace(find1, replacelist1.join(
", "));
434 fragment.replace(find2, replacelist2.join(
", "));
442 for (
const QString& define : std::as_const(defines))
443 glsldefines += QString(
"#define MYTHTV_%1\n").arg(define);
456 QString glslsamplers;
457 for (
int i = start; i < end; ++i)
458 glslsamplers += QString(
"uniform sampler2D s_texture%1;\n").arg(i);
461 fragment = glsldefines + extensions + glslsamplers + fragment;
474 QSize Size, GLenum TextureTarget)
476 QString texnew {
"2D" };
477 if (TextureTarget == QOpenGLTexture::TargetRectangle)
482 QString texold {
"2D" };
488 LOG(VB_GENERAL, LOG_INFO,
LOC +
489 QString(
"New frame format: %1:%2 %3x%4 (Tex: %5) -> %6:%7 %8x%9 (Tex: %10)")
497 QString::number(Size.width()),
498 QString::number(Size.height()))
515 std::vector<QSize> sizes;
516 sizes.push_back(Size);
520 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to create input textures");
525 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Created %1 input textures for '%2'")
574 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Resetting input format");
583 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Invalid software frame");
590 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Frame format is not supported");
640 Frame->m_pitches[0] =
Frame->m_pitches[0] << 1;
641 Frame->m_pitches[1] =
Frame->m_pitches[1] << 1;
642 Frame->m_pitches[2] =
Frame->m_pitches[2] << 1;
646 Frame->m_offsets[0] =
Frame->m_offsets[0] + pitches[0];
647 Frame->m_offsets[1] =
Frame->m_offsets[1] + pitches[1];
648 Frame->m_offsets[2] =
Frame->m_offsets[2] + pitches[2];
650 Frame->m_pitches = pitches;
651 Frame->m_offsets = offsets;
676 bool hwframes =
false;
677 bool useframebufferimage =
false;
689 VideoResizing resize;
696 if (inputtextures.empty())
703 Frame->m_displayed =
false;
714 if (!inputtextures.empty())
717 QSize newsize = inputtextures[0]->m_size;
720 GLenum newtargettexture = inputtextures[0]->m_target;
734 m_shaders[
Default]->setUniformValue(
"u_transform", *inputtextures[0]->m_transform);
739 if (inputtextures[0]->m_allowGLSLDeint)
746 LOG(VB_PLAYBACK, LOG_DEBUG,
"Using existing framebuffer");
747 useframebufferimage =
true;
751 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"Nothing to display");
761 bool deinterlacing =
false;
762 bool basicdeinterlacing =
false;
770 deinterlacing =
true;
775 deinterlacing =
true;
781 basicdeinterlacing =
true;
788 if (deinterlacing &&
Frame)
799 if (yuvoutput && !resize)
821 if (!resize && !tiled && !basicdeinterlacing)
828 if ((totexture + blitcost) < noresizecost)
861 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Disabled resizing");
866 QOpenGLTexture::Filter filter = ((resize &
Sampling) ==
Sampling) ? QOpenGLTexture::Nearest : QOpenGLTexture::Linear;
871 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Resizing from %1x%2 to %3x%4 for %5")
880 QOpenGLTexture::Filter filter = (resize.testFlag(
Sampling)) ? QOpenGLTexture::Nearest : QOpenGLTexture::Linear;
881 if (inputtextures[0]->m_filter != filter)
893 if (useframebufferimage)
922 (fbo !=
nullptr) && (tex !=
nullptr))
937 QRect trect2 = vrect;
946 std::vector<MythGLTexture*> textures {};
956 inputtextures.clear();
957 inputtextures.push_back(nexttexture);
959 deinterlacing =
false;
985 trect = QRect(trect.left() >> 1, trect.top(), trect.width() >> 1, trect.height());
987 trect = QRect(trect.left(), trect.top() >> 1, trect.width(), trect.height() >> 1);
997 static const QPen kNopen(Qt::NoPen);
998 static const QBrush kRedBrush(QBrush(QColor(127, 0, 0, 255)));
1003 std::vector<MythGLTexture*> textures;
1035 texture->m_valid =
false;
1037 texture->m_valid =
false;
1039 texture->m_valid =
false;
1043 std::vector<MythGLTexture*>& Textures)
1051 size_t count = Current.size();
1055 for (
uint i = 0; i < count; ++i)
1056 Textures.push_back(
reinterpret_cast<MythGLTexture*
>(prev[i]));
1057 for (
uint i = 0; i < count; ++i)
1059 for (
uint i = 0; i < count; ++i)
1065 std::ranges::transform(Current, std::back_inserter(Textures),
1077 case FMT_YV12:
return "opengl-yv12";
1078 case FMT_NV12:
return "opengl-nv12";
1093 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to create bicubic shader. Disabling");
1099 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Created bicubic sampler");
1110 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Disabling bicubic sampler");
bool GetBoolSetting(const QString &key, bool defaultval=false)
static std::vector< MythVideoTextureOpenGL * > Retrieve(MythRenderOpenGL *Context, MythVideoColourSpace *ColourSpace, MythVideoFrame *Frame, FrameScanType Scan)
MythVideoTextureOpenGL * GetTexture()
MythVideoTextureOpenGL * Map(std::vector< MythVideoTextureOpenGL * > &Inputs, QSize DisplaySize)
std::vector< MythVideoTextureOpenGL * > m_prevTextures
MythVideoTextureOpenGL * m_frameBufferTexture
bool SetupFrameFormat(VideoFrameType InputType, VideoFrameType OutputType, QSize Size, GLenum TextureTarget)
QOpenGLFramebufferObject * m_frameBuffer
MythOpenGLVideo(MythRenderOpenGL *Render, MythVideoColourSpace *ColourSpace, MythVideoBounds *Bounds, const MythVideoProfilePtr &VideoProfile, const QString &Profile)
~MythOpenGLVideo() override
void BindTextures(bool Deinterlacing, std::vector< MythVideoTextureOpenGL * > &Current, std::vector< MythGLTexture * > &Textures)
bool m_chromaUpsamplingFilter
std::array< int, ShaderCount > m_shaderCost
std::array< QOpenGLShaderProgram *, ShaderCount > m_shaders
static QString TypeToProfile(VideoFrameType Type)
QOpenGLFunctions::OpenGLFeatures m_features
void CleanupDeinterlacers()
MythOpenGLTonemap * m_toneMap
std::vector< MythVideoTextureOpenGL * > m_inputTextures
void ResetTextures() override
Clear reference frames after a seek as they will contain old images.
std::vector< MythVideoTextureOpenGL * > m_nextTextures
void PrepareFrame(MythVideoFrame *Frame, FrameScanType Scan=kScan_Progressive) override
Update the current input texture using the data from the given video frame.
void ColourSpaceUpdate(bool PrimariesChanged) override
MythDeintType m_fallbackDeinterlacer
void SetupBicubic(VideoResizing &Resize)
void RenderFrame(MythVideoFrame *Frame, bool TopFieldFirst, FrameScanType Scan, StereoscopicMode StereoOverride, bool DrawBorder=false) override
void UpdateShaderParameters()
bool AddDeinterlacer(const MythVideoFrame *Frame, FrameScanType Scan, MythDeintType Filter=DEINT_SHADER, bool CreateReferences=true)
MythRenderOpenGL * m_openglRender
void ResetFrameFormat() override
bool CreateVideoShader(VideoShaderType Type, MythDeintType Deint=DEINT_NONE)
Create the appropriate shader for the operation Type.
QString GetProfile() const override
void SetShaderProgramParams(QOpenGLShaderProgram *Program, const QMatrix4x4 &Value, const char *Uniform)
int GetMaxTextureUnits(void) const
void DrawBitmap(MythGLTexture *Texture, QOpenGLFramebufferObject *Target, QRect Source, QRect Destination, QOpenGLShaderProgram *Program, int Alpha=255, qreal Scale=1.0)
void SetViewPort(QRect Rect, bool ViewportOnly=false) override
void DeleteShaderProgram(QOpenGLShaderProgram *Program)
void BindFramebuffer(QOpenGLFramebufferObject *Framebuffer)
void DeleteFramebuffer(QOpenGLFramebufferObject *Framebuffer)
QOpenGLFunctions::OpenGLFeatures GetFeatures(void) const
bool EnableShaderProgram(QOpenGLShaderProgram *Program)
void logDebugMarker(const QString &Message)
QOpenGLShaderProgram * CreateShaderProgram(const QString &Vertex, const QString &Fragment)
void DeleteTexture(MythGLTexture *Texture)
void DrawRect(QOpenGLFramebufferObject *Target, QRect Area, const QBrush &FillBrush, const QPen &LinePen, int Alpha)
int GetExtraFeatures(void) const
void SetTextureFilters(MythGLTexture *Texture, QOpenGLTexture::Filter Filter, QOpenGLTexture::WrapMode Wrap=QOpenGLTexture::ClampToEdge)
MythVideoColourSpace contains a QMatrix4x4 that can convert YCbCr data to RGB.
float GetDisplayGamma(void) const
QStringList GetColourMappingDefines(void)
QMatrix4x4 GetPrimaryMatrix(void)
bool UpdateColourSpace(const MythVideoFrame *Frame)
Set the current colourspace to use.
float GetColourGamma(void) const
static bool FormatIs422(VideoFrameType Type)
static uint GetNumPlanes(VideoFrameType Type)
static QString DeinterlacerName(MythDeintType Deint, bool DoubleRate, VideoFrameType Format=FMT_NONE)
static bool FormatIsNV12(VideoFrameType Type)
static QString FormatDescription(VideoFrameType Type)
static bool FormatIs444(VideoFrameType Type)
static bool FormatIs420(VideoFrameType Type)
static bool FormatIsRGB(VideoFrameType Type)
static bool HardwareFramesFormat(VideoFrameType Type)
static bool YUVFormat(VideoFrameType Type)
static int ColorDepth(int Format)
static bool HardwareFormat(VideoFrameType Type)
VideoFrameType m_inputType
StereoscopicMode m_stereoMode
uint64_t m_discontinuityCounter
MythVideoColourSpace * m_videoColourSpace
QSize m_masterViewportSize
VideoFrameType m_outputType
void OutputChanged(QSize VideoDim, QSize VideoDispDim, float)
static QString VideoResizeToString(VideoResizing Resize)
void UpdateColourSpace(bool PrimariesChanged)
virtual void ResetFrameFormat()
MythDeintType m_deinterlacer
static void SetTextureFilters(MythRenderOpenGL *Context, const std::vector< MythVideoTextureOpenGL * > &Textures, QOpenGLTexture::Filter Filter, QOpenGLTexture::WrapMode Wrap=QOpenGLTexture::ClampToEdge)
static std::vector< MythVideoTextureOpenGL * > CreateTextures(MythRenderOpenGL *Context, VideoFrameType Type, VideoFrameType Format, std::vector< QSize > Sizes, GLenum Target=QOpenGLTexture::Target2D)
Create a set of textures suitable for the given Type and Format.
static VideoFramebuffer CreateVideoFrameBuffer(MythRenderOpenGL *Context, VideoFrameType OutputType, QSize Size, bool HighPrecision=true)
static void DeleteTextures(MythRenderOpenGL *Context, std::vector< MythVideoTextureOpenGL * > &Textures)
static void UpdateTextures(MythRenderOpenGL *Context, const MythVideoFrame *Frame, const std::vector< MythVideoTextureOpenGL * > &Textures)
Update the contents of the given Textures for data held in Frame.
static pid_list_t::iterator find(const PIDInfoMap &map, pid_list_t &list, pid_list_t::iterator begin, pid_list_t::iterator end, bool find_open)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
std::array< int, 3 > FrameOffsets
std::array< int, 3 > FramePitches
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
static const QString YUVFragmentShader
static const QString DefaultVertexShader
static const QString GLSL300VertexShader
static const QString BicubicShader
static const QString YUVFragmentExtensions
static const QString GLSL300YUVFragmentShader
static const QString GLSL300YUVFragmentExtensions
static const QString RGBFragmentShader
#define GL_TEXTURE_EXTERNAL_OES
std::shared_ptr< MythVideoProfile > MythVideoProfilePtr
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
bool is_interlaced(FrameScanType Scan)
@ kStereoscopicModeTopAndBottomDiscard
@ kStereoscopicModeSideBySideDiscard