天天看点

opengl es2.0 实现播放器渲染

//media_gl.h

#ifndef MEDIA_GL_H

#define MEDIA_GL_H

//type:没使用,x,y为视口坐标,w,h为视口宽和高

int init_view(int x,int y,int w,int h,int type);

void uninit_view();

//type:3 RGB格式,4 RGBA格式,w 图片宽度,h图片高度,imgdata图片内存格式数据(rgb数组)

void update_texture(int type,int w,int h,void* imgdata);

//

void update_draw();

//x,y为视口坐标,w,h为视口宽和高,需要配合窗口一起调用

void update_viewsize(int x,int y,int w,int h);

//turn:顺时针旋转角度 0,90,180,270

void update_viewturn(int turn);

#endif

//media_gl.c

#include "media_gl.h"

#if defined( __APPLE__ ) && !defined(__MACOSX)

#include <OpenGLES/ES2/gl.h>

#import <OpenGLES/ES2/glext.h>

#elif defined(linux) || defined(__linux) || defined(__linux__)

#include <GLES2/gl2.h>

#include <GLES2/gl2ext.h>

#else

#include <GL/glew.h>

#endif

struct media_point

{

float _x;

float _y;

float _tx;

float _ty;

};

struct media_view

{

GLuint _prpgram;

GLuint _vexctbuf;

GLuint _textureid;

int _vexctbuf_index;

};

#define shader_vs " \

attribute vec4 position;\n \

attribute vec2 texcoord;\n \

varying vec2 v_texcoord;\n \

void main() {\n \

gl_Position = position;\n \

v_texcoord = texcoord;\n \

}"

#define shader_fs  " \

varying vec2 v_texcoord;\n \

uniform sampler2D texture0;\n \

void main() {\n \

gl_FragColor= texture2D(texture0, v_texcoord);\n \

}"

struct media_view _g_view = {0,0,0,0};

static GLuint _compile(const char * source, int type) 

{

GLint status;

GLuint shader = glCreateShader(type);

glShaderSource(shader, 1, &source, 0);

glCompileShader(shader);

glGetShaderiv(shader, GL_COMPILE_STATUS, &status);

if (status == GL_FALSE) 

{

glDeleteShader(shader);

return 0;

}

return shader;

}

static int _create_program(int type)

{

GLuint fsid,vsid,pid;

GLint status;

pid = glCreateProgram();

//fs

fsid = _compile(shader_fs,GL_FRAGMENT_SHADER);

if(fsid == 0)

{

glDeleteProgram(pid);

return -1;

else 

{

glAttachShader(pid,fsid);

}

//vs

vsid = _compile(shader_vs,GL_VERTEX_SHADER);

if(vsid == 0)

{

glDeleteProgram(pid);

return -1;

else 

{

glAttachShader(pid, vsid);

}

//attrib

glBindAttribLocation(pid, 0, "position");

glBindAttribLocation(pid, 1, "texcoord");

//link

glLinkProgram(pid);

glGetProgramiv(pid, GL_LINK_STATUS, &status);

if (status == 0) 

{

glDeleteProgram(pid);

return -1;

}

glUseProgram(pid);

_g_view._prpgram = pid;

return 0;

}

int init_view(int x,int y,int w,int h,int type)

{

static struct media_point _rect[4*4] = {

//0

{-1.0f,-1.0f,0.0f,0.0f},//0

{1.0f,-1.0f,1.0f,0.0f}, //1

{-1.0f,1.0f,0.0f,1.0f}, //2

{1.0f,1.0f,1.0f,1.0f}, //3

//90

{-1.0f,1.0f,0.0f,0.0f}, //0

{-1.0f,-1.0f,1.0f,0.0f},//1

{1.0f,1.0f,0.0f,1.0f}, //2

{1.0f,-1.0f,1.0f,1.0f}, //3

//180

{1.0f,1.0f,0.0f,0.0f}, //0

{-1.0f,1.0f,1.0f,0.0f}, //1

{1.0f,-1.0f,0.0f,1.0f}, //2

{-1.0f,-1.0f,1.0f,1.0f},//3

//270

{1.0f,-1.0f,0.0f,0.0f}, //0

{1.0f,1.0f,1.0f,0.0f}, //1

{-1.0f,-1.0f,0.0f,1.0f},//2

{-1.0f,1.0f,1.0f,1.0f}, //3

};

uninit_view();

//program

if(_create_program(type) != 0)

{

return -1;

}

glUseProgram(_g_view._prpgram);

//v buffer

glGenBuffers(1, &_g_view._vexctbuf);

glBindBuffer(GL_ARRAY_BUFFER, _g_view._vexctbuf);

glBufferData(GL_ARRAY_BUFFER, sizeof(_rect), _rect, GL_STATIC_DRAW);

//

glViewport(x,y,w,h);

glClearColor(0.0f,0.0f,0.0f,1.0f);

return 0;

}

void uninit_view()

{

if(_g_view._prpgram > 0)

{

glDeleteProgram(_g_view._prpgram);

_g_view._prpgram = 0;

}

if(_g_view._vexctbuf > 0)

{

glDeleteBuffers(1,&_g_view._vexctbuf);

_g_view._vexctbuf = 0;

}

if(_g_view._textureid > 0)

{

glDeleteTextures(1,&_g_view._textureid);

_g_view._textureid = 0;

}

}

void update_texture(int type,int w,int h,void* buf)

{

GLuint gid = 0;

glGenTextures(1, &gid);

glActiveTexture(GL_TEXTURE0);

glBindTexture(GL_TEXTURE_2D, gid);

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

switch(type)

{

case 4:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)w, (GLsizei)h, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);

break;

case 3:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei)w, (GLsizei)h, 0, GL_RGB, GL_UNSIGNED_BYTE, buf);

break;

default:

glDeleteTextures(1,&gid);

return;

}

if(_g_view._textureid > 0)

{

glDeleteTextures(1,&_g_view._textureid);

}

_g_view._textureid = gid;

}

void update_draw()

{

if(_g_view._textureid > 0)

{

glClear(GL_COLOR_BUFFER_BIT);

glEnableVertexAttribArray(0);

glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,sizeof(struct media_point),(GLvoid*)0); 

glEnableVertexAttribArray(1);

glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,sizeof(struct media_point),(GLvoid*)8); 

glDrawArrays(GL_TRIANGLE_STRIP, _g_view._vexctbuf_index, 4);

}

}

void update_viewsize(int x,int y,int w,int h)

{

glViewport(x,y,w,h);

}

//turn 0,90,180,270

void update_viewturn(int turn)

{

switch(turn)

{

case  0:_g_view._vexctbuf_index = 0;

break;

case  90:_g_view._vexctbuf_index = 4;

break;

case  180:_g_view._vexctbuf_index = 8;

break;

case  270:_g_view._vexctbuf_index = 12;

break;

}

}

使用说明:(目前只支持RBGA、RBG格式)

1、播放器打开时调用一次init_view(),设置播放器尺寸;

2、播放器关闭时调用一次uninit_view();

3、每一帧 调用update_texture()递交解码图片数据,之后调用update_draw()

4、缩放播放器时 调用update_viewsize()设置视图大小

5、屏幕旋转时 调用update_viewturn(),设置顺时针旋转角度(0度,90度,180度,270度)

继续阅读