GoPlay是一款基於FFmpeg/OpenGL ES 2.0 的iOS播放器。支持FFmpeg內嵌的全部格式。並且能夠自定義各類濾鏡, 包括VR、水印等。git
關於iOS視頻播放,蘋果提供的AVPlayer性能是很是出色的,可是有個缺點,就是支持播放的格式並很少,僅僅支持mp4/mov/ts等有限的幾種格式。顯然業界中比較知名的jikplayer確實彌補了這種缺陷,然而ijkplayer是在FFmpeg/ffplay的基礎上進行開發的,最終是經過SDL2.0進行顯示。在當前大環境下,VR、水印、貼圖、九宮格等濾鏡盛行,在ijkplayer中默認是支持avfilter濾鏡的,可是並無支持GPU濾鏡;那麼有沒有一種辦法能夠播放AVPlayer不支持格式的視頻,又可以在視頻上無限制的加濾鏡,例如GPUImage那麼方便那麼絲滑的作法呢?上面兩個痛點也就是GoPlay解決的問題。github
關於格式支持,採用了業界比較出名的FFmpeg解封裝不一樣的視頻格式;在解碼階段,若是開啓了VideoToolBox硬解碼,那麼就採用iOS的硬解碼方式,不然自動切換到FFmpeg的軟解碼方式。算法
爲了方便濾鏡的接入,濾鏡包括濾鏡鏈的實現都採用了GPUImage相似的作法,若是使用過GPUImage,那麼就能夠無縫的切換到GoPlay,同時能夠根據GPUImage的已有濾鏡自定義濾鏡,無限擴展本身的濾鏡庫。GoPlay和GPUImage的濾鏡類好比下表。緩存
GOPlay | GPUImage | |
---|---|---|
輸入 | FFMovie | GPUImageMovie |
濾鏡 | FFFilter | GPUImageFilter |
輸出顯示 | FFView | GPUImageView |
GoPlay主要有5個線程(包括主線程),其中OpenGL ES渲染、濾鏡都是在一個統一的異步線程中處理,在這方面與GPUImage的處理稍有不一樣。異步線程能夠防止阻塞UI界面,串行能夠防止線程間加鎖從而致使的性能損耗。線程模型以下。異步
解封裝線程 -- FFmpeg解封裝,讀取packet,分發到視頻解碼線程和音頻解碼線程ide
視頻解碼線程 -- 將packet解碼成frame,並保存到隊列緩存中性能
音頻解碼線程 -- 將packet解碼成frame,並保存到隊列緩存中線程
OpenGL ES渲染、濾鏡處理線程視頻
在業界中,廣泛沒有認識到音頻視頻二者的同步算法是控制學的問題,而僅僅停留在誰快誰慢的問題上。在現實中,音頻和視頻的PTS的偏差是客觀存在的,咱們須要經過一種控制學算法實現音頻和視頻的相對同步,須要考慮到累積偏差的存在,在相對範圍內,同步算法是具備自我調節能力的,當超出某個範圍了,那麼就須要丟幀了,不然會影響觀感。在這麼多開源項目中,FFmpeg/ffplay實現了這種思想。隊列
若是真正理解了音視頻同步算法,那麼丟幀的作法就很簡單了,當超出了音視頻同步算法的調節範圍,並且是視頻幀慢於音頻幀不少,那麼此時就須要丟調視頻幀。
全景圖像是將一張平面圖片映射到一個球面上。本質上也是一種濾鏡處理,即要處理好頂點座標和紋理座標的映射關係。
ArcBall本質上是將二維平面上的滑動轉換成三維立體球的轉動,具體的作法以屏幕中心爲球心,畫一個球。在屏幕中滑動時,就將滑動的點映射到球面上,若是滑動的範圍超出了球的範圍,那麼就映射到最靠近球面的點上。根據起始點的四元數和終點的四元數的差值(求逆),就能夠獲得旋轉的角度。
濾鏡鏈的思路來源於GPUImage,但多路濾鏡的處理狀況並無沿襲GPUImageTwoInput之流的作法。在多路濾鏡的處理上,水印濾鏡中進行了一種嘗試。
關於GoPlay的相關原理基本上到這裏結束了。感興趣的能夠在GoPlay中找到相關的實現,固然也能夠提BUG一塊兒討論。