使用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,一经查实,立即删除!

相关文章

C 学习笔记 - 数组

在学习了 C 语言的数组之后,我发现 C 中的数组与 C# 中的数组除了书写形式上略有区别,其它的基本上都一模一样。 因为之前有 C# 的底子,所有学习 C 语言,感觉也挺轻松的,不过 C 和 C# 之前还是有很多不一样的地方&…

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

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

.net SerialPort

虚拟串口并定时向虚拟串口定时发数据http://scorpiomiracle.iteye.com/blog/653923C#中如何使用SerialPort控件向单片机发送数据?http://zhidao.baidu.com/question/206863745.html?frqrl&index2&qbltopic_question_2_2 转载于:https://www.cnblogs.com/su…

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

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

linux嵌入式c网络编程,嵌入式Linux网络编程之:网络高级编程

本文引用地址:http://www.eepw.com.cn/article/257115.htm在实际情况中,人们往往遇到多个客户端连接服务器端的情况。由于之前介绍的如connet()、recv()和send()等都是阻塞性函数,如果资源没有准备好,则调用该函数的进程将进入睡眠…

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选项,下面有个…

Oracle 执行计划 提示 'PLAN_TABLE' is old version 解决方法

用set autotrace 或者 explain plan for 生成执行计划时,有如下提示:Note----- - PLAN_TABLE is old version导致这个错误的原因是曾经使用toad的执行计划分析过,所以执行了它自带的脚本生成了plan_table。解决办法,drop掉plan_…

C#磁盘遍历——递归

static void Main(string[] args){//创建秒表,记录查询的总时间Stopwatch timer new Stopwatch();timer.Start();//传入本地磁盘路径,遍历当前路径下的所有文件LoadDirectory("G:\传智播客.Net培训—就业班精品");timer.Stop();Console.Write…

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原型,米格粉们千万不要看这架飞机&…

硬盘安装Linux救援系统,硬盘安装linux系统

这里推荐大家使用Daemon Tool 这个Windows下的软件将ISO文件“解”到硬盘上。比方说shrike-i386-disc1.iso可以解压缩到C:盘的cd1目录,shrike-i386-disc2.iso解压缩到C:盘的cd2目录,shrike-i386-disc3.iso可以解压缩到C:盘的cd3目录待用。把cd1&#xff…

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

删除android系统自带的第三方软件

一般手机买来的时候都捆绑了第三方软件,并不是我们所需要的,那我们就删除它们,我们也有选择的权利。 第一步:原理。android捆绑的软件基本安装在/system/app文件下,删除下面的对应的了第三方软件APK文件即可完美卸载 如…

struts2 中文件的位置问题

开发情况下,js文件,模板文件等不是很重要的文件一般放在WebRoot根目录下, 这种情况下的模板文件中添加 css或者js 文件时是相对文件自身添加的,必要时可以通过..来返回到WebRoot根目录,例如: WebRoot目录下…