使用GPUImage实现视频滤镜

关于GPUImage

这里直接引用官方描述:
The GPUImage framework is a BSD-licensed iOS library that lets you apply GPU-accelerated filters and other effects to images, live camera video, and movies. In comparison to Core Image (part of iOS 5.0), GPUImage allows you to write your own custom filters, supports deployment to iOS 4.0, and has a simpler interface. However, it currently lacks some of the more advanced features of Core Image, such as facial detection.
项目地址:https://github.com/BradLarson/GPUImage

滤镜基本原理

滤镜处理的原理就是把静态图片或者视频的每一帧进行图形变换再显示出来。它的本质就是像素点的坐标和颜色变化,这点从GPUImage项目中滤镜的源代码就可以了解到。
例如下面就是一个名为DarkenBlend的滤镜代码:


NSString *const kGPUImageDarkenBlendFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
varying highp vec2 textureCoordinate2;

uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;

void main()
{

lowp vec4 base = texture2D(inputImageTexture, textureCoordinate);
lowp vec4 overlayer = texture2D(inputImageTexture2, textureCoordinate2);gl_FragColor = vec4(min(overlayer.rgb * base.a, base.rgb * overlayer.a) + overlayer.rgb * (1.0 - base.a) + base.rgb * (1.0 - overlayer.a), 1.0);

}
);


GPUImage的最新版本已经内置了125个滤镜。也支持编写自定义滤镜(custom filter)。

图像处理流程

数据源需要实现GPUImageOutput接口,而后续各个环节(包括最后处理输出结果)的对象都要实现GPUImageInput接口。每个处理环节都是从上一个环节获取图像数据,进行处理后再将结果传递给下一个。下游的处理对象称为上一步的target。使用addTarget:方法为处理链路添加每个环节的对象。一个常见的链条如下:
数据源(例如GPUImageVideoCamera或者GPUImageMovie)->各类filter->GPUImageView
如果需要将结果输出到文件,只要把上述流程中最末的GPUImageView改为一个GPUImageMovieWriter即可。所以滤镜的添加和替换,以及输出结果都十分简单方便。

附一张GPUImage的结构图
Snip20160222_3

接入app

将滤镜接入app非常简单,只要创建一个GPUImageMovie,一个具体的GPUImageFilter和一个用来显示的GPUImageView,然后按处理链条的上下游关系把它们用addTarget串起来。
下面附上我的app里面的调用代码(预览视频):

_movie = [[GPUImageMovie alloc] initWithURL:url];
_movie.shouldRepeat = YES;
_movie.playAtActualSpeed = YES;
_movie.playSound = YES;
_movie.delegate = self;GPUImageMissEtikateFilter *filter = [[GPUImageMissEtikateFilter alloc] init];//胶片效果
[_movie addTarget:filter];
[filter addTarget:self.gpuImageView];[_movie startProcessing];

然后就是一些重要的参数设置:
playAtActualSpeed
控制GPUImageView预览视频时的速度是否要保持真实的速度。如果设为NO,则会将视频的所有帧无间隔渲染,导致速度非常快。设为YES,则会根据视频本身时长计算出每帧的时间间隔,然后每渲染一帧,就sleep一个时间间隔,从而达到正常的播放速度。

shouldRepeat
控制视频是否循环播放。

当你不想预览,而是想将处理过的结果输出到文件时,步骤也类似,只是不再需要创建GPUImageView,而是需要一个GPUImageMovieWriter:

_writer = [[GPUImageMovieWriter alloc] initWithMovieURL:filtedMovieURL size:CGSizeMake(480, 640) fileType:(NSString *)kUTTypeMPEG4 outputSettings:outputSettings];
_writer.encodingLiveVideo = NO;
_writer.shouldPassthroughAudio = NO;
_movie.audioEncodingTarget = _writer;
_movie.playAtActualSpeed = NO;
[_movie addTarget:_curFilter];
[_curFilter addTarget:_writer];
[_movie enableSynchronizedEncodingUsingMovieWriter:_writer];
[_writer startRecording];
[_movie startProcessing];

一些局限和踩过的坑

1.预览时不支持播放声音
视频结果输出到GPUImageView预览时不支持播放声音,所以要自行添加声音播放:
自行创建了一个播放器对象

(void) setupSound
{
if (theAudioPlayer != nil)
{

[theAudioPlayer pause];
[theAudioPlayer seekToTime:kCMTimeZero];
theAudioPlayer = nil;

}
theAudioPlayer = [[AVPlayer alloc] initWithURL:self.url];
}

跟GPUImageView的图像同步播放

if (self.playSound && hasAudioTrack)
{[theAudioPlayer seekToTime:kCMTimeZero];[theAudioPlayer play];
}

由于GPUImageMovie里面没有在这几个重要位置提供回调,所以只能在源代码中直接添加,这也导致了对源码的侵入,不利于以后版本升级。

2.GPUImageView预览视频并循环播放时,当播放重新开始时,有大约50%的概率会有红屏闪一下,目前还未定位到原因

3.GPUImageView预览视频时,app切到后台会crash,所以要特别处理下,在willDisappear和handleApplicationWillEnterBackgroundNotify这两个时机都要暂停滤镜处理:

if (_movie) {[_movie endProcessing];[_movie removeAllTargets];_movie = nil;
}


对应的,在willAppear和handleApplicationWillEnterForegroundNotify这两个时机要重启处理:
if (!_movie) {_movie = [[GPUImageMovie alloc] initWithURL:url];
}_movie.shouldRepeat = YES;
_movie.playAtActualSpeed = YES;
_movie.playSound = YES;
_movie.delegate = self;[_movie addTarget:_curFilter];
[_curFilter addTarget:self.gpuImageView];[_movie startProcessing];

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/261132.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

yunos5 linux内核,魅蓝5S、魅蓝5对比看差异 选Android还是YunOS?

原标题:魅蓝5S、魅蓝5对比看差异 选Android还是YunOS?几天前魅族发布了魅蓝5S,这款手机刚好2月20日上午10点开始销售,在魅族官方店和天猫都可以买到。作为新一代入门级手机,魅蓝5S最大得卖点恐怕就是加入了18W快充功能…

微软ASP.NET站点部署指南(3):使用Web.Config文件的Transformations

1. 综述 大多数程序里都会在Web.config里设置参数,并且在部署的时候需要更改。每次都手工更改这些配置很乏味,也容易出错。该章节将会告诉你如果通过自动化更新Web.config文件来避免这些问题。 2. Web.config Transformations 与Web Deploy Parameters 有…

myeclipse不编译

错误: org.eclipse.core.internal.registry.configurationElementHandle cannot be cast to org.eclipse.jdt.core.compiler.CompilationParticipant) 解决: 关掉MyEclipse>把MyEclipse安装目录下的configuration中的update目录删掉>重…

eclipse配置PHP自动提示代码

为什么80%的码农都做不了架构师?>>> 配置php自动提示代码 (html/js和PHP方法一样) 1. 打开 Eclipse的 Window -> Preferences -> PHPeclipse -> PHP -> Code Assist 打开里面的Enable auto activation选项,下面有个…

linux卸载minicoda2,MiniConda2下载 MiniConda python 2.7 v4.3.30.2 Linux 64位 官方免费版(附安装步骤) 下载-脚本之家...

MiniConda python 2.7 Linux版是一款可以在Linux系统下使用的Python 环境管理工具,同时MiniConda是一个开源的软件包管理系统和环境管理系统,用于安装多个版本的软件包及其依赖关系,并在它们之间轻松切换,本次为大家提供的是Linux…

使用 python 操作 redis

1.安装pyredis (1)使用 # easy_install redis (2)直接编译安装 #wget https://pypi.python.org/packages/source/r/redis/redis-2.9.1.tar.gz #tar xvzf redis-2.9.1.tar.gz #cd redis-2.9.1 #python setup.py install 2.简单的re…

android-XML解析Dom,Sax,Pull

android平台上解析xml的常见的工具有三种:dom,sax,pull。 第一种是DOM, 它的特点是一次全部加载,如果对于数据量小的情况下,它的效率还可以,如果XML文件很大的情况下,速度就会慢起来。 第二种方…

射击的乐趣:WIN32诠释打飞机游戏

一楼留给链接http://blog.csdn.net/crocodile__/article/details/11860129 楼上神贴,膜拜片刻...... 一、游戏玩法和已经实现的功能 1.打开游戏会有提示是否开始游戏。 2.键盘↑↓←→控制保卫者飞机(米格21原型,米格粉们千万不要看这架飞机&…

内容营销11金规

内容营销11金规 现在也许是解释和讲述一个很重要观点的好时机:创造给力的内容十分关键,但还不够。你还必须提出满足大量其他目标的材料,而这些材料,符合给力的内容的惯例,或者(你知道我们马上谈论这一点&am…

eclipse3.4 SVN插件安装

2019独角兽企业重金招聘Python工程师标准>>> SVN插件: http://subclipse.tigris.org/update_1.6.x 汉化版,现在我这边eclipse3.4是可用的。 转载于:https://my.oschina.net/dreamnight/blog/695060

连接两个linux系统软件,【技术共享】synergy-两台电脑共享一套鼠标键盘-Linuxwindows...

PS:这软件倒是不错,可是这要求两台电脑显示器都可以看到.当然一般我们是用不到的.再加上是局域网,直接用远程桌面连接或者控制软件也可以的.前些天,我把自己的台式电脑搬到实验室,与实验室里分配给我的电脑一起用。为了方便使用,我尝试了下用…

容错性设计

即便你的产品90%的时间都运行良好。但是如果在用户需要帮助时置之不理,他们是不会忘记这一点的。——《getting real》 我们有时候不能不面对产品出错的时候。无论设计得多么用心,无论做了多少测试,用户仍然会遇到错误和问题。既然…

Spring Data 系列(二) Spring+JPA入门(集成Hibernate)

通过【Spring Data 系列(一) 入门】的介绍,通过对比的方式认识到Spring提供的JdbcTemplate的强大功能。通过使用JdbcTemplate,操作数据库,不需要手动处理Connection,Statement等底层SQL对象。可是,Spring对数据库的操作还远远没有…

emmet-vim

最近啊,我投奔了网页的开发,看了一本《head first HTML and CSS》的书,感觉非常不错,然后又配置了一些vim里面用到的插件,现在我把学习到的东西记录下来! 首先,我不会在这里写emmet 的具体操作方…

百度epoll

epoll编辑epoll是Linux内核为处理大批量句柄而作了改进的poll,是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。目 录 1简介 2优点 2.1 支持一个进程打开大数目的socket描述符2.2 …

linux命令 正则表达式,详解Linux命令中的正则表达式

详解Linux命令中的正则表达式Mark Do 2017年9月19日 暂无评论 阅读 981 次命令中的正则表达式如果要在命令输出或文本中筛选内容时使用模糊查找,就需要使用正则表达式。正则表达式是一套由多个元字符组成的模糊查找模式,使用正则表达式可以快速查找和定位…

【转】符串搜索工具及XenoCode字符串自动解密工具

【http://www.cnblogs.com/chengchen/archive/2008/07/14/1242244.html】 我们在使用OD破解软件的时候,字符串搜索是最常用的功能之一。但是在DONET平台下似乎没有什么比较好的软件,于是自己动手写了一个软件。这个软件可以自动搜索DONET程序集中的所有的…

linux 封装python,基于linux下python学习(封装)

一、面向对象类的设计:在程序开发中,要设计一个类,通常需要满足以下三个要求:1、类名 这类事物的名字,满足大驼峰命名法2、属性 这类事物具有什么样的特征3、 方法 这类事物具有什么样的行为eg:小明今年18岁&#xf…

图解RAID 0, RAID 1, RAID 5, RAID 10

RAID(Redundant Array of Independent Disk 独立冗余磁盘阵列)技术是加州大学伯克利分校1987年提出,最初是为了组合小的廉价磁盘来代替大的昂贵磁盘,同时希望磁盘失效时不会使对数据的访问受损 失而开发出一定水平的数据保护技术。RAID就是一种由多块廉价…

Spring JPA 中的Repository体系

为什么80%的码农都做不了架构师&#xff1f;>>> Repository体系 org.springframework.data.repository.Repository<T, ID> ---- Repository体系的顶级接口,是个空接口 interface CrudRepository<T, ID extends Serializable> extends Repository<T,…