windows下用OPENGL播放視訊
2.OPENGL 標準定義了基本的渲染API ,還定義了視窗系統的API ,WINDOWS 用wgl**,定義在 wingdi.h
3.本程式碼採用OPENGL 1.2 支援頂點著色
標頭檔案
#pragma once
#include "videodisplay.h"
#include <GL/glew.h>
class OpenGLDisplay2 : public VideoDisplay
{
public:
OpenGLDisplay2(void);
~OpenGLDisplay2(void);
public:
int init(HWND hwnd,int w,int h);
void fini();
int display(uint8_t* Y,uint8_t* U,uint8_t* V);
private:
void InitShaders();
private:
HDC hGLDC;
HGLRC hGLRC;
GLuint p;
GLuint id_y, id_u, id_v; // Texture id
GLuint textureUniformY, textureUniformU,textureUniformV;
GLint v, f;
int m_nWidth2;
int m_nHeight2;
HWND videoHwnd;
int gw;
int gh;
};
原始碼
#include "StdAfx.h"
#include "OpenGLDisplay2.h"
//#include "opengl.h"
#pragma comment(lib, "glew32.lib")
#define ATTRIB_VERTEX 3
#define ATTRIB_TEXTURE 4
OpenGLDisplay2::OpenGLDisplay2(void)
{
hGLDC = NULL;
hGLRC = NULL;
p = v = f = 0;
id_y = id_u = id_v = 0;
textureUniformY = textureUniformU = textureUniformV = 0;
videoHwnd = NULL;
gw = gh = 0;
m_nWidth2 = m_nHeight2 = 0;
}
OpenGLDisplay2::~OpenGLDisplay2(void)
{
fini();
}
int OpenGLDisplay2::init(HWND hwnd,int w,int h)
{
fini();
hGLDC = GetDC(hwnd);
videoHwnd = hwnd;
m_nWidth2 = w;
m_nHeight2 = h;
/* Set the pixel format for the DC */
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cDepthBits = 16;
pfd.iLayerType = PFD_MAIN_PLANE;
SetPixelFormat(hGLDC,
ChoosePixelFormat(hGLDC, &pfd), &pfd);
/* Create and enable the render context */
hGLRC = wglCreateContext(hGLDC);
wglMakeCurrent(hGLDC, hGLRC);
GLenum err = glewInit();
if (GLEW_OK != err)
{
const char* str = (const char*)glewGetErrorString(err);
int err = 1;
}
const char *version = (const char*)glGetString(GL_VERSION);
const char *extensions = (const char*)glGetString(GL_EXTENSIONS);
if(version && (version[0]>'1' || (version[0]=='1' && version[2]>='2')))
{
InitShaders();
RECT rc;
::GetWindowRect(videoHwnd,&rc);
gw = rc.right - rc.left;
gh = rc.bottom - rc.top;
glViewport( 0, 0, gw, gh );
return TRUE;
}
return FALSE;
}
void OpenGLDisplay2::fini()
{
if (id_y>0)
glDeleteTextures(1,&id_y);
if (id_u>0)
glDeleteTextures(1,&id_u);
if (id_v>0)
glDeleteTextures(1,&id_v);
id_v = 0;
id_u = 0;
id_y = 0;
if (p>0)
glDeleteProgram(p);
if (v>0)
glDeleteShader(v);
if (f>0)
glDeleteProgram(f);
p = v = f = 0;
if (hGLDC && hGLRC)
wglMakeCurrent(NULL, NULL);
if (hGLRC)
wglDeleteContext(hGLRC);
if (hGLDC)
ReleaseDC(videoHwnd, hGLDC);
hGLRC = NULL;
hGLDC = NULL;
}
int OpenGLDisplay2::display(uint8_t* Y,uint8_t* U,uint8_t* V)
{
RECT rc;
::GetWindowRect(videoHwnd,&rc);
int w = rc.right - rc.left;
int h = rc.bottom - rc.top;
glViewport( 0, 0, w, h );
if ((w != gw || h != gh) )
{
// fini();
// return FALSE;
}
//Clear
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);
//Y
//
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, id_y);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0,0, m_nWidth2, m_nHeight2, GL_LUMINANCE, GL_UNSIGNED_BYTE, Y);
glUniform1i(textureUniformY, 0);
//U
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, id_u);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,m_nWidth2/2, m_nHeight2/2, GL_LUMINANCE, GL_UNSIGNED_BYTE, U);
glUniform1i(textureUniformU, 1);
//V
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, id_v);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0,0, m_nWidth2/2, m_nHeight2/2, GL_LUMINANCE, GL_UNSIGNED_BYTE, V);
glUniform1i(textureUniformV, 2);
// Draw
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
SwapBuffers(hGLDC);
return TRUE;
}
char *const vertexShaderString = \
""\
"attribute vec4 position;"\
"attribute vec2 texcoord;"\
"uniform mat4 modelViewProjectionMatrix;"\
"varying vec2 v_texcoord;"\
"void main()"\
"{"\
" gl_Position = modelViewProjectionMatrix * position;"\
"v_texcoord = texcoord.xy;"\
"}"\
"";
char *const yuvFragmentShaderString = \
"varying vec2 v_texcoord;"\
"uniform sampler2D s_texture_y;"\
"uniform sampler2D s_texture_u;"\
"uniform sampler2D s_texture_v;"
"void main()"\
"{"\
" float y = texture2D(s_texture_y, v_texcoord).r;"\
" float u = texture2D(s_texture_u, v_texcoord).r - 0.5;"\
" float v = texture2D(s_texture_v, v_texcoord).r - 0.5;"\
" float r = y + 1.402 * v;"\
" float g = y - 0.344 * u - 0.714 * v;"\
" float b = y + 1.772 * u;"\
"gl_FragColor = vec4(r,g,b,1.0); "\
"}";
//Init Shader
const char * vs = \
"attribute vec4 vertexIn; "\
"attribute vec2 textureIn;"\
"varying vec2 textureOut;"
"void main(void)"\
"{"\
" gl_Position = vertexIn; "\
"textureOut = textureIn;"\
"}";
const char* fs = \
"varying vec2 textureOut;"\
"uniform sampler2D tex_y;"\
"uniform sampler2D tex_u;"\
"uniform sampler2D tex_v;"\
"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, 1, 1,"\
" 0, -0.39465, 2.03211,"\
" 1.13983, -0.58060, 0) * yuv; "\
" gl_FragColor = vec4(rgb, 1);"\
"}";
void OpenGLDisplay2::InitShaders()
{
GLint vertCompiled, fragCompiled, linked;
// const char *vs,*fs;
//Shader: step1
v = glCreateShader(GL_VERTEX_SHADER);
f = glCreateShader(GL_FRAGMENT_SHADER);
//Shader: step2
glShaderSource(v, 1, &vs,NULL);
glShaderSource(f, 1, &fs,NULL);
//Shader: step3
glCompileShader(v);
//Debug
glGetShaderiv(v, GL_COMPILE_STATUS, &vertCompiled);
glCompileShader(f);
glGetShaderiv(f, GL_COMPILE_STATUS, &fragCompiled);
//Program: Step1
p = glCreateProgram();
//Program: Step2
glAttachShader(p,v);
glAttachShader(p,f);
glBindAttribLocation(p, ATTRIB_VERTEX, "vertexIn");
glBindAttribLocation(p, ATTRIB_TEXTURE, "textureIn");
//Program: Step3
glLinkProgram(p);
//Debug
glGetProgramiv(p, GL_LINK_STATUS, &linked);
//Program: Step4
glUseProgram(p);
//Get Uniform Variables Location
textureUniformY = glGetUniformLocation(p, "tex_y");
textureUniformU = glGetUniformLocation(p, "tex_u");
textureUniformV = glGetUniformLocation(p, "tex_v");
static const GLfloat vertexVertices[] = {
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f,
};
static const GLfloat textureVertices[] = {
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
};
//Set Arrays
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, vertexVertices);
//Enable it
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_TEXTURE, 2, GL_FLOAT, 0, 0, textureVertices);
glEnableVertexAttribArray(ATTRIB_TEXTURE);
//Init Texture
glGenTextures(1, &id_y);
glBindTexture(GL_TEXTURE_2D, id_y);
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);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_nWidth2, m_nHeight2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,NULL);
glGenTextures(1, &id_u);
glBindTexture(GL_TEXTURE_2D, id_u);
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);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_nWidth2/2, m_nHeight2/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,NULL);
glGenTextures(1, &id_v);
glBindTexture(GL_TEXTURE_2D, id_v);
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);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_nWidth2/2, m_nHeight2/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,NULL);
}
//如果出現視窗複用播放視訊,視訊不顯示在在播放視訊的視窗
int VideoPlayerDlg::Init()
{
hGLDC = ::GetDC(m_hImageWnd);
/* Set the pixel format for the DC */
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cDepthBits = 16;
pfd.iLayerType = PFD_MAIN_PLANE;
SetPixelFormat(hGLDC,ChoosePixelFormat(hGLDC, &pfd), &pfd);
::ReleaseDC(m_hImageWnd,hGLDC);
return TRUE;
}