問題背景:
2017年的蘋果WWDC大會上,蘋果宣佈HEVC支持HLS,涉及了iOS、MacOS和tvOS等系統終端。蘋果之所以樂意這個事情,首先HLS就是他們家的,近些年一直把HLS致力於推成Web標準,其次蘋果手握大量H.265的專利,也不想谷歌的AOM對應的VP9標準一家獨大,HLS雖然延時有些大,但不可否認的,目前HLS是跨平臺做的最好的協議。
我們之所以想實現下這塊是因爲近年來:
1.視頻監控領域現在攝像頭和NVR對H.265支持的越來越好,很多設備後臺默認配置現在就是H.265,所以設備端(IPC和NVR)支持了,播放端也要跟着支持起來;
2.有實實在在的Web端播放需求,隨着目前設備上雲速度加快,無論是傳統行業還是消費類攝像頭,現在不僅僅在Native App播放,也有很多Web端播放需求。像在Web端分享一條鏈接就能在小程序上直播視頻就很有用,特別是和一些報警聯動起來,的確會方便不少;
3.視頻監控還有一個重要需求就是視頻回放功能,因爲事後查詢很必要,H.265相比較H.264在1080P分辨率下,要節省將近50%的帶寬。同時在畫質不變情況下,相比較H.264碼率也可以將近降低50%左右,所以無論從存儲和帶寬壓力和還是從畫質提升上,HEVC編碼都是非常剛需的。
綜上,HLS在分發視頻時不僅僅要支持H.264,也要支持HEVC,可以根據請求客戶端類型和設備碼流編碼格式進行匹配分發。
瞭解更多關於音視頻&IOT,歡迎關注公衆號:智媒黑板報
注:
1. HEVC即High Efficency Video Coding是AVC(Advance Video Codeing)的演進版本,其中HEVC又稱爲H.265,而AVC也叫做H.264,這兩個其實是一回事。至於爲啥有兩個別名,簡單來說視頻編碼標準以前主要由兩個國際化標準組織制定,其中H.26X系列,是由國際電信聯盟電信標準化部門ITU-T制定,AVC和HEVC主要是ISO國際標準化組織MPEG制定,從H.264開始,它兩聯合制定過視頻編碼標準,所以具有了兩個名字,但是實際是一回事。對於下一代標準也在去年正式定稿,其中ITU-T稱爲H.266,MPEG則稱爲VCC,感興趣的可以瞭解下視頻編碼的發展歷程。
支持原理:
HLS支持H.264已經比較成熟,就是將碼流進行MPEG-TS切片,然後通過HLS協議分發出去,客戶端通過解析m3u8裏面的TS片段對應的URL,然後不斷循環拉TS片段進行播放即可。目前在Web端,移動端支持的都非常好,系統無論是IOS還是Android 基本都可以原生支持播放。
HLS支持HEVC,採用的技術和H.264基本一樣,其中變化點主要是H.265的切片文件封裝格式是Fragmented Mp4簡稱FMP4,其次m3u8裏面的版本採用V7,服務端只要做好適配即可。
給三個鏈接,大家可以抓包學習協議細節:
HEVC HLS with fMP4:
http://bitmovin-a.akamaihd.net/content/dataset/multi-codec/hevc/stream_fmp4.m3u8
HEVC HLS with TS (not supported by Apple):
http://bitmovin-a.akamaihd.net/content/dataset/multi-codec/hevc/stream_ts.m3u8
HEVC MPEG-DASH:
http://bitmovin-a.akamaihd.net/content/dataset/multi-codec/hevc/stream.mpd
其中FMP4封裝格式是HTML5的Media Source Extensions支持的封裝格式,像B站的flv.js項目核心就是將FLV文件流轉封裝爲FMP4片段,然後通過該接口送給瀏覽器進行解碼播放,同時FMP4也是DASH協議的媒體文件封裝格式,它和MP4封裝格式非常類似,其實就是把大的MP4文件進行切片,每個切片都有它自己的meta數據,這樣就可以單獨播放並且特別適合網絡漸進式傳輸和漸進式播放,同時也方便支持Trick-Play播放。大體結構示意圖如下:
用MP4 Reader解析了一個FMP4文件:
支持要點:
1. 服務端支持HEVC和H.264相比有啥不同?
主要在拉到設備端原始碼流後,對NALU TYPE的判斷有不同。
其中收到H.264判斷方法如下:
int nalu_type = buf[0] & 0x1F;
其中nalu_type爲5則表示IDR幀,6表示SEI、7表示SPS、8表示PPS;
對HEVC的NALU類型判斷:
int nalu_type = (buf[0] & 0x7E)>>1;
//or
int nalu_type = (buf[0] >> 1) & 0x3F;
其中nalu_type19代表IDR幀,32位VPS、33位SPS、34爲PPS、39爲SEI;
網上這塊內容非常多,可以找來學習看下,不再贅述。
2. 基於Ffmpeg對MPEG-TS和FMP4的切片需要注意哪些?
封裝這塊直接基於Ffmpeg進行即可,簡單快捷,沒有必要自己完整實現這個。其中適配兩種封裝格式比較簡單,不清楚FFMPEG接口的可以參考下面鏈接進行學習,遇到需要兼容的問題是:
音頻部分:兼容MPEG-TS的ADTS和FMP4的ASC音視頻規格參數
音頻我們採用的AAC格式,對於FLV、MP4、FMP4和Mov封裝格式,封裝音頻AAC時需要去掉ADTS頭形成MPEG-4 Audio Specific Configuration bitstream,對於MPEG-TS封裝格式則需要加上ADTS頭,這是在音頻方面需要兼容的。
由於我們採用了FFmpeg進行打包和封裝MPEG-TS和FMP4片段,則藉助FFMPEG的Bitstream Filters即BSF機制即可。
音頻我們去掉ADTS頭形成ASC,一般就是將讀出來的AvPacket進行過濾器進行轉化下即可:
示例代碼:
AVBitStreamFilterContext*m_pAacbsf = = av_bitstream_filter_init("aac_adtstoasc");
視頻部分:
無論是H.264還是H.265,封裝格式都有兩種:AnnexB( Annex B of the ITU-T H.264 specification)和AVCC/HVCC格式,其中前者就是在每幀如SPS PPS IDR前面加上StartCode即00 00 00 01 或者00 00 01作爲視頻幀之間的分界符,後者則沒有StartCode,是將SPS、PPS和IDR幀封裝成Container(比如FLV的TAG,MP4的Box),再在前面加上該視頻幀的長度即可,一般長度用四字節表示。
視頻部分一般我們能拿到裸流,所以分別按照不同封裝格式的要求進行封裝即可。如果是MPEG-TS到FMP4的轉化則可以繼續使用FFMPEG的BSF機制進行碼流過濾:
注:
FFMPEG的 Bitstream Filters作用:
1.比特流濾波器對編碼後的數據進行操作(壓縮碼流)。
2.不進行解碼操作,但是支持比特流級別的修改。
3. M3U8要進行升級變化?
這塊我們只做了最簡單的適配和兼容,其中變化很小,其它字段如果你要用可以參考HLS協議規範自行添加。
HLS+FMP4 H.265切片的對應m3u8直播文件
有些媒體格式需要一個 format-specific sequence 來初始化一個 parser, 在 Media Segment 被 parse 之前. 這個字段叫做 Media Initialization Section, 通過 EXT-X-MAP tag 來指定,對於FMP4的初始化Init.mp4的下載鏈接則在這裏指定。
HLS+TS H.264切片的對應m3u8回放文件
HLS+FMP4 H.265切片的對應m3u8回放文件
4. 當前客戶端支持情況怎麼樣?
在蘋果產品家族,支持HLS+Fmp4方案,至少應該在 iOS 11, tvOS 11 及 macOS 10.13以後系統進行測試,安卓我們也進行了測試,其中在安卓8以上手機部分機型支持。總體而言,用系統自帶瀏覽器和微信上測試,IOS基本沒有啥問題,播放很順暢,對協議和媒體的兼容性也較好,但是安卓支持的不是很好,例如一些時間戳稍微有問題就不能播放或者黑屏。
5. H.264是否可以採用HLS+FMP4方案?
就切片和封裝格式而言,FMP4可以封裝H.265當然也可以封裝H.264,但是兼容性的問題主要是有些原生瀏覽器客戶端不能支持HLS+FMP4方案(包括解析HLS協議和解封裝FMP4),所以對於H.264我們依然採用老方案即HLS+MPEG-TS,對於H.265我們才採用HLS+FMP4.
6. 對於音視頻編碼要求和一些HLS的M3U8,還有什麼具體要求?
可能有些音視頻在播放過程中存在一定的問題,這時需要進一步參考HLS規範,看對一些細節方面的要求,可以參考下面鏈接。
https://developer.apple.com/documentation/http_live_streaming/hls_authoring_specification_for_apple_devices#//apple_ref/doc/uid/TP40016596-CH4-SW1
比較重要的幾條:
HEVC的Profile,Level和Tier必須小於或等於Main10的Profile,Level 5.0,High Tier;
HEVC 的幀率必須控制在60fps以內,實際我們一般就是30fps或者25fps;
HEVC的分辨率,我們設備端設置的爲720P或者1080P;
測試情況:
下面是一些我們的測試截圖:左圖iPhone8手機IOS13.3微信端測試,右圖Vivo安卓8.1自帶瀏覽器測試,同時我們在IOS12小程序和安卓10上測試也是可以的。
最後總結:
這篇文章主要講了HLS協議如果要支持對HEVC進行FMP4切片,大概會遇到哪些問題,已經這些問題的基本思路,同時給出了最簡單的實現效果。在調試過程中還要解決音視頻時間戳問題導致的黑屏、花屏和音畫不同步等問題。這些問題不屬於HLS的範疇,所以沒進行進一步詳細描述,同時也有些HLS的新字段沒啓用,這點要根據場景和需求來開發。
參考鏈接:
1.https://developer.apple.com/streaming/
2. https://www.jianshu.com/p/1bfe4470349b
3. https://tools.ietf.org/html/rfc8216
4.https://tools.ietf.org/html/draft-pantos-http-live-streaming-23#page-7
5. https://developer.apple.com/videos/play/wwdc2016/504/
6. https://blog.csdn.net/leixiaohua1020/article/details/39802913
7.http://www.ffmpeg.org/ffmpeg-bitstream-filters.html
往期文章回顧:
音視頻解封裝:MP4核心Box詳解及H264&AAC打包方案
個人轉載內容至朋友圈和羣聊天,無需特別申請版權許可。
引用轉載該訂閱號文章,註明文章來源即可。
記得右下角點“在看”,還可以關注該訂閱號,防止遺漏推送哦
今天就說這麼多,祝您工作順利!