summaryrefslogtreecommitdiffstats
path: root/src/plugins/android/videonode
diff options
context:
space:
mode:
authorYoann Lopes <yoann.lopes@digia.com>2014-01-20 17:20:26 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-01-20 17:26:21 +0100
commita0746fe49c186566fc8c619daf0b8bb82929ac55 (patch)
tree346af347a087cb2ed738ce84be54e7b997c9b707 /src/plugins/android/videonode
parent437db8df51c8ce11f6d856d1c0441572cf218e1f (diff)
Android: fixed video rendering with multiple media players.
It seems all Android media players share the same video buffers, which results in textures containing frames for the wrong media player. When getting a new frame, we now copy it into a FBO in order to avoid that another media player overwrites the frame being shown on screen. Task-number: QTBUG-35868 Change-Id: I6701cf7368a3ef9e73d649c3ece1f206cafd5bb3 Reviewed-by: Christian Stromme <christian.stromme@digia.com>
Diffstat (limited to 'src/plugins/android/videonode')
-rw-r--r--src/plugins/android/videonode/qandroidsgvideonode.cpp162
-rw-r--r--src/plugins/android/videonode/qandroidsgvideonode.h9
-rw-r--r--src/plugins/android/videonode/qandroidsgvideonodeplugin.cpp4
3 files changed, 94 insertions, 81 deletions
diff --git a/src/plugins/android/videonode/qandroidsgvideonode.cpp b/src/plugins/android/videonode/qandroidsgvideonode.cpp
index 7f13dc981..8c441a748 100644
--- a/src/plugins/android/videonode/qandroidsgvideonode.cpp
+++ b/src/plugins/android/videonode/qandroidsgvideonode.cpp
@@ -61,41 +61,42 @@ public:
}
protected:
+
const char *vertexShader() const {
- return
- "uniform highp mat4 qt_Matrix; \n"
- "uniform highp mat4 texMatrix; \n"
- "attribute highp vec4 qt_VertexPosition; \n"
- "attribute highp vec2 qt_VertexTexCoord; \n"
- "varying highp vec2 qt_TexCoord; \n"
- "void main() { \n"
- " qt_TexCoord = (texMatrix * vec4(qt_VertexTexCoord, 0.0, 1.0)).xy; \n"
- " gl_Position = qt_Matrix * qt_VertexPosition; \n"
- "}";
+ const char *shader =
+ "uniform highp mat4 qt_Matrix; \n"
+ "attribute highp vec4 qt_VertexPosition; \n"
+ "attribute highp vec2 qt_VertexTexCoord; \n"
+ "varying highp vec2 qt_TexCoord; \n"
+ "void main() { \n"
+ " qt_TexCoord = qt_VertexTexCoord; \n"
+ " gl_Position = qt_Matrix * qt_VertexPosition; \n"
+ "}";
+ return shader;
}
const char *fragmentShader() const {
- return
- "#extension GL_OES_EGL_image_external : require \n"
- "uniform samplerExternalOES videoTexture; \n"
- "uniform lowp float opacity; \n"
- "varying highp vec2 qt_TexCoord; \n"
- "void main() \n"
- "{ \n"
- " gl_FragColor = texture2D(videoTexture, qt_TexCoord) * opacity; \n"
- "}";
+ static const char *shader =
+ "uniform sampler2D rgbTexture;"
+ "uniform lowp float opacity;"
+ ""
+ "varying highp vec2 qt_TexCoord;"
+ ""
+ "void main()"
+ "{"
+ " gl_FragColor = texture2D(rgbTexture, qt_TexCoord) * opacity;"
+ "}";
+ return shader;
}
void initialize() {
m_id_matrix = program()->uniformLocation("qt_Matrix");
- m_id_texMatrix = program()->uniformLocation("texMatrix");
- m_id_texture = program()->uniformLocation("videoTexture");
+ m_id_Texture = program()->uniformLocation("rgbTexture");
m_id_opacity = program()->uniformLocation("opacity");
}
int m_id_matrix;
- int m_id_texMatrix;
- int m_id_texture;
+ int m_id_Texture;
int m_id_opacity;
};
@@ -104,15 +105,12 @@ class QAndroidSGVideoNodeMaterial : public QSGMaterial
public:
QAndroidSGVideoNodeMaterial()
: m_textureId(0)
+ , m_textureUpdated(false)
+ , m_opacity(1.0)
{
setFlag(Blending, false);
}
- ~QAndroidSGVideoNodeMaterial()
- {
- m_frame = QVideoFrame();
- }
-
QSGMaterialType *type() const {
static QSGMaterialType theType;
return &theType;
@@ -124,81 +122,93 @@ public:
int compare(const QSGMaterial *other) const {
const QAndroidSGVideoNodeMaterial *m = static_cast<const QAndroidSGVideoNodeMaterial *>(other);
- return m_textureId - m->m_textureId;
- }
+ int diff = m_textureId - m->m_textureId;
+ if (diff)
+ return diff;
- void setVideoFrame(const QVideoFrame &frame) {
- QMutexLocker lock(&m_frameMutex);
- m_frame = frame;
+ return (m_opacity > m->m_opacity) ? 1 : -1;
}
- bool updateTexture()
- {
- QMutexLocker lock(&m_frameMutex);
- bool texMatrixDirty = false;
-
- if (m_frame.isValid()) {
- QVariantList list = m_frame.handle().toList();
-
- GLuint texId = list.at(0).toUInt();
- QMatrix4x4 mat = qvariant_cast<QMatrix4x4>(list.at(1));
-
- texMatrixDirty = texId != m_textureId || mat != m_texMatrix;
-
- m_textureId = texId;
- m_texMatrix = mat;
-
- // the texture is already bound and initialized at this point,
- // no need to call glTexParams
+ void updateBlending() {
+ setFlag(Blending, qFuzzyCompare(m_opacity, qreal(1.0)) ? false : true);
+ }
- } else {
- m_textureId = 0;
+ void updateTexture(GLuint id, const QSize &size) {
+ if (m_textureId != id || m_textureSize != size) {
+ m_textureId = id;
+ m_textureSize = size;
+ m_textureUpdated = true;
}
+ }
- return texMatrixDirty;
+ void bind()
+ {
+ glBindTexture(GL_TEXTURE_2D, m_textureId);
+ if (m_textureUpdated) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ m_textureUpdated = false;
+ }
}
- QVideoFrame m_frame;
- QMutex m_frameMutex;
+ QSize m_textureSize;
GLuint m_textureId;
- QMatrix4x4 m_texMatrix;
+ bool m_textureUpdated;
+ qreal m_opacity;
};
+
+QAndroidSGVideoNode::QAndroidSGVideoNode(const QVideoSurfaceFormat &format)
+ : m_format(format)
+{
+ setFlags(OwnsMaterial | UsePreprocess);
+ m_material = new QAndroidSGVideoNodeMaterial;
+ setMaterial(m_material);
+}
+
+QAndroidSGVideoNode::~QAndroidSGVideoNode()
+{
+ m_frame = QVideoFrame();
+}
+
+void QAndroidSGVideoNode::setCurrentFrame(const QVideoFrame &frame)
+{
+ QMutexLocker lock(&m_frameMutex);
+ m_frame = frame;
+ markDirty(DirtyMaterial);
+}
+
void QAndroidSGVideoNodeMaterialShader::updateState(const RenderState &state,
QSGMaterial *newMaterial,
QSGMaterial *oldMaterial)
{
Q_UNUSED(oldMaterial);
QAndroidSGVideoNodeMaterial *mat = static_cast<QAndroidSGVideoNodeMaterial *>(newMaterial);
- program()->setUniformValue(m_id_texture, 0);
+ program()->setUniformValue(m_id_Texture, 0);
- if (mat->updateTexture())
- program()->setUniformValue(m_id_texMatrix, mat->m_texMatrix);
+ mat->bind();
- if (state.isOpacityDirty())
- program()->setUniformValue(m_id_opacity, state.opacity());
+ if (state.isOpacityDirty()) {
+ mat->m_opacity = state.opacity();
+ mat->updateBlending();
+ program()->setUniformValue(m_id_opacity, GLfloat(mat->m_opacity));
+ }
if (state.isMatrixDirty())
program()->setUniformValue(m_id_matrix, state.combinedMatrix());
}
-QAndroidSGVideoNode::QAndroidSGVideoNode(const QVideoSurfaceFormat &format)
- : m_format(format)
+void QAndroidSGVideoNode::preprocess()
{
- setFlag(QSGNode::OwnsMaterial);
- m_material = new QAndroidSGVideoNodeMaterial;
- setMaterial(m_material);
-}
+ QMutexLocker lock(&m_frameMutex);
-void QAndroidSGVideoNode::setCurrentFrame(const QVideoFrame &frame)
-{
- m_material->setVideoFrame(frame);
- markDirty(DirtyMaterial);
-}
+ GLuint texId = 0;
+ if (m_frame.isValid())
+ texId = m_frame.handle().toUInt();
-QVideoFrame::PixelFormat QAndroidSGVideoNode::pixelFormat() const
-{
- return m_format.pixelFormat();
+ m_material->updateTexture(texId, m_frame.size());
}
QT_END_NAMESPACE
diff --git a/src/plugins/android/videonode/qandroidsgvideonode.h b/src/plugins/android/videonode/qandroidsgvideonode.h
index b5b383fb6..5da72dd2d 100644
--- a/src/plugins/android/videonode/qandroidsgvideonode.h
+++ b/src/plugins/android/videonode/qandroidsgvideonode.h
@@ -43,6 +43,7 @@
#define QANDROIDSGVIDEONODE_H
#include <private/qsgvideonode_p.h>
+#include <qmutex.h>
QT_BEGIN_NAMESPACE
@@ -52,14 +53,18 @@ class QAndroidSGVideoNode : public QSGVideoNode
{
public:
QAndroidSGVideoNode(const QVideoSurfaceFormat &format);
+ ~QAndroidSGVideoNode();
void setCurrentFrame(const QVideoFrame &frame);
- QVideoFrame::PixelFormat pixelFormat() const;
+ QVideoFrame::PixelFormat pixelFormat() const { return m_format.pixelFormat(); }
+
+ void preprocess();
private:
- QVideoSurfaceFormat m_format;
QAndroidSGVideoNodeMaterial *m_material;
+ QMutex m_frameMutex;
QVideoFrame m_frame;
+ QVideoSurfaceFormat m_format;
};
QT_END_NAMESPACE
diff --git a/src/plugins/android/videonode/qandroidsgvideonodeplugin.cpp b/src/plugins/android/videonode/qandroidsgvideonodeplugin.cpp
index 155c66ada..e1fb286a2 100644
--- a/src/plugins/android/videonode/qandroidsgvideonodeplugin.cpp
+++ b/src/plugins/android/videonode/qandroidsgvideonodeplugin.cpp
@@ -44,14 +44,12 @@
QT_BEGIN_NAMESPACE
-#define ExternalGLTextureHandle (QAbstractVideoBuffer::UserHandle + 1)
-
QList<QVideoFrame::PixelFormat> QAndroidSGVideoNodeFactoryPlugin::supportedPixelFormats(
QAbstractVideoBuffer::HandleType handleType) const
{
QList<QVideoFrame::PixelFormat> pixelFormats;
- if (handleType == ExternalGLTextureHandle)
+ if (handleType == QAbstractVideoBuffer::GLTextureHandle)
pixelFormats.append(QVideoFrame::Format_BGR32);
return pixelFormats;