ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

OpenGL播放视频特效

2021-09-21 17:05:53  阅读:179  来源: 互联网

标签:特效 OpenGL int attribute programId vec2 ._ position 播放


特效可以在着色器中处理

        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;
}

标签:特效,OpenGL,int,attribute,programId,vec2,._,position,播放
来源: https://blog.csdn.net/csdn1126274345/article/details/120403168

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有