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