2016年是移動直播爆發年,不到半年的時間內無數移動直播App掀起了全民直播的熱潮。然而我的以爲直播的門檻相對較高,從推流端到服務端器到播放端,無不須要專業的技術來支撐,僅僅推流端就有很多須要學習的知識.目前大部分直播採用的都是RTMP協議,我這裏寫一個簡單的Demo,幫助你們更好的理解直播推流的過程,主要包括:音視頻採集, 音視頻編碼, 數據打包, RTMP協議等相關的知識等.項目結構分的很清楚,各個模塊也用協議進行了分離,方便你們學習不一樣的模塊.git
創建tcp鏈接github
創建rtmp鏈接,以及發送各類控制指令算法
獲取原始視頻數據和音頻數據服務器
對原始視頻數據和音頻數據進行壓縮編碼網絡
對編碼後的視頻數據和音頻數據進行打包app
發送打包後的音頻和視頻數據框架
`SGSimpleSession` 是Api接口層,負責對外提供可直接調用的接口,同時也是一個數據分發中心,獲取到的原始音視頻數據和編碼後的數據都在這裏被分發到不一樣的類進行處理.tcp
視頻相關的類ide
1.SGVideoSource 原始視頻數據獲取類,底層用的是AVFoundation框架來實現.對外提供原始未經編碼的的視頻數據,同時提供圖像預覽功能.若是須要添加美顏,攝像頭切換,翻轉,閃光燈等操做,也是在這裏處理的.性能
原始視頻幀: 原始視頻數據其實就是一幀一幀的數據,它們沒有通過壓縮編碼,每一幀包含了圖像信息和時間信息,咱們經過代碼提取出圖片.
fps :1s中包含的幀數就是幀速(fps),通常fps的範圍是15~30幀,幀速越高畫面越流暢,帶寬消耗量越大.實際直播中,大部分採用15到20就能夠了.
分辨率 : 一幀的圖像的大小,iOS原生的有352*288,640*480,1280*720等,通常直播採用640 *480,而後裁剪爲640 *360.
碼率 : 也叫比特率,數據傳輸時單位時間傳送的數據位數. 能夠理解爲碼率決定一幀圖像的顯示精細程度.在必定範圍內,碼率越大,圖像越清晰,消耗帶寬或者文件體積就越大.超過必定範圍後,清晰度不變.通常640 * 480分辨率的,碼率512kbps就可以保證清晰度.
2.SGVideoConfig這個視頻配置的類,主要包括壓縮等級,分辨率,碼率等的配置
3.SGH264Encoder這個類是編碼器,主要功能是對原始的視頻幀進行編碼壓縮處理,這裏採用的是`硬編碼`,編碼輸出格式爲H264格式.
編碼 : 編碼是指將原始的幀數據編碼壓縮,編碼後數據更小,方便在網絡上傳輸.原始數據體積較大,網絡傳輸十分不方便,所以須要將數據壓縮,視頻壓縮算法當前比較主流的是H264,這裏咱們壓縮格式是H264格式.H264有不一樣的壓縮等級,壓縮等級不一樣,壓縮比也不一樣.常見的壓縮等級有:`baseline ` , `main` , `high`.
硬編碼 : 硬編碼是相對軟編碼而言的,通常軟編碼是經過cpu來運算,比較消耗cpu性能,耗時大,可是兼容性好,軟編碼通常採用ffmpeg或者x264.相對而言,硬編碼使用gpu來編碼,速度效率很高.這裏採用的是iOS自帶的硬解碼,只支持iOS8之後的系統.
壓縮後的視頻幀 : 壓縮後的視頻有三種幀類型:I ,B ,P幀,I幀也叫關鍵幀.通過解碼後可以獨立展現出一幅圖像,P幀是前向預測幀,參考前一幀才能解碼顯示出一幅完整的圖像.B 爲雙向預測幀,必須參考前一幀和後一幀才能解碼出圖像.所以,I幀的壓縮比最低,大約爲0.7,它只能採用幀內壓縮,P幀壓縮比次之,大概能達到0.5,B幀壓縮比則更高,達到了0.3~0.5,B幀和P幀採用的是幀內壓縮和幀間壓縮技術(也就是運動估計,原理是相鄰幀的圖像有一部分是同樣的,專業術語叫空間冗餘).實際上,視頻壓縮等級不一樣,幀種類也不一樣,好比`baseline等級`壓縮後的視頻只有I幀 和 P幀.`main等級` 和 `high等級` 則三種幀都包含,它們的總體壓縮比要比`baseline`要高.可是由於B幀須要參考前一幀和後一幀才能顯示,很容易形成卡頓狀況,由於萬一後面的幀沒有獲取到,致使前一幀已也不能顯示,因此在實際應用中(直播app),通常壓縮等級採用`baseline`.
gop : 這個我試着描述一下:由於除了I幀,其它幀都不能獨立渲染顯示,理論上只須要一個I幀其它所有是非I幀,這樣壓縮比最高,可是由於`(B幀和P幀)參考其餘幀`的緣由會有必定的偏差,當一段時間後,累計偏差會原來越大,致使圖像失真.解決辦法就是以一小段爲一個單元,每一個單元第一幀都是I幀;這樣,即便前面某一小段出了問題也不會影響後面的一小段,每個小段咱們稱做一個關gop.每一個gop的第一幀必定是關鍵幀,由於你的沒得參考;一般咱們設置gop的大小爲1s到3s,所以關鍵幀與關鍵幀之間的間隔就是1s的幀數(對應gop爲1s)到3s的幀數(對應gop爲3s),根據上面的定義,1s的幀數爲fps,所以關鍵幀間隔爲1*fps 到 3*fps.秒開的優化點之一就是減少gop大小,由於gop第一幀是關鍵幀,能獨立渲染出來,用戶進入直播間的時間是隨機的,爲確保用戶儘快拿到關鍵幀,儘快渲染出圖像;同時gop越小,關鍵幀數量就越多,帶寬消耗量就越大.
4.SGH264Packager 這個類負責對已經編碼好的H264幀數據進行打包處理,打包成符合RTMP協議格式的數據,而後才能發送.
SGAudioSource 這個類主要負責錄製音頻數據,輸出原始音頻幀,音頻的格式爲PCM格式.
SGAudioConfig 這個類是音頻配置相關的類,主要包括聲道數,碼率,採樣率的配置.
SGAACEncoder 這個類做用是將原始PCM音頻數據進行編碼壓縮,編碼結果爲AAC格式的音頻數據,這裏採用的是硬編碼.軟編碼的庫有faac.
SGAACPackager 這個了類做用是將編碼後的AAC格式數據大波按成符合RTMP協議的數據.
`SGStreamSession`這個類主要是用來創建tcp鏈接,底層數據的讀取和發送,以及鏈接狀態的回調,整個鏈接狀態貫穿整個項目,十分重要.
`SGRtmpSession`這個類主要與RTMP相關,主要負責與服務器交互,包括RTMP握手,指令的發送,對數據的進一步封裝,封裝成消息,而後再發送.指令有不少,說點重要的,好比握手完成之後,要從新協商消息大小(默認128字節),可是128字節過小,影響效率,通常都稍微改大點,好比這裏設置爲16kb,若是太大也很差,會致使帶寬浪費.這個類涉及到rtmp相關的比較多,比較難以理解,網上有開源的實現librtmp這個庫,能夠用這個來替代.
以上就是整個項目的基本結構,整個過程相似工廠流水線,能夠自行對各個模塊進行替換和研究.demo中註釋也很多,方便理解.是否是感受信息量有點大?可能有些地方說的不嚴謹,還望你們多多指正哈.
這個項目在去年7月份左右就寫完了,後來加了一些烏七八糟的東西,後來項目掛了,轉戰新項目(仍是直播).中間寫過幾篇入門文章,原本打算寫成一個系列文章,無奈太忙了,寫的不完整.新年伊始,趁着項目不太忙,趕忙整理了一下,純碼字,若是有任何問題能夠直接留言.
附上學習博客:
雷曉華博士的博客:這個是很是好的視音頻開發技術文章,喜歡視音頻的能夠看看 http://blog.csdn.net/leixiaohua1020
硬編碼的詳細說明: http://www.jianshu.com/p/a6530fa46a88