私のプログラムはビデオ フレームを 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();
}