前沿
隨著移動技術的成熟和即將到來的5G時代 ,越來越多的公司開發(fā)移動視頻軟件來占領市場,隨著抖音的登場 視頻APP現(xiàn)已是火海一片,BAT紛紛入場。
為了能在紅海中分一杯羹 我司決定開發(fā)一款賽馬的視頻觀看項目,在項目的開發(fā)中 對蘋果的AVFoundation框架進行了了解和學習 在學習過程中越來越佩服AVFoundation框架的厲害之處。我會分幾篇文章來分析AVFoundation中常用的API和類
AVFoundation入門
在學習AVFoundation之初,最大的挑戰(zhàn)就是理解該框架所提供的大量類及其功能。該框架包含的類超過100個、大量協(xié)議的集合及許多不同的功能和常量。在第一次遇到這些問題時看似掌握這個框架有一定的難度, 但是如果你將這個框架仔細地按功能單元進行分解,就會變得比較容易理解。下面就看一下 AVFoundation所提供的一些核心功能。
-
音頻播放和記錄
AVAudioPlayer和AVAudioRecorder可以在應用程序中提供一種更簡單的整合音頻播放和記錄的功能。這些方法并不是AVFoundation用于播放和記錄音頻的唯一方式,卻是學習起來最簡單并且功能最強大的方法
-
媒體文件檢查
AVFoundation提供檢查正在使用的媒體文件的功能??梢圆榭催@些媒體資源來確定是否適合一些特定的任務,比如是否可以用于回放或其是否可以被編輯和導出。還可以獲取該媒體資源相關的技術參數(shù),比如內(nèi)容持續(xù)時間 創(chuàng)建日期或首選播放音量等。此外,該框架還基于AVMetadataItem類提供功能強大的元數(shù)據(jù)支持。這就允許開發(fā)者讀寫關于媒體資源的描述信息。
-
視頻播放
AVFoundation框架可以讓你播放從本地文件或遠程流中獲取的視頻資源,并對視頻播放和內(nèi)容的展示進行控制。這一部分的核心類是AVPlayer和AVPlayerItem,正是這兩個類讓你能夠對資源的播放進行控制,此外它還可以整合其他更高級的功能,如控制子標題和章節(jié)信息等。或者讓你鏈接訪問音頻和視頻這兩個不同的資源。
-
媒體捕捉
AVFoundation提供了一個豐富的API集來讓你可以對這些設備進行精密控制。攝像頭捕捉的核心類是AVCaptureSession,其作為所有活動的匯集點來接收攝像頭設備由各路流發(fā)過來的電影和圖片。這也是AVFoundation框架的一個可靠功能。
-
媒體編輯
AVFoundation框架語允許創(chuàng)建可以將多個音頻和視頻資源進行組合的應用程序,允許修改和編輯獨立的媒體片段,隨時修改音頻文件的參數(shù)以及添加動畫標題和場景切換效果。
AVFoundation有關資源組合的功能源于AVAsset的子類AVComposition。AVComposition中的軌道都是AVAssetTrack的子類AVCompositionTrack。一個組合軌跡本身由一個或多個媒體片斷組成,由AVCompositionTrackSegment類定義,代表這個組合中的實際媒體區(qū)域,描述如下圖所示:

AVComposition和AVCompositionTrack都是不可變對象,提供對資源的只讀操作。這些對象提供了一個合適的接口讓應用程序的一部分可以進行播放或處理。但當需要創(chuàng)建自己的組合時,就需要使用AVMutableComposition和AVMutableCompositionTrack所提供的可變子類。要創(chuàng)建自定義組合,需指定在將要添加到組合的源媒體的時間范圍,還要指定要添加片段的每個軌道的位置。
-
媒體處理
雖然通過AVFoundation框架可以在不通過對媒體資源字節(jié)一級進行操作的前提下實現(xiàn)大量功能,但有時你可能還是需要訪問更低層的數(shù)據(jù)并對其進行操作。幸運的是,當需要執(zhí)行更高級的媒體處理任務時,可以使用AVAssetReader 和AVAssetWriter類來實現(xiàn)這些功能。這些類提供直接訪問視頻幀和音頻樣本的功能,所以可以對媒體資源進行任何更高級的處理。
視頻的基本知識點
- 流媒體開發(fā):
- 網(wǎng)絡層(socket或st)負責傳輸
- 協(xié)議層(rtmp或hls)負責網(wǎng)絡打包
- 封裝層(flv、ts)負責編解碼數(shù)據(jù)的封裝
- 編碼層(h.264和aac)負責圖像,音頻壓縮
不經(jīng)過壓縮編碼的視頻,根本沒辦法保存,更何況網(wǎng)絡中的傳輸,視頻錄制完成后,要先編碼,再傳輸,在解碼,再播放(重現(xiàn))
幀:每幀代表一幅靜止的圖像
-
序列GOP: (
Group of Pictures)畫面組,一個GOP就是一組連續(xù)的畫面,每個畫面都是一幀,一個GOP就是很多幀的集合. (直播的數(shù)據(jù),其實是一組圖片,包括I幀、P幀、B幀,當用戶第一次觀看的時候,會尋找I幀,而播放器會到服務器尋找到最近的I幀反饋給用戶。因此,GOP Cache增加了端到端延遲,因為它必須要拿到最近的I幀). GOP Cache的長度越長,畫面質量越好- 在H264中圖像以序列為單位進行組織,一個序列是一段圖像編碼后的數(shù)據(jù)流。
- 一個序列的第一個圖像叫做 IDR 圖像(立即刷新圖像),IDR 圖像都是 I 幀圖像。
- H.264 引入 IDR 圖像是為了解碼的重同步,當解碼器解碼到 IDR 圖像時,立即將參考幀隊列清空,將已解碼的數(shù)據(jù)全部輸出或拋棄,重新查找參數(shù)集,開始一個新的序列。
- 這樣,如果前一個序列出現(xiàn)重大錯誤,在這里可以獲得重新同步的機會。
- IDR圖像之后的圖像永遠不會使用IDR之前的圖像的數(shù)據(jù)來解碼。
- 一個序列就是一段內(nèi)容差異不太大的圖像編碼后生成的一串數(shù)據(jù)流
- 當運動變化比較少時,一個序列可以很長,因為運動變化少就代表圖像畫面的內(nèi)容變動很小,所以就可以編一個I幀,然后一直P幀、B幀了。
- 當運動變化多時,可能一個序列就比較短了,比如就包含一個I幀和3、4個P幀。
- 在視頻編碼序列中,GOP即Group of picture(圖像組),指兩個I幀之間的距離
碼率: 圖片進行壓縮后每秒顯示的數(shù)據(jù)量。
幀率: 每秒顯示的圖片數(shù)。影響畫面流暢度,與畫面流暢度成正比:幀率越大,畫面越流暢;幀率越小,畫面越有跳動感。(由于人類眼睛的特殊生理結構,如果所看畫面之幀率高于16的時候,就會認為是連貫的,此現(xiàn)象稱之為視覺暫留。并且當幀速達到一定數(shù)值后,再增長的話,人眼也不容易察覺到有明顯的流暢度提升了。)
分辨率:(矩形)圖片的長度和寬度,即圖片的尺寸
壓縮前的每秒數(shù)據(jù)量:幀率X分辨率(單位應該是若干個字節(jié))
壓縮比:壓縮前的每秒數(shù)據(jù)量/碼率 (對于同一個視頻源并采用同一種視頻編碼算法,則:壓縮比越高,畫面質量越差。)
視頻文件格式:文件的后綴,比如
.wmv,.mov,.mp4,.mp3,.avi
,(主要用處:根據(jù)文件格式,系統(tǒng)會自動判斷用什么軟件打開,
注意: 隨意修改文件格式,對文件的本身不會造成太大的影響,比如把avi改成mp4,文件還是avi.)視頻封裝格式:一種儲存視頻信息的容器,流式封裝可以有
TS、FLV等,索引式的封裝有MP4,MOV,AVI等,(主要作用:一個視頻文件往往會包含圖像和音頻,還有一些配置信息(如圖像和音頻的關聯(lián),如何解碼它們等):這些內(nèi)容需要按照一定的規(guī)則組織、封裝起來.
注意:會發(fā)現(xiàn)封裝格式跟文件格式一樣,因為一般視頻文件格式的后綴名即采用相應的視頻封裝格式的名稱,所以視頻文件格式就是視頻封裝格式。)視頻封裝格式和視頻壓縮編碼標準:就好像項目工程和編程語言,封裝格式就是一個項目的工程,視頻編碼方式就是編程語言,一個項目工程可以用不同語言開發(fā)。
視頻編碼框架
-
FFmpeg:是一個跨平臺的開源視頻框架,能實現(xiàn)如視頻編碼,解碼,轉碼,串流,播放等豐富的功能。其支持的視頻格式以及播放協(xié)議非常豐富,幾乎包含了所有音視頻編解碼、封裝格式以及播放協(xié)議。- -Libswresample:可以對音頻進行重采樣,rematrixing 以及轉換采樣格式等操 作。
- -Libavcodec:提供了一個通用的編解碼框架,包含了許多視頻,音頻,字幕流 等編碼/解碼器。
- -Libavformat:用于對視頻進行封裝/解封裝。
- -Libavutil:包含一些共用的函數(shù),如隨機數(shù)生成,數(shù)據(jù)結構,數(shù)學運算等。
- -Libpostproc:用于進行視頻的一些后期處理。
- -Libswscale:用于視頻圖像縮放,顏色空間轉換等。
- -Libavfilter:提供濾鏡功能。
-
X264:把視頻原數(shù)據(jù)YUV編碼壓縮成H.264格式 -
VideoToolbox:蘋果自帶的視頻硬解碼和硬編碼API,但是在iOS8之后才開放。 -
AudioToolbox:蘋果自帶的音頻硬解碼和硬編碼API
編碼的常見流程
- 在進行當前信號編碼時,編碼器首先會產(chǎn)生對當前信號做預測的信號,稱作預測信號(predicted signal)
- 預測的方式:
- 時間上的預測(interprediction),亦即使用先前幀的信號做預測
- 空間上的預測 (intra prediction),亦即使用同一張幀之中相鄰像素的信號做預測
- 得到預測信號后,編碼器會將當前信號與預測信號相減得到殘余信號(residual signal),并只對殘余信號進行編碼
- 如此一來,可以去除一部份時間上或是空間上的冗余信息
- 編碼器并不會直接對殘余信號進行編碼,而是先將殘余信號經(jīng)過變換(通常為離散余弦變換)然后量化以進一步去除空間上和感知上的冗余信息
- 量化后得到的量化系數(shù)會再透過熵編碼,去除統(tǒng)計上的冗余信息
視頻編碼技術
-
視頻壓縮編碼標準:對視頻進行壓縮(視頻編碼)或者解壓縮(視頻解碼)的編碼技術,比如
MPEG,H.264,這些視頻編碼技術是壓縮編碼視頻的- 主要作用:是將視頻像素數(shù)據(jù)壓縮成為視頻碼流,從而降低視頻的數(shù)據(jù)量。如果視頻不經(jīng)過壓縮編碼的話,體積通常是非常大的,一部電影可能就要上百G的空間。
- 注意:最影響視頻質量的是其視頻編碼數(shù)據(jù)和音頻編碼數(shù)據(jù),跟封裝格式?jīng)]有多大關系
MPEG:一種視頻壓縮方式,它采用了幀間壓縮,僅存儲連續(xù)幀之間有差別的地方 ,從而達到較大的壓縮比H.264/AVC:
一種視頻壓縮方式,采用事先預測和與MPEG中的P-B幀一樣的幀預測方法壓縮,它可以根據(jù)需要產(chǎn)生適合網(wǎng)絡情況傳輸?shù)囊曨l流,還有更高的壓縮比,有更好的圖象質量-
在H264協(xié)議里定義了三種幀
- I幀:完整編碼的幀叫I幀
- P幀:參考之前的I幀生成的只包含差異部分編碼的幀叫P幀
- B幀:參考前后的幀編碼的幀叫B幀
-
H264采用的核心算法是幀內(nèi)壓縮和幀間壓縮
- 幀內(nèi)壓縮是生成I幀的算法
- 幀間壓縮是生成B幀和P幀的算法
-
H264的壓縮方法:
- 分組: 把幾幀圖像分為一組(GOP,也就是一個序列),為防止運動變化,幀數(shù)不宜取多
- 定義幀: 將每組內(nèi)各幀圖像定義為三種類型,即I幀、B幀和P幀;
- 預測幀: 以I幀做為基礎幀,以I幀預測P幀,再由I幀和P幀預測B幀;
- 數(shù)據(jù)傳輸: 最后將I幀數(shù)據(jù)與預測的差值信息進行存儲和傳輸。
注意1:如果是從單個畫面清晰度比較,
MPEG4有優(yōu)勢;從動作連貫性上的清晰度,H.264有優(yōu)勢注意2:由于264的算法更加復雜,程序實現(xiàn)煩瑣,運行它需要更多的處理器和內(nèi)存資源。因此,運行
264對系統(tǒng)要求是比較高的。注意3:由于264的實現(xiàn)更加靈活,它把一些實現(xiàn)留給了廠商自己去實現(xiàn),雖然這樣給實現(xiàn)帶來了很多好處,但是不同產(chǎn)品之間互通成了很大的問題,造成了通過A公司的編碼器編出的數(shù)據(jù),必須通過A公司的解碼器去解這樣尷尬的事情
-
H.265/HEVC:一種視頻壓縮方式,基于H.264,保留原來的某些技術,同時對一些相關的技術加以改進,以改善碼流、編碼質量、延時和算法復雜度之間的關系,達到最優(yōu)化設置。-
H.265是一種更為高效的編碼標準,能夠在同等畫質效果下將內(nèi)容的體積壓縮得更小,傳輸時更快更省帶寬
-
I-frames幀:(關鍵幀)保留一副完整的畫面,解碼時只需要本幀數(shù)據(jù)就可以完成(這些幀都是一些單獨的幀或關鍵幀,包含創(chuàng)建完整圖片 需要的所有數(shù)據(jù)。每個GOP都正好有一個I-frames。由于它是獨立幀,其尺寸最大,但也是解壓最快的)
*P-frames幀:(差別幀,預測幀)保留這一幀跟之前幀的差別,解碼時需要用之前緩存的畫面疊加上本幀定義的差別,生成最終畫面。(P幀沒有完整畫面數(shù)據(jù),只有與前一幀的畫面差別的數(shù)據(jù))B-frames幀:(雙向差別幀)保留的是本幀與前后幀的差別,解碼B幀,不僅要取得之前的緩存畫面,還要解碼之后的畫面,通過前后畫面的與本幀數(shù)據(jù)的疊加取得最終的畫面。B幀壓縮率高,但是解碼時CPU會比較累幀內(nèi)(Intraframe)壓縮:當壓縮一幀圖像時,僅考慮本幀的數(shù)據(jù)而不考慮相鄰幀之間的冗余信息,幀內(nèi)一般采用有損壓縮算法(幀內(nèi)壓縮通過消除包含在每個獨立視頻幀內(nèi)的色彩及結構中的冗余信息來進行壓縮,因此可在不降低圖片質量的情況下盡可能縮小尺寸,這類壓縮同JEPG壓縮原理類似。但通常用于對原始圖片的一部分進行處理以生成極高質量的照片。通過這一過程創(chuàng)建的幀稱為I-frames)幀間(Interframe)壓縮:時間壓縮(Temporal compression),它通過比較時間軸上不同幀之間的數(shù)據(jù)進行壓縮。幀間壓縮一般是無損的(在幀內(nèi)壓縮中,很多幀被組合在一起作為一組圖片(簡稱GOP),對于GOP所存在的時間維度的冗余可以被消除。如果想象視頻文件中的經(jīng)典場景,就會有一些特定運動元素的概念,比如行駛的汽車或街上走路的行人,場景的背景環(huán)境通常是固定的,固定的背景環(huán)境就代表一個時間維度上的冗余,這個冗余就可以通過壓縮方式消除)
編碼方式
-
編碼的方式有兩種:
- 硬編碼:使用非CPU進行編碼,如顯卡GPU、專用的DSP、FPGA、ASIC芯片等
- 軟編碼:使用CPU進行編碼,軟編碼通常使用:ffmpeg+x264
- ffmpeg:是一套開源的、用于對音視頻進行編碼&解碼&轉化計算機程序
- x264:x264是一種免費的、開源的、具有更優(yōu)秀算法的H.264/MPEG-4 AVC視頻壓縮編碼方式
-
對比:(沒有對比就沒有傷害)
- 軟編碼:實現(xiàn)直接、簡單,參數(shù)調(diào)整方便,升級易,但CPU負載重,性能較硬編碼低
- 性能高,對CPU沒有壓力,但是對其他硬件要求較高(如GPU等)
-
iOS中編碼方式:
- 在iOS8之前,蘋果并沒有開放硬編碼的接口,所以只能采用ffpeng+x624進行軟編碼
- 在iOS8之后,蘋果開放了接口,并且封裝了VideoToolBox&AudioToolbox兩個框架,分別用于對視頻&音頻進行硬編碼
*muxing(合成):將視頻流、音頻流甚至是字幕流封裝到一個文件中(容器格式(FLV,TS)),作為一個信號進行傳輸。