//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度)