特效可以在着色器中处理
const char* vs =
{
"precision lowp float; "
"uniform mat4 _MVP;"
"attribute vec2 _position;"
"attribute vec2 _uvY;"
"attribute vec2 _uvU;"
"attribute vec2 _uvV;"
"varying vec2 _outUVY;"
"varying vec2 _outUVU;"
"varying vec2 _outUVV;"
"void main()"
"{"
" _outUVY = _uvY;"
" _outUVU = _uvU;"
" _outUVV = _uvV;"
" vec4 pos = vec4(_position,0,1);"
" gl_Position = _MVP * pos;"
"}"
};
const char* ps =
{
"precision lowp float; "
"uniform sampler2D _textureYUV;"
"varying vec2 _outUVY;"
"varying vec2 _outUVU;"
"varying vec2 _outUVV;"
"void main()"
"{"
" vec3 yuv;"
" vec3 rgb; "
" vec3 color; "
" yuv.x = texture2D(_textureYUV, _outUVY).a;"
" yuv.y = texture2D(_textureYUV, _outUVU).a - 0.5;"
" yuv.z = texture2D(_textureYUV, _outUVV).a - 0.5;"
" rgb = mat3( 1, 1, 1,"
" 0, -0.39465, 2.03210,"
" 1.13983, -0.58060, 0) * yuv;"
"color.r = yuv.y;"
"color.g = yuv.y;"
"color.b = yuv.y;"
"color.r = (rgb.r + rgb.g + rgb.b)/3;"
"color.g = (rgb.r + rgb.g + rgb.b)/3;"
"color.b = (rgb.r + rgb.g + rgb.b)/3;"
" gl_FragColor = vec4(color, 1);"
"}"
};
以下是视频嵌入图片
#pragma once
extern "C"
{
#include <libavutil/imgutils.h>
#include <libavutil/parseutils.h>
#include <libswscale/swscale.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libavutil/file.h>
}
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"swscale.lib")
#pragma comment(lib,"OpenGL32.lib")
#pragma comment(lib,"FreeImage.lib")
struct FrameInfor
{
AVFrame*_data;
int _dataSize;
int _width;
int _height;
int64_t _pts;
double _timeBase;
};
class FFVideoReader
{
public:
AVFormatContext*_formatCtx;
int _videoIndex;
AVCodecContext* _codecCtx;
AVCodec* _codec;
AVFrame* _frame;
public:
int _screenW;
int _screenH;
int _imageSize;
public:
FFVideoReader()
{
_formatCtx = 0;
_videoIndex = -1;
_codecCtx = 0;
_codec = 0;
_frame = 0;
_screenW = 0;
_screenH = 0;
}
~FFVideoReader()
{
av_free(_frame);
avcodec_close(_codecCtx);
avformat_close_input(&_formatCtx);
}
void setup()
{
av_register_all();
_formatCtx = avformat_alloc_context();
}
int load(const char* filepath = "11.flv")
{
int ret = 0;
//! 打开文件
if (avformat_open_input(&_formatCtx, filepath, NULL, NULL) != 0)
{
return -1;
}
//! 检测文件中是否存在数据流
if (avformat_find_stream_info(_formatCtx, NULL) < 0)
{
return -1;
}
//! 获取视频流索引
_videoIndex = -1;
for (int i = 0; i < _formatCtx->nb_streams; i++)
{
if (_formatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
_videoIndex = i;
break;
}
}
/**
* 没有视频流,则返回
*/
if (_videoIndex == -1)
{
return -1;
}
_codecCtx = _formatCtx->streams[_videoIndex]->codec;
double dur = _formatCtx->duration/double(AV_TIME_BASE);
_codec = avcodec_find_decoder(_codecCtx->codec_id);
if (_codec == NULL)
{
return -1;
}
/**
* 打开解码器
*/
if (avcodec_open2(_codecCtx, _codec, NULL) < 0)
{
return -1;
}
_frame = av_frame_alloc();
_screenW = _codecCtx->width;
_screenH = _codecCtx->height;
return 0;
}
bool readFrame(FrameInfor& infor)
{
AVPacket packet;
av_init_packet(&packet);
for (;;)
{
if (av_read_frame(_formatCtx, &packet))
{
av_free_packet(&packet);
return false;
}
if (packet.stream_index != _videoIndex)
{
continue;
}
int frame_finished = 0;
int res = avcodec_decode_video2(_codecCtx, _frame, &frame_finished, &packet);
if (frame_finished)
{
AVStream* streams = _formatCtx->streams[_videoIndex];
double tmbase = av_q2d(streams->time_base);
int64_t pts = _frame->pts;
av_packet_unref(&packet);
infor._data = _frame;
infor._dataSize = 0;
infor._width = _screenW;
infor._height = _screenH;
infor._pts = _frame->pts;
infor._timeBase = av_q2d(streams->time_base);
return true;
}
}
return false;
}
};
#pragma once
#include <assert.h>
class ShaderId
{
public:
ShaderId()
{
_shaderId = -1;
}
int _shaderId;
};
/**
* 程序
*/
class ProgramId
{
public:
int _programId;
ShaderId _vertex;
ShaderId _fragment;
public:
ProgramId()
{
_programId = -1;
}
public:
/**
* 加载函数
*/
bool createProgram( const char* vertex,const char* fragment )
{
bool error = false;
do
{
if (vertex)
{
_vertex._shaderId = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( _vertex._shaderId, 1, &vertex, 0 );
glCompileShader( _vertex._shaderId );
GLint compileStatus;
glGetShaderiv( _vertex._shaderId, GL_COMPILE_STATUS, &compileStatus );
error = compileStatus == GL_FALSE;
if( error )
{
GLchar messages[256];
glGetShaderInfoLog( _vertex._shaderId, sizeof(messages), 0,messages);
assert( messages && 0 != 0);
break;
}
}
if (fragment)
{
_fragment._shaderId = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( _fragment._shaderId, 1, &fragment, 0 );
glCompileShader( _fragment._shaderId );
GLint compileStatus;
glGetShaderiv( _fragment._shaderId, GL_COMPILE_STATUS, &compileStatus );
error = compileStatus == GL_FALSE;
if( error )
{
GLchar messages[256];
glGetShaderInfoLog( _fragment._shaderId, sizeof(messages), 0,messages);
assert( messages && 0 != 0);
break;
}
}
_programId = glCreateProgram( );
if (_vertex._shaderId)
{
glAttachShader( _programId, _vertex._shaderId);
}
if (_fragment._shaderId)
{
glAttachShader( _programId, _fragment._shaderId);
}
glLinkProgram( _programId );
GLint linkStatus;
glGetProgramiv( _programId, GL_LINK_STATUS, &linkStatus );
if (linkStatus == GL_FALSE)
{
GLchar messages[256];
glGetProgramInfoLog( _programId, sizeof(messages), 0, messages);
break;
}
glUseProgram(_programId);
} while(false);
if (error)
{
if (_fragment._shaderId)
{
glDeleteShader(_fragment._shaderId);
_fragment._shaderId = 0;
}
if (_vertex._shaderId)
{
glDeleteShader(_vertex._shaderId);
_vertex._shaderId = 0;
}
if (_programId)
{
glDeleteProgram(_programId);
_programId = 0;
}
}
return true;
}
/**
* 使用程序
*/
virtual void begin()
{
glUseProgram(_programId);
}
/**
* 使用完成
*/
virtual void end()
{
glUseProgram(0);
}
};
class PROGRAM_P2_UV2 :public ProgramId
{
public:
typedef int attribute;
typedef int uniform;
public:
attribute _position;
attribute _uv;
uniform _MVP;
uniform _texture;
public:
PROGRAM_P2_UV2()
{
_position = -1;
_uv = -1;
_MVP = -1;
_texture = -1;
}
~PROGRAM_P2_UV2()
{
}
/// 初始化函数
virtual bool initialize()
{
const char* vs =
{
"precision lowp float; "
"uniform mat4 _MVP;"
"attribute vec2 _position;"
"attribute vec2 _uv;"
"varying vec2 _outUV;"
"void main()"
"{"
" _outUV = _uv;"
" vec4 pos = vec4(_position,0,1);"
" gl_Position = _MVP * pos;"
"}"
};
const char* ps =
{
"precision lowp float; "
"uniform sampler2D _texture;"
"varying vec2 _outUV;"
"void main()"
"{"
" vec4 color = texture2D(_texture,_outUV);"
" gl_FragColor = color;"
"}"
};
bool res = createProgram(vs,ps);
if(res)
{
_position = glGetAttribLocation(_programId,"_position");
_uv = glGetAttribLocation(_programId,"_uv");
_texture = glGetUniformLocation(_programId,"_texture");
_MVP = glGetUniformLocation(_programId,"_MVP");
}
return res;
}
/**
* 使用程序
*/
virtual void begin()
{
glUseProgram(_programId);
glEnableVertexAttribArray(_position);
glEnableVertexAttribArray(_uv);
}
/**
* 使用完成
*/
virtual void end()
{
glDisableVertexAttribArray(_position);
glDisableVertexAttribArray(_uv);
glUseProgram(0);
}
};
class PROGRAM_YUV :public ProgramId
{
public:
typedef int attribute;
typedef int uniform;
public:
attribute _position;
attribute _uv;
uniform _MVP;
uniform _textureY;
uniform _textureU;
uniform _textureV;
public:
PROGRAM_YUV()
{
_position = -1;
_uv = -1;
_MVP = -1;
_textureY = -1;
_textureU = -1;
_textureV = -1;
}
~PROGRAM_YUV()
{
}
/// 初始化函数
virtual bool initialize()
{
const char* vs =
{
"precision lowp float; "
"uniform mat4 _MVP;"
"attribute vec2 _position;"
"attribute vec2 _uv;"
"varying vec2 _outUV;"
"void main()"
"{"
" _outUV = _uv;"
" vec4 pos = vec4(_position,0,1);"
" gl_Position = _MVP * pos;"
"}"
};
const char* ps =
{
"precision lowp float; "
"uniform sampler2D _textureY;"
"uniform sampler2D _textureU;"
"uniform sampler2D _textureV;"
"varying vec2 _outUV;"
"void main()"
"{"
" vec3 yuv;"
" vec3 rgb; "
" yuv.x = texture2D(_textureY, _outUV).a;"
" yuv.y = texture2D(_textureU, _outUV).a - 0.5;"
" yuv.z = texture2D(_textureV, _outUV).a - 0.5;"
" rgb = mat3( 1, 1, 1,"
" 0, -0.39465, 2.03210,"
" 1.13983, -0.58060, 0) * yuv;"
" gl_FragColor = vec4(rgb, 1);"
"}"
};
bool res = createProgram(vs,ps);
if(res)
{
_position = glGetAttribLocation(_programId,"_position");
_uv = glGetAttribLocation(_programId,"_uv");
_textureY = glGetUniformLocation(_programId,"_textureY");
_textureU = glGetUniformLocation(_programId,"_textureU");
_textureV = glGetUniformLocation(_programId,"_textureV");
_MVP = glGetUniformLocation(_programId,"_MVP");
}
return res;
}
/**
* 使用程序
*/
virtual void begin()
{
glUseProgram(_programId);
glEnableVertexAttribArray(_position);
glEnableVertexAttribArray(_uv);
}
/**
* 使用完成
*/
virtual void end()
{
glDisableVertexAttribArray(_position);
glDisableVertexAttribArray(_uv);
glUseProgram(0);
}
};
class PROGRAM_YUV1_RGB :public ProgramId
{
public:
typedef int attribute;
typedef int uniform;
public:
attribute _position;
attribute _uvY;
attribute _uvU;
attribute _uvV;
uniform _MVP;
uniform _textureYUV;
uniform _textureRGB;
uniform _contrl;
public:
PROGRAM_YUV1_RGB()
{
_position = -1;
_uvY = -1;
_uvU = -1;
_uvV = -1;
_MVP = -1;
_textureYUV = -1;
}
~PROGRAM_YUV1_RGB()
{
}
/// 初始化函数
virtual bool initialize()
{
const char* vs =
{
"precision lowp float; "
"uniform mat4 _MVP;"
"attribute vec2 _position;"
"attribute vec2 _uvY;"
"attribute vec2 _uvU;"
"attribute vec2 _uvV;"
"varying vec2 _outUVY;"
"varying vec2 _outUVU;"
"varying vec2 _outUVV;"
"void main()"
"{"
" _outUVY = _uvY;"
" _outUVU = _uvU;"
" _outUVV = _uvV;"
" vec4 pos = vec4(_position,0,1);"
" gl_Position = _MVP * pos;"
"}"
};
const char* ps =
{
"precision lowp float; "
"uniform sampler2D _textureYUV;"
"uniform sampler2D _textureRGB;"
"uniform float _contrl;"
"varying vec2 _outUVY;"
"varying vec2 _outUVU;"
"varying vec2 _outUVV;"
"void main()"
"{"
" vec3 yuv;"
" vec3 rgb; "
" vec3 oColor;"
" yuv.x = texture2D(_textureYUV, _outUVY).a;"
" yuv.y = texture2D(_textureYUV, _outUVU).a - 0.5;"
" yuv.z = texture2D(_textureYUV, _outUVV).a - 0.5;"
" rgb = mat3( 1, 1, 1,"
" 0, -0.39465, 2.03210,"
" 1.13983, -0.58060, 0) * yuv;"
" vec3 color1 = texture2D(_textureRGB, _outUVY).rgb;"
" oColor.r = color1.r * (1.0 - _contrl) + rgb.r * _contrl;"
" oColor.g = color1.g * (1.0 - _contrl) + rgb.g * _contrl;"
" oColor.b = color1.b * (1.0 - _contrl) + rgb.b * _contrl;"
" gl_FragColor = vec4(oColor, 1);"
"}"
};
bool res = createProgram(vs,ps);
if(res)
{
_position = glGetAttribLocation(_programId,"_position");
_uvY = glGetAttribLocation(_programId,"_uvY");
_uvU = glGetAttribLocation(_programId,"_uvU");
_uvV = glGetAttribLocation(_programId,"_uvV");
_textureYUV = glGetUniformLocation(_programId,"_textureYUV");
_textureRGB = glGetUniformLocation(_programId,"_textureRGB");
_contrl = glGetUniformLocation(_programId,"_contrl");
_MVP = glGetUniformLocation(_programId,"_MVP");
}
return res;
}
/**
* 使用程序
*/
virtual void begin()
{
glUseProgram(_programId);
glEnableVertexAttribArray(_position);
glEnableVertexAttribArray(_uvY);
glEnableVertexAttribArray(_uvU);
glEnableVertexAttribArray(_uvV);
}
/**
* 使用完成
*/
virtual void end()
{
glDisableVertexAttribArray(_position);
glDisableVertexAttribArray(_uvY);
glDisableVertexAttribArray(_uvU);
glDisableVertexAttribArray(_uvV);
glUseProgram(0);
}
};
class PROGRAM_YUV1 :public ProgramId
{
public:
typedef int attribute;
typedef int uniform;
public:
attribute _position;
attribute _uvY;
attribute _uvU;
attribute _uvV;
uniform _MVP;
uniform _textureYUV;
public:
PROGRAM_YUV1()
{
_position = -1;
_uvY = -1;
_uvU = -1;
_uvV = -1;
_MVP = -1;
_textureYUV = -1;
}
~PROGRAM_YUV1()
{
}
/// 初始化函数
virtual bool initialize()
{
const char* vs =
{
"precision lowp float; "
"uniform mat4 _MVP;"
"attribute vec2 _position;"
"attribute vec2 _uvY;"
"attribute vec2 _uvU;"
"attribute vec2 _uvV;"
"varying vec2 _outUVY;"
"varying vec2 _outUVU;"
"varying vec2 _outUVV;"
"void main()"
"{"
" _outUVY = _uvY;"
" _outUVU = _uvU;"
" _outUVV = _uvV;"
" vec4 pos = vec4(_position,0,1);"
" gl_Position = _MVP * pos;"
"}"
};
const char* ps =
{
"precision lowp float; "
"uniform sampler2D _textureYUV;"
"varying vec2 _outUVY;"
"varying vec2 _outUVU;"
"varying vec2 _outUVV;"
"void main()"
"{"
" vec3 yuv;"
" vec3 rgb; "
" vec3 oColor;"
" yuv.x = texture2D(_textureYUV, _outUVY).a;"
" yuv.y = texture2D(_textureYUV, _outUVU).a - 0.5;"
" yuv.z = texture2D(_textureYUV, _outUVV).a - 0.5;"
" rgb = mat3( 1, 1, 1,"
" 0, -0.39465, 2.03210,"
" 1.13983, -0.58060, 0) * yuv;"
" oColor.r = (rgb.r + rgb.g + rgb.b )/3.0;"
" oColor.g = (rgb.r + rgb.g + rgb.b )/3.0;"
" oColor.b = (rgb.r + rgb.g + rgb.b )/3.0;"
" gl_FragColor = vec4(oColor, 1);"
"}"
};
bool res = createProgram(vs,ps);
if(res)
{
_position = glGetAttribLocation(_programId,"_position");
_uvY = glGetAttribLocation(_programId,"_uvY");
_uvU = glGetAttribLocation(_programId,"_uvU");
_uvV = glGetAttribLocation(_programId,"_uvV");
_textureYUV = glGetUniformLocation(_programId,"_textureYUV");
_MVP = glGetUniformLocation(_programId,"_MVP");
}
return res;
}
/**
* 使用程序
*/
virtual void begin()
{
glUseProgram(_programId);
glEnableVertexAttribArray(_position);
glEnableVertexAttribArray(_uvY);
glEnableVertexAttribArray(_uvU);
glEnableVertexAttribArray(_uvV);
}
/**
* 使用完成
*/
virtual void end()
{
glDisableVertexAttribArray(_position);
glDisableVertexAttribArray(_uvY);
glDisableVertexAttribArray(_uvU);
glDisableVertexAttribArray(_uvV);
glUseProgram(0);
}
};
// 09OpenGLEffect.cpp : 定义应用程序的入口点。
//
#define __STDC_CONSTANT_MACROS
#define _CRT_SECURE_NO_WARNINGS
#include "framework.h"
#include "09OpenGLEffect.h"
#include "glew/glew.h"
#include "FFVideoReader.hpp"
#include "Thread.hpp"
#include "Timestamp.hpp"
#include "GLContext.h"
#include "CELLShader.hpp"
#include "CELLMath.hpp"
#include "FreeImage.h"
#define MAX_LOADSTRING 100
#define WM_UPDATE_VIDEO WM_USER + 100
// 全局变量:
HINSTANCE hInst; // 当前实例
WCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
WCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
class DecodeThread :public Thread
{
public:
FFVideoReader _ffReader;
HWND _hWnd;
bool _exitFlag;
Timestamp _timestamp;
GLContext _glContext;
unsigned _textureYUV;
unsigned _textureRGB;
float _contrl;
bool _flags;
PROGRAM_YUV1_RGB _shaderTex;
unsigned _pbo[2];
int _DMA;
int _WRITE;
void* _dmaPtr;
public:
DecodeThread()
{
_exitFlag = false;
_hWnd = 0;
_DMA = 0;
_WRITE = 1;
_dmaPtr = 0;
_contrl = 0;
_flags = false;
}
virtual void setup(HWND hwnd, const char* fileName = "11.flv")
{
_hWnd = hwnd;
_ffReader.setup();
_ffReader.load(fileName);
_glContext.setup(hwnd, GetDC(hwnd));
glewInit();
glEnable(GL_TEXTURE_2D);
_textureYUV = createTexture(_ffReader._screenW, _ffReader._screenH + _ffReader._screenH / 2);
_textureRGB = createTextureFromImage("bg.png");
_shaderTex.initialize();
//创建PBuffer
_pbo[0] = createPBuffer(_ffReader._screenW, _ffReader._screenH + _ffReader._screenH / 2);
_pbo[1] = createPBuffer(_ffReader._screenW, _ffReader._screenH + _ffReader._screenH / 2);
}
/**
* 加载文件
*/
virtual void load(const char* fileName)
{
_ffReader.load(fileName);
}
virtual void shutdown()
{
_exitFlag = true;
Thread::join();
_glContext.shutdown();
}
/**
* 线程执行函数
*/
virtual bool run()
{
_timestamp.update();
while (!_exitFlag)
{
FrameInfor* infor = new FrameInfor();
if (!_ffReader.readFrame(*infor))
{
break;
}
double tims = infor->_pts * infor->_timeBase * 1000;
//! 这里需要通知窗口进行重绘制更新,显示更新数据
if (infor->_data->data[0] == 0
|| infor->_data->data[1] == 0
|| infor->_data->data[2] == 0)
{
continue;
}
PostMessage(_hWnd, WM_UPDATE_VIDEO, (WPARAM)infor, 0);
double elsped = _timestamp.getElapsedTimeInMilliSec();
double sleeps = (tims - elsped);
if (sleeps > 1)
{
Sleep((DWORD)sleeps);
}
}
return true;
}
void updateImage(GLubyte* dst, int x, int y, int w, int h, void* data)
{
int pitch = _ffReader._screenW;
GLubyte* dst1 = dst + y * pitch + x;
GLubyte* src = (GLubyte*)(data);
int size = w;
for (int i = 0; i < h; ++i)
{
memcpy(dst1, src, w);
dst1 += pitch;
src += w;
}
}
void updateTexture(FrameInfor* infor)
{
int w = _ffReader._screenW;
int h = _ffReader._screenH + _ffReader._screenH / 2;
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _pbo[_WRITE]);
GLubyte* dst = (GLubyte*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
if (dst != 0)
{
memcpy(dst, infor->_data->data[0], _ffReader._screenW * _ffReader._screenH);
updateImage(dst, 0, _ffReader._screenH, _ffReader._screenW / 2, _ffReader._screenH / 2, infor->_data->data[1]);
updateImage(dst, _ffReader._screenW / 2, _ffReader._screenH, _ffReader._screenW / 2, _ffReader._screenH / 2, infor->_data->data[2]);
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
}
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _pbo[_DMA]);
glBindTexture(GL_TEXTURE_2D, _textureYUV);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
std::swap(_DMA, _WRITE);
}
void render()
{
struct Vertex
{
CELL::float2 pos;
CELL::float2 uvY;
CELL::float2 uvU;
CELL::float2 uvV;
};
RECT rt;
GetClientRect(_hWnd, &rt);
int w = rt.right - rt.left;
int h = rt.bottom - rt.top;
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(1, 0, 0, 1);
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, w, h, 0, -100, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
float yv = (float)_ffReader._screenH / (float)(_ffReader._screenH + _ffReader._screenH / 2);
float fw = _ffReader._screenW;
float fh = _ffReader._screenH;
float x = 0;
float y = 0;
float Yv = (float)fh / (float)(fh + fh / 2);
float Uu0 = 0;
float Uv0 = Yv;
float Uu1 = 0.5f;
float Uv1 = 1.0f;
float Vu0 = 0.5f;
float Vv0 = Yv;
float Vu1 = 1.0f;
float Vv1 = 1.0f;
Vertex vertex[] =
{
CELL::float2(x,y), CELL::float2(0,0), CELL::float2(Uu0,Uv0), CELL::float2(Vu0,Vv0),
CELL::float2(x + w,y), CELL::float2(1,0), CELL::float2(Uu1,Uv0), CELL::float2(Vu1,Vv0),
CELL::float2(x,y + h), CELL::float2(0,Yv), CELL::float2(Uu0,Uv1), CELL::float2(Vu0,Vv1),
CELL::float2(x + w, y + h), CELL::float2(1,Yv), CELL::float2(Uu1,Uv1), CELL::float2(Vu1,Vv1),
};
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _textureYUV);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, _textureRGB);
_shaderTex.begin();
CELL::matrix4 matMVP = CELL::ortho<float>(0, w, h, 0, -100, 100);
glUniformMatrix4fv(_shaderTex._MVP, 1, false, matMVP.data());
glUniform1i(_shaderTex._textureYUV, 0);
glUniform1i(_shaderTex._textureRGB, 1);
glUniform1f(_shaderTex._contrl, _contrl);
if (_flags)
{
_contrl += 1 / 25.0f;
if (_contrl >= 1.0f)
{
_flags = false;
}
}
else
{
_contrl -= 1 / 25.0f;
if (_contrl <= 0.0f)
{
_flags = true;
}
}
glVertexAttribPointer(_shaderTex._position, 2, GL_FLOAT, false, sizeof(Vertex), vertex);
glVertexAttribPointer(_shaderTex._uvY, 2, GL_FLOAT, false, sizeof(Vertex), &vertex[0].uvY);
glVertexAttribPointer(_shaderTex._uvU, 2, GL_FLOAT, false, sizeof(Vertex), &vertex[0].uvU);
glVertexAttribPointer(_shaderTex._uvV, 2, GL_FLOAT, false, sizeof(Vertex), &vertex[0].uvV);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
_shaderTex.end();
_glContext.swapBuffer();
}
protected:
/**
* 使用FreeImage加载图片
*/
unsigned createTextureFromImage(const char* fileName)
{
//1 获取图片格式
FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName, 0);
if (fifmt == FIF_UNKNOWN)
{
return 0;
}
//2 加载图片
FIBITMAP* dib = FreeImage_Load(fifmt, fileName, 0);
FREE_IMAGE_COLOR_TYPE type = FreeImage_GetColorType(dib);
//! 获取数据指针
FIBITMAP* temp = dib;
dib = FreeImage_ConvertTo32Bits(dib);
FreeImage_Unload(temp);
BYTE* pixels = (BYTE*)FreeImage_GetBits(dib);
int width = FreeImage_GetWidth(dib);
int height = FreeImage_GetHeight(dib);
for (int i = 0; i < width * height * 4; i += 4)
{
BYTE temp = pixels[i];
pixels[i] = pixels[i + 2];
pixels[i + 2] = temp;
}
unsigned res = createTexture(width, height, GL_RGBA, pixels);
FreeImage_Unload(dib);
return res;
}
unsigned createTexture(int w, int h, unsigned fmt = GL_ALPHA, const void* data = 0)
{
unsigned texId;
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, fmt, w, h, 0, fmt, GL_UNSIGNED_BYTE, data);
return texId;
}
unsigned createPBuffer(int w, int h)
{
unsigned pbuffer = 0;
glGenBuffers(1, &pbuffer);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbuffer);
glBufferData(GL_PIXEL_UNPACK_BUFFER, w * h, 0, GL_STREAM_DRAW);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
return pbuffer;
}
};
DecodeThread g_decode;
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_MY09OPENGLEFFECT, szWindowClass, MAX_LOADSTRING);
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MY09OPENGLEFFECT));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_MY09OPENGLEFFECT);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
RegisterClassExW(&wcex);
hInst = hInstance; // 将实例句柄存储在全局变量中
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
return FALSE;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
g_decode.setup(hWnd, "1.flv");
g_decode.start();
MSG msg;
// 主消息循环:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, NULL, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
g_decode.shutdown();
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_UPDATE_VIDEO:
{
FrameInfor* infor = (FrameInfor*)wParam;
g_decode.updateTexture(infor);
delete infor;
g_decode.render();
}
break;
case WM_DESTROY:
g_decode.shutdown();
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}