前沿
隨著移動技術(shù)的成熟和即將到來的5G時代 混弥,越來越多的公司開發(fā)移動視頻軟件來占領(lǐng)市場,隨著抖音的登場 視頻APP現(xiàn)已是火海一片对省,BAT紛紛入場蝗拿。
為了能在紅海中分一杯羹 我司決定開發(fā)一款賽馬的視頻觀看項目晾捏,在項目的開發(fā)中 對蘋果的AVFoundation框架進(jìn)行了了解和學(xué)習(xí) 在學(xué)習(xí)過程中越來越佩服AVFoundation
框架的厲害之處。我會分幾篇文章來分析AVFoundation
中常用的API和類
AVFoundation入門
在學(xué)習(xí)AVFoundation
之初哀托,最大的挑戰(zhàn)就是理解該框架所提供的大量類及其功能惦辛。該框架包含的類超過100個、大量協(xié)議的集合及許多不同的功能和常量仓手。在第一次遇到這些問題時看似掌握這個框架有一定的難度胖齐, 但是如果你將這個框架仔細(xì)地按功能單元進(jìn)行分解,就會變得比較容易理解俗或。下面就看一下 AVFoundation所提供的一些核心功能市怎。
-
音頻播放和記錄
AVAudioPlayer
和AVAudioRecorder
可以在應(yīng)用程序中提供一種更簡單的整合音頻播放和記錄的功能。這些方法并不是AVFoundation
用于播放和記錄音頻的唯一方式辛慰,卻是學(xué)習(xí)起來最簡單并且功能最強(qiáng)大的方法
-
媒體文件檢查
AVFoundation
提供檢查正在使用的媒體文件的功能区匠。可以查看這些媒體資源來確定是否適合一些特定的任務(wù)帅腌,比如是否可以用于回放或其是否可以被編輯和導(dǎo)出驰弄。還可以獲取該媒體資源相關(guān)的技術(shù)參數(shù),比如內(nèi)容持續(xù)時間 創(chuàng)建日期或首選播放音量等速客。此外戚篙,該框架還基于AVMetadataItem
類提供功能強(qiáng)大的元數(shù)據(jù)支持。這就允許開發(fā)者讀寫關(guān)于媒體資源的描述信息溺职。
-
視頻播放
AVFoundation
框架可以讓你播放從本地文件或遠(yuǎn)程流中獲取的視頻資源岔擂,并對視頻播放和內(nèi)容的展示進(jìn)行控制。這一部分的核心類是AVPlayer
和AVPlayerItem
浪耘,正是這兩個類讓你能夠?qū)Y源的播放進(jìn)行控制乱灵,此外它還可以整合其他更高級的功能,如控制子標(biāo)題和章節(jié)信息等七冲⊥匆校或者讓你鏈接訪問音頻和視頻這兩個不同的資源。
-
媒體捕捉
AVFoundation
提供了一個豐富的API集來讓你可以對這些設(shè)備進(jìn)行精密控制澜躺。攝像頭捕捉的核心類是AVCaptureSession
蝉稳,其作為所有活動的匯集點來接收攝像頭設(shè)備由各路流發(fā)過來的電影和圖片。這也是AVFoundation
框架的一個可靠功能掘鄙。
-
媒體編輯
AVFoundation
框架語允許創(chuàng)建可以將多個音頻和視頻資源進(jìn)行組合的應(yīng)用程序耘戚,允許修改和編輯獨立的媒體片段,隨時修改音頻文件的參數(shù)以及添加動畫標(biāo)題和場景切換效果操漠。
AVFoundation
有關(guān)資源組合的功能源于AVAsset
的子類AVComposition
收津。AVComposition
中的軌道都是AVAssetTrack
的子類AVCompositionTrack
。一個組合軌跡本身由一個或多個媒體片斷組成,由AVCompositionTrackSegment
類定義朋截,代表這個組合中的實際媒體區(qū)域,描述如下圖所示:
AVComposition
和AVCompositionTrack
都是不可變對象吧黄,提供對資源的只讀操作部服。這些對象提供了一個合適的接口讓應(yīng)用程序的一部分可以進(jìn)行播放或處理。但當(dāng)需要創(chuàng)建自己的組合時拗慨,就需要使用AVMutableComposition
和AVMutableCompositionTrack
所提供的可變子類廓八。要創(chuàng)建自定義組合,需指定在將要添加到組合的源媒體的時間范圍赵抢,還要指定要添加片段的每個軌道的位置剧蹂。
-
媒體處理
雖然通過AVFoundation
框架可以在不通過對媒體資源字節(jié)一級進(jìn)行操作的前提下實現(xiàn)大量功能,但有時你可能還是需要訪問更低層的數(shù)據(jù)并對其進(jìn)行操作烦却。幸運(yùn)的是宠叼,當(dāng)需要執(zhí)行更高級的媒體處理任務(wù)時,可以使用AVAssetReader
和AVAssetWriter
類來實現(xiàn)這些功能其爵。這些類提供直接訪問視頻幀和音頻樣本的功能冒冬,所以可以對媒體資源進(jìn)行任何更高級的處理。
視頻的基本知識點
- 流媒體開發(fā):
- 網(wǎng)絡(luò)層(socket或st)負(fù)責(zé)傳輸
- 協(xié)議層(rtmp或hls)負(fù)責(zé)網(wǎng)絡(luò)打包
- 封裝層(flv摩渺、ts)負(fù)責(zé)編解碼數(shù)據(jù)的封裝
- 編碼層(h.264和aac)負(fù)責(zé)圖像简烤,音頻壓縮
不經(jīng)過壓縮編碼的視頻,根本沒辦法保存摇幻,更何況網(wǎng)絡(luò)中的傳輸横侦,視頻錄制完成后,要先編碼绰姻,再傳輸枉侧,在解碼,再播放(重現(xiàn))
幀:每幀代表一幅靜止的圖像
-
序列GOP: (
Group of Pictures
)畫面組龙宏,一個GOP就是一組連續(xù)的畫面棵逊,每個畫面都是一幀,一個GOP就是很多幀的集合. (直播的數(shù)據(jù)银酗,其實是一組圖片辆影,包括I幀、P幀黍特、B幀蛙讥,當(dāng)用戶第一次觀看的時候,會尋找I幀灭衷,而播放器會到服務(wù)器尋找到最近的I幀反饋給用戶次慢。因此,GOP Cache增加了端到端延遲,因為它必須要拿到最近的I幀). GOP Cache的長度越長迫像,畫面質(zhì)量越好- 在H264中圖像以序列為單位進(jìn)行組織劈愚,一個序列是一段圖像編碼后的數(shù)據(jù)流。
- 一個序列的第一個圖像叫做 IDR 圖像(立即刷新圖像)闻妓,IDR 圖像都是 I 幀圖像菌羽。
- H.264 引入 IDR 圖像是為了解碼的重同步,當(dāng)解碼器解碼到 IDR 圖像時由缆,立即將參考幀隊列清空注祖,將已解碼的數(shù)據(jù)全部輸出或拋棄,重新查找參數(shù)集均唉,開始一個新的序列是晨。
- 這樣,如果前一個序列出現(xiàn)重大錯誤舔箭,在這里可以獲得重新同步的機(jī)會罩缴。
- IDR圖像之后的圖像永遠(yuǎn)不會使用IDR之前的圖像的數(shù)據(jù)來解碼。
- 一個序列就是一段內(nèi)容差異不太大的圖像編碼后生成的一串?dāng)?shù)據(jù)流
- 當(dāng)運(yùn)動變化比較少時层扶,一個序列可以很長靴庆,因為運(yùn)動變化少就代表圖像畫面的內(nèi)容變動很小,所以就可以編一個I幀怒医,然后一直P幀炉抒、B幀了。
- 當(dāng)運(yùn)動變化多時稚叹,可能一個序列就比較短了焰薄,比如就包含一個I幀和3、4個P幀扒袖。
- 在視頻編碼序列中塞茅,GOP即Group of picture(圖像組),指兩個I幀之間的距離
碼率: 圖片進(jìn)行壓縮后每秒顯示的數(shù)據(jù)量季率。
幀率: 每秒顯示的圖片數(shù)野瘦。影響畫面流暢度,與畫面流暢度成正比:幀率越大飒泻,畫面越流暢鞭光;幀率越小,畫面越有跳動感泞遗。(由于人類眼睛的特殊生理結(jié)構(gòu)惰许,如果所看畫面之幀率高于16的時候,就會認(rèn)為是連貫的史辙,此現(xiàn)象稱之為視覺暫留汹买。并且當(dāng)幀速達(dá)到一定數(shù)值后佩伤,再增長的話,人眼也不容易察覺到有明顯的流暢度提升了晦毙。)
分辨率:(矩形)圖片的長度和寬度生巡,即圖片的尺寸
壓縮前的每秒數(shù)據(jù)量:幀率X分辨率(單位應(yīng)該是若干個字節(jié))
壓縮比:壓縮前的每秒數(shù)據(jù)量/碼率 (對于同一個視頻源并采用同一種視頻編碼算法,則:壓縮比越高见妒,畫面質(zhì)量越差障斋。)
視頻文件格式:文件的后綴,比如
.wmv
,.mov
,.mp4
,.mp3
,.avi
,(主要用處:根據(jù)文件格式徐鹤,系統(tǒng)會自動判斷用什么軟件打開,
注意: 隨意修改文件格式,對文件的本身不會造成太大的影響邀层,比如把avi
改成mp4
,文件還是avi.
)視頻封裝格式:一種儲存視頻信息的容器返敬,流式封裝可以有
TS
、FLV
等寥院,索引式的封裝有MP4
,MOV
,AVI
等劲赠,(主要作用:一個視頻文件往往會包含圖像和音頻,還有一些配置信息(如圖像和音頻的關(guān)聯(lián)秸谢,如何解碼它們等):這些內(nèi)容需要按照一定的規(guī)則組織凛澎、封裝起來.
注意:會發(fā)現(xiàn)封裝格式跟文件格式一樣,因為一般視頻文件格式的后綴名即采用相應(yīng)的視頻封裝格式的名稱,所以視頻文件格式就是視頻封裝格式估蹄。)視頻封裝格式和視頻壓縮編碼標(biāo)準(zhǔn):就好像項目工程和編程語言塑煎,封裝格式就是一個項目的工程,視頻編碼方式就是編程語言臭蚁,一個項目工程可以用不同語言開發(fā)最铁。
視頻編碼框架
-
FFmpeg
:是一個跨平臺的開源視頻框架,能實現(xiàn)如視頻編碼,解碼,轉(zhuǎn)碼,串流,播放等豐富的功能。其支持的視頻格式以及播放協(xié)議非常豐富,幾乎包含了所有音視頻編解碼垮兑、封裝格式以及播放協(xié)議冷尉。- -Libswresample:可以對音頻進(jìn)行重采樣,rematrixing 以及轉(zhuǎn)換采樣格式等操 作。
- -Libavcodec:提供了一個通用的編解碼框架,包含了許多視頻,音頻,字幕流 等編碼/解碼器系枪。
- -Libavformat:用于對視頻進(jìn)行封裝/解封裝雀哨。
- -Libavutil:包含一些共用的函數(shù),如隨機(jī)數(shù)生成,數(shù)據(jù)結(jié)構(gòu),數(shù)學(xué)運(yùn)算等。
- -Libpostproc:用于進(jìn)行視頻的一些后期處理私爷。
- -Libswscale:用于視頻圖像縮放,顏色空間轉(zhuǎn)換等雾棺。
- -Libavfilter:提供濾鏡功能。
-
X264
:把視頻原數(shù)據(jù)YUV編碼壓縮成H.264格式 -
VideoToolbox
:蘋果自帶的視頻硬解碼和硬編碼API衬浑,但是在iOS8之后才開放垢村。 -
AudioToolbox
:蘋果自帶的音頻硬解碼和硬編碼API
編碼的常見流程
- 在進(jìn)行當(dāng)前信號編碼時,編碼器首先會產(chǎn)生對當(dāng)前信號做預(yù)測的信號嚎卫,稱作預(yù)測信號(predicted signal)
- 預(yù)測的方式:
- 時間上的預(yù)測(interprediction)嘉栓,亦即使用先前幀的信號做預(yù)測
- 空間上的預(yù)測 (intra prediction)宏榕,亦即使用同一張幀之中相鄰像素的信號做預(yù)測
- 得到預(yù)測信號后,編碼器會將當(dāng)前信號與預(yù)測信號相減得到殘余信號(residual signal)侵佃,并只對殘余信號進(jìn)行編碼
- 如此一來麻昼,可以去除一部份時間上或是空間上的冗余信息
- 編碼器并不會直接對殘余信號進(jìn)行編碼,而是先將殘余信號經(jīng)過變換(通常為離散余弦變換)然后量化以進(jìn)一步去除空間上和感知上的冗余信息
- 量化后得到的量化系數(shù)會再透過熵編碼馋辈,去除統(tǒng)計上的冗余信息
視頻編碼技術(shù)
-
視頻壓縮編碼標(biāo)準(zhǔn):對視頻進(jìn)行壓縮(視頻編碼)或者解壓縮(視頻解碼)的編碼技術(shù),比如
MPEG
抚芦,H.264
,這些視頻編碼技術(shù)是壓縮編碼視頻的- 主要作用:是將視頻像素數(shù)據(jù)壓縮成為視頻碼流,從而降低視頻的數(shù)據(jù)量迈螟。如果視頻不經(jīng)過壓縮編碼的話叉抡,體積通常是非常大的,一部電影可能就要上百G的空間答毫。
- 注意:最影響視頻質(zhì)量的是其視頻編碼數(shù)據(jù)和音頻編碼數(shù)據(jù)褥民,跟封裝格式?jīng)]有多大關(guān)系
MPEG
:一種視頻壓縮方式,它采用了幀間壓縮洗搂,僅存儲連續(xù)幀之間有差別的地方 消返,從而達(dá)到較大的壓縮比H.264/AVC
:
一種視頻壓縮方式,采用事先預(yù)測和與MPEG
中的P-B幀一樣的幀預(yù)測方法壓縮,它可以根據(jù)需要產(chǎn)生適合網(wǎng)絡(luò)情況傳輸?shù)囊曨l流,還有更高的壓縮比耘拇,有更好的圖象質(zhì)量-
在H264協(xié)議里定義了三種幀
- I幀:完整編碼的幀叫I幀
- P幀:參考之前的I幀生成的只包含差異部分編碼的幀叫P幀
- B幀:參考前后的幀編碼的幀叫B幀
-
H264采用的核心算法是幀內(nèi)壓縮和幀間壓縮
- 幀內(nèi)壓縮是生成I幀的算法
- 幀間壓縮是生成B幀和P幀的算法
-
H264的壓縮方法:
- 分組: 把幾幀圖像分為一組(GOP撵颊,也就是一個序列),為防止運(yùn)動變化,幀數(shù)不宜取多
- 定義幀: 將每組內(nèi)各幀圖像定義為三種類型,即I幀、B幀和P幀;
- 預(yù)測幀: 以I幀做為基礎(chǔ)幀,以I幀預(yù)測P幀,再由I幀和P幀預(yù)測B幀;
- 數(shù)據(jù)傳輸: 最后將I幀數(shù)據(jù)與預(yù)測的差值信息進(jìn)行存儲和傳輸惫叛。
注意1:如果是從單個畫面清晰度比較倡勇,
MPEG4
有優(yōu)勢;從動作連貫性上的清晰度嘉涌,H.264
有優(yōu)勢注意2:由于264的算法更加復(fù)雜译隘,程序?qū)崿F(xiàn)煩瑣,運(yùn)行它需要更多的處理器和內(nèi)存資源洛心。因此固耘,運(yùn)行
264
對系統(tǒng)要求是比較高的。注意3:由于264的實現(xiàn)更加靈活词身,它把一些實現(xiàn)留給了廠商自己去實現(xiàn)厅目,雖然這樣給實現(xiàn)帶來了很多好處,但是不同產(chǎn)品之間互通成了很大的問題法严,造成了通過A公司的編碼器編出的數(shù)據(jù)损敷,必須通過A公司的解碼器去解這樣尷尬的事情
-
H.265/HEVC
:一種視頻壓縮方式,基于H.264
,保留原來的某些技術(shù)深啤,同時對一些相關(guān)的技術(shù)加以改進(jìn)拗馒,以改善碼流、編碼質(zhì)量溯街、延時和算法復(fù)雜度之間的關(guān)系诱桂,達(dá)到最優(yōu)化設(shè)置洋丐。-
H.265
是一種更為高效的編碼標(biāo)準(zhǔn),能夠在同等畫質(zhì)效果下將內(nèi)容的體積壓縮得更小挥等,傳輸時更快更省帶寬
-
I-frames幀
:(關(guān)鍵幀)保留一副完整的畫面友绝,解碼時只需要本幀數(shù)據(jù)就可以完成(這些幀都是一些單獨的幀或關(guān)鍵幀,包含創(chuàng)建完整圖片 需要的所有數(shù)據(jù)肝劲。每個GOP都正好有一個I-frames迁客。由于它是獨立幀,其尺寸最大辞槐,但也是解壓最快的)
*P-frames幀
:(差別幀掷漱,預(yù)測幀)保留這一幀跟之前幀的差別,解碼時需要用之前緩存的畫面疊加上本幀定義的差別榄檬,生成最終畫面卜范。(P幀沒有完整畫面數(shù)據(jù),只有與前一幀的畫面差別的數(shù)據(jù))B-frames幀
:(雙向差別幀)保留的是本幀與前后幀的差別丙号,解碼B幀,不僅要取得之前的緩存畫面缰冤,還要解碼之后的畫面犬缨,通過前后畫面的與本幀數(shù)據(jù)的疊加取得最終的畫面。B幀壓縮率高棉浸,但是解碼時CPU會比較累幀內(nèi)(Intraframe)壓縮
:當(dāng)壓縮一幀圖像時怀薛,僅考慮本幀的數(shù)據(jù)而不考慮相鄰幀之間的冗余信息,幀內(nèi)一般采用有損壓縮算法(幀內(nèi)壓縮通過消除包含在每個獨立視頻幀內(nèi)的色彩及結(jié)構(gòu)中的冗余信息來進(jìn)行壓縮,因此可在不降低圖片質(zhì)量的情況下盡可能縮小尺寸迷郑,這類壓縮同JEPG壓縮原理類似枝恋。但通常用于對原始圖片的一部分進(jìn)行處理以生成極高質(zhì)量的照片。通過這一過程創(chuàng)建的幀稱為I-frames)幀間(Interframe)壓縮
:時間壓縮(Temporal compression)嗡害,它通過比較時間軸上不同幀之間的數(shù)據(jù)進(jìn)行壓縮焚碌。幀間壓縮一般是無損的(在幀內(nèi)壓縮中,很多幀被組合在一起作為一組圖片(簡稱GOP)霸妹,對于GOP所存在的時間維度的冗余可以被消除十电。如果想象視頻文件中的經(jīng)典場景,就會有一些特定運(yùn)動元素的概念叹螟,比如行駛的汽車或街上走路的行人鹃骂,場景的背景環(huán)境通常是固定的,固定的背景環(huán)境就代表一個時間維度上的冗余罢绽,這個冗余就可以通過壓縮方式消除)
編碼方式
-
編碼的方式有兩種:
- 硬編碼:使用非CPU進(jìn)行編碼畏线,如顯卡GPU、專用的DSP良价、FPGA寝殴、ASIC芯片等
- 軟編碼:使用CPU進(jìn)行編碼蒿叠,軟編碼通常使用:ffmpeg+x264
- ffmpeg:是一套開源的、用于對音視頻進(jìn)行編碼&解碼&轉(zhuǎn)化計算機(jī)程序
- x264:x264是一種免費(fèi)的杯矩、開源的栈虚、具有更優(yōu)秀算法的H.264/MPEG-4 AVC視頻壓縮編碼方式
-
對比:(沒有對比就沒有傷害)
- 軟編碼:實現(xiàn)直接、簡單史隆,參數(shù)調(diào)整方便魂务,升級易,但CPU負(fù)載重泌射,性能較硬編碼低
- 性能高粘姜,對CPU沒有壓力,但是對其他硬件要求較高(如GPU等)
-
iOS中編碼方式:
- 在iOS8之前熔酷,蘋果并沒有開放硬編碼的接口孤紧,所以只能采用ffpeng+x624進(jìn)行軟編碼
- 在iOS8之后,蘋果開放了接口拒秘,并且封裝了VideoToolBox&AudioToolbox兩個框架号显,分別用于對視頻&音頻進(jìn)行硬編碼
*muxing(合成)
:將視頻流、音頻流甚至是字幕流封裝到一個文件中(容器格式(FLV
躺酒,TS
))押蚤,作為一個信號進(jìn)行傳輸。