分享一个利用OpenGl处理图像的H264与H265播放器
来源:互联网 发布:php服务器绑定域名 编辑:程序博客网 时间:2024/06/06 05:24
现在的图形化处理对OpenGL的运用越来越多,除了系统的播放控件可以进行视频的播放以外,还可以使用openGL来进行视频的播放,以下是一个简易的H264与H265的播发器分享给大家
-------------------------------------------------------------------------------------------------------
#import <UIKit/UIKit.h>
@interface vsGLView : UIView
- (instancetype) initWithFrame:(CGRect)frame;
// 更新图像(rgb24)
-(void)updateImage:(void*)rgb :(UInt32)rgbSize :(UInt32)width :(UInt32)height;
//清除残余图像
- (void) clear;
@end
#import "vsGLView.h"
#import <QuartzCore/QuartzCore.h>
#import <OpenGLES/EAGLDrawable.h>
#import <OpenGLES/EAGL.h>
#import <OpenGLES/ES2/gl.h>
#import <OpenGLES/ES2/glext.h>
//////////////////////////////////////////////////////////
#pragma mark - shaders
#define STRINGIZE(x) #x
#define STRINGIZE2(x) STRINGIZE(x)
#define SHADER_STRING(text) @ STRINGIZE2(text)
NSString *const vertexShaderString =SHADER_STRING
(
attribute vec4 position;
attribute vec2 texcoord;
uniform mat4 modelViewProjectionMatrix;
varying vec2 v_texcoord;
void main()
{
gl_Position = modelViewProjectionMatrix * position;
v_texcoord = texcoord.xy;
}
);
NSString *const rgbFragmentShaderString =SHADER_STRING
(
varying highp vec2 v_texcoord;
uniform sampler2D s_texture;
void main()
{
gl_FragColor = texture2D(s_texture, v_texcoord);
}
);
NSString *const yuvFragmentShaderString =SHADER_STRING
(
varying highp vec2 v_texcoord;
uniform sampler2D s_texture_y;
uniform sampler2D s_texture_u;
uniform sampler2D s_texture_v;
void main()
{
highp float y = texture2D(s_texture_y, v_texcoord).r;
highp float u = texture2D(s_texture_u, v_texcoord).r - 0.5;
highp float v = texture2D(s_texture_v, v_texcoord).r - 0.5;
highp float r = y + 1.402 * v;
highp float g = y - 0.344 * u - 0.714 * v;
highp float b = y + 1.772 * u;
gl_FragColor = vec4(r,g,b,1.0);
}
);
static BOOL validateProgram(GLuint prog)
{
GLint status;
glValidateProgram(prog);
#ifdef DEBUG
GLint logLength;
glGetProgramiv(prog,GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0)
{
GLchar *log = (GLchar *)malloc(logLength);
glGetProgramInfoLog(prog, logLength, &logLength, log);
NSLog(@"Program validate log:\n%s", log);
free(log);
}
#endif
glGetProgramiv(prog,GL_VALIDATE_STATUS, &status);
if (status ==GL_FALSE) {
NSLog(@"Failed to validate program %d", prog);
returnNO;
}
returnYES;
}
static GLuint compileShader(GLenum type,NSString *shaderString)
{
GLint status;
constGLchar *sources = (GLchar *)shaderString.UTF8String;
GLuint shader =glCreateShader(type);
if (shader == 0 || shader ==GL_INVALID_ENUM) {
NSLog(@"Failed to create shader %d", type);
return 0;
}
glShaderSource(shader, 1, &sources,NULL);
glCompileShader(shader);
#ifdef DEBUG
GLint logLength;
glGetShaderiv(shader,GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0)
{
GLchar *log = (GLchar *)malloc(logLength);
glGetShaderInfoLog(shader, logLength, &logLength, log);
NSLog(@"Shader compile log:\n%s", log);
free(log);
}
#endif
glGetShaderiv(shader,GL_COMPILE_STATUS, &status);
if (status ==GL_FALSE) {
glDeleteShader(shader);
NSLog(@"Failed to compile shader:\n");
return 0;
}
return shader;
}
static void mat4f_LoadOrtho(float left,float right, float bottom,float top, float near,float far, float* mout)
{
float r_l = right - left;
float t_b = top - bottom;
float f_n = far - near;
float tx = - (right + left) / (right - left);
float ty = - (top + bottom) / (top - bottom);
float tz = - (far + near) / (far - near);
mout[0] = 2.0f / r_l;
mout[1] = 0.0f;
mout[2] = 0.0f;
mout[3] = 0.0f;
mout[4] = 0.0f;
mout[5] = 2.0f / t_b;
mout[6] = 0.0f;
mout[7] = 0.0f;
mout[8] = 0.0f;
mout[9] = 0.0f;
mout[10] = -2.0f / f_n;
mout[11] = 0.0f;
mout[12] = tx;
mout[13] = ty;
mout[14] = tz;
mout[15] = 1.0f;
}
//////////////////////////////////////////////////////////
#pragma mark - frame renderers
@protocol KxMovieGLRenderer
- (BOOL) isValid;
- (NSString *) fragmentShader;
- (void) resolveUniforms: (GLuint) program;
- (void) setFrame: (void*)rgb :(UInt32)rgbSize :(UInt32)width :(UInt32)height;
- (BOOL) prepareRender;
@end
@interface KxMovieGLRenderer_RGB :NSObject<KxMovieGLRenderer> {
GLint _uniformSampler;
GLuint _texture;
}
@end
@implementation KxMovieGLRenderer_RGB
- (BOOL) isValid
{
return (_texture != 0);
}
- (NSString *) fragmentShader
{
returnrgbFragmentShaderString;
}
- (void) resolveUniforms: (GLuint) program
{
_uniformSampler =glGetUniformLocation(program,"s_texture");
}
- (void) setFrame: (void*)rgb :(UInt32)rgbSize :(UInt32)width :(UInt32)height;
{
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
if (0 ==_texture)
glGenTextures(1, &_texture);
glBindTexture(GL_TEXTURE_2D,_texture);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
width,
height,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
rgb);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
- (BOOL) prepareRender
{
if (_texture == 0)
returnNO;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,_texture);
glUniform1i(_uniformSampler, 0);
returnYES;
}
- (void) dealloc
{
if (_texture) {
glDeleteTextures(1, &_texture);
_texture = 0;
}
}
@end
//////////////////////////////////////////////////////////
#pragma mark - gl view
enum {
ATTRIBUTE_VERTEX,
ATTRIBUTE_TEXCOORD,
};
@implementation vsGLView {
CAEAGLLayer *eaglLayer;
EAGLContext *_context;
GLuint _framebuffer;
GLuint _renderbuffer;
GLint _frameWidth;
GLint _frameHeight;
GLint _backingWidth;
GLint _backingHeight;
GLuint _program;
GLint _uniformMatrix;
GLfloat _vertices[8];
NSLock *synlock;
id<KxMovieGLRenderer> _renderer;
}
+ (Class) layerClass
{
return [CAEAGLLayerclass];
}
- (void)layoutSubviews
{
[superlayoutSubviews];
}
- (instancetype) initWithFrame:(CGRect)frame
{
self = [superinitWithFrame:frame];
if (self) {
self.contentScaleFactor = 2.0;
_renderer = [[KxMovieGLRenderer_RGBalloc] init];
// NSLog(@"OK use RGB GL renderer");
eaglLayer = (CAEAGLLayer*)self.layer;
eaglLayer.opaque =YES;
eaglLayer.drawableProperties = [NSDictionarydictionaryWithObjectsAndKeys:
[NSNumbernumberWithBool:FALSE],kEAGLDrawablePropertyRetainedBacking,
kEAGLColorFormatRGBA8,kEAGLDrawablePropertyColorFormat,
nil];
_context = [[EAGLContextalloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
if (!_context ||
![EAGLContextsetCurrentContext:_context]) {
NSLog(@"failed to setup EAGLContext");
self =nil;
returnnil;
}
glGenFramebuffers(1, &_framebuffer);
glGenRenderbuffers(1, &_renderbuffer);
glBindFramebuffer(GL_FRAMEBUFFER,_framebuffer);
glBindRenderbuffer(GL_RENDERBUFFER,_renderbuffer);
[_contextrenderbufferStorage:GL_RENDERBUFFERfromDrawable:(CAEAGLLayer*)self.layer];
glGetRenderbufferParameteriv(GL_RENDERBUFFER,GL_RENDERBUFFER_WIDTH, &_backingWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER,GL_RENDERBUFFER_HEIGHT, &_backingHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _renderbuffer);
GLenum status =glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status !=GL_FRAMEBUFFER_COMPLETE) {
NSLog(@"failed to make complete framebuffer object %x", status);
self =nil;
returnnil;
}
GLenum glError =glGetError();
if (GL_NO_ERROR != glError) {
NSLog(@"failed to setup GL %x", glError);
self =nil;
returnnil;
}
if (![selfloadShaders]) {
self =nil;
returnnil;
}
_vertices[0] = -1.0f; // x0
_vertices[1] = -1.0f; // y0
_vertices[2] = 1.0f; // ..
_vertices[3] = -1.0f;
_vertices[4] = -1.0f;
_vertices[5] = 1.0f;
_vertices[6] = 1.0f; // x3
_vertices[7] = 1.0f; // y3
// NSLog(@"OK setup GL");
synlock = [[NSLockalloc] init];
[selfclear];
}
returnself;
}
- (void)disMiss
{
_renderer =nil;
synlock =nil;
if (_framebuffer) {
glDeleteFramebuffers(1, &_framebuffer);
_framebuffer = 0;
}
if (_renderbuffer) {
glDeleteRenderbuffers(1, &_renderbuffer);
_renderbuffer = 0;
}
if (_program) {
glDeleteProgram(_program);
_program = 0;
}
if ([EAGLContextcurrentContext] == _context) {
[EAGLContextsetCurrentContext:nil];
}
_context =nil;
}
- (void)dealloc
{
_renderer =nil;
synlock =nil;
if (_framebuffer) {
glDeleteFramebuffers(1, &_framebuffer);
_framebuffer = 0;
}
if (_renderbuffer) {
glDeleteRenderbuffers(1, &_renderbuffer);
_renderbuffer = 0;
}
if (_program) {
glDeleteProgram(_program);
_program = 0;
}
if ([EAGLContextcurrentContext] == _context) {
[EAGLContextsetCurrentContext:nil];
}
_context =nil;
}
- (void)setContentMode:(UIViewContentMode)contentMode
{
[synlocklock];
[supersetContentMode:contentMode];
[synlockunlock];
if (_renderer.isValid) {
[selfclear];
}
}
- (BOOL)loadShaders
{
BOOL result =NO;
GLuint vertShader = 0, fragShader = 0;
_program =glCreateProgram();
vertShader = compileShader(GL_VERTEX_SHADER,vertexShaderString);
if (!vertShader)
goto exit;
fragShader = compileShader(GL_FRAGMENT_SHADER,_renderer.fragmentShader);
if (!fragShader)
goto exit;
glAttachShader(_program, vertShader);
glAttachShader(_program, fragShader);
glBindAttribLocation(_program,ATTRIBUTE_VERTEX, "position");
glBindAttribLocation(_program,ATTRIBUTE_TEXCOORD, "texcoord");
glLinkProgram(_program);
GLint status;
glGetProgramiv(_program,GL_LINK_STATUS, &status);
if (status ==GL_FALSE) {
NSLog(@"Failed to link program %d",_program);
goto exit;
}
result = validateProgram(_program);
_uniformMatrix =glGetUniformLocation(_program,"modelViewProjectionMatrix");
[_rendererresolveUniforms:_program];
exit:
if (vertShader)
glDeleteShader(vertShader);
if (fragShader)
glDeleteShader(fragShader);
if (result) {
// NSLog(@"OK setup GL programm");
} else {
glDeleteProgram(_program);
_program = 0;
}
return result;
}
// 更新图像(rgb24)
-(void)updateImage:(void*)rgb :(UInt32)rgbSize :(UInt32)width :(UInt32)height
{
if (![synlocktryLock])
return;
staticconst GLfloat texCoords[] = {
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
};
[EAGLContextsetCurrentContext:_context];
glUseProgram(_program);
glBindFramebuffer(GL_FRAMEBUFFER,_framebuffer);
glViewport(0, 0,_backingWidth, _backingHeight);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_DEPTH_BUFFER_BIT |GL_COLOR_BUFFER_BIT);
if (rgb) {
[_renderersetFrame:rgb :rgbSize :width :height];
if ([_rendererprepareRender]) {
GLfloat modelviewProj[16];
mat4f_LoadOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, modelviewProj);
glUniformMatrix4fv(_uniformMatrix, 1,GL_FALSE, modelviewProj);
glVertexAttribPointer(ATTRIBUTE_VERTEX, 2,GL_FLOAT, 0, 0,_vertices);
glEnableVertexAttribArray(ATTRIBUTE_VERTEX);
glVertexAttribPointer(ATTRIBUTE_TEXCOORD, 2,GL_FLOAT, 0, 0, texCoords);
glEnableVertexAttribArray(ATTRIBUTE_TEXCOORD);
#if 0
if (!validateProgram(_program))
{
NSLog(@"Failed to validate program");
[synlock unlock];
return;
}
#endif
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
glBindRenderbuffer(GL_RENDERBUFFER,_renderbuffer);
[_contextpresentRenderbuffer:GL_RENDERBUFFER];
[synlockunlock];
}
- (void)clear
{
[synlocklock];
[EAGLContextsetCurrentContext:_context];
glUseProgram(_program);
glBindFramebuffer(GL_FRAMEBUFFER,_framebuffer);
glViewport(0, 0,_backingWidth, _backingHeight);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_DEPTH_BUFFER_BIT |GL_COLOR_BUFFER_BIT);
glBindRenderbuffer(GL_RENDERBUFFER,_renderbuffer);
[_contextpresentRenderbuffer:GL_RENDERBUFFER];
[synlockunlock];
}
@end
- 分享一个利用OpenGl处理图像的H264与H265播放器
- ubuntu下播放h264,h265文件
- ubuntu下播放h264,h265文件
- H264 H265
- 测试h265和h264的编码效果
- 分离h265/h264裸流的帧
- HEVC/H265 标准介绍 和与 H264比较
- H265/H264/Mjpeg/mpeg
- H265 H264重要链接
- h264和h265
- ffmpeg h264转h265
- 一个vlc播放器的 利用
- web无插件解码播放H264/H265(js解码HTML5播放)
- h264 图像宽度与高度的获取
- h264 图像宽度与高度的获取
- H264/H265码流的编码码率设置
- 使用ffmpeg的lib库解码H264/H265
- h264 丢包花屏处理的一个想法
- 1.1 使用IntelliJ IDEA搭建Spring-Boot的"Hello World"项目
- Python学习零散杂记(2017-10-27)
- python_批量转换腾讯云短信模版格式
- vue读书笔记6
- 使用Android Studio开发遇到的问题集合(转载)
- 分享一个利用OpenGl处理图像的H264与H265播放器
- HDU 3478 Catch【kurskal+二分图染色】
- Linux学习:platform平台总线、平台设备、平台驱动
- Gearman详解
- JAVA泛型浅谈
- 实习生面试经验累计
- 云存储:对象存储管理与安全
- 了解Minimax算法
- 【Java】阿里巴巴java规范插件安装记录