上一篇文章 实战FFmpeg--iOS平台使用FFmpeg将视频文件转换为YUV文件 演示了如何将视频文件转换为yuv文件保存,现在要做的是如何将yuv文件利用OpenGLES渲染展示出图像画面。要将一个视频文件渲染成连续的视频画面,首先要解决如何渲染一张yuv图片文件。下面就来看看如何通过OpenGLES来渲染yuv图片。

  本文的实现是参照网上的一些零碎的信息做出来的,费了不少精力。使用opengles首先要知道它的基本使用流程,opengles的基本使用参看文章 [OpenGL ES 01]OpenGL ES之初体验[OpenGL ES 02]OpenGL ES渲染管线与着色器 ,仔细学习这2篇文章就能对opengles的使用会有清楚的认识。至于利用opengles来渲染yuv,这就是深层次的运用了,关于yuv的渲染,雷神的文章那必须要仔细仔细再仔细的看的 最简单的视音频播放示例6:OpenGL播放YUV420P(通过Texture,使用Shader)出,将opengl渲染yuv的流程和细节讲的很透彻,前提是要大概懂点c++方面的东西,这个使用的是vs的开发环境。我对opengles的认识,要得益于这三篇,让我对opengles有了比较深刻的认识。

  现在开始在Xcode中实现yuv文件的渲染。首先,要提一提cocoaChina上的一篇帖子 OpenGL播放yuv视频 ,我写的工程就是参考了这篇帖子中的代码,展示yuv的openglesview的原型就是这篇帖子给的代码,所以这篇帖子以及帖子后面别人的跟帖是需要仔细看的,因为楼主没有给出完整的demo,所以我在仔细研究了这篇帖子之后,写出了实现opengles渲染yuv的demo。

  以下罗列下cocoaChina上的帖子 OpenGL播放yuv视频 渲染yuv中楼主与跟贴者互动中说明的要注意的地方:

//初始化
OpenGLView20 *glView = [[OpenGLView20 alloc] initWithFrame:frame];
//设置视频原始尺寸
[glView setVideoSize: height:];
//渲染yuv
[glView displayYUV420pData:yuvBuffer width:352height:;
//将352,288换成你自己的
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSData *reader = [NSData dataWithContentsOfFile:@"/Users/sky/Desktop/yuvtest/yuvtest/201461110423.yuv"];
NSLog(@"the reader length is %i", reader.length); UInt8 * pFrameRGB = (UInt8*)[reader bytes]; //[self.opengl displayYUV420pData:pFrameRGB width:1280 height:720]; OpenGLView20 * myview = [[OpenGLView20 alloc]initWithFrame:CGRectMake(, , , )]; [self.view addSubview:myview];
NSLog(@"window before added %@", myview.window);
[myview setVideoSize: height:];
[myview displayYUV420pData:pFrameRGB width: height:];
} 我这样写,yuv的图像总是显示不出来,现在出现的问题是在文件的这个地方 #ifdef DEBUG GLenum err = glGetError();
if (err != GL_NO_ERROR)
{
printf("GL_ERROR=======>%d\n", err);
}
struct timeval nowtime;
gettimeofday(&nowtime, NULL);
if (nowtime.tv_sec != _time.tv_sec)
{
printf("视频 %d 帧率: %d\n", self.tag, _frameRate);
memcpy(&_time, &nowtime, sizeof(struct timeval));
_frameRate = ;
}
else
{
_frameRate++;
}
#endif GL_ERROR=======> 这个错误,是否因为我对这个库用错了,还是因为其他的原因,有点不懂
[self.view addSubview:myview];执行后,需要点时间来创建缓冲区,不能立马显示数据。
你可以把创建和addsubview提前到别的地方 或者延后点再调用displayYUV420pData 看效果可以这样
[myview displayYUV420pData:pFrameRGB width: height:];
改成
dispatch_async(dispatch_get_global_queue(, ), ^{
sleep();
[glView displayYUV420pData:data width: height:];
});
这个类有个bug:动态创建的view,有时候显示图像显示不出来,卡的要死,内存还会不断增大, 帧率打印是 1帧/秒。

治标的办法有2种:

.把创建view放到viewDidLoad或者更早的地方,创建好后添加到视图上,这种不会出问题。

.如果实在是需要动态创建,则创建并添加到视图上后,执行glview.layer.borderWidth = 1.0;glview.layer.borderWidth = ;相当于刷新下视图,然后再调用display。这种需要找合适的时机刷新,刷新和渲染最好有时间间隔。

这个bug的原因我不清楚,貌似OpenGL的conext绑定有问题。也找不到彻底的解决方案。有谁知道原因的话,告诉我,谢谢。
就是这里描述的问题 http://www.cocoachina.com/bbs/read.php?tid=110721
#import "SkyViewController.h"
#import "OpenGLView20.h" @interface SkyViewController ()
//@property OpenGLView20* opengl;
@property (nonatomic , strong) OpenGLView20* opengl;
@property (nonatomic , strong) NSData* yuvData;
@property (nonatomic , strong) NSData* yuvData1;
@end @implementation SkyViewController - (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.yuvData = [NSData dataWithContentsOfFile:@"/Users/sky/Desktop/yuvtest/yuvtest/201461110423.yuv"];
self.yuvData1 = [NSData dataWithContentsOfFile:@"/Users/sky/Desktop/yuvtest/yuvtest/2014611103511.yuv"];
NSLog(@"the reader length is %lu", (unsigned long)self.yuvData.length);
self.opengl =[[OpenGLView20 alloc]initWithFrame:CGRectMake(, , , )];
[self.view addSubview:self.opengl]; } - (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated]; UInt8 * pFrameRGB = (UInt8*)[self.yuvData bytes];
UInt8 * pFrameRGB1 = (UInt8*)[self.yuvData1 bytes]; NSLog(@"window before added %@", self.opengl.window);
[self.opengl setVideoSize: height:];
int n = ;
while (n--) {
[self.opengl displayYUV420pData:pFrameRGB width: height:];
[self.opengl displayYUV420pData:pFrameRGB1 width: height:];
} } - (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
} @end 那个文件里面不是有个帧率么,虽说那个算法不是很准确,也差不多,那个里面算出来的。我观察了一下,播放24帧用了3秒多,不过这个是在模拟器里面运行的,毕竟模拟器没有硬件来处理这些东西,在真机里面还没测,测了之后告诉你

  上面罗列的内容就是帖子的关键点,我是看了这些跟贴才整出可运行的demo的,搞这个demo的过程中遇到各种问题,费神啊,还好经过几个回合终于搞定了。

  下面贴出我的代码,也就是上面帖子中谈到的关键地方:

//
// ViewController.m
// OpenGLESRenderYUVImage
//
// Created by dev.temobi on 15/4/29.
// Copyright (c) 2015年 dev.temobi. All rights reserved.
// #import "ViewController.h" #import "OpenGLView20.h" @interface ViewController () @end @implementation ViewController
{
NSData *yuvData;
OpenGLView20 * myview;
} - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib. NSString *yuvFile = [[NSBundle mainBundle] pathForResource:@"jpgimage1_image_640_480" ofType:@"yuv"];
yuvData = [NSData dataWithContentsOfFile:yuvFile];
NSLog(@"the reader length is %lu", (unsigned long)yuvData.length); myview = [[OpenGLView20 alloc]initWithFrame:CGRectMake(, , self.view.frame.size.width - , self.view.frame.size.height - )];
[self.view addSubview:myview];
} - (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated]; UInt8 * pFrameRGB = (UInt8*)[yuvData bytes];
[myview setVideoSize: height:];
[myview displayYUV420pData:pFrameRGB width: height:];
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} @end

  贴一张demo的运行效果图:

  我写的完整demo -- OpenGLESRenderYUVImage 下载地址为:http://pan.baidu.com/s/1hq09qoG

实战OpenGLES--iOS平台使用OpenGLES渲染YUV图片的更多相关文章

  1. 实战FFmpeg + OpenGLES--iOS平台上视频解码和播放

    一个星期的努力终于搞定了视频的播放,利用FFmpeg解码视频,将解码的数据通过OpenGLES渲染播放.搞清楚了自己想知道的和完成了自己的学习计划,有点小兴奋.明天就是“五一”,放假三天,更开心啦. ...

  2. 实战FFmpeg--iOS平台使用FFmpeg将视频文件转换为YUV文件

    做播放器的开发这里面涉及的东西太多,我只能一步步往前走,慢慢深入.播放器播放视频采用的是渲染yuv文件.首先,要知道yuv文件是怎么转换得来的,其次,要知道怎么把视频文件保存为yuv文件.雷神的文章1 ...

  3. 《React Native 精解与实战》书籍连载「iOS 平台与 React Native 混合开发」

    此文是我的出版书籍<React Native 精解与实战>连载分享,此书由机械工业出版社出版,书中详解了 React Native 框架底层原理.React Native 组件布局.组件与 ...

  4. cordova插件iOS平台实战开发注意点

    cordova插件是其设计理念的精髓部分,创建并使用自定义插件也是一件比较容易的事.但在这个过程中也容易进入一些误区或者有一些错误的理解,下面从笔者实际开发中遇到的问题出发,对其中的一些注意点和重要概 ...

  5. 实战FFmpeg--编译iOS平台使用的FFmpeg库(支持arm64的FFmpeg2.6.2)

    编译环境:Mac OS X 10.10.2 ,Xcode 6.3  iOS SDK 8.3        FFmpeg库的下载地址是 http://www.ffmpeg.org/releases/ . ...

  6. iOS 平台开发OpenGL ES程序注意事项

    本人最近从Android平台的OpenGL ES开发转到iOS平台的OpenGL ES开发,由于平台不同,所以开发中会有一些区别,再次列出需要注意的几点. 1.首先需要了解iOS主要开发框架,再次仅介 ...

  7. iOS 视图,动画渲染机制探究

    腾讯Bugly特约作者:陈向文 终端的开发,首当其冲的就是视图.动画的渲染,切换等等.用户使用 App 时最直接的体验就是这个界面好不好看,动画炫不炫,滑动流不流畅.UI就是 App 的门面,它的体验 ...

  8. 在iOS平台使用ffmpeg解码h264视频流(转)

    在iOS平台使用ffmpeg解码h264视频流,有需要的朋友可以参考下. 对于视频文件和rtsp之类的主流视频传输协议,ffmpeg提供avformat_open_input接口,直接将文件路径或UR ...

  9. 在iOS平台使用ffmpeg解码h264视频流

    来源:http://www.aichengxu.com/view/37145 在iOS平台使用ffmpeg解码h264视频流,有需要的朋友可以参考下. 对于视频文件和rtsp之类的主流视频传输协议,f ...

随机推荐

  1. 为什么printf()用%f输出double型,而scanf却用%lf呢?

    转:https://blog.csdn.net/bat67/article/details/52056057 示例:double x:scanf(“%f”,&x):输入“123.4”,输出x的 ...

  2. Python集成开发环境(IDE:Integrated Development Environment): PyCharm

    原文地址:https://www.runoob.com/python/python-install.html IDE下载安装 PyCharm 是由 JetBrains 打造的一款 Python IDE ...

  3. ISO/IEC 9899:2011 附录C——顺序点

    附录C——顺序点 1.以下是在5.1.2.3中所描述的顺序点(sequence point): ——在一个函数调用中的函数指示符(function designator)和实际参数的计算,与实际调用之 ...

  4. MSYS2 更新源

    博客转载自:https://blog.csdn.net/puputaoexin/article/details/81780492 在使用msys2下载文件的时候回出现下载速度奇慢,且经常因为各种原因报 ...

  5. 【linux基础】ubuntu16.04 安装后,屏幕分辨率过低且不可调节

    前言 安装CUDA和NVIDIA驱动之后,屏幕分辨率过低且不可调节,尝试了几种方法都没成功解决,特此讲解决方法记录下来. 解决过程 注销进入登录界面,按ctrl+alt+F1进入命令行终端,输入账户名 ...

  6. Java高级面试题整理(附答案)

    这是我收集的10道高级Java面试问题列表.这些问题主要来自 Java 核心部分 ,不涉及 Java EE 相关问题.你可能知道这些棘手的 Java 问题的答案,或者觉得这些不足以挑战你的 Java ...

  7. 【视频开发】【CUDA开发】ffmpeg Nvidia硬件加速总结

    原文链接:https://developer.nvidia.com/ffmpeg GPU-accelerated video processing integrated into the most p ...

  8. filter和map内置函数

    filter filter()函数接收一个函数 f 和一个list,这个函数 f 的作用是对每个元素进行判断,返回 True或 False,filter()根据判断结果自动过滤掉不符合条件的元素,返回 ...

  9. 超简单的react和typescript和引入scss项目搭建流程

    1.首先我们先创建一个react项目,react官网也有react项目搭建的命令 npx create-react-app my-app cd my-app 2.安装我们项目需要的样式依赖,这个项目我 ...

  10. laravel迁移文件中字段方法对应的数据库类型

    /* *Blueprint类中的方法方法 <-> 数据库数据类型 * */ // 数字 increments();// int(10) unsigned primarykey auto_i ...