使用GPUImage实现视频滤镜
關(guān)于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.
項(xiàng)目地址:https://github.com/BradLarson/GPUImage
濾鏡基本原理
濾鏡處理的原理就是把靜態(tài)圖片或者視頻的每一幀進(jìn)行圖形變換再顯示出來。它的本質(zhì)就是像素點(diǎn)的坐標(biāo)和顏色變化,這點(diǎn)從GPUImage項(xiàng)目中濾鏡的源代碼就可以了解到。
例如下面就是一個(gè)名為DarkenBlend的濾鏡代碼:
NSString *const kGPUImageDarkenBlendFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
varying highp vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
void main()
{
}
);
GPUImage的最新版本已經(jīng)內(nèi)置了125個(gè)濾鏡。也支持編寫自定義濾鏡(custom filter)。
圖像處理流程
數(shù)據(jù)源需要實(shí)現(xiàn)GPUImageOutput接口,而后續(xù)各個(gè)環(huán)節(jié)(包括最后處理輸出結(jié)果)的對(duì)象都要實(shí)現(xiàn)GPUImageInput接口。每個(gè)處理環(huán)節(jié)都是從上一個(gè)環(huán)節(jié)獲取圖像數(shù)據(jù),進(jìn)行處理后再將結(jié)果傳遞給下一個(gè)。下游的處理對(duì)象稱為上一步的target。使用addTarget:方法為處理鏈路添加每個(gè)環(huán)節(jié)的對(duì)象。一個(gè)常見的鏈條如下:
數(shù)據(jù)源(例如GPUImageVideoCamera或者GPUImageMovie)->各類filter->GPUImageView
如果需要將結(jié)果輸出到文件,只要把上述流程中最末的GPUImageView改為一個(gè)GPUImageMovieWriter即可。所以濾鏡的添加和替換,以及輸出結(jié)果都十分簡(jiǎn)單方便。
附一張GPUImage的結(jié)構(gòu)圖
接入app
將濾鏡接入app非常簡(jiǎn)單,只要?jiǎng)?chuàng)建一個(gè)GPUImageMovie,一個(gè)具體的GPUImageFilter和一個(gè)用來顯示的GPUImageView,然后按處理鏈條的上下游關(guān)系把它們用addTarget串起來。
下面附上我的app里面的調(diào)用代碼(預(yù)覽視頻):
然后就是一些重要的參數(shù)設(shè)置:
playAtActualSpeed
控制GPUImageView預(yù)覽視頻時(shí)的速度是否要保持真實(shí)的速度。如果設(shè)為NO,則會(huì)將視頻的所有幀無間隔渲染,導(dǎo)致速度非常快。設(shè)為YES,則會(huì)根據(jù)視頻本身時(shí)長(zhǎng)計(jì)算出每幀的時(shí)間間隔,然后每渲染一幀,就sleep一個(gè)時(shí)間間隔,從而達(dá)到正常的播放速度。
shouldRepeat
控制視頻是否循環(huán)播放。
當(dāng)你不想預(yù)覽,而是想將處理過的結(jié)果輸出到文件時(shí),步驟也類似,只是不再需要?jiǎng)?chuàng)建GPUImageView,而是需要一個(gè)GPUImageMovieWriter:
一些局限和踩過的坑
1.預(yù)覽時(shí)不支持播放聲音
視頻結(jié)果輸出到GPUImageView預(yù)覽時(shí)不支持播放聲音,所以要自行添加聲音播放:
自行創(chuàng)建了一個(gè)播放器對(duì)象
(void) setupSound
{
if (theAudioPlayer != nil)
{
}
theAudioPlayer = [[AVPlayer alloc] initWithURL:self.url];
}
跟GPUImageView的圖像同步播放
由于GPUImageMovie里面沒有在這幾個(gè)重要位置提供回調(diào),所以只能在源代碼中直接添加,這也導(dǎo)致了對(duì)源碼的侵入,不利于以后版本升級(jí)。
2.GPUImageView預(yù)覽視頻并循環(huán)播放時(shí),當(dāng)播放重新開始時(shí),有大約50%的概率會(huì)有紅屏閃一下,目前還未定位到原因
3.GPUImageView預(yù)覽視頻時(shí),app切到后臺(tái)會(huì)crash,所以要特別處理下,在willDisappear和handleApplicationWillEnterBackgroundNotify這兩個(gè)時(shí)機(jī)都要暫停濾鏡處理:
對(duì)應(yīng)的,在willAppear和handleApplicationWillEnterForegroundNotify這兩個(gè)時(shí)機(jī)要重啟處理:
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];
總結(jié)
以上是生活随笔為你收集整理的使用GPUImage实现视频滤镜的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MATLAB小技巧(28)模糊综合评价
- 下一篇: N元语法模型的数据稀疏问题解决方法之一: