opengl 在显示的YUV视频序列上画多个框

在之前的文章中,

opengl 在显示的图像视频上画多个框

记录了如何将BMP图像通过opengl显示,并在显示画面上叠加图层。

这一次我们输入一段YUV序列,利用Shader将YUV转换为RGB并显示,同时叠加多个图层上去。代码中调试遇到了一些问题,图像数据总是不能正常的显示,问题的详细解释如code中的注释所示。

 

// VideoPlayer.cpp : Defines the entry point for the console application.
//
#include <stdio.h>

#include <GLTools.h>	// OpenGL toolkit
#include <GLShaderManager.h>

#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif

#include <GL/glew.h>
#include <GL/freeglut.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>




//Select one of the Texture mode (Set '1'):
#define TEXTURE_DEFAULT   0
//Rotate the texture
#define TEXTURE_ROTATE    0
//Show half of the Texture
#define TEXTURE_HALF      1

const int screen_w = 640, screen_h = 480;
const int pixel_w = 640, pixel_h = 480;
//YUV 422 file
FILE *infile = NULL;
unsigned char buf[pixel_w*pixel_h * 2];
unsigned char *plane[3];


GLuint p;
GLuint id_y, id_u, id_v; // Texture id
GLuint textureUniformY, textureUniformU, textureUniformV;


GLShaderManager	shaderManager;
GLBatch	squareBatch;
GLBatch	squareBatch_v2;
GLfloat blockSize = 0.2f;
GLfloat vVerts[] = {
	-blockSize, -blockSize, 0.0f,
	blockSize, -blockSize, 0.0f,
	blockSize, blockSize, 0.0f,
	-blockSize, blockSize, 0.0f };

GLfloat blockSize_v2 = 0.3f;
GLfloat vVerts_v2[] = {
	-blockSize_v2, -blockSize_v2, 0.0f,
	blockSize_v2, -blockSize_v2, 0.0f,
	blockSize_v2, blockSize_v2, 0.0f,
	-blockSize_v2, blockSize_v2, 0.0f };


void add_rect_roi()
{

	GLfloat vRed[] = { 0.9f, 0.0f, 0.9f, 0.8f };
	//glEnable(GL_DEPTH_TEST);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	//glBlendFunc(GL_ZERO, GL_ZERO);
	shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed);
	squareBatch.Draw();
	glDisable(GL_BLEND);
}

void test_line()
{
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	glLineWidth(5);
	//glBegin(GL_LINES);
	glBegin(GL_LINE_STRIP);
	//glBegin(GL_LINE_LOOP);
	glVertex3f(-0.4, 0.5, 0.0f);
	glVertex3f(0.4, 0.5, 0.0f);
	glVertex3f(-0.4, -0.5, 0.0f);
	glVertex3f(0.4, -0.5, 0.0f);
	glEnd();


	glLineWidth(10);
	glColor3f(0.0, 0.7, 0.0);
	glBegin(GL_LINE_STRIP);
	//glVertex3f(-0.4, 0.5, 0.0f);
	glVertex3f(0.4, 0.5, -0.5f);
	glVertex3f(-0.4, -0.5, -0.5f);
	glVertex3f(0.2, -0.5, -0.5f);
	glEnd();


	glDisable(GL_BLEND);
}


void add_rect_roi_v2()
{
	GLfloat vColor[] = { 0.0f, 1.0f, 0.9f, 0.5f };

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vColor);
	squareBatch_v2.Draw();

	glBegin(GL_TRIANGLES);
	glVertex3f(-0.5f, 0.0f, 0.0f);
	glVertex3f(-0.0f, 0.5f, 0.0f);
	glVertex3f(0.5f, 0.0f, 0.0f);

	glEnd();

	glDisable(GL_BLEND);
}


#define ATTRIB_VERTEX 3
#define ATTRIB_TEXTURE 4

void display(void)
{
	if (fread(buf, 1, pixel_w*pixel_h *  2, infile) != pixel_w*pixel_h * 2)
	{
		// Loop
		fseek(infile, 0, SEEK_SET);
		fread(buf, 1, pixel_w*pixel_h * 2, infile);
	}
	//add_rect_roi();
	//Clear
	glClearColor(255, 0, 0, 0.5f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glUseProgram(p); //每一帧都要调用该函数,不然视频数据就不会显示
	//Y
	//
	glActiveTexture(GL_TEXTURE0);

	glBindTexture(GL_TEXTURE_2D, id_y);

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, pixel_w, pixel_h, 0, GL_RED, GL_UNSIGNED_BYTE, plane[0]);

	glUniform1i(textureUniformY, 0);

	//U
	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D, id_u);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, pixel_w / 2, pixel_h, 0, GL_RED, GL_UNSIGNED_BYTE, plane[1]);
	glUniform1i(textureUniformU, 1);

	//V
	glActiveTexture(GL_TEXTURE2);
	glBindTexture(GL_TEXTURE_2D, id_v);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, pixel_w / 2, pixel_h, 0, GL_RED, GL_UNSIGNED_BYTE, plane[2]);
	glUniform1i(textureUniformV, 2);


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

	
	add_rect_roi();
	add_rect_roi_v2();
	test_line();


	//Double
	glutSwapBuffers();
	//Single
	//glFlush();
}

void timeFunc(int value)
{
	display();
	// Timer: 40ms
	glutTimerFunc(40, timeFunc, 0);
}

char *textFileRead(char * filename)
{
	char *s = (char *)malloc(8000);
	memset(s, 0, 8000);
	FILE *infile = fopen(filename, "rb");
	int len = fread(s, 1, 8000, infile);
	fclose(infile);
	s[len] = 0;
	return s;
}

//Init Shader
void InitShaders()
{
	GLint vertCompiled, fragCompiled, linked;

	GLint v, f;
	static const char *vs, *fs;
	//Shader: step1
	v = glCreateShader(GL_VERTEX_SHADER);
	f = glCreateShader(GL_FRAGMENT_SHADER);
	//Get source code
	//vs = textFileRead("Shader.vsh");
	//fs = textFileRead("Shader.fsh");

	vs =
		"attribute vec4 vertexIn;\n"
		"attribute vec2 textureIn;\n"
		"varying vec2 textureOut;\n"
		"void main(void)\n"
		"{\n"
		"gl_Position = vertexIn;\n"
		"textureOut = textureIn;\n"
		"}\n";

	fs =
		"varying vec2 textureOut;\n"
		"uniform sampler2D tex_y;\n"
		"uniform sampler2D tex_u;\n"
		"uniform sampler2D tex_v;\n"
		"void main(void)\n"
		"{\n"
		"vec3 yuv;\n"
		"vec3 rgb;\n"
		"yuv.x = texture2D(tex_y, textureOut).r;\n"
		"yuv.y = texture2D(tex_u, textureOut).r - 0.5;\n"
		"yuv.z = texture2D(tex_v, textureOut).r - 0.5;\n"
		"rgb = mat3(1, 1, 1, 0, -0.39465, 2.03211, 1.13983, -0.58060, 0) * yuv;\n"
		"gl_FragColor = vec4(rgb, 1.0f);\n"
		"}\n";


	//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");

#if TEXTURE_ROTATE
	static const GLfloat vertexVertices[] = {
		-1.0f, -0.5f,
		0.5f, -1.0f,
		-0.5f, 1.0f,
		1.0f, 0.5f,
	};
#else
	static const GLfloat vertexVertices[] = {
		-1.0f, -1.0f,
		1.0f, -1.0f,
		-1.0f, 1.0f,
		1.0f, 1.0f,
	};
#endif

#if TEXTURE_HALF
	static const GLfloat textureVertices[] = {
		0.0f, 1.0f,
		0.5f, 1.0f,
		0.0f, 0.0f,
		0.5f, 0.0f,
	};
#else
	static const GLfloat textureVertices[] = {
		0.0f, 1.0f,
		1.0f, 1.0f,
		0.0f, 0.0f,
		1.0f, 0.0f,
	};
#endif
	//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);

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

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


	shaderManager.InitializeStockShaders();

	squareBatch.Begin(GL_LINE_LOOP, 4);
	glLineWidth(2.0f);
	squareBatch.CopyVertexData3f(vVerts);
	squareBatch.End();


	squareBatch_v2.Begin(GL_LINE_LOOP, 4);
	glLineWidth(3.0f);
	squareBatch_v2.CopyVertexData3f(vVerts_v2);
	squareBatch_v2.End();


}



int main(int argc, char* argv[])
{
	if ((infile = fopen("D:\\y422p.yuv", "rb")) == NULL){
		printf("cannot open this file\n");
		return -1;
	}

	//YUV Data
	plane[0] = buf;
	plane[1] = plane[0] + pixel_w*pixel_h;
	plane[2] = plane[0] + pixel_w*pixel_h * 3 / 2;

	//Init GLUT
	glutInit(&argc, argv);
	//GLUT_DOUBLE
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA /*| GLUT_STENCIL | GLUT_DEPTH*/);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(screen_w, screen_h);
	glutCreateWindow("Video Player By OpenGL (Texture)");
	printf("Version: %s\n", glGetString(GL_VERSION));

	if (glewInit() != GLEW_OK)
	{
		printf("Failed to initialize GLEW ... exiting");
		exit(EXIT_FAILURE);
	}


	glutDisplayFunc(&display);
	glutTimerFunc(40, timeFunc, 0);

	InitShaders();

	// Begin!
	glutMainLoop();

	return 0;
}

 

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值