windows下,OpenGL播放NV12

基于上一次的环境,用C++简单地封装了一下OpenGL的播放实现

windows下的OpenGL视频播放器开发环境_zhuxian2009的专栏-CSDN博客目录一、GLFW二、GLAD三、新建VS工程四、配置VS工程五、一个简单的Demo程序六、编译运行本文记录VS2017开发OpenGL的环境。首先,选择OpengGL的库,glfw+glad一、GLFWGLFW是一个开源的多平台库,用于桌面上的 OpenGL、OpenGL ES 和 Vulkan 开发。它提供了一个简单的 API,用于创建窗口、上下文和表面,接收输入和事件。GLFW 是用 C 语言编写的,支持 Windows、macOS、X11 和 Wayla..https://blog.csdn.net/zhuxian2009/article/details/122768446

//YUVReader.h

#pragma once

#include <sys/timeb.h>
#include "glad/glad.h"  
#include "GLFW/glfw3.h"

#pragma comment(lib, "glfw3.lib")


// 获取毫秒 时间戳
static int64_t getCurrentTime()
{
    struct timeb rawtime;
    ftime(&rawtime);
    return rawtime.time * 1000 + rawtime.millitm;
}

class CYUVRender
{
public:
    CYUVRender(int nFrameW, int nFrameH);
    virtual ~ CYUVRender();

    int OpenPlayer();
    int InputData(unsigned char *pData, int nDataSize);
    int ClosePlayer();

    int ShouldClose();

private:
    int InitShader();
    static void error_callback(int error, const char* description);

private:
    //yuv w and h
    int m_nFrameW = -1;
    int m_nFrameH = -1;
    GLFWwindow* m_pWindow = NULL;
    GLuint m_textureUniformY;
    GLuint m_textureUniformUV;
    GLuint m_id_y;
    GLuint m_id_uv; // Texture id
};

//YUVReader.cpp
#include "YUVRender.h"

 CYUVRender:: CYUVRender(int nFrameW, int nFrameH):
    m_nFrameW(nFrameW),m_nFrameH(nFrameH)
{
    OpenPlayer();
    InitShader();
}

 CYUVRender::~ CYUVRender()
{

}

int CYUVRender::InputData(unsigned char *pData, int nDataSize)
{
    if (nDataSize < m_nFrameW*m_nFrameH * 3 / 2)
    {
        //error
        return -1;
    }
    //Clear
    glClearColor(0.0, 255, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    //glClearColor(0.5f, 0.5f, 0.7f, 1.0f);
    //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //glDisable(GL_DEPTH_TEST);

    //Y
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, m_id_y);
    //glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, pixel_w, pixel_h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, plane0);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_nFrameW, m_nFrameH, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pData);
    //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);
    glUniform1i(m_textureUniformY, 0);

    //UV
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, m_id_uv);
    //glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, pixel_w / 2, pixel_h / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, plane1);
    //glTexImage2D(GL_TEXTURE_2D, 0, GL_RG, pixel_w >> 1, pixel_h >> 1, 0, GL_RG, GL_UNSIGNED_BYTE, buf + pixel_w * pixel_h);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, m_nFrameW >> 1, m_nFrameH >> 1, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, pData + m_nFrameW * m_nFrameH);
    //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);
    glUniform1i(m_textureUniformUV, 1);

    // Draw
    //glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glfwSwapBuffers(m_pWindow);
    glfwPollEvents();
    return 0;
}

int  CYUVRender::InitShader()
{
    GLuint prog;
    GLint vertCompiled, fragCompiled, linked;

    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;\n"
        "uniform sampler2D textureY;\n"
        "uniform sampler2D textureUV;\n"
        "void main(void)\n"
        "{\n"
        "vec3 yuv; \n"
        "vec3 rgb; \n"
        "yuv.x = texture2D(textureY, textureOut).r; \n"
        "yuv.y = texture2D(textureUV, textureOut).r - 0.5; \n"
        "yuv.z = texture2D(textureUV, textureOut).a - 0.5; \n"
        "rgb = mat3( 1,       1,         1, \n"
        "0,       -0.39465,  2.03211, \n"
        "1.13983, -0.58060,  0) * yuv; \n"
        "gl_FragColor = vec4(rgb, 1); \n"
        "}\n"
    };

    GLuint v = glCreateShader(GL_VERTEX_SHADER);
    GLuint f = glCreateShader(GL_FRAGMENT_SHADER);

    glShaderSource(v, 1, &vs, NULL);
    glShaderSource(f, 1, fs, NULL);
    glCompileShader(v);
    glGetShaderiv(v, GL_COMPILE_STATUS, &vertCompiled);
    glCompileShader(f);
    glGetShaderiv(f, GL_COMPILE_STATUS, &fragCompiled);

    prog = glCreateProgram();
    glAttachShader(prog, v);
    glAttachShader(prog, f);
    glBindAttribLocation(prog, 4, "vertexIn");            //vertex   4
    glBindAttribLocation(prog, 2, "textureIn");            //texture 2
    glLinkProgram(prog);
    glGetProgramiv(prog, GL_LINK_STATUS, &linked);
    glUseProgram(prog);

    glDeleteShader(v);
    glDeleteShader(f);

    m_textureUniformY = glGetUniformLocation(prog, "textureY");
    m_textureUniformUV = glGetUniformLocation(prog, "textureUV");

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

    glVertexAttribPointer(4, 2, GL_FLOAT, 0, 0, vertexVertices);   //vertex  4
    glEnableVertexAttribArray(4);

    glVertexAttribPointer(2, 2, GL_FLOAT, 0, 0, textureVertices);  //texture 2
    glEnableVertexAttribArray(2);

    //init texture
    glGenTextures(1, &m_id_y);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, m_id_y);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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);
    glUniform1i(m_textureUniformY, 0);

    glGenTextures(1, &m_id_uv);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, m_id_uv);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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);
    glUniform1i(m_textureUniformUV, 1);

    return 0;
}

void CYUVRender::error_callback(int error, const char* description)
{

}

int CYUVRender::OpenPlayer()
{
    glfwSetErrorCallback(error_callback);

    if (!glfwInit())
    {
        return -1;
    }

    m_pWindow = glfwCreateWindow(1280, 720, "OpenGL Player", NULL, NULL);
    

    glfwMakeContextCurrent(m_pWindow);
    gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
    glfwSwapInterval(2);

    return 0;
}

int  CYUVRender::ClosePlayer()
{
    if (!m_pWindow)
    {
        glfwTerminate();
    }
    return 0;
}

int CYUVRender::ShouldClose()
{
    if (!m_pWindow)
    {
        return 1;
    }
    return glfwWindowShouldClose(m_pWindow);
}

调用

//YUV_OpenGL_Demo.cpp
#include <iostream>
#include <windows.h>
#include "YUVRender.h"

void print_help()
{
    std::cout << "e.g : YUV_OpenGL_Demo frameW frameH filename" << std::endl;
    getchar();
}

int main(int argc, char *argv[])
{
    std::cout << "Hello OpenGL!\n";
    if (argc != 4)
    {
        print_help();
        return 0;
    }

    int nFrameW = atoi(argv[1]);
    int nFrameH = atoi(argv[2]);
    char *fileName = argv[3];

    std::cout << "nFrameW=" << nFrameW << " nFrameH=" << nFrameW << " filename=" << fileName << std::endl;

    CYUVRender yuvRender(nFrameW, nFrameH);

    unsigned long nFrameSize = nFrameW * nFrameH * 3 / 2;
    FILE *infile;
    unsigned char *buf = new unsigned char[nFrameSize];

    if (fopen_s(&infile, fileName, "rb") != NULL)
    {
        printf("cannot open %s\n", fileName);
        return false;
    }

    while (!yuvRender.ShouldClose())
    {

        if (fread(buf, 1, nFrameSize, infile) != nFrameSize)
        {
            // Loop  
            fseek(infile, 0, SEEK_SET);
            fread(buf, 1, nFrameSize, infile);
        }

        int64_t t0 = getCurrentTime();
        yuvRender.InputData(buf, nFrameSize);
        std::cout << "InputData use time="<< getCurrentTime() - t0<<std::endl;
        
        //Sleep(20);
    }
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值