Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Work with QOpenGLWidget in multiThread

Work with QOpenGLWidget in multiThread

Scheduled Pinned Locked Moved Solved General and Desktop
12 Posts 2 Posters 4.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Miyoku
    wrote on last edited by
    #1

    Hi

    So i know that we can only have one openGLcontext per thread, and i need only one. With my window, i have two buttons, each create a QThread, the capture need a QOpenGLContext, the other doesn't.
    0_1500986770482_Sans titre.png

    Here is the code when i push the capture button:

    void MainWindow::capture(QWidget *widget)
    {
        if(!launch){
            QOpenGLWidget* OWidget = reinterpret_cast<QOpenGLWidget*> (widget);
            OWidget->context()->create();
            OWidget->makeCurrent();
            c = new C_anccap();
            c->CaptureCall(OWidget);
            launch = true;
        }
    }
    
    
    int C_anccap::CaptureCall (QOpenGLWidget* widget)
    {
    	// Debug console.
    	//SetupConsole();
        this->m_SDIin.m_videoDC = GetDC((HWND)widget->effectiveWinId());
        if(this->Configure() == E_FAIL)
    		return FALSE;
    
        if(this->SetupSDIDevices() == E_FAIL)
    		return FALSE;
    
    
    	// Calculate the window size based on the incoming and outgoing video signals
        this->CalcWindowSize();
        this->SetupGL();
    	
        if(this->StartSDIPipeline() == E_FAIL)
    		return FALSE;
    
        widget->context()->doneCurrent();
    
        thread = new QThread(this);
        widget->context()->moveToThread(thread);
        QSignalMapper* signalMapper = new QSignalMapper(this);
        QObject::connect(thread,SIGNAL(started()),signalMapper,SLOT(map()));
        signalMapper->setMapping(thread, widget);
        QObject::connect(signalMapper, SIGNAL(mapped(QWidget*)),this, SLOT(LoopAnimation(QWidget*)));
        this->moveToThread(thread);
        thread->start();
    
    }
    
    

    I'm trying to display gltexture continuously thanks to this QThread but i can't managed to display anything. Moreover, i think i didn't get something with the QOpenGLContext because as soon i start capturing, I can't touch any other windows without having an exception
    "Cannot make QOpenGLContext current in a different thread" from qopenglcontext.cpp line 952.
    I don't know if i did something wrong (probably) or if I didn't get something.
    Can you help me?

    jsulmJ 1 Reply Last reply
    0
    • M Miyoku

      Hi

      So i know that we can only have one openGLcontext per thread, and i need only one. With my window, i have two buttons, each create a QThread, the capture need a QOpenGLContext, the other doesn't.
      0_1500986770482_Sans titre.png

      Here is the code when i push the capture button:

      void MainWindow::capture(QWidget *widget)
      {
          if(!launch){
              QOpenGLWidget* OWidget = reinterpret_cast<QOpenGLWidget*> (widget);
              OWidget->context()->create();
              OWidget->makeCurrent();
              c = new C_anccap();
              c->CaptureCall(OWidget);
              launch = true;
          }
      }
      
      
      int C_anccap::CaptureCall (QOpenGLWidget* widget)
      {
      	// Debug console.
      	//SetupConsole();
          this->m_SDIin.m_videoDC = GetDC((HWND)widget->effectiveWinId());
          if(this->Configure() == E_FAIL)
      		return FALSE;
      
          if(this->SetupSDIDevices() == E_FAIL)
      		return FALSE;
      
      
      	// Calculate the window size based on the incoming and outgoing video signals
          this->CalcWindowSize();
          this->SetupGL();
      	
          if(this->StartSDIPipeline() == E_FAIL)
      		return FALSE;
      
          widget->context()->doneCurrent();
      
          thread = new QThread(this);
          widget->context()->moveToThread(thread);
          QSignalMapper* signalMapper = new QSignalMapper(this);
          QObject::connect(thread,SIGNAL(started()),signalMapper,SLOT(map()));
          signalMapper->setMapping(thread, widget);
          QObject::connect(signalMapper, SIGNAL(mapped(QWidget*)),this, SLOT(LoopAnimation(QWidget*)));
          this->moveToThread(thread);
          thread->start();
      
      }
      
      

      I'm trying to display gltexture continuously thanks to this QThread but i can't managed to display anything. Moreover, i think i didn't get something with the QOpenGLContext because as soon i start capturing, I can't touch any other windows without having an exception
      "Cannot make QOpenGLContext current in a different thread" from qopenglcontext.cpp line 952.
      I don't know if i did something wrong (probably) or if I didn't get something.
      Can you help me?

      jsulmJ Offline
      jsulmJ Offline
      jsulm
      Lifetime Qt Champion
      wrote on last edited by
      #2

      @Miyoku Why do you need more than one thread?

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      M 1 Reply Last reply
      0
      • M Offline
        M Offline
        Miyoku
        wrote on last edited by Miyoku
        #3
        This post is deleted!
        jsulmJ 1 Reply Last reply
        0
        • M Miyoku

          This post is deleted!

          jsulmJ Offline
          jsulmJ Offline
          jsulm
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @Miyoku I don't think you need a loop to capture video from a camera. How do you capture the video? Using http://doc.qt.io/qt-5/qcamera.html ? You should use the asynchronous nature of Qt as much as possible to avoid using multithreading.

          https://forum.qt.io/topic/113070/qt-code-of-conduct

          M 1 Reply Last reply
          0
          • jsulmJ jsulm

            @Miyoku Why do you need more than one thread?

            M Offline
            M Offline
            Miyoku
            wrote on last edited by
            #5
            This post is deleted!
            1 Reply Last reply
            0
            • jsulmJ jsulm

              @Miyoku I don't think you need a loop to capture video from a camera. How do you capture the video? Using http://doc.qt.io/qt-5/qcamera.html ? You should use the asynchronous nature of Qt as much as possible to avoid using multithreading.

              M Offline
              M Offline
              Miyoku
              wrote on last edited by
              #6

              @jsulm sorry for the double post, i'm deleting one of them.
              For your answer, in fact i'm using a specific hardware, the SDI Quadro input to get 4 SDI input and capture them thanks to the GPU.
              I don't know how the QCamera work, but do you think it's working with SDI input?

              jsulmJ 1 Reply Last reply
              0
              • M Miyoku

                @jsulm sorry for the double post, i'm deleting one of them.
                For your answer, in fact i'm using a specific hardware, the SDI Quadro input to get 4 SDI input and capture them thanks to the GPU.
                I don't know how the QCamera work, but do you think it's working with SDI input?

                jsulmJ Offline
                jsulmJ Offline
                jsulm
                Lifetime Qt Champion
                wrote on last edited by
                #7

                @Miyoku I don't know whether it works with your camera, but you can try.
                If not, then maybe you can capture the video in an extra thread but hen send the frames via a signal to main thread where you show the frames then. The problem is: in Qt you are only allow to access UI directly from main thread.

                https://forum.qt.io/topic/113070/qt-code-of-conduct

                M 1 Reply Last reply
                0
                • jsulmJ jsulm

                  @Miyoku I don't know whether it works with your camera, but you can try.
                  If not, then maybe you can capture the video in an extra thread but hen send the frames via a signal to main thread where you show the frames then. The problem is: in Qt you are only allow to access UI directly from main thread.

                  M Offline
                  M Offline
                  Miyoku
                  wrote on last edited by
                  #8

                  @jsulm Ok, so here I'm quite stuck, if i want to use an OpenGLWidget, it's because my driver capture the video stream in GLTexture, so the frame are in the GPU not in the CPU. But in order to capture them, i need an OpenGLContext active (which i've succeed to pass to my thread with movetothread) but if i have to make the display in the main thread, it will create a conflict.

                  jsulmJ 1 Reply Last reply
                  0
                  • M Miyoku

                    @jsulm Ok, so here I'm quite stuck, if i want to use an OpenGLWidget, it's because my driver capture the video stream in GLTexture, so the frame are in the GPU not in the CPU. But in order to capture them, i need an OpenGLContext active (which i've succeed to pass to my thread with movetothread) but if i have to make the display in the main thread, it will create a conflict.

                    jsulmJ Offline
                    jsulmJ Offline
                    jsulm
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    @Miyoku Maybe you can get rid of the loop using a QTimer in main thread?

                    https://forum.qt.io/topic/113070/qt-code-of-conduct

                    M 2 Replies Last reply
                    0
                    • jsulmJ jsulm

                      @Miyoku Maybe you can get rid of the loop using a QTimer in main thread?

                      M Offline
                      M Offline
                      Miyoku
                      wrote on last edited by
                      #10

                      @jsulm That could work indeed! didn't think about that, I'm going to try that thanks

                      1 Reply Last reply
                      0
                      • jsulmJ jsulm

                        @Miyoku Maybe you can get rid of the loop using a QTimer in main thread?

                        M Offline
                        M Offline
                        Miyoku
                        wrote on last edited by
                        #11

                        @jsulm I've changed my way of doing, i'm now using a QTimer to capture the frame. But i still have no feedback from the display. I'm wondering if my way of using the QOpenGLWidget is right.

                        int C_anccap::LoopAnimation()
                        {
                            Owidget->makeCurrent();
                        
                            if (this->CaptureVideo() != GL_FAILURE_NV)
                            {
                                if (this->rec[0].isStarted) {
                                    glGetTexImage(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA, GL_UNSIGNED_BYTE, this->rec[0].pixels.get());
                                }
                            }
                            if (C_anccap::exit) {
                                this->Shutdown();
                                return FALSE;
                            }
                            return TRUE;
                        }
                        
                        
                        void MyOpenGLWidget::initializeGL()
                        {
                            initializeOpenGLFunctions();
                            glClearColor(1.0f,1.0f,1.0f,1.0f);
                            context()->create();
                            makeCurrent();
                            c = new C_anccap();
                            c->CaptureCall(this);
                        }
                        
                        void MyOpenGLWidget::resizeGL(int w, int h)
                        {
                            if(h==0)
                                h =1;
                            glViewport(0,0,w,h);
                            glMatrixMode(GL_PROJECTION);
                            glLoadIdentity();
                            perspectiveGL(45.0f,w/h,0.1f,100.0f);
                            glMatrixMode(GL_MODELVIEW);
                            glLoadIdentity();
                        
                        }
                        
                        void MyOpenGLWidget::paintGL()
                        {
                            //QPainter p(this);
                            // p.beginNativePainting();
                             c->DisplayVideo();
                            // p.endNativePainting();
                        }
                        void MyOpenGLWidget::perspectiveGL(GLdouble fovY, GLdouble aspect, GLdouble zNear, GLdouble zFar){
                            const GLdouble pi = 3.1415926535897932384626433832795;
                            GLdouble fW, fH;
                            fH = tan( fovY / 360 * pi) * zNear;
                            fW = fH * aspect;
                            glFrustum( -fW,fW,-fH,fH,zNear,zFar);
                        }
                        
                        GLboolean C_anccap::DisplayVideo()
                        {
                        	//
                        	// Draw texture contents to graphics window.
                        	//
                            //widget->makeCurrent();
                        	// Reset view parameters
                        	glViewport(0, 0, m_windowWidth, m_windowHeight);
                        	glMatrixMode(GL_PROJECTION);
                        	glLoadIdentity();
                            glOrtho(0.0, (GLdouble) m_windowWidth, 0.0, (GLdouble) m_windowHeight, -1, 1);
                        	glMatrixMode(GL_MODELVIEW);
                        	glLoadIdentity();
                        
                        	// Draw contents of each video texture
                        	glEnable(GL_TEXTURE_RECTANGLE_NV);  
                        
                        	// Set draw color
                        	glColor3f(1.0f, 1.0f, 1.0f);
                        
                        	// Draw captured streams to graphics window.
                        	switch(m_SDIin.GetNumVideoObjects()) {
                        		case 1:
                        		drawOne();
                        		break;
                        		case 2:
                        		drawTwo();
                        		break;
                        		case 3:
                        		drawThree();
                        		break;
                        		case 4:
                        		drawFour();
                        		break;
                        		default:
                        		drawOne();
                        	};
                        
                        GLvoid C_anccap::drawOne()
                        {
                        	// Enable texture
                        	glEnable(GL_TEXTURE_RECTANGLE_NV);  
                        	
                        	// Bind texture object for first video stream
                        	glBindTexture(GL_TEXTURE_RECTANGLE_NV, m_SDIin.GetTextureObjectHandle(0));  
                        
                        	// Draw textured quad in lower left quadrant of graphics window.
                        	glBegin(GL_QUADS);
                        	glTexCoord2f(0.0, 0.0); glVertex2f(-1, -1); 
                        	glTexCoord2f(0.0, (GLfloat)m_videoHeight); glVertex2f(-1, 1); 
                        	glTexCoord2f((GLfloat)m_videoWidth, (GLfloat)m_videoHeight); glVertex2f(1, 1); 
                        	glTexCoord2f((GLfloat)m_videoWidth, 0.0); glVertex2f(1, -1); 
                        	glEnd();
                        	GLenum g = glGetError();
                        	assert(glGetError() == GL_NO_ERROR);
                        
                        	// Disable texture
                        	glDisable(GL_TEXTURE_RECTANGLE_NV);
                        }
                        

                        I'm dropping all the code required for the display. Maybe you'll see some errors in the way i'm using it.
                        To precise, MyOpenGLWidget inherit QOpenGLWidget.
                        I'm quite sure that i'm capturing the frame because the nvidia driver send no error, i just can't manage to display them

                        M 1 Reply Last reply
                        0
                        • M Miyoku

                          @jsulm I've changed my way of doing, i'm now using a QTimer to capture the frame. But i still have no feedback from the display. I'm wondering if my way of using the QOpenGLWidget is right.

                          int C_anccap::LoopAnimation()
                          {
                              Owidget->makeCurrent();
                          
                              if (this->CaptureVideo() != GL_FAILURE_NV)
                              {
                                  if (this->rec[0].isStarted) {
                                      glGetTexImage(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA, GL_UNSIGNED_BYTE, this->rec[0].pixels.get());
                                  }
                              }
                              if (C_anccap::exit) {
                                  this->Shutdown();
                                  return FALSE;
                              }
                              return TRUE;
                          }
                          
                          
                          void MyOpenGLWidget::initializeGL()
                          {
                              initializeOpenGLFunctions();
                              glClearColor(1.0f,1.0f,1.0f,1.0f);
                              context()->create();
                              makeCurrent();
                              c = new C_anccap();
                              c->CaptureCall(this);
                          }
                          
                          void MyOpenGLWidget::resizeGL(int w, int h)
                          {
                              if(h==0)
                                  h =1;
                              glViewport(0,0,w,h);
                              glMatrixMode(GL_PROJECTION);
                              glLoadIdentity();
                              perspectiveGL(45.0f,w/h,0.1f,100.0f);
                              glMatrixMode(GL_MODELVIEW);
                              glLoadIdentity();
                          
                          }
                          
                          void MyOpenGLWidget::paintGL()
                          {
                              //QPainter p(this);
                              // p.beginNativePainting();
                               c->DisplayVideo();
                              // p.endNativePainting();
                          }
                          void MyOpenGLWidget::perspectiveGL(GLdouble fovY, GLdouble aspect, GLdouble zNear, GLdouble zFar){
                              const GLdouble pi = 3.1415926535897932384626433832795;
                              GLdouble fW, fH;
                              fH = tan( fovY / 360 * pi) * zNear;
                              fW = fH * aspect;
                              glFrustum( -fW,fW,-fH,fH,zNear,zFar);
                          }
                          
                          GLboolean C_anccap::DisplayVideo()
                          {
                          	//
                          	// Draw texture contents to graphics window.
                          	//
                              //widget->makeCurrent();
                          	// Reset view parameters
                          	glViewport(0, 0, m_windowWidth, m_windowHeight);
                          	glMatrixMode(GL_PROJECTION);
                          	glLoadIdentity();
                              glOrtho(0.0, (GLdouble) m_windowWidth, 0.0, (GLdouble) m_windowHeight, -1, 1);
                          	glMatrixMode(GL_MODELVIEW);
                          	glLoadIdentity();
                          
                          	// Draw contents of each video texture
                          	glEnable(GL_TEXTURE_RECTANGLE_NV);  
                          
                          	// Set draw color
                          	glColor3f(1.0f, 1.0f, 1.0f);
                          
                          	// Draw captured streams to graphics window.
                          	switch(m_SDIin.GetNumVideoObjects()) {
                          		case 1:
                          		drawOne();
                          		break;
                          		case 2:
                          		drawTwo();
                          		break;
                          		case 3:
                          		drawThree();
                          		break;
                          		case 4:
                          		drawFour();
                          		break;
                          		default:
                          		drawOne();
                          	};
                          
                          GLvoid C_anccap::drawOne()
                          {
                          	// Enable texture
                          	glEnable(GL_TEXTURE_RECTANGLE_NV);  
                          	
                          	// Bind texture object for first video stream
                          	glBindTexture(GL_TEXTURE_RECTANGLE_NV, m_SDIin.GetTextureObjectHandle(0));  
                          
                          	// Draw textured quad in lower left quadrant of graphics window.
                          	glBegin(GL_QUADS);
                          	glTexCoord2f(0.0, 0.0); glVertex2f(-1, -1); 
                          	glTexCoord2f(0.0, (GLfloat)m_videoHeight); glVertex2f(-1, 1); 
                          	glTexCoord2f((GLfloat)m_videoWidth, (GLfloat)m_videoHeight); glVertex2f(1, 1); 
                          	glTexCoord2f((GLfloat)m_videoWidth, 0.0); glVertex2f(1, -1); 
                          	glEnd();
                          	GLenum g = glGetError();
                          	assert(glGetError() == GL_NO_ERROR);
                          
                          	// Disable texture
                          	glDisable(GL_TEXTURE_RECTANGLE_NV);
                          }
                          

                          I'm dropping all the code required for the display. Maybe you'll see some errors in the way i'm using it.
                          To precise, MyOpenGLWidget inherit QOpenGLWidget.
                          I'm quite sure that i'm capturing the frame because the nvidia driver send no error, i just can't manage to display them

                          M Offline
                          M Offline
                          Miyoku
                          wrote on last edited by
                          #12

                          @Miyoku NeverMind i succeed to make it appears thanks, a lot, i just need to make it refresh every frame. I will do it with a timer.
                          Thanks a lot for your time

                          1 Reply Last reply
                          0

                          • Login

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved