From 167a941f8070f4a9abacb3aa2f61ee6ee00d6cb8 Mon Sep 17 00:00:00 2001 From: Mladen Milinkovic Date: Thu, 7 Oct 2021 19:37:23 +0200 Subject: [PATCH] GLRenderer: added GLES support --- src/videoplayer/backend/glrenderer.cpp | 44 ++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/src/videoplayer/backend/glrenderer.cpp b/src/videoplayer/backend/glrenderer.cpp index 7c9c38b..5cb985d 100644 --- a/src/videoplayer/backend/glrenderer.cpp +++ b/src/videoplayer/backend/glrenderer.cpp @@ -20,6 +20,7 @@ extern "C" { } #define DEBUG_GL 0 +#define FORCE_GLES 0 #define OPENGL_CORE 0 #define OPENGL_VER 2,0 @@ -33,6 +34,17 @@ extern "C" { #define asGL(glCall) glCall #endif +#if defined(GL_ES_VERSION_2_0) || FORCE_GLES +#define USE_GLES +#define TEXTURE_RGB_FORMAT GL_RGBA +// NOTE: we don't currently support more than 8bpp on GLES +#define TEXTURE_U16_FORMAT GL_R8 +#else +#undef USE_GLES +#define TEXTURE_RGB_FORMAT GL_BGRA +#define TEXTURE_U16_FORMAT GL_R16 +#endif + using namespace SubtitleComposer; enum { ID_Y, ID_U, ID_V, ID_OVR, ID_SIZE }; @@ -82,6 +94,9 @@ void GLRenderer::setupProfile() { QSurfaceFormat format(QSurfaceFormat::defaultFormat()); +#if FORCE_GLES + format.setRenderableType(QSurfaceFormat::OpenGLES); +#endif format.setVersion(OPENGL_VER); #if DEBUG_GL format.setOption(QSurfaceFormat::DebugContext); @@ -126,7 +141,7 @@ GLRenderer::setFrameFormat(int width, int height, int compBits, int crWidthShift m_crHeight = crHeight; m_glType = compBytes == 1 ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT; - m_glFormat = compBytes == 1 ? GL_R8 : GL_R16; + m_glFormat = compBytes == 1 ? GL_R8 : TEXTURE_U16_FORMAT; delete[] m_bufYUV; m_bufSize = bufSize; @@ -261,7 +276,11 @@ GLRenderer::initShader() delete m_vertShader; m_vertShader = new QOpenGLShader(QOpenGLShader::Vertex, this); bool success = m_vertShader->compileSourceCode( +#ifdef USE_GLES + "#version 100\n" +#else "#version 120\n" +#endif "attribute vec4 vPos;" "attribute vec2 vVidTex;" "attribute vec2 vOvrTex;" @@ -288,7 +307,13 @@ GLRenderer::initShader() csms.append(QString::number(csm[i], 'g', 10)); } - success = m_fragShader->compileSourceCode(QStringLiteral("#version 120\n" + success = m_fragShader->compileSourceCode(QStringLiteral( +#ifdef USE_GLES + "#version 100\n" + "precision mediump float;\n" +#else + "#version 120\n" +#endif "varying vec2 vfVidTex;" "varying vec2 vfOvrTex;" "uniform sampler2D texY;" @@ -348,8 +373,15 @@ GLRenderer::initializeGL() QMutexLocker l(&m_texMutex); initializeOpenGLFunctions(); - qDebug() << "OpenGL version: " << reinterpret_cast(glGetString(GL_VERSION)); - qDebug() << "GLSL version: " << reinterpret_cast(glGetString(GL_SHADING_LANGUAGE_VERSION)); + qDebug().nospace() << "GL API: OpenGL " << (format().renderableType() == QSurfaceFormat::OpenGLES ? "ES" : "Desktop") + << ' ' << format().majorVersion() << "." << format().minorVersion() +#ifdef USE_GLES + << " (compiled for OpenGL ES)"; +#else + << " (compiled for OpenGL Desktop)"; +#endif + qDebug() << "OpenGL version:" << reinterpret_cast(glGetString(GL_VERSION)); + qDebug() << "GLSL version:" << reinterpret_cast(glGetString(GL_SHADING_LANGUAGE_VERSION)); if(m_vao.create()) m_vao.bind(); @@ -453,13 +485,13 @@ GLRenderer::uploadMM(int texWidth, int texHeight, T *texBuf, const T *texSrc) if(D == 1) { asGL(glTexImage2D(GL_TEXTURE_2D, level, m_glFormat, texWidth, texHeight, 0, GL_RED, m_glType, texSrc)); } else { // D == 4 - asGL(glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, texWidth, texHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, texSrc)); + asGL(glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, texWidth, texHeight, 0, TEXTURE_RGB_FORMAT, GL_UNSIGNED_BYTE, texSrc)); } } else { if(D == 1) { asGL(glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, texWidth, texHeight, GL_RED, m_glType, texSrc)); } else { // D == 4 - asGL(glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, texWidth, texHeight, GL_BGRA, GL_UNSIGNED_BYTE, texSrc)); + asGL(glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, texWidth, texHeight, TEXTURE_RGB_FORMAT, GL_UNSIGNED_BYTE, texSrc)); } } -- GitLab From 0242ebca3c5439dfde63a12074212c4d80fc0f1e Mon Sep 17 00:00:00 2001 From: Mladen Milinkovic Date: Thu, 7 Oct 2021 23:55:47 +0200 Subject: [PATCH] SubtitleTextOverlay: RGB/BGR pixel support --- src/videoplayer/backend/glrenderer.cpp | 5 ++++- src/videoplayer/subtitletextoverlay.cpp | 21 ++++++++++++++++++--- src/videoplayer/subtitletextoverlay.h | 6 ++++-- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/videoplayer/backend/glrenderer.cpp b/src/videoplayer/backend/glrenderer.cpp index 5cb985d..6dad043 100644 --- a/src/videoplayer/backend/glrenderer.cpp +++ b/src/videoplayer/backend/glrenderer.cpp @@ -113,6 +113,9 @@ GLRenderer::setOverlay(SubtitleTextOverlay *overlay) if(m_overlay) disconnect(m_overlay, nullptr, this, nullptr); m_overlay = overlay; +#ifdef USE_GLES + overlay->invertPixels(true); +#endif connect(m_overlay, &SubtitleTextOverlay::repaintNeeded, this, QOverload<>::of(&GLRenderer::update)); } @@ -607,7 +610,7 @@ GLRenderer::uploadSubtitle() // overlay asGL(glActiveTexture(GL_TEXTURE0 + ID_OVR)); asGL(glBindTexture(GL_TEXTURE_2D, m_idTex[ID_OVR])); - uploadMM(img.width(), img.height(), m_mmOvr, img.bits()); + uploadMM(img.width(), img.height(), m_mmOvr, img.constBits()); if(m_texNeedInit) { asGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)); asGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)); diff --git a/src/videoplayer/subtitletextoverlay.cpp b/src/videoplayer/subtitletextoverlay.cpp index afcb344..9fedd5b 100644 --- a/src/videoplayer/subtitletextoverlay.cpp +++ b/src/videoplayer/subtitletextoverlay.cpp @@ -18,7 +18,8 @@ using namespace SubtitleComposer; SubtitleTextOverlay::SubtitleTextOverlay() - : m_fontSize(SCConfig::fontSize()) + : m_invertPixels(false), + m_fontSize(SCConfig::fontSize()) { m_font.setStyleStrategy(QFont::PreferAntialias); } @@ -192,6 +193,16 @@ SubtitleTextOverlay::image() return m_image; } +void +SubtitleTextOverlay::invertPixels(bool invert) +{ + if(m_invertPixels == invert) + return; + m_invertPixels = invert; + setTextColor(m_textColor); + setOutlineColor(m_textOutline.color()); +} + const QSize & SubtitleTextOverlay::textSize() { @@ -278,8 +289,10 @@ SubtitleTextOverlay::setFontSize(int fontSize) } void -SubtitleTextOverlay::setTextColor(const QColor &color) +SubtitleTextOverlay::setTextColor(QColor color) { + if(m_invertPixels) + color = QColor(color.blue(), color.green(), color.red(), color.alpha()); if(m_textColor == color) return; m_textColor = color; @@ -287,8 +300,10 @@ SubtitleTextOverlay::setTextColor(const QColor &color) } void -SubtitleTextOverlay::setOutlineColor(const QColor &color) +SubtitleTextOverlay::setOutlineColor(QColor color) { + if(m_invertPixels) + color = QColor(color.blue(), color.green(), color.red(), color.alpha()); if(m_textOutline.color() == color) return; m_textOutline.setColor(color); diff --git a/src/videoplayer/subtitletextoverlay.h b/src/videoplayer/subtitletextoverlay.h index 5cbe508..204c1fb 100644 --- a/src/videoplayer/subtitletextoverlay.h +++ b/src/videoplayer/subtitletextoverlay.h @@ -36,6 +36,7 @@ public: const QSize & textSize(); inline bool isDirty() const { return m_dirty; } inline double renderScale() const { return m_renderScale; } + void invertPixels(bool invert); private: void drawImage(); @@ -53,12 +54,13 @@ public slots: void setDoc(const RichDocument *doc); void setFontFamily(const QString &family); void setFontSize(int fontSize); - void setTextColor(const QColor &color); - void setOutlineColor(const QColor &color); + void setTextColor(QColor color); + void setOutlineColor(QColor color); void setOutlineWidth(int width); inline void setRenderScale(double scale) { m_renderScale = scale; } private: + bool m_invertPixels; QString m_text; const RichDocument *m_doc = nullptr; QFont m_font; -- GitLab From 89dd7a6bcef81e400946985201a5d92f84b0e980 Mon Sep 17 00:00:00 2001 From: Mladen Milinkovic Date: Sat, 9 Oct 2021 11:42:31 +0200 Subject: [PATCH] Moved texture upload code to GLRenderer --- src/videoplayer/backend/glrenderer.cpp | 97 ++++++++++++++++++++ src/videoplayer/backend/glrenderer.h | 5 ++ src/videoplayer/backend/renderthread.cpp | 107 +---------------------- src/videoplayer/backend/renderthread.h | 3 - 4 files changed, 106 insertions(+), 106 deletions(-) diff --git a/src/videoplayer/backend/glrenderer.cpp b/src/videoplayer/backend/glrenderer.cpp index 6dad043..ca99b14 100644 --- a/src/videoplayer/backend/glrenderer.cpp +++ b/src/videoplayer/backend/glrenderer.cpp @@ -66,6 +66,7 @@ GLRenderer::GLRenderer(QWidget *parent) m_fragShader(nullptr), m_shaderProg(nullptr), m_texNeedInit(true), + m_lastFormat(-1), m_idTex(nullptr), m_vaBuf(nullptr) { @@ -228,6 +229,102 @@ GLRenderer::setColorspace(const AVFrame *frame) m_csCM.scale(pixMult, pixMult, pixMult); } +bool +GLRenderer::validTextureFormat(const AVPixFmtDescriptor *fd) +{ + const uint64_t &f = fd->flags; + if((f & AV_PIX_FMT_FLAG_BITSTREAM)) { + qCritical("uploadTexture() failed: unsupported frame format [%s] - bitstream", fd->name); + return false; + } + if((f & AV_PIX_FMT_FLAG_PAL)) { + qCritical("uploadTexture() failed: unsupported frame format [%s] - palette", fd->name); + return false; + } + if((f & AV_PIX_FMT_FLAG_BE)) { + qCritical("uploadTexture() failed: unsupported frame format [%s] - bigendian", fd->name); + return false; + } + + const bool isYUV = !(f & AV_PIX_FMT_FLAG_RGB); + const bool isPlanar = f & AV_PIX_FMT_FLAG_PLANAR; + if(isPlanar && isYUV) { + const quint8 b = fd->comp[0].depth > 8 ? 2 : 1; + if(fd->comp[0].step != b || fd->comp[1].step != b || fd->comp[2].step != b) { + qCritical("validTextureFormat() failed: unsupported plane step [%d, %d, %d] %s", + fd->comp[0].step, fd->comp[1].step, fd->comp[2].step, fd->name); + return false; + } + if(fd->comp[0].offset || fd->comp[1].offset || fd->comp[2].offset) { + qCritical("validTextureFormat() failed: unsupported plane offset [%d, %d, %d] %s", + fd->comp[0].offset, fd->comp[1].offset, fd->comp[2].offset, fd->name); + return false; + } + if(fd->comp[0].shift || fd->comp[1].shift || fd->comp[2].shift) { + qCritical("validTextureFormat() failed: unsupported plane shift [%d, %d, %d] %s", + fd->comp[0].shift, fd->comp[1].shift, fd->comp[2].shift, fd->name); + return false; + } + if(fd->comp[0].depth != fd->comp[1].depth || fd->comp[0].depth != fd->comp[2].depth) { + qCritical("validTextureFormat() failed: unsupported plane depths [%d, %d, %d] %s", + fd->comp[0].depth, fd->comp[1].depth, fd->comp[2].depth, fd->name); + return false; + } + if(fd->nb_components < 3) { + qCritical("validTextureFormat() failed: unsupported plane count [%d] %s", + fd->nb_components, fd->name); + return false; + } + } else { + qCritical("validTextureFormat() failed: unsupported frame format [%s]", fd->name); + return false; + } + return true; +} + +int +GLRenderer::uploadTexture(AVFrame *frame) +{ + const AVPixFmtDescriptor *fd = av_pix_fmt_desc_get(AVPixelFormat(frame->format)); + if(m_lastFormat != frame->format) { + if(!validTextureFormat(fd)) + return -1; + m_lastFormat = frame->format; + } + + if(!frame->linesize[0] || !frame->linesize[1] || !frame->linesize[2]) { + qCritical("uploadTexture() failed: invalid linesize [%d, %d, %d]", + frame->linesize[0], frame->linesize[1], frame->linesize[2]); + return -1; + } + + QMutexLocker l(&m_texMutex); + + setFrameFormat(frame->width, frame->height, + fd->comp[0].depth, fd->log2_chroma_w, fd->log2_chroma_h); + + setColorspace(frame); + + if(frame->linesize[0] > 0) + setFrameY(frame->data[0], frame->linesize[0]); + else + setFrameY(frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0]); + + if(frame->linesize[1] > 0) + setFrameU(frame->data[1], frame->linesize[1]); + else + setFrameU(frame->data[1] + frame->linesize[1] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[1]); + + if(frame->linesize[2] > 0) + setFrameV(frame->data[2], frame->linesize[2]); + else + setFrameV(frame->data[2] + frame->linesize[2] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[2]); + + update(); + + return 0; +} + void GLRenderer::setFrameY(quint8 *buf, quint32 pitch) { diff --git a/src/videoplayer/backend/glrenderer.h b/src/videoplayer/backend/glrenderer.h index bb90396..037c817 100644 --- a/src/videoplayer/backend/glrenderer.h +++ b/src/videoplayer/backend/glrenderer.h @@ -21,6 +21,8 @@ extern "C" { QT_FORWARD_DECLARE_CLASS(QOpenGLShader) QT_FORWARD_DECLARE_CLASS(QOpenGLShaderProgram) +struct AVPixFmtDescriptor; + namespace SubtitleComposer { class SubtitleTextOverlay; @@ -40,6 +42,7 @@ public: void setFrameFormat(int width, int height, int compBits, int crWidthShift, int crHeightShift); void setColorspace(const AVFrame *frame); + int uploadTexture(AVFrame *frame); void setFrameY(quint8 *buf, quint32 pitch); void setFrameU(quint8 *buf, quint32 pitch); void setFrameV(quint8 *buf, quint32 pitch); @@ -60,6 +63,7 @@ private: template void uploadMM(int texWidth, int texHeight, T *texBuf, const T *texSrc); void uploadYUV(); void uploadSubtitle(); + bool validTextureFormat(const AVPixFmtDescriptor *fd); private: SubtitleTextOverlay *m_overlay; @@ -85,6 +89,7 @@ private: QOpenGLShaderProgram *m_shaderProg; bool m_texNeedInit; + int m_lastFormat; int m_vpWidth, m_vpHeight; int m_texY, m_texU, m_texV, m_texOvr; GLuint *m_idTex; diff --git a/src/videoplayer/backend/renderthread.cpp b/src/videoplayer/backend/renderthread.cpp index 051832d..3c16965 100644 --- a/src/videoplayer/backend/renderthread.cpp +++ b/src/videoplayer/backend/renderthread.cpp @@ -23,8 +23,7 @@ using namespace SubtitleComposer; RenderThread::RenderThread(VideoState *state, QObject *parent) : QThread(parent), - m_vs(state), - m_lastFormat(-1) + m_vs(state) { } @@ -412,8 +411,10 @@ RenderThread::videoImageDisplay() #endif if(!vp->uploaded) { - if(uploadTexture(vp->frame) < 0) + if(m_vs->glRenderer->uploadTexture(vp->frame) < 0) { + requestInterruption(); return; + } vp->uploaded = true; } @@ -473,103 +474,3 @@ RenderThread::toggleAudioDisplay() m_vs->showMode = ShowMode(next); } } - -bool -RenderThread::validTextureFormat(const AVPixFmtDescriptor *fd) -{ - const uint64_t &f = fd->flags; - if((f & AV_PIX_FMT_FLAG_BITSTREAM)) { - qCritical("uploadTexture() failed: unsupported frame format [%s] - bitstream", fd->name); - return false; - } - if((f & AV_PIX_FMT_FLAG_PAL)) { - qCritical("uploadTexture() failed: unsupported frame format [%s] - palette", fd->name); - return false; - } - if((f & AV_PIX_FMT_FLAG_BE)) { - qCritical("uploadTexture() failed: unsupported frame format [%s] - bigendian", fd->name); - return false; - } - - m_isYUV = !(f & AV_PIX_FMT_FLAG_RGB); - m_isPlanar = f & AV_PIX_FMT_FLAG_PLANAR; - if(m_isPlanar && m_isYUV) { - const quint8 b = fd->comp[0].depth > 8 ? 2 : 1; - if(fd->comp[0].step != b || fd->comp[1].step != b || fd->comp[2].step != b) { - qCritical("validTextureFormat() failed: unsupported plane step [%d, %d, %d] %s", - fd->comp[0].step, fd->comp[1].step, fd->comp[2].step, fd->name); - return false; - } - if(fd->comp[0].offset || fd->comp[1].offset || fd->comp[2].offset) { - qCritical("validTextureFormat() failed: unsupported plane offset [%d, %d, %d] %s", - fd->comp[0].offset, fd->comp[1].offset, fd->comp[2].offset, fd->name); - return false; - } - if(fd->comp[0].shift || fd->comp[1].shift || fd->comp[2].shift) { - qCritical("validTextureFormat() failed: unsupported plane shift [%d, %d, %d] %s", - fd->comp[0].shift, fd->comp[1].shift, fd->comp[2].shift, fd->name); - return false; - } - if(fd->comp[0].depth != fd->comp[1].depth || fd->comp[0].depth != fd->comp[2].depth) { - qCritical("validTextureFormat() failed: unsupported plane depths [%d, %d, %d] %s", - fd->comp[0].depth, fd->comp[1].depth, fd->comp[2].depth, fd->name); - return false; - } - if(fd->nb_components < 3) { - qCritical("validTextureFormat() failed: unsupported plane count [%d] %s", - fd->nb_components, fd->name); - return false; - } - } else { - qCritical("validTextureFormat() failed: unsupported frame format [%s]", fd->name); - return false; - } - return true; -} - -int -RenderThread::uploadTexture(AVFrame *frame) -{ - const AVPixFmtDescriptor *fd = av_pix_fmt_desc_get(AVPixelFormat(frame->format)); - if(m_lastFormat != frame->format) { - if(!validTextureFormat(fd)) { - requestInterruption(); - return -1; - } - m_lastFormat = frame->format; - } - - if(m_isPlanar && m_isYUV) { - if(!frame->linesize[0] || !frame->linesize[1] || !frame->linesize[2]) { - qCritical("uploadTexture() failed: invalid linesize [%d, %d, %d]", - frame->linesize[0], frame->linesize[1], frame->linesize[2]); - return -1; - } - - QMutexLocker l(m_vs->glRenderer->mutex()); - - m_vs->glRenderer->setFrameFormat(frame->width, frame->height, - fd->comp[0].depth, fd->log2_chroma_w, fd->log2_chroma_h); - - m_vs->glRenderer->setColorspace(frame); - - if(frame->linesize[0] > 0) - m_vs->glRenderer->setFrameY(frame->data[0], frame->linesize[0]); - else - m_vs->glRenderer->setFrameY(frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0]); - - if(frame->linesize[1] > 0) - m_vs->glRenderer->setFrameU(frame->data[1], frame->linesize[1]); - else - m_vs->glRenderer->setFrameU(frame->data[1] + frame->linesize[1] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[1]); - - if(frame->linesize[2] > 0) - m_vs->glRenderer->setFrameV(frame->data[2], frame->linesize[2]); - else - m_vs->glRenderer->setFrameV(frame->data[2] + frame->linesize[2] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[2]); - - m_vs->glRenderer->update(); - } - - return 0; -} diff --git a/src/videoplayer/backend/renderthread.h b/src/videoplayer/backend/renderthread.h index a2d0677..8a563f4 100644 --- a/src/videoplayer/backend/renderthread.h +++ b/src/videoplayer/backend/renderthread.h @@ -37,14 +37,11 @@ private: double computeTargetDelay(double delay); void updateSampleDisplay(short *samples, int samplesSize); void toggleAudioDisplay(); - bool validTextureFormat(const AVPixFmtDescriptor *fd); - int uploadTexture(AVFrame *frame); void videoImageDisplay(); void videoAudioDisplay(); private: VideoState *m_vs; - int m_lastFormat; bool m_isYUV; bool m_isPlanar; }; -- GitLab From c6a0fa92e4f803e35b56588fca89204220a75c97 Mon Sep 17 00:00:00 2001 From: Mladen Milinkovic Date: Sat, 9 Oct 2021 12:02:34 +0200 Subject: [PATCH] GLRenderer: added YUV >8bpp support on GLES --- src/videoplayer/backend/glrenderer.cpp | 69 ++++++++++++++++++-------- src/videoplayer/backend/glrenderer.h | 2 + src/videoplayer/backend/videostate.h | 1 + 3 files changed, 51 insertions(+), 21 deletions(-) diff --git a/src/videoplayer/backend/glrenderer.cpp b/src/videoplayer/backend/glrenderer.cpp index ca99b14..f8c3351 100644 --- a/src/videoplayer/backend/glrenderer.cpp +++ b/src/videoplayer/backend/glrenderer.cpp @@ -17,6 +17,7 @@ extern "C" { #include "libavutil/pixdesc.h" +#include "libswscale/swscale.h" } #define DEBUG_GL 0 @@ -37,14 +38,18 @@ extern "C" { #if defined(GL_ES_VERSION_2_0) || FORCE_GLES #define USE_GLES #define TEXTURE_RGB_FORMAT GL_RGBA -// NOTE: we don't currently support more than 8bpp on GLES -#define TEXTURE_U16_FORMAT GL_R8 +// NOTE: we don't support rendering >8bpp on GLES, so 16bit textures are never used +// and cpu will convert the frame to 8bpp +#define TEXTURE_U16_FORMAT 0x822A #else #undef USE_GLES #define TEXTURE_RGB_FORMAT GL_BGRA #define TEXTURE_U16_FORMAT GL_R16 #endif +#define FRAME_IS_YUV(f) ((f & AV_PIX_FMT_FLAG_RGB) == 0) +#define FRAME_IS_PLANAR(f) ((f & AV_PIX_FMT_FLAG_PLANAR) != 0) + using namespace SubtitleComposer; enum { ID_Y, ID_U, ID_V, ID_OVR, ID_SIZE }; @@ -54,6 +59,7 @@ GLRenderer::GLRenderer(QWidget *parent) : QOpenGLWidget(parent), m_overlay(nullptr), m_mmOvr(nullptr), + m_frameConvCtx(nullptr), m_bufYUV(nullptr), m_mmYUV(nullptr), m_bufSize(0), @@ -86,6 +92,7 @@ GLRenderer::~GLRenderer() } m_vao.destroy(); doneCurrent(); + sws_freeContext(m_frameConvCtx); delete[] m_bufYUV; delete[] m_mmYUV; delete[] m_mmOvr; @@ -180,7 +187,7 @@ GLRenderer::setColorspace(const AVFrame *frame) const AVPixFmtDescriptor *fd = av_pix_fmt_desc_get(AVPixelFormat(frame->format)); const quint8 compBits = fd->comp[0].depth; const quint8 compBytes = compBits > 8 ? 2 : 1; - const bool isYUV = ~fd->flags & AV_PIX_FMT_FLAG_RGB; + const bool isYUV = FRAME_IS_YUV(fd->flags); qDebug("Color range: %s(%d); primaries: %s(%d); xfer: %s(%d); space: %s(%d); depth: %d", av_color_range_name(frame->color_range), frame->color_range, @@ -246,9 +253,7 @@ GLRenderer::validTextureFormat(const AVPixFmtDescriptor *fd) return false; } - const bool isYUV = !(f & AV_PIX_FMT_FLAG_RGB); - const bool isPlanar = f & AV_PIX_FMT_FLAG_PLANAR; - if(isPlanar && isYUV) { + if(FRAME_IS_YUV(f) && FRAME_IS_PLANAR(f)) { const quint8 b = fd->comp[0].depth > 8 ? 2 : 1; if(fd->comp[0].step != b || fd->comp[1].step != b || fd->comp[2].step != b) { qCritical("validTextureFormat() failed: unsupported plane step [%d, %d, %d] %s", @@ -300,25 +305,47 @@ GLRenderer::uploadTexture(AVFrame *frame) QMutexLocker l(&m_texMutex); - setFrameFormat(frame->width, frame->height, - fd->comp[0].depth, fd->log2_chroma_w, fd->log2_chroma_h); +#ifdef USE_GLES + if(fd->comp[0].depth > 8) { + // convert >8bpp YUV + frame->format = AV_PIX_FMT_YUV420P; - setColorspace(frame); + const static AVPixFmtDescriptor *fd8 = av_pix_fmt_desc_get(AVPixelFormat(frame->format)); + m_frameConvCtx = sws_getCachedContext(m_frameConvCtx, + frame->width, frame->height, AVPixelFormat(m_lastFormat), + frame->width, frame->height, AVPixelFormat(frame->format), + 0, nullptr, nullptr, nullptr); - if(frame->linesize[0] > 0) - setFrameY(frame->data[0], frame->linesize[0]); - else - setFrameY(frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0]); + setFrameFormat(frame->width, frame->height, + fd8->comp[0].depth, fd8->log2_chroma_w, fd8->log2_chroma_h); - if(frame->linesize[1] > 0) - setFrameU(frame->data[1], frame->linesize[1]); - else - setFrameU(frame->data[1] + frame->linesize[1] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[1]); + setColorspace(frame); - if(frame->linesize[2] > 0) - setFrameV(frame->data[2], frame->linesize[2]); - else - setFrameV(frame->data[2] + frame->linesize[2] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[2]); + sws_scale(m_frameConvCtx, frame->data, frame->linesize, 0, frame->height, + m_pixels, reinterpret_cast(m_pitch)); + } else +#endif + { + setFrameFormat(frame->width, frame->height, + fd->comp[0].depth, fd->log2_chroma_w, fd->log2_chroma_h); + + setColorspace(frame); + + if(frame->linesize[0] > 0) + setFrameY(frame->data[0], frame->linesize[0]); + else + setFrameY(frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0]); + + if(frame->linesize[1] > 0) + setFrameU(frame->data[1], frame->linesize[1]); + else + setFrameU(frame->data[1] + frame->linesize[1] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[1]); + + if(frame->linesize[2] > 0) + setFrameV(frame->data[2], frame->linesize[2]); + else + setFrameV(frame->data[2] + frame->linesize[2] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[2]); + } update(); diff --git a/src/videoplayer/backend/glrenderer.h b/src/videoplayer/backend/glrenderer.h index 037c817..ae6b0cb 100644 --- a/src/videoplayer/backend/glrenderer.h +++ b/src/videoplayer/backend/glrenderer.h @@ -22,6 +22,7 @@ QT_FORWARD_DECLARE_CLASS(QOpenGLShader) QT_FORWARD_DECLARE_CLASS(QOpenGLShaderProgram) struct AVPixFmtDescriptor; +struct SwsContext; namespace SubtitleComposer { class SubtitleTextOverlay; @@ -72,6 +73,7 @@ private: QOpenGLVertexArrayObject m_vao; + SwsContext *m_frameConvCtx; quint8 *m_bufYUV, *m_mmYUV; quint32 m_bufSize; GLsizei m_bufWidth, m_bufHeight; diff --git a/src/videoplayer/backend/videostate.h b/src/videoplayer/backend/videostate.h index a669f0f..160b6f7 100644 --- a/src/videoplayer/backend/videostate.h +++ b/src/videoplayer/backend/videostate.h @@ -24,6 +24,7 @@ extern "C" { #include "libavformat/avformat.h" #include "libavcodec/avfft.h" +#include "libswscale/swscale.h" } -- GitLab From 0f8f441d3b4da3be178f21b8e0bd06b9e47138be Mon Sep 17 00:00:00 2001 From: Mladen Milinkovic Date: Sat, 9 Oct 2021 13:02:03 +0200 Subject: [PATCH] GLRenderer: avoid re-uploading same texture --- src/videoplayer/backend/glrenderer.cpp | 6 ++++++ src/videoplayer/backend/glrenderer.h | 1 + src/videoplayer/backend/renderthread.cpp | 2 ++ 3 files changed, 9 insertions(+) diff --git a/src/videoplayer/backend/glrenderer.cpp b/src/videoplayer/backend/glrenderer.cpp index f8c3351..5c0086f 100644 --- a/src/videoplayer/backend/glrenderer.cpp +++ b/src/videoplayer/backend/glrenderer.cpp @@ -347,6 +347,7 @@ GLRenderer::uploadTexture(AVFrame *frame) setFrameV(frame->data[2] + frame->linesize[2] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[2]); } + m_texUploaded = false; update(); return 0; @@ -665,6 +666,11 @@ GLRenderer::uploadMM(int texWidth, int texHeight, T *texBuf, const T *texSrc) void GLRenderer::uploadYUV() { + if(!m_texNeedInit && m_texUploaded) + return; + + m_texUploaded = true; + // load Y data asGL(glActiveTexture(GL_TEXTURE0 + ID_Y)); asGL(glBindTexture(GL_TEXTURE_2D, m_idTex[ID_Y])); diff --git a/src/videoplayer/backend/glrenderer.h b/src/videoplayer/backend/glrenderer.h index ae6b0cb..b517786 100644 --- a/src/videoplayer/backend/glrenderer.h +++ b/src/videoplayer/backend/glrenderer.h @@ -91,6 +91,7 @@ private: QOpenGLShaderProgram *m_shaderProg; bool m_texNeedInit; + bool m_texUploaded; int m_lastFormat; int m_vpWidth, m_vpHeight; int m_texY, m_texU, m_texV, m_texOvr; diff --git a/src/videoplayer/backend/renderthread.cpp b/src/videoplayer/backend/renderthread.cpp index 3c16965..695e74b 100644 --- a/src/videoplayer/backend/renderthread.cpp +++ b/src/videoplayer/backend/renderthread.cpp @@ -34,6 +34,8 @@ RenderThread::run() for(;;) { if(remaining_time > 0.0) av_usleep((int64_t)(remaining_time * double(AV_TIME_BASE))); + else + yieldCurrentThread(); // allow gui to update remaining_time = REFRESH_RATE; if(isInterruptionRequested()) break; -- GitLab