8#include "libmythbase/mythconfig.h"
20#include "libavutil/stereo3d.h"
23#define LOC QString("GLVid: ")
38 :
MythVideoGPU(Render, ColourSpace, Bounds, VideoProfile, Profile),
39 m_openglRender(Render)
43 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Fatal error");
57 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Chroma upsampling filter %1")
79 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Primaries conversion changed - recreating shaders");
92 m_shaders[i]->setUniformValue(
"m_colourGamma", colourgamma);
93 m_shaders[i]->setUniformValue(
"m_displayGamma", displaygamma);
109 QVector4D parameters(lineheight,
111 maxheight - lineheight,
119 m_shaders[i]->setUniformValue(
"m_frameData", parameters);
122 QVector2D size { rect ? 1.0F :
static_cast<GLfloat
>(
m_videoDim.width()),
123 rect ? 1.0F :
static_cast<GLfloat
>(
m_videoDim.height()) };
124 m_shaders[i]->setUniformValue(
"m_textureSize", size);
147 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Removing single field textures");
161 bool CreateReferences )
190 deinterlacer =
Frame->GetSingleRateOption(Filter);
192 if (!deinterlacer || other)
230 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Forcing OpenGL YV12 for basic deinterlacer");
235 std::vector<QSize> sizes;
236 sizes.emplace_back(size);
242 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Created %1 single field textures")
250 uint refstocreate = ((deinterlacer ==
DEINT_HIGH) && CreateReferences) ? 2 : 0;
252 if (totaltextures > max)
255 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Insufficent texture units for deinterlacer '%1' (%2 < %3)")
258 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Falling back to '%1'")
269 std::vector<QSize> sizes;
286 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Created deinterlacer '%1' (%2->%3)")
321 for (
const QString& define : std::as_const(defines))
322 glsldefines += QString(
"#define MYTHTV_%1\n").arg(define);
327 vertex = MediaCodecVertexShader;
341 static const QString glsl300(
"#version 300 es\n");
345 glsldefines.append(glsl300);
366#if CONFIG_VIDEOTOOLBOX
385 if (topfield && !basic)
386 defines <<
"TOPFIELD";
394 defines <<
"ONEFIELD";
397 case DEINT_MEDIUM: cost *= 5; defines <<
"LINEARBLEND";
break;
398 case DEINT_HIGH: cost *= 15; defines <<
"KERNEL"; kernel =
true;
break;
409 for (
int i = (kernel ? 2 : 0); (i >= 0) && count; i--)
411 QString
find = QString(
"s_texture%1").arg(i);
412 QStringList replacelist;
413 for (
int j = (i * count); j < ((i + 1) * count); ++j)
414 replacelist << QString(
"s_texture%1").arg(j);
415 fragment.replace(
find, replacelist.join(
", "));
421 for (
int i = 1 ; i >= 0; i--)
423 QString find1 = QString(
"sampler2D kernelTex%1").arg(i);
424 QString find2 = QString(
"kernelTex%1").arg(i);
425 QStringList replacelist1;
426 QStringList replacelist2;
427 for (
int j = 0; j < count; ++j)
429 replacelist1 << QString(
"sampler2D kernelTexture%1%2").arg(i).arg(j);
430 replacelist2 << QString(
"kernelTexture%1%2").arg(i).arg(j);
432 fragment.replace(find1, replacelist1.join(
", "));
433 fragment.replace(find2, replacelist2.join(
", "));
441 for (
const QString& define : std::as_const(defines))
442 glsldefines += QString(
"#define MYTHTV_%1\n").arg(define);
455 QString glslsamplers;
456 for (
int i = start; i < end; ++i)
457 glslsamplers += QString(
"uniform sampler2D s_texture%1;\n").arg(i);
460 fragment = glsldefines + extensions + glslsamplers + fragment;
473 QSize Size, GLenum TextureTarget)
475 QString texnew {
"2D" };
476 if (TextureTarget == QOpenGLTexture::TargetRectangle)
481 QString texold {
"2D" };
487 LOG(VB_GENERAL, LOG_INFO,
LOC +
488 QString(
"New frame format: %1:%2 %3x%4 (Tex: %5) -> %6:%7 %8x%9 (Tex: %10)")
496 QString::number(Size.width()),
497 QString::number(Size.height()))
514 std::vector<QSize> sizes;
515 sizes.push_back(Size);
519 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to create input textures");
524 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Created %1 input textures for '%2'")
573 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Resetting input format");
582 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Invalid software frame");
589 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Frame format is not supported");
639 Frame->m_pitches[0] =
Frame->m_pitches[0] << 1;
640 Frame->m_pitches[1] =
Frame->m_pitches[1] << 1;
641 Frame->m_pitches[2] =
Frame->m_pitches[2] << 1;
645 Frame->m_offsets[0] =
Frame->m_offsets[0] + pitches[0];
646 Frame->m_offsets[1] =
Frame->m_offsets[1] + pitches[1];
647 Frame->m_offsets[2] =
Frame->m_offsets[2] + pitches[2];
649 Frame->m_pitches = pitches;
650 Frame->m_offsets = offsets;
675 bool hwframes =
false;
676 bool useframebufferimage =
false;
688 VideoResizing resize;
695 if (inputtextures.empty())
702 Frame->m_displayed =
false;
713 if (!inputtextures.empty())
716 QSize newsize = inputtextures[0]->m_size;
719 GLenum newtargettexture = inputtextures[0]->m_target;
733 m_shaders[
Default]->setUniformValue(
"u_transform", *inputtextures[0]->m_transform);
738 if (inputtextures[0]->m_allowGLSLDeint)
745 LOG(VB_PLAYBACK, LOG_DEBUG,
"Using existing framebuffer");
746 useframebufferimage =
true;
750 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"Nothing to display");
760 bool deinterlacing =
false;
761 bool basicdeinterlacing =
false;
769 deinterlacing =
true;
774 deinterlacing =
true;
780 basicdeinterlacing =
true;
787 if (deinterlacing &&
Frame)
798 if (yuvoutput && !resize)
820 if (!resize && !tiled && !basicdeinterlacing)
827 if ((totexture + blitcost) < noresizecost)
860 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Disabled resizing");
865 QOpenGLTexture::Filter filter = ((resize &
Sampling) ==
Sampling) ? QOpenGLTexture::Nearest : QOpenGLTexture::Linear;
870 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Resizing from %1x%2 to %3x%4 for %5")
879 QOpenGLTexture::Filter filter = (resize.testFlag(
Sampling)) ? QOpenGLTexture::Nearest : QOpenGLTexture::Linear;
880 if (inputtextures[0]->m_filter != filter)
892 if (useframebufferimage)
921 (fbo !=
nullptr) && (tex !=
nullptr))
936 QRect trect2 = vrect;
945 std::vector<MythGLTexture*> textures {};
955 inputtextures.clear();
956 inputtextures.push_back(nexttexture);
958 deinterlacing =
false;
984 trect = QRect(trect.left() >> 1, trect.top(), trect.width() >> 1, trect.height());
986 trect = QRect(trect.left(), trect.top() >> 1, trect.width(), trect.height() >> 1);
996 static const QPen kNopen(Qt::NoPen);
997 static const QBrush kRedBrush(QBrush(QColor(127, 0, 0, 255)));
1002 std::vector<MythGLTexture*> textures;
1034 texture->m_valid =
false;
1036 texture->m_valid =
false;
1038 texture->m_valid =
false;
1042 std::vector<MythGLTexture*>& Textures)
1050 size_t count = Current.size();
1054 for (
uint i = 0; i < count; ++i)
1055 Textures.push_back(
reinterpret_cast<MythGLTexture*
>(prev[i]));
1056 for (
uint i = 0; i < count; ++i)
1058 for (
uint i = 0; i < count; ++i)
1064 std::transform(Current.cbegin(), Current.cend(), std::back_inserter(Textures),
1076 case FMT_YV12:
return "opengl-yv12";
1077 case FMT_NV12:
return "opengl-nv12";
1092 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to create bicubic shader. Disabling");
1098 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Created bicubic sampler");
1109 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