Go to the documentation of this file.
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);
324 #ifdef USING_MEDIACODEC
326 vertex = MediaCodecVertexShader;
340 static const QString glsl300(
"#version 300 es\n");
344 glsldefines.append(glsl300);
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;
725 #ifdef USING_MEDIACODEC
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");
MythOpenGLTonemap * m_toneMap
uint64_t m_discontinuityCounter
void DeleteFramebuffer(QOpenGLFramebufferObject *Framebuffer)
static bool HardwareFramesFormat(VideoFrameType Type)
MythVideoTextureOpenGL * Map(std::vector< MythVideoTextureOpenGL * > &Inputs, QSize DisplaySize)
void ResetTextures() override
Clear reference frames after a seek as they will contain old images.
MythVideoTextureOpenGL * m_frameBufferTexture
MythOpenGLVideo(MythRenderOpenGL *Render, MythVideoColourSpace *ColourSpace, MythVideoBounds *Bounds, const MythVideoProfilePtr &VideoProfile, const QString &Profile)
static const QString BicubicShader
bool UpdateColourSpace(const MythVideoFrame *Frame)
Set the current colourspace to use.
void logDebugMarker(const QString &Message)
static bool FormatIsRGB(VideoFrameType Type)
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
MythVideoColourSpace * m_videoColourSpace
~MythOpenGLVideo() override
std::array< int, 3 > FramePitches
void DrawBitmap(MythGLTexture *Texture, QOpenGLFramebufferObject *Target, QRect Source, QRect Destination, QOpenGLShaderProgram *Program, int Alpha=255, qreal Scale=1.0)
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
static bool HardwareFormat(VideoFrameType Type)
void PrepareFrame(MythVideoFrame *Frame, FrameScanType Scan=kScan_Progressive) override
Update the current input texture using the data from the given video frame.
static void SetTextureFilters(MythRenderOpenGL *Context, const std::vector< MythVideoTextureOpenGL * > &Textures, QOpenGLTexture::Filter Filter, QOpenGLTexture::WrapMode Wrap=QOpenGLTexture::ClampToEdge)
std::array< int, 3 > FrameOffsets
static bool FormatIs422(VideoFrameType Type)
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.
bool SetupFrameFormat(VideoFrameType InputType, VideoFrameType OutputType, QSize Size, GLenum TextureTarget)
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
QOpenGLFunctions::OpenGLFeatures GetFeatures(void) const
MythDeintType m_fallbackDeinterlacer
void SetShaderProgramParams(QOpenGLShaderProgram *Program, const QMatrix4x4 &Value, const char *Uniform)
QOpenGLFramebufferObject * m_frameBuffer
#define GL_TEXTURE_EXTERNAL_OES
QStringList GetColourMappingDefines(void)
static bool YUVFormat(VideoFrameType Type)
QOpenGLFunctions::OpenGLFeatures m_features
void BindTextures(bool Deinterlacing, std::vector< MythVideoTextureOpenGL * > &Current, std::vector< MythGLTexture * > &Textures)
void ColourSpaceUpdate(bool PrimariesChanged) override
MythRenderOpenGL * m_openglRender
void DrawRect(QOpenGLFramebufferObject *Target, QRect Area, const QBrush &FillBrush, const QPen &LinePen, int Alpha)
static QString TypeToProfile(VideoFrameType Type)
void RenderFrame(MythVideoFrame *Frame, bool TopFieldFirst, FrameScanType Scan, StereoscopicMode StereoOverride, bool DrawBorder=false) override
std::vector< MythVideoTextureOpenGL * > m_inputTextures
bool m_chromaUpsamplingFilter
void SetupBicubic(VideoResizing &Resize)
bool AddDeinterlacer(const MythVideoFrame *Frame, FrameScanType Scan, MythDeintType Filter=DEINT_SHADER, bool CreateReferences=true)
float GetColourGamma(void) const
static const QString GLSL300VertexShader
std::vector< MythVideoTextureOpenGL * > m_prevTextures
static QString VideoResizeToString(VideoResizing Resize)
static int ColorDepth(int Format)
void DeleteTexture(MythGLTexture *Texture)
static const QString GLSL300YUVFragmentExtensions
MythDeintType m_deinterlacer
void UpdateShaderParameters()
int GetExtraFeatures(void) const
VideoFrameType m_outputType
float GetDisplayGamma(void) const
void DeleteShaderProgram(QOpenGLShaderProgram *Program)
void CleanupDeinterlacers()
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
void OutputChanged(QSize VideoDim, QSize VideoDispDim, float)
StereoscopicMode m_stereoMode
static bool FormatIs444(VideoFrameType Type)
bool GetBoolSetting(const QString &key, bool defaultval=false)
int GetMaxTextureUnits(void) const
static bool FormatIs420(VideoFrameType Type)
std::array< QOpenGLShaderProgram *, ShaderCount > m_shaders
void BindFramebuffer(QOpenGLFramebufferObject *Framebuffer)
static QString FormatDescription(VideoFrameType Type)
bool CreateVideoShader(VideoShaderType Type, MythDeintType Deint=DEINT_NONE)
Create the appropriate shader for the operation Type.
static const QString YUVFragmentExtensions
MythVideoTextureOpenGL * GetTexture()
static QString DeinterlacerName(MythDeintType Deint, bool DoubleRate, VideoFrameType Format=FMT_NONE)
static void DeleteTextures(MythRenderOpenGL *Context, std::vector< MythVideoTextureOpenGL * > &Textures)
static VideoFramebuffer CreateVideoFrameBuffer(MythRenderOpenGL *Context, VideoFrameType OutputType, QSize Size, bool HighPrecision=true)
void SetTextureFilters(MythGLTexture *Texture, QOpenGLTexture::Filter Filter, QOpenGLTexture::WrapMode Wrap=QOpenGLTexture::ClampToEdge)
std::vector< MythVideoTextureOpenGL * > m_nextTextures
static uint GetNumPlanes(VideoFrameType Type)
QMatrix4x4 GetPrimaryMatrix(void)
@ kStereoscopicModeTopAndBottomDiscard
static const QString DefaultVertexShader
static const QString YUVFragmentShader
virtual void ResetFrameFormat()
void UpdateColourSpace(bool PrimariesChanged)
void SetViewPort(QRect Rect, bool ViewportOnly=false) override
std::shared_ptr< MythVideoProfile > MythVideoProfilePtr
@ kStereoscopicModeSideBySideDiscard
static const QString RGBFragmentShader
QSize m_masterViewportSize
bool is_interlaced(FrameScanType Scan)
static bool FormatIsNV12(VideoFrameType Type)
std::array< int, ShaderCount > m_shaderCost
MythVideoColourSpace contains a QMatrix4x4 that can convert YCbCr data to RGB.
VideoFrameType m_inputType
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 const QString GLSL300YUVFragmentShader
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)
static std::vector< MythVideoTextureOpenGL * > Retrieve(MythRenderOpenGL *Context, MythVideoColourSpace *ColourSpace, MythVideoFrame *Frame, FrameScanType Scan)
QOpenGLShaderProgram * CreateShaderProgram(const QString &Vertex, const QString &Fragment)
bool EnableShaderProgram(QOpenGLShaderProgram *Program)
QString GetProfile() const override
void ResetFrameFormat() override