19#include "libavutil/stereo3d.h"
22#define LOC QString("GLVid: ")
37 :
MythVideoGPU(Render, ColourSpace, Bounds, VideoProfile, Profile),
38 m_openglRender(Render)
42 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Fatal error");
56 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Chroma upsampling filter %1")
78 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Primaries conversion changed - recreating shaders");
91 m_shaders[i]->setUniformValue(
"m_colourGamma", colourgamma);
92 m_shaders[i]->setUniformValue(
"m_displayGamma", displaygamma);
108 QVector4D parameters(lineheight,
110 maxheight - lineheight,
118 m_shaders[i]->setUniformValue(
"m_frameData", parameters);
121 QVector2D size { rect ? 1.0F :
static_cast<GLfloat
>(
m_videoDim.width()),
122 rect ? 1.0F :
static_cast<GLfloat
>(
m_videoDim.height()) };
123 m_shaders[i]->setUniformValue(
"m_textureSize", size);
146 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Removing single field textures");
160 bool CreateReferences )
189 deinterlacer =
Frame->GetSingleRateOption(Filter);
191 if (!deinterlacer || other)
229 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Forcing OpenGL YV12 for basic deinterlacer");
234 std::vector<QSize> sizes;
235 sizes.emplace_back(size);
241 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Created %1 single field textures")
249 uint refstocreate = ((deinterlacer ==
DEINT_HIGH) && CreateReferences) ? 2 : 0;
251 if (totaltextures > max)
254 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Insufficent texture units for deinterlacer '%1' (%2 < %3)")
257 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Falling back to '%1'")
268 std::vector<QSize> sizes;
285 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Created deinterlacer '%1' (%2->%3)")
320 for (
const QString& define : std::as_const(defines))
321 glsldefines += QString(
"#define MYTHTV_%1\n").arg(define);
326 vertex = MediaCodecVertexShader;
340 static const QString glsl300(
"#version 300 es\n");
344 glsldefines.append(glsl300);
365#if CONFIG_VIDEOTOOLBOX
384 if (topfield && !basic)
385 defines <<
"TOPFIELD";
393 defines <<
"ONEFIELD";
396 case DEINT_MEDIUM: cost *= 5; defines <<
"LINEARBLEND";
break;
397 case DEINT_HIGH: cost *= 15; defines <<
"KERNEL"; kernel =
true;
break;
408 for (
int i = (kernel ? 2 : 0); (i >= 0) && count; i--)
410 QString
find = QString(
"s_texture%1").arg(i);
411 QStringList replacelist;
412 for (
int j = (i * count); j < ((i + 1) * count); ++j)
413 replacelist << QString(
"s_texture%1").arg(j);
414 fragment.replace(
find, replacelist.join(
", "));
420 for (
int i = 1 ; i >= 0; i--)
422 QString find1 = QString(
"sampler2D kernelTex%1").arg(i);
423 QString find2 = QString(
"kernelTex%1").arg(i);
424 QStringList replacelist1;
425 QStringList replacelist2;
426 for (
int j = 0; j < count; ++j)
428 replacelist1 << QString(
"sampler2D kernelTexture%1%2").arg(i).arg(j);
429 replacelist2 << QString(
"kernelTexture%1%2").arg(i).arg(j);
431 fragment.replace(find1, replacelist1.join(
", "));
432 fragment.replace(find2, replacelist2.join(
", "));
440 for (
const QString& define : std::as_const(defines))
441 glsldefines += QString(
"#define MYTHTV_%1\n").arg(define);
454 QString glslsamplers;
455 for (
int i = start; i < end; ++i)
456 glslsamplers += QString(
"uniform sampler2D s_texture%1;\n").arg(i);
459 fragment = glsldefines + extensions + glslsamplers + fragment;
472 QSize Size, GLenum TextureTarget)
474 QString texnew {
"2D" };
475 if (TextureTarget == QOpenGLTexture::TargetRectangle)
480 QString texold {
"2D" };
486 LOG(VB_GENERAL, LOG_INFO,
LOC +
487 QString(
"New frame format: %1:%2 %3x%4 (Tex: %5) -> %6:%7 %8x%9 (Tex: %10)")
495 QString::number(Size.width()),
496 QString::number(Size.height()))
513 std::vector<QSize> sizes;
514 sizes.push_back(Size);
518 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to create input textures");
523 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Created %1 input textures for '%2'")
572 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Resetting input format");
581 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Invalid software frame");
588 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Frame format is not supported");
638 Frame->m_pitches[0] =
Frame->m_pitches[0] << 1;
639 Frame->m_pitches[1] =
Frame->m_pitches[1] << 1;
640 Frame->m_pitches[2] =
Frame->m_pitches[2] << 1;
644 Frame->m_offsets[0] =
Frame->m_offsets[0] + pitches[0];
645 Frame->m_offsets[1] =
Frame->m_offsets[1] + pitches[1];
646 Frame->m_offsets[2] =
Frame->m_offsets[2] + pitches[2];
648 Frame->m_pitches = pitches;
649 Frame->m_offsets = offsets;
674 bool hwframes =
false;
675 bool useframebufferimage =
false;
687 VideoResizing resize;
694 if (inputtextures.empty())
701 Frame->m_displayed =
false;
712 if (!inputtextures.empty())
715 QSize newsize = inputtextures[0]->m_size;
718 GLenum newtargettexture = inputtextures[0]->m_target;
732 m_shaders[
Default]->setUniformValue(
"u_transform", *inputtextures[0]->m_transform);
737 if (inputtextures[0]->m_allowGLSLDeint)
744 LOG(VB_PLAYBACK, LOG_DEBUG,
"Using existing framebuffer");
745 useframebufferimage =
true;
749 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"Nothing to display");
759 bool deinterlacing =
false;
760 bool basicdeinterlacing =
false;
768 deinterlacing =
true;
773 deinterlacing =
true;
779 basicdeinterlacing =
true;
786 if (deinterlacing &&
Frame)
797 if (yuvoutput && !resize)
819 if (!resize && !tiled && !basicdeinterlacing)
826 if ((totexture + blitcost) < noresizecost)
859 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Disabled resizing");
864 QOpenGLTexture::Filter filter = ((resize &
Sampling) ==
Sampling) ? QOpenGLTexture::Nearest : QOpenGLTexture::Linear;
869 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Resizing from %1x%2 to %3x%4 for %5")
878 QOpenGLTexture::Filter filter = (resize.testFlag(
Sampling)) ? QOpenGLTexture::Nearest : QOpenGLTexture::Linear;
879 if (inputtextures[0]->m_filter != filter)
891 if (useframebufferimage)
920 (fbo !=
nullptr) && (tex !=
nullptr))
935 QRect trect2 = vrect;
944 std::vector<MythGLTexture*> textures {};
954 inputtextures.clear();
955 inputtextures.push_back(nexttexture);
957 deinterlacing =
false;
983 trect = QRect(trect.left() >> 1, trect.top(), trect.width() >> 1, trect.height());
985 trect = QRect(trect.left(), trect.top() >> 1, trect.width(), trect.height() >> 1);
995 static const QPen kNopen(Qt::NoPen);
996 static const QBrush kRedBrush(QBrush(QColor(127, 0, 0, 255)));
1001 std::vector<MythGLTexture*> textures;
1033 texture->m_valid =
false;
1035 texture->m_valid =
false;
1037 texture->m_valid =
false;
1041 std::vector<MythGLTexture*>& Textures)
1049 size_t count = Current.size();
1053 for (
uint i = 0; i < count; ++i)
1054 Textures.push_back(
reinterpret_cast<MythGLTexture*
>(prev[i]));
1055 for (
uint i = 0; i < count; ++i)
1057 for (
uint i = 0; i < count; ++i)
1063 std::transform(Current.cbegin(), Current.cend(), std::back_inserter(Textures),
1075 case FMT_YV12:
return "opengl-yv12";
1076 case FMT_NV12:
return "opengl-nv12";
1091 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to create bicubic shader. Disabling");
1097 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Created bicubic sampler");
1108 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