File subtitlecomposer-ARM_GLES.patch of Package subtitlecomposer

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

openSUSE Build Service is sponsored by