使用GPUImage实现视频滤镜

2020/6/14 23:25:33

本文主要是介绍使用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的结构图

作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个我的iOS交 流群:519832104 不管你是小白还 是大牛欢迎入驻,分享经验,讨论技术,大家一起交流学习成长!

另附上一份各好友收集的大厂面试题,需要iOS开发学习资料、面试真题,可以添加 iOS开发进阶交流群,进群可自行下载!

接入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];
复制代码

点击此处,立即与iOS大牛交流学习



这篇关于使用GPUImage实现视频滤镜的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程