-1

私のプログラムはビデオ フレームを OpenGL テクスチャとして表示します。

OpenGL の初期化に問題があります。ビデオを見るには、スレッドのレンダリングを開始し、停止してからやり直す必要があります。CRenderThread::InitOpenGL() 関数に何か欠けていると思います。OpenGL を正しく初期化するにはどうすればよいですか?

私の環境:

ウィンドウズ 7 x64

Microsoft Visual Studio 2008 x64

コードは次のとおりです。

#include "RenderThread.h"
#include <QtDebug>
#include <vm_time.h>

static Ipp32u UMCToInternalFormat(UMC::ColorFormat format)
{
switch(format)
{
case UMC::BGR24: return GL_BGR;
case UMC::BGR32: return GL_BGRA;
case UMC::RGB24: return GL_RGB;
case UMC::RGB32: return GL_RGBA;
}
return 0;
}

CRenderThread::CRenderThread(const WId& rnWindowHandle)
:   m_bInitialized(false)
,   m_WindowHandle(rnWindowHandle)
,   m_Texture(0)
,   m_fTextureWidth(0.0f)
,   m_fTextureHeight(0.0f)
,   m_nFrameWidth(0)
,   m_nFrameHeight(0)
,   m_nWindowWidth(0)
,   m_nWindowHeight(0)
{
}

void CRenderThread::PrepareWork()
{
// Wait until first frame comes
if(!m_bAbort)
    Suspend();
}

void CRenderThread::DoOnStop()
{
if(m_WindowGLResourceContext)
{
    wglDeleteContext(m_WindowGLResourceContext);
    m_WindowGLResourceContext = 0;
}
    ReleaseDC(m_WindowHandle, m_WindowDC);

if(m_Texture)
{
    glDeleteTextures(1, &m_Texture);
    m_Texture = 0;
}
}

void CRenderThread::InitOpenGL()
{
PIXELFORMATDESCRIPTOR pfd = {
    sizeof(PIXELFORMATDESCRIPTOR),  1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
    PFD_TYPE_RGBA, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0
};

m_WindowDC = GetDC(m_WindowHandle);
if(!m_WindowDC)
    return;

if(!SetPixelFormat(m_WindowDC, ChoosePixelFormat(m_WindowDC, &pfd), &pfd))
    return;

m_WindowGLResourceContext = wglCreateContext(m_WindowDC); // create rendering context
if(!m_WindowGLResourceContext)
    return;

if(!wglMakeCurrent(m_WindowDC, m_WindowGLResourceContext)) // set it as current
    return;

// OpenGL context already tied to output window
// to disable all slow GL components
// it is not mandatory to disable all if we have accelerated card
glClearColor(0.0f, 170.0f, 255.0f, 1.0f);
glClearDepth(1.0);
glDepthFunc(GL_NEVER);

// disable slow GL extensions
glDisable(GL_DEPTH_TEST); glDisable(GL_ALPHA_TEST);   glDisable(GL_BLEND);
glDisable(GL_DITHER);     glDisable(GL_FOG);          glDisable(GL_STENCIL_TEST);
glDisable(GL_LIGHTING);   glDisable(GL_LOGIC_OP);     glDisable(GL_TEXTURE_1D);
glDisable(GL_TEXTURE_2D);

glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
glPixelTransferi(GL_RED_SCALE,   1);  glPixelTransferi(GL_RED_BIAS,   0);
glPixelTransferi(GL_GREEN_SCALE, 1);  glPixelTransferi(GL_GREEN_BIAS, 0);
glPixelTransferi(GL_BLUE_SCALE,  1);  glPixelTransferi(GL_BLUE_BIAS,  0);
glPixelTransferi(GL_ALPHA_SCALE, 1);  glPixelTransferi(GL_ALPHA_BIAS, 0);

glEnable(GL_TEXTURE_2D);
glGenTextures(1, &m_Texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

glViewport(0, 0, m_nWindowWidth, m_nWindowHeight);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glRasterPos2i(-1, 1);       // move to the upper left corner
glPixelZoom(1.0, -1.0);     // top to bottom

SwapBuffers(m_WindowDC);

m_bInitialized = true;
}

void CRenderThread::SetRenderFrame(PVideoData pFrame)
{
Q_ASSERT(pFrame.get());
{
    //boost::mutex::scoped_lock Lock(m_FrameMutex);
    m_pFrameToRender = pFrame;
}

// Resume thread to render current frame
Resume();
}

void CRenderThread::DoWork()
{
IppiSize    CurWinSize;
UMC::Status nStatus = UMC::UMC_OK;

::RECT rect;
GetClientRect(m_WindowHandle, &rect);
CurWinSize.height = rect.bottom;
CurWinSize.width  = rect.right;

if(!m_bInitialized)
    InitOpenGL();

if(CurWinSize.width > IPP_MAX_16S || CurWinSize.height > IPP_MAX_16S) // window seems to be destroyed
    return;

// reinit buffers if window size has been changed
if(CurWinSize.height != m_nWindowHeight || CurWinSize.width != m_nWindowWidth)
{
    m_nWindowWidth  = CurWinSize.width;
    m_nWindowHeight = CurWinSize.height;

    glViewport(0, 0, m_nWindowWidth, m_nWindowHeight);
}

// Render frame
{
    //boost::mutex::scoped_lock Lock(m_FrameMutex);
    if(m_pFrameToRender.get())
    {
        if(m_nWindowWidth && m_nWindowHeight)
        {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

            m_nFrameWidth   = m_pFrameToRender->GetWidth();
            m_nFrameHeight  = m_pFrameToRender->GetHeight();
            m_nRenderFormat = UMCToInternalFormat(m_pFrameToRender->GetColorFormat());

            glTexImage2D(GL_TEXTURE_2D, 0, 3, m_nFrameWidth, m_nFrameHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, m_pFrameToRender->GetBufferPointer());
            //glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_nFrameWidth, m_nFrameHeight, m_nRenderFormat, GL_UNSIGNED_BYTE, m_pFrameToRender->GetBufferPointer());

            glBegin(GL_POLYGON);
            glTexCoord2i(0, 0); glVertex2f(-1.0,  1.0);
            glTexCoord2i(1, 0); glVertex2f( 1.0,  1.0);
            glTexCoord2i(1, 1); glVertex2f( 1.0, -1.0);
            glTexCoord2i(0, 1); glVertex2f(-1.0, -1.0);
            glEnd();

            glFlush();

            SwapBuffers(m_WindowDC);   // to draw on physical screen
        }
    }
}

// Wait for next frame to render
if(!m_bAbort)
    Suspend();
}
4

1 に答える 1

2

すべてが必ずしもあなたの問題に関連しているわけではありません。

glClearColor(0.0f, 170.0f, 255.0f, 1.0f);

クリア カラーは、[0,255] ではなく [0,1] の範囲にクランプされます。


// disable slow GL extensions
glDisable(GL_DEPTH_TEST); glDisable(GL_ALPHA_TEST);   glDisable(GL_BLEND);
glDisable(GL_DITHER);     glDisable(GL_FOG);          glDisable(GL_STENCIL_TEST);
glDisable(GL_LIGHTING);   glDisable(GL_LOGIC_OP);     glDisable(GL_TEXTURE_1D);
glDisable(GL_TEXTURE_2D);

これら (およびほとんどすべての opengl 設定) は、デフォルトで無効になっています。これらはすべて何もしていません。しかし、何も傷つけません。


glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
glPixelTransferi(GL_RED_SCALE,   1);  glPixelTransferi(GL_RED_BIAS,   0);
glPixelTransferi(GL_GREEN_SCALE, 1);  glPixelTransferi(GL_GREEN_BIAS, 0);
glPixelTransferi(GL_BLUE_SCALE,  1);  glPixelTransferi(GL_BLUE_BIAS,  0);
glPixelTransferi(GL_ALPHA_SCALE, 1);  glPixelTransferi(GL_ALPHA_BIAS, 0);

繰り返しますが、これらはすべてデフォルトです。


glEnable(GL_TEXTURE_2D);
glGenTextures(1, &m_Texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

これは実際には本当の問題かもしれません。glTexParameter現在バインドされているテクスチャにのみ影響しますが、ここではテクスチャをバインドせずに呼び出しています。したがって、これらは何もしていません。後で実際にテクスチャを使用すると、最小フィルターにミップマッピングが設定され、表示されなくなる可能性があります。glTexParameter影響を与えたいテクスチャをバインドした後、呼び出しを移動します。

于 2012-07-16T16:11:47.670 に答える