5955d0b373
- Add subtitlecomposer-ARM_GLES.patch - Allow build on more targets OBS-URL: https://build.opensuse.org/request/show/925670 OBS-URL: https://build.opensuse.org/package/show/KDE:Extra/subtitlecomposer?expand=0&rev=29
800 lines
27 KiB
Diff
800 lines
27 KiB
Diff
From 167a941f8070f4a9abacb3aa2f61ee6ee00d6cb8 Mon Sep 17 00:00:00 2001
|
|
From: Mladen Milinkovic <maxrd2@smoothware.net>
|
|
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<const char *>(glGetString(GL_VERSION));
|
|
- qDebug() << "GLSL version: " << reinterpret_cast<const char *>(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<const char *>(glGetString(GL_VERSION));
|
|
+ qDebug() << "GLSL version:" << reinterpret_cast<const char *>(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 <maxrd2@smoothware.net>
|
|
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<quint8, 4>(img.width(), img.height(), m_mmOvr, img.bits());
|
|
+ uploadMM<quint8, 4>(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 <maxrd2@smoothware.net>
|
|
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<class T, int D> 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 <maxrd2@smoothware.net>
|
|
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<const int *>(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 <maxrd2@smoothware.net>
|
|
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
|
|
|