opengl 顯示UYVY422格式的數據

前面我們分享過如何顯示YUV420P的圖像,渲染YUV420P數據

這此我們分享一下UYVY422格式圖像的渲染方法,關於YUV420P和UYVY422的區別,網上有很多圖例可以幫大家理解。

直接看代碼,代碼是直接可以運行的。

完整代碼和資源文件,請訪問:

https://download.csdn.net/download/szfhy/11940081

#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>


//macro to write shader programs inline
#ifndef GLSL
#define GLSL(version, A) "#version " #version "\n" #A
#endif


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


GLuint g_program;
GLuint yuvID;
GLuint texUniformUYVY422;


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);
	}
	//Clear
	glClearColor(255, 0, 0, 0.5f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glUseProgram(g_program); //每一幀都要調用該函數,不然視頻數據就不會顯示
	//Y
	//
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, yuvID);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pixel_w /2 , pixel_h , 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
	glUniform1i(texUniformUYVY422, 0);

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

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

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

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

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

	GLint vID, fID;
	static const char *vs, *fs;
	//Shader: step1
	vID = glCreateShader(GL_VERTEX_SHADER);
	fID = glCreateShader(GL_FRAGMENT_SHADER);

	vs = GLSL(400,
		attribute vec4 vertexIn;
		attribute vec2 textureIn;
		varying vec2 texOut;
		void main(void)
		{
			gl_Position = vertexIn;
			texOut = textureIn;
		}
	);

	fs = GLSL(400,
		uniform sampler2D texUYVY422;
		varying vec2 texOut;

		const lowp vec3 offset = vec3(-0.0625, -0.5, -0.5);
		//vec3 offset = vec3(-16.0/255.0 , -128.0/255.0 , -128.0/255.0);
		const mediump mat3 converter = mat3(
			1.164, 1.164, 1.164,
			0.000,-0.391, 2.018,
			1.596,-0.813, 0.000
			);


		void main(void)
		{
			vec3 yuvColor;
			vec2 TexCoord = texOut;
			ivec2  TexSize = textureSize(texUYVY422, 0);//紋理圖片大小
			int texCoordX = int(TexCoord.x*TexSize.x * 2);

			if (mod(texCoordX, 2.0) == 1.0)
				yuvColor.x = texture2D(texUYVY422, TexCoord).w;
			else
				yuvColor.x = texture2D(texUYVY422, TexCoord).y;

			yuvColor.y = texture2D(texUYVY422, TexCoord).x; // color u
			yuvColor.z = texture2D(texUYVY422, TexCoord).z; // color v

			vec3 rgbColor;
			yuvColor += offset;
			rgbColor = converter * yuvColor;

			gl_FragColor = vec4(rgbColor, 1.0f);
		}
	);


	//Shader: step2
	glShaderSource(vID, 1, &vs, NULL);
	glShaderSource(fID, 1, &fs, NULL);
	//Shader: step3
	glCompileShader(vID);
	//Debug
	glGetShaderiv(vID, GL_COMPILE_STATUS, &vertCompiled);
	glCompileShader(fID);
	glGetShaderiv(fID, GL_COMPILE_STATUS, &fragCompiled);

	if (vertCompiled == GL_FALSE) {
		char szLog[1024] = { 0 };
		GLsizei logLen = 0;//實際錯誤日誌長度		
		glGetShaderInfoLog(vID, 1024, &logLen, szLog);
		printf("Compile shader fail error log is : %s \n shader code :\n %s \n ", szLog, vs);
		glDeleteShader(vID);
		vID = 0;
	}

	if (fragCompiled == GL_FALSE) {
		char szLog[1024] = { 0 };		
		GLsizei logLen = 0;//實際錯誤日誌長度		
		glGetShaderInfoLog(fID, 1024, &logLen, szLog);		
		printf("Compile shader fail error log is : %s \n shader code :\n %s \n ", szLog, fs);
		glDeleteShader(fID);
		fID = 0;
	}
	//Program: Step1
	g_program = glCreateProgram();
	//Program: Step2
	glAttachShader(g_program, vID);
	glAttachShader(g_program, fID);

	glBindAttribLocation(g_program, ATTRIB_VERTEX, "vertexIn");
	glBindAttribLocation(g_program, ATTRIB_TEXTURE, "textureIn");
	//Program: Step3
	glLinkProgram(g_program);
	//Debug
	glGetProgramiv(g_program, GL_LINK_STATUS, &linked);
	if (linked == GL_FALSE) {
		char szLog[1024] = { 0 };
		GLsizei logLen = 0;//實際錯誤日誌長度		
		glGetShaderInfoLog(g_program, 1024, &logLen, szLog);
		printf("Compile shader fail error log is : %s \n  ", szLog);
		glDeleteProgram(g_program);
		g_program = 0;
	}

	//Program: Step4
	glUseProgram(g_program);


	//Get Uniform Variables Location
	texUniformUYVY422 = glGetUniformLocation(g_program, "tex_y");

	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, &yuvID);
	glBindTexture(GL_TEXTURE_2D, yuvID);
	//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_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	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("..\\data\\frame11.yuv", "rb")) == NULL){
		printf("cannot open this file\n");
		return -1;
	}


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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章