Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ OpenGL QML项:当存在';It’没什么可渲染的_C++_Qt_Opengl_Video_Qml - Fatal编程技术网

C++ OpenGL QML项:当存在';It’没什么可渲染的

C++ OpenGL QML项:当存在';It’没什么可渲染的,c++,qt,opengl,video,qml,C++,Qt,Opengl,Video,Qml,我在QML项目上使用OpenGL渲染时遇到了一个非常意外的问题。我正在加载4台现场摄像机的图像。结果发现第四个摄像头有故障,没有图像。发生这种情况时,此摄影机会毫无理由地假定另一个摄影机的图像,即使它们是完全独立的对象!可以看到网格中的第四个对象重复第一个图像 我所做的只是通过main.qml实例化一个类: import QtQuick 2.0 import OpenGlMaterialQQuickItem 1.0 Grid { columns: 2 spacing: 0

我在QML项目上使用OpenGL渲染时遇到了一个非常意外的问题。我正在加载4台现场摄像机的图像。结果发现第四个摄像头有故障,没有图像。发生这种情况时,此摄影机会毫无理由地假定另一个摄影机的图像,即使它们是完全独立的对象!可以看到网格中的第四个对象重复第一个图像

我所做的只是通过main.qml实例化一个类:

import QtQuick 2.0
import OpenGlMaterialQQuickItem 1.0

Grid {
    columns: 2
    spacing: 0    
    width: 1280
    height: 720

    OpenGlMaterialQQuickItem {
        width: 640
        height: 360
        uri: "rtsp://admin:123456@192.168.1.178:10554/tcp/av0_0"
    }
    OpenGlMaterialQQuickItem {
        width: 640
        height: 360
        uri: "rtsp://admin:123456@192.168.1.198:10554/tcp/av0_0"
    }
    OpenGlMaterialQQuickItem {
        width: 640
        height: 360
        uri: "rtsp://admin:123456@192.168.1.72:10554/tcp/av0_0"
    }
    OpenGlMaterialQQuickItem {
        width: 640
        height: 360
        uri: "rtsp://admin:123456@192.168.1.155:10554/tcp/av0_0"
    }

}
以下是
OpenGlMaterialQQuickItem
类:

#include "OpenGlMaterialQQuickItem.h"

//https://github.com/KDE/plasma-framework/blob/e7329b95ed3e654e7b5edb4cf7c044b91f8d4d0a/src/declarativeimports/core/fadingnode.cpp

#define GET_STR(x) #x
#define VERTEX_ATTRIBUTE 3

struct State
{
    public://TEMPORARY
        int frameWidth = 1920;
        int frameHeight = 1080;
        unsigned char *datas[3] = {0};

    private:
        bool firstRender = true;

    public:
        void updateData(unsigned char**data, int frameWidth, int frameHeight)
        {
            this->frameWidth = frameWidth;
            this->frameHeight = frameHeight;

            if (firstRender) {
                datas[0] = new unsigned char[frameWidth*frameHeight];  //Y
                datas[1] = new unsigned char[frameWidth*frameHeight/4];//U
                datas[2] = new unsigned char[frameWidth*frameHeight/4];//V
                firstRender = false;
            }

            memcpy(datas[0], data[0], frameWidth*frameHeight);
            memcpy(datas[1], data[1], frameWidth*frameHeight/4);
            memcpy(datas[2], data[2], frameWidth*frameHeight/4);
        }

        int compare(const State *other) const {
            std::cout << "compare called " << std::endl;
            /*
            uint rgb = color.rgba();
            uint otherRgb = other->color.rgba();

            if (rgb == otherRgb) {
                return 0;
            } else if (rgb < otherRgb) {
                return -1;
            } else {
                return 1;
            }
            */
            return -1;
        }
};

class Shader : public QSGSimpleMaterialShader<State>
{
    //QSG_DECLARE_SIMPLE_COMPARABLE_SHADER(Shader, State);
    QSG_DECLARE_SIMPLE_SHADER(Shader, State);
    private:
        QOpenGLFunctions *glFuncs = nullptr;
        GLuint unis[3] = {0};
        GLuint texs[3] = {0};
        QSize m_viewportSize;
        bool firstRender = true;
    public:
        const char *vertexShader() const override {
            return GET_STR(
                        uniform highp mat4 qt_Matrix;
                        attribute vec4 vertexIn;
                        attribute vec2 textureIn;
                        varying vec2 textureOut;
                        void main(void)
                        {
                            gl_Position = qt_Matrix * vertexIn;
                            textureOut = textureIn;
                        }
                );
        }

        const char *fragmentShader() const override {
            return GET_STR(
                        varying vec2 textureOut;
                        uniform sampler2D tex_y;
                        uniform sampler2D tex_u;
                        uniform sampler2D tex_v;
                        uniform lowp float qt_Opacity;
                        void main(void)
                        {
                            vec3 yuv;
                            vec3 rgb;
                            yuv.x = texture2D(tex_y, textureOut).r;
                            yuv.y = texture2D(tex_u, textureOut).r - 0.5;
                            yuv.z = texture2D(tex_v, textureOut).r - 0.5;
                            rgb = mat3(1.0, 1.0, 1.0,
                                0.0, -0.39465, 2.03211,
                                1.13983, -0.58060, 0.0) * yuv;
                            gl_FragColor = vec4(rgb, 1.0) * qt_Opacity;
                        }
                    );
        }

        QList<QByteArray> attributes() const override
        {
            return {QByteArrayLiteral("vertexIn"), QByteArrayLiteral("textureIn")};
        }

        void initialize()
        {
            if (!program()->isLinked()) {
                return; //shader not linked, exit otherwise we crash, BUG: 336272
            }

            QSGSimpleMaterialShader<State>::initialize();
            glFuncs = QOpenGLContext::currentContext()->functions();
            program()->bind();

            glFuncs->glGenTextures(3, texs);//TODO: delete these textures on exit
        }

        void updateState(const State *state, const State *) override
        {
            //Y
            glFuncs->glBindTexture(GL_TEXTURE_2D, texs[0]);
            glFuncs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glFuncs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glFuncs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, state->frameWidth, state->frameHeight, 0, GL_RED, GL_UNSIGNED_BYTE, 0);

            //U
            glFuncs->glBindTexture(GL_TEXTURE_2D, texs[1]);
            glFuncs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glFuncs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glFuncs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, state->frameWidth/2, state->frameHeight / 2, 0, GL_RED, GL_UNSIGNED_BYTE, 0);

            //V
            glFuncs->glBindTexture(GL_TEXTURE_2D, texs[2]);
            glFuncs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glFuncs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glFuncs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, state->frameWidth / 2, state->frameHeight / 2, 0, GL_RED, GL_UNSIGNED_BYTE, 0);

            glFuncs->glActiveTexture(GL_TEXTURE0);
            glFuncs->glBindTexture(GL_TEXTURE_2D, texs[0]);
            glFuncs->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, state->frameWidth, state->frameHeight, GL_RED, GL_UNSIGNED_BYTE, state->datas[0]);
            glFuncs->glUniform1i(unis[0], 0);

            glFuncs->glActiveTexture(GL_TEXTURE0+1);
            glFuncs->glBindTexture(GL_TEXTURE_2D, texs[1]); 
            glFuncs->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, state->frameWidth/2, state->frameHeight / 2, GL_RED, GL_UNSIGNED_BYTE, state->datas[1]);
            glFuncs->glUniform1i(unis[1],1);

            glFuncs->glActiveTexture(GL_TEXTURE0+2);
            glFuncs->glBindTexture(GL_TEXTURE_2D, texs[2]);
            glFuncs->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, state->frameWidth / 2, state->frameHeight / 2, GL_RED, GL_UNSIGNED_BYTE, state->datas[2]);
            glFuncs->glUniform1i(unis[2], 2);

            glFuncs->glDrawArrays(GL_TRIANGLE_STRIP,0,4);

            //release some things here?
        }

        void resolveUniforms() override
        {
            unis[0] = program()->uniformLocation("tex_y");
            unis[1] = program()->uniformLocation("tex_u");
            unis[2] = program()->uniformLocation("tex_v");
        }
};

class Node: public QSGGeometryNode, public FrameUpdater
{
    public:
        State state;
        Node()
        {            
            material = Shader::createMaterial();
            setMaterial(material);
            setFlag(OwnsMaterial, true);

            QSGGeometry *g = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4);
            QSGGeometry::updateTexturedRectGeometry(g, QRect(), QRect());
            setGeometry(g);
            setFlag(QSGNode::OwnsGeometry, true);
        }

        void setItem(QQuickItem* item) {
            this->item = item;
        }

        void setUri(std::string uri) {
            this->uri = uri;
        }

        void beginStream() {
            stream = new MediaStream(uri);
            stream->setFrameUpdater((FrameUpdater *) this);
            boost::thread mediaThread(&MediaStream::run, stream);
        }

        void updateData(unsigned char**data, int frameWidth, int frameHeight)
        {
            material->state()->updateData(data, frameWidth, frameHeight);
            markDirty(QSGNode::DirtyMaterial);//is this really needed?
            QMetaObject::invokeMethod(item, &QQuickItem::update, Qt::QueuedConnection);
        }

    private:
        QSGSimpleMaterial<State> *material;
        MediaStream* stream;
        QQuickItem* item;
        std::string uri;

};

QSGNode * OpenGlMaterialQQuickItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *) //override
{
    Node *n = static_cast<Node *>(node);
    if (!node) {
        n = new Node();
        n->setItem(this);
        n->setUri(this->uri);//TODO: How do I know that when updatePaintNode is called, the object will already have a defined uri?
        n->beginStream();
    }
    QSGGeometry::updateTexturedRectGeometry(n->geometry(), boundingRect(), QRectF(0, 0, 1, 1));
    //static_cast<QSGSimpleMaterial<State>*>(n->material())->state()->color = m_color;


    n->markDirty(QSGNode::DirtyGeometry | QSGNode::DirtyMaterial);//what is this?
    return n;
}
#包括“OpenGlMaterialQQuickItem.h”
//https://github.com/KDE/plasma-framework/blob/e7329b95ed3e654e7b5edb4cf7c044b91f8d4d0a/src/declarativeimports/core/fadingnode.cpp
#定义GET_STR(x)#x
#定义顶点属性3
结构状态
{
public://TEMPORARY
int frameWidth=1920;
int frameHeight=1080;
无符号字符*数据[3]={0};
私人:
bool firstRender=true;
公众:
void updateData(无符号字符**数据,整数帧宽,整数帧高)
{
此->帧宽度=帧宽度;
此->框架高度=框架高度;
if(firstRender){
数据[0]=新的无符号字符[frameWidth*frameHeight];//Y
数据[1]=新的无符号字符[frameWidth*frameHeight/4];//U
数据[2]=新的无符号字符[frameWidth*frameHeight/4];//V
firstRender=false;
}
memcpy(数据[0],数据[0],帧宽*帧高);
memcpy(数据[1],数据[1],帧宽*帧高/4);
memcpy(数据[2],数据[2],帧宽*帧高/4);
}
int比较(常数状态*其他)常数{
std::cout isLinked()){
return;//着色器未链接,请退出,否则会崩溃,错误:336272
}
QSGSimpleMaterialShader::initialize();
glFuncs=QOpenGLContext::currentContext()->functions();
program()->bind();
glFuncs->glGenTextures(3,texs);//TODO:退出时删除这些纹理
}
无效更新状态(常量状态*状态,常量状态*)覆盖
{
//Y
glFuncs->glBindTexture(GL_TEXTURE_2D,texs[0]);
glFuncs->glTexParameteri(GL\u纹理\u 2D、GL\u纹理\u MAG\u过滤器、GL\u线性);
glFuncs->glTexParameteri(GL\u纹理\u 2D、GL\u纹理\u最小\u过滤器、GL\u线性);
glFuncs->glTexImage2D(GL_纹理_2D,0,GL_红色,状态->帧宽,状态->帧高,0,GL_红色,GL_无符号字节,0);
//U
glFuncs->glBindTexture(GL_TEXTURE_2D,texs[1]);
glFuncs->glTexParameteri(GL\u纹理\u 2D、GL\u纹理\u MAG\u过滤器、GL\u线性);
glFuncs->glTexParameteri(GL\u纹理\u 2D、GL\u纹理\u最小\u过滤器、GL\u线性);
glFuncs->glTexImage2D(GL_纹理_2D,0,GL_红色,状态->帧宽/2,状态->帧高/2,0,GL_红色,GL_无符号字节,0);
//五
glFuncs->glBindTexture(GL_TEXTURE_2D,texs[2]);
glFuncs->glTexParameteri(GL\u纹理\u 2D、GL\u纹理\u MAG\u过滤器、GL\u线性);
glFuncs->glTexParameteri(GL\u纹理\u 2D、GL\u纹理\u最小\u过滤器、GL\u线性);
glFuncs->glTexImage2D(GL_纹理_2D,0,GL_红色,状态->帧宽/2,状态->帧高/2,0,GL_红色,GL_无符号字节,0);
glFuncs->glActiveTexture(GL_TEXTURE0);
glFuncs->glBindTexture(GL_TEXTURE_2D,texs[0]);
glFuncs->glTexSubImage2D(GL_纹理_2D,0,0,状态->帧宽,状态->帧高,GL_红色,GL_无符号字节,状态->数据[0]);
glFuncs->glUniform1i(unis[0],0);
glFuncs->glActiveTexture(GL_TEXTURE0+1);
glFuncs->glBindTexture(GL_TEXTURE_2D,texs[1]);
glFuncs->glTexSubImage2D(GL_纹理_2D,0,0,状态->帧宽/2,状态->帧高/2,GL_红色,GL_无符号字节,状态->数据[1]);
glFuncs->glUniform1i(unis[1],1);
glFuncs->glActiveTexture(GL_TEXTURE0+2);
glFuncs->glBindTexture(GL_TEXTURE_2D,texs[2]);
glFuncs->glTexSubImage2D(GL_纹理_2D,0,0,状态->帧宽/2,状态->帧高/2,GL_红色,GL_无符号字节,状态->数据[2]);
glFuncs->glUniform1i(unis[2],2);
glFuncs->gldrawArray(GL_三角形_带,0,4);
//在这里放些东西?
}
void()重写
{
unis[0]=program()->uniformLocation(“tex_y”);
unis[1]=program()->uniformLocation(“tex_”);
unis[2]=program()->uniformLocation(“tex_v”);
}
};
类节点:public QSGGeometryNode,public FrameUpdater
{
公众:
国家;
节点()
{            
材质=着色器::createMaterial();
材料(材料);
setFlag(OwnsMaterial,true);
QSGGeometry*g=新的QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(),4);
QSGGeometry::updateTexturedRectGeometry(g,QRect(),QRect());
集合几何(g);
setFlag(QSGNode::OwnsGeometry,true);
}
无效集合项(QQuickItem*项){
此->项目=项目;
}
void setUri(标准::字符串uri){
这个->uri=uri;
}
void beginStream(){
流=新媒体流(uri);
stream->setFrameUpdater((FrameUpdater*)this);
boost::thread mediaThread(&MediaStream::run,stream);
}
void updateData(无符号字符**数据,整数帧宽,整数帧高)
{
材质->状态()->更新数据(数据、帧宽、帧高);
markDirty(QSGNode::DirtyMaterial);//这真的需要吗?
QMetaObject::invokeMethod(item,&QQuickItem::update,Qt::QueuedConnection);
}
私人:
QSG非物质*物质;
媒体流*stream;
QQuickItem*项目;
std::字符串u