常用的流媒體協議主要有 HTTP 漸進下載和基於RTSP/RTP 的實時流媒體協議,
這二種基本是完全不同的東西,目前比較方便又好用的我建議使用 HTTP 漸進下載的方法。
在這個中 apple 公司的 HTTP Live Streaming 是這個方面的代表。它最初是蘋果公司針對iPhone、iPod、iTouch和iPad等移動設備而開發的流.現在見到在桌面也有很多應用了, HTML5 是直接支持這個。
我們可以看看 HTTP Live Streaming 是怎麼樣工作的。平時的直播技術中,播放模式中必須等待整個文件下載完才行,在 HLS 技術中 Web 服務器向客戶端提供接近實時的音視頻流。但在使用的過程中是使用的標准的 HTTP 協議,所以這時,只要使用 HLS 的技術,就能在普通的 HTTP 的應用上直接提供點播和直播。
要詳細了解原理,我們先看看這個所需要的步驟。
視頻采集 ->編碼器 -> 流分割 -> 普通 web 服務(索引文件和視頻文件) -> 客戶端
內容准備的過程大約二種,一是視頻采集,編碼器首先將攝像機實時采集的音視頻數據壓縮編碼為符合特定標准的音視頻基本流,也可以拿編碼完了的文件,有一點必須保證,就是一定要使用H.264視頻和AAC音頻,因為發明這個的是蘋果公司,只支持這個。
然後給這些封裝成成為符合MPEG-2(MPEG 2 TS、MPEG2 PS之所以使用這個,主要是因為聲音和視頻會交織在一起,也會有關鍵幀來讓視頻可以直接播放).
流分割部分在這個中,比起 RTSP 之類和普通點播的最大不同,就是他會給 MPEG-2 分割成很多個 ts 的文件。分割過程大多是按時間來切,根據國外的資料,建議切 10s 一個的文件,如果碼流高可以 5 秒一次。
在分割還有一點不同,就是這時流分割器會生成一個含有指向這些小TS文件指針的索引文件,所以這個文件也必須在 web 服務器上,不能少。每多 10s 時,就會多一個 ts 文件,所以索引也會根著修改成最新的幾段視頻。
最後,這些切分了的小的一系列的 ts 文件,放到普通的 web 服務器中就行了。這時在 CDN 中也是一樣,因為請求這些文件會使用標准的 HTTP 協議。
索引文件後綴是.m3u8 ,索引文件采用擴展的M3U播放列表格式,其實就一文本。
內部的視頻的地址會是如下
http://media.example.com/s_96ksegment1.ts http://media.example.com/s_96ksegment2.ts http://media.example.com/s_96ksegment3.ts
所以這時可以直接做 Cache 和直接放到 Web 服務器中,簡單方便。 如果 MIME 的信息輸出不對的話,記的要修改這加入 ts 和 m3u8 的後綴支持
.m3u8 application/x-mpegURL .ts video/MP2T
最後就是客戶端,如果是 HTML 直接在 HTML5 中直接支持這種視頻可以使用如下標簽
如果是應用客戶端(Safari QuickTime之類),就得裝軟件來支持,客戶端會根據選擇的流的索引來下載文件,當下載了最少二段後開始播放。直接 m3u8 的索引結束。
另外,HTTP可以設計成的自適應比特率流,在不同網絡環境,選擇下載不同碼流的視頻。
所以整個 HTTP Live Streaming 無論是直播還是點播,都能做到近似實時的方式來進行流播放。理論的最小時延是每個切片的長.
HTTP Live Streaming(HLS)技術,並實現了一個HLS編碼器HLSLiveEncoder,C++寫的。
其功能是采集攝像頭與麥克風,實時進行H.264視頻編碼和AAC音頻編碼,並按照HLS的協議規范,生成分段的標准TS文件以及m3u8索引文件。
通過HLSLiveEncoder和第三方Http服務器(例如:Nginx),成功實現了HTTP Live Streaming直播,並在iphone上測試通過。
HTTP Live Streaming(HLS)是蘋果公司(Apple Inc.)實現的基於HTTP的流媒體傳輸協議,可實現流媒體的直播和點播,主要應用在iOS系統,為iOS設備(如iPhone、iPad)提供音視頻直播和點播方案。
HLS點播,基本上就是常見的分段HTTP點播,不同在於,它的分段非常小。要實現HLS點播,重點在於對媒體文件分段,目前有不少開源工具可以使用,只談HLS直播技術。
相對於常見的流媒體直播協議,例如RTMP協議、RTSP協議、MMS協議等,HLS直播最大的不同在於,直播客戶端獲取到的,並不是一個完整的數據流。
HLS協議在服務器端將直播數據流存儲為連續的、很短時長的媒體文件(MPEG-TS格式),而客戶端則不斷的下載並播放這些小文件,因為服務器端總是會將最新的直播數據生成新的小文件,這樣客戶端只要不停的按順序播放從服務器獲取到的文件,就實現了直播。
由此可見,基本上可以認為,HLS是以點播的技術方式來實現直播。由於數據通過HTTP協議傳輸,所以完全不用考慮防火牆或者代理的問題,而且分段文件的時長很短,客戶端可以很快的選擇和切換碼率,以適應不同帶寬條件下的播放。
不過HLS的這種技術特點,決定了它的延遲一般總是會高於普通的流媒體直播協議。
根據以上的了解要實現HTTP Live Streaming直播,需要研究並實現以下技術關鍵點
其中第1點和第2點,我之前的文章中已經提到過了,而最後一點,我們可以借助現有的HTTP服務器,所以,實現第3點和第4點是關鍵所在。
原文:http://www.cnblogs.com/haibindev/archive/2013/01/30/2880764.html
通過以上分析,實現HLS LiveEncoder直播編碼器,其邏輯和流程基本上很清楚了:分別開啟音頻與視頻編碼線程,通過DirectShow(或其他)技術來實現音視頻采集,隨後分別調用libx264和libfaac進行視頻和音頻編碼。兩個編碼線程實時編碼音視頻數據後,根據自定義的分片策略,存儲在某個MPEG-TS格式分段文件中,當完成一個分段文件的存儲後,更新m3u8索引文件。如下圖所示:
上圖中HLSLiveEncoder當收到視頻和音頻數據後,需要首先判斷,當前分片是否應該結束,並創建新分片,以延續TS分片的不斷生成。
需要注意的是,新的分片,應當從關鍵幀開始,防止播放器解碼失敗。核心代碼如下所示:
TsMuxer的接口也是比較簡單的。
m3u8,是HTTP Live Streaming直播的索引文件。
m3u8基本上可以認為就是.m3u格式文件,
區別在於,m3u8文件使用UTF-8字符編碼。
#EXTM3U m3u文件頭,必須放在第一行 #EXT-X-MEDIA-SEQUENCE 第一個TS分片的序列號 #EXT-X-TARGETDURATION 每個分片TS的最大的時長 #EXT-X-ALLOW-CACHE 是否允許cache #EXT-X-ENDLIST m3u8文件結束符 #EXTINF extra info,分片TS的信息,如時長,帶寬等
一個簡單的m3u8索引文件
在Nginx工作目錄下啟動HLSLiveEncoder,並用VLC播放器連接播放
通過iPhone播放的效果
蘋果官方對於視頻直播服務提出了 HLS (HTTP Live Streaming) 解決方案,該方案主要適用范圍在於:
首先,需要大家先對 HLS 的概念進行預覽。
HLS 的目的在於,讓用戶可以在蘋果設備(包括MAC OS X)上通過普通的網絡服務完成流媒體的播放。 HLS 同時支持流媒體的實時廣播和點播服務。同時也支持不同 bit 速率的多個備用流(平時根據當前網速去自適應視頻的清晰度),這樣客戶端也好根據當前網絡的帶寬去只能調整當前使用的視頻流。安全方面,HLS 提供了通過 HTTPS 加密對媒體文件進行加密並 對用戶進行驗證,允許視頻發布者去保護自己的網絡。
HLS 是蘋果公司QuickTime X和iPhone軟件系統的一部分。它的工作原理是把整個流分成一個個小的基於HTTP的文件來下載,每次只下載一些。當媒體流正在播放時,客戶端可以選擇從許多不同的備用源中以不同的速率下載同樣的資源,允許流媒體會話適應不同的數據速率。
在開始一個流媒體會話時,客戶端會下載一個包含元數據的extended M3U (m3u8) playlist文件,用於尋找可用的媒體流。
HLS只請求基本的HTTP報文,與實時傳輸協議(RTP)不同,HLS可以穿過任何允許HTTP數據通過的防火牆或者代理服務器。它也很容易使用內容分發網絡來傳輸媒體流。
蘋果對於自家的 HLS 推廣也是采取了強硬措施,當你的直播內容持續十分鐘 或者每五分鐘內超過 5 MB 大小時,你的 APP 直播服務必須采用 HLS 架構,否則不允許上架。(詳情)
Adobe Flash Media Server
Helix Universal Server
Nginx RTMP Module
其中輸入視頻源是由攝像機預先錄制好的。
之後這些源會被編碼 MPEG-4(H.264 video 和 AAC audio)格式然後用硬件打包到MPEG-2 的傳輸流中。
MPEG-4
MPEG-2
MPEG-2 傳輸流會被分散為小片段然後保存為一個或多個系列的 .ts 格式的媒體文件。
這個過程需要借助編碼工具來完成,比如 Apple stream segmenter。
純音頻會被編碼為一些音頻小片段,通常為包含 ADTS頭的AAC、MP3、或者 AC-3格式。
ADTS全稱是(Audio Data Transport Stream),是AAC的一種十分常見的傳輸格式。
一般的AAC解碼器都需要把AAC的ES流打包成ADTS的格式,一般是在AAC ES流前添加7個字節的ADTS header。
ES流- Elementary Streams (原始流):對視頻、音頻信號及其他數據進行編碼壓縮後 的數據流稱為原始流。原始流包括訪問單元,比如視頻原始流的訪問單元就是一副圖像的編碼數據。
同時上面提到的那個切片器(segmenter)也會創建一個索引文件,通常會包含這些媒體文件的一個列表,也能包含元數據。他一般都是一個.M38U 個hi的列表。列表元素會關聯一個 URL 用於客戶端訪問。然後按序去請求這些 URL。
服務端可以采用硬件編碼和軟件編碼兩種形式,其功能都是按照上文描述的規則對現有的媒體文件進行切片並使用索引文件進行管理。而軟件切片通常會使用 Apple 公司提供的工具或者第三方的集成工具。
媒體編碼器獲取到音視頻設備的實時信號,將其編碼後壓縮用於傳輸。而編碼格式必須配置為客戶端所支持的格式,比如 H.264 視頻和HE-AAC 音頻。當前,支持 用於視頻的 MPEG-2 傳輸流和 純音頻 MPEG 基本流。編碼器通過本地網絡將 MPEG-2 傳輸流分發出去,送到流切片器那裡。標准傳輸流和壓縮傳輸流無法混合使用。傳輸流可以被打包成很多種不同的壓縮格式,這裡有兩個表詳細列舉了支持的壓縮格式類型。
EXT-X-DISCONTINUITY
流切片器(通常是一個軟件)會通過本地網絡從上面的媒體編碼器中讀取數據,然後將著這些數據一組相等時間間隔的 小 媒體文件。雖然沒一個片段都是一個單獨的文件,但是他們的來源是一個連續的流,切完照樣可以無縫重構回去。
小
切片器在切片同時會創建一個索引文件,索引文件會包含這些切片文件的引用。每當一個切片文件生成後,索引文件都會進行更新。索引用於追蹤切片文件的有效性和定位切片文件的位置。切片器同時也可以對你的媒體片段進行加密並且創建一個密鑰文件作為整個過程的一部分。
如果已近有編碼後的文件(而不是編碼流),你可以使用文件切片器,通過它對編碼後的媒體文件進行 MPEG-2 流的封裝並且將它們分割為等長度的小片段。切片器允許你使用已經存在的音視頻庫用於 HLS 服務。它和流切片器的功能相似,但是處理的源從流替換流為了文件。
媒體片段是由切片器生成的,基於編碼後的媒體源,並且是由一系列的 .ts 格式的文件組成,其中包含了你想通過 MPEG-2 傳送流攜帶的 H.264 視頻 和 AAC /MP3/AC-3 音頻。對於純音頻的廣播,切片器可以生產 MPEG 基礎音頻流,其中包含了 ADTS頭的AAC、MP3、或者AC3等音頻。
.ts
通常由切片器附帶生成,保存為 .M3U8 格式,.m3u 一般用於 MP3 音頻的索引文件。 Note如果你的擴展名是.m3u,並且系統支持.mp3文件,那客戶的軟件可能要與典型的 MP3 playList 保持一致來完成 流網絡音頻的播放。
.M3U8
.m3u
下面是一個 .M3U8 的 playlist 文件樣例,其中包含了三個沒有加密的十秒鐘的媒體文件:
#EXT-X-VERSION:3 #EXTM3U #EXT-X-TARGETDURATION:10 #EXT-X-MEDIA-SEQUENCE:1 # Old-style integer duration; avoid for newer clients. #EXTINF:10, http://media.example.com/segment0.ts # New-style floating-point duration; use for modern clients. #EXTINF:10.0, http://media.example.com/segment1.ts #EXTINF:9.5, http://media.example.com/segment2.ts #EXT-X-ENDLIST
為了更精確,你可以在 version 3 或者之後的協議版本中使用 float 數來標記媒體片段的時長,並且要明確寫明版本號,如果沒有版本號,則必須與 version 1 協議保持一致。你可以使用官方提供的切片器去生產各種各樣的 playlist 索引文件,詳見媒體文件切片器
分布式系統是一個網絡服務或者一個網絡緩存系統,用於通過 HTTP 向客戶端發送媒體文件和索引文件。不用自定義模塊發送內容。通常僅僅需要很簡單的網絡配置即可使用。而且這種配置一般就是限制指定 .M38U 文件和 .ts 文件的 MIME 類型。詳見部署 HTTP Live Streaming
客戶端開始時回去抓取 索引文件(.m3u8/.m3u),其中用URL來標記不同的流。索引文件可以指定可用媒體文件的位置,解密的密鑰,以及任何可以切換的流。對於選中的流,客戶端會有序的下載每一個可獲得的文件。每一個文件都包含流中的連環碎片。一旦下載到足夠量的數據,客戶端會開始向用戶展示重新裝配好的媒體資源。
客戶端負責抓取任何解密密鑰,認證或者展示一個用於認證的界面,之後再解密需要的文件。
這個過程會一直持續知道出現 結束標記 #EXT-X-ENDLIST。如果結束標記不出現,該索引就是用於持續廣播的。客戶端會定期的加載一些新的索引文件。客戶端會從新更新的索引文件中去查找加密密鑰並且將關聯的URL加入到請求隊列中去。
#EXT-X-ENDLIST
使用 HLS 需要使用一些工具,當然大部分工具都是服務器端使用的,這裡簡單了解一下就行,包括 media stream segmenter, a media file segmenter, a stream validator, an id3 tag generator, a variant playlist generator.這些工具用英文注明是為了當你在蘋果開發中心中尋找時方便一些。
通常包含 Live 和 VOD (點播)兩種
點播VOD的特點就是可以獲取到一個靜態的索引文件,其中那個包含一套完整的資源文件地址。這種模式允許客戶端訪問全部節目。VOD點播擁有先進的下載技術,包括加密認證技術和動態切換文件傳輸速率的功能(通常用於不同分辨率視頻之間的切換)。
Live 會話就是實時事件的錄制展示。它的索引文件一直處於動態變化的,你需要不斷的更新索引文件 playlist 然後移除舊的索引文件。這種類型通過向索引文件添加媒體地址可以很容易的轉化為VOD類型。在轉化時不要移除原來舊的源,而是通過添加一個#ET-X-ENDLIST 標記來終止實時事件。轉化時如果你的索引文件中包含 EXT-X-PLAYLIST-TYPE 標簽,你需要將值從EVENT 改為 VOD。
#ET-X-ENDLIST
EXT-X-PLAYLIST-TYPE
EVENT
VOD
ps:自己抓了一個直播的源,從索引中看到的結果是第一次回抓到代表不同帶寬的playList(抓取地址:http://dlhls.cdn.zhanqi.tv/zqlive/34338_PVMT5.m3u8)
http://dlhls.cdn.zhanqi.tv/zqlive/34338_PVMT5.m3u8
#EXTM3U #EXT-X-VERSION:3 #EXT-X-STREAM-INF:PROGRAM-ID=1,PUBLISHEDTIME=1453914627,CURRENTTIME=1454056509,BANDWIDTH=700000,RESOLUTION=1280x720 34338_PVMT5_700/index.m3u8?Dnion_vsnae=34338_PVMT5 #EXT-X-STREAM-INF:PROGRAM-ID=1,PUBLISHEDTIME=1453914627,CURRENTTIME=1454056535,BANDWIDTH=400000 34338_PVMT5_400/index.m3u8?Dnion_vsnae=34338_PVMT5 #EXT-X-STREAM-INF:PROGRAM-ID=1,PUBLISHEDTIME=1453914627,CURRENTTIME=1454056535,BANDWIDTH=1024000 34338_PVMT5_1024/index.m3u8?Dnion_vsnae=34338_PVMT5
這裡面的鏈接不是視頻源URL,而是一個用於流切換的主索(下面會有介紹)引我猜想是需要對上一次的抓包地址做一個拼接
組合的結果就是:http://dlhls.cdn.zhanqi.tv/zqlive/34338_PVMT5_1024/index.m3u8?Dnion_vsnae=34338_PVMT5(純屬小學智力題。。。)將它作為抓取地址再一次的結果
http://dlhls.cdn.zhanqi.tv/zqlive/34338_PVMT5_1024/index.m3u8?Dnion_vsnae=34338_PVMT5
#EXTM3U #EXT-X-VERSION:3 #EXT-X-MEDIA-SEQUENCE:134611 #EXT-X-TARGETDURATION:10 #EXTINF:9.960, 35/1454056634183_128883.ts?Dnion_vsnae=34338_PVMT5 #EXTINF:9.960, 35/1454056644149_128892.ts?Dnion_vsnae=34338_PVMT5 #EXTINF:9.960, 35/1454056654075_128901.ts?Dnion_vsnae=34338_PVMT5
同理,繼續向下抓:(拼接地址:http://dlhls.cdn.zhanqi.tv/zqlive/34338_PVMT5_1024/index.m3u8?Dnion_vsnae=34338_PVMT5/35/1454056634183_128883.ts?Dnion_vsnae=34338_PVMT5/36/1454059958599_131904.ts?Dnion_vsnae=34338_PVMT5) 抓取結果:
http://dlhls.cdn.zhanqi.tv/zqlive/34338_PVMT5_1024/index.m3u8?Dnion_vsnae=34338_PVMT5/35/1454056634183_128883.ts?Dnion_vsnae=34338_PVMT5/36/1454059958599_131904.ts?Dnion_vsnae=34338_PVMT5
#EXTM3U #EXT-X-VERSION:3 #EXT-X-MEDIA-SEQUENCE:134984 #EXT-X-TARGETDURATION:10 #EXTINF:9.280, 36/1454059988579_131931.ts?Dnion_vsnae=34338_PVMT5 #EXTINF:9.960, 36/1454059998012_131940.ts?Dnion_vsnae=34338_PVMT5 #EXTINF:9.960, 36/1454060007871_131949.ts?Dnion_vsnae=34338_PVMT5
相比於第二次又獲取了一個片段的索引,而且只要是第二次之後,資源地址都會包含 .ts,說明裡面是有視頻資源URL的,不過具體的截取方法還是需要查看前面提到的IETF的那套標准的HLS的協議,利用裡面的協議應該就能拼接出完整的資源路徑進行下載。反正我用蘋果自帶的MPMoviePlayerController直接播放是沒有問題的,的確是直播資源。與之前說過的蘋果自帶的QuickTime類似,都遵循了HLS協議用於流媒體播放。而每次通過拼接獲取下一次的索引,符合協議裡提到的不斷的更替索引的動作。
如果內容需要加密,你可以在索引文件中找到密鑰的相關信息。如果索引文件中包含了一個密鑰文件的信息,那接下來的媒體文件就必須使用密鑰解密後才能解密打開了。當前的 HLS 支持使用16-octet 類型密鑰的 AES-128 加密。這個密鑰格式是一個由著在二進制格式中的16個八進制組的數組打包而成的。
加密的配置模式通常包含三種:
理論上,不定期的碎片個數生成密鑰會更安全,但是定期的生成密鑰不會對系統的性能產生太大的影響。
你可以通過 HTTP 或者 HTTPS 提供密鑰。也可以選擇使用你自己的基於會話的認證安排去保護發送的key。更多詳情可以參考通過 HTTPS 安全的提供預約
密鑰文件需要一個 initialization vector (IV) 去解碼加密的媒體文件。IV 可以隨著密鑰定期的改變。
HTTPS通常用於發送密鑰,同時,他也可以用於平時的媒體片段和索引文件的傳輸。但是當擴展性更重要時,這樣做是不推薦的。HTTPS 請求通常都是繞開 web 服務緩存,導致所有內容請求都是通過你的服務進行轉發,這有悖於分布式網絡連接系統的目的。
處於這個原因,確保你發送的網絡內容都明白非常重要。當處於實況廣播模式時索引文件不會像分片媒體文件一樣長時間的被緩存,他會動態不停地變化。
如果你的視頻具備流切換功能,這對於用戶來說是一個非常棒的體驗,處於不同的帶寬、不同的網速播放不同清晰度的視頻流,這樣只能的流切換可以保證用戶感覺到非常流暢的觀影體驗,同時不同的設備也可以作為選擇的條件,比如視網膜屏可以再網速良好的情況下播放清晰度更高的視頻流。
這種功能的實現在於,索引文件的特殊結構
有別於普通的索引,具備流熱切換的索引通常由主索引和鏈接不同帶寬速率的資源的子索引,由子索引再鏈接對引得.ts視頻切片文件。其中主索引只下載一次,而子索引則會不停定期的下載,通常會先使用主索引中列出的第一個子索引,之後才會根據當時的網絡情況去動態切換合適的流。客戶端會在任何時間去切換不同的流。比如連入或者退出一個 wifi 熱點。所有的切換都會使用相同的音頻文件(換音頻沒多大意思相對於視頻)在不同的流之間平滑的進行切換。 這一套不同速率的視頻都是有工具生成的,使用variantplaylistcreator 工具並且為 mediafilesegmenter 或者mediastreamsegmenter 指定 -generate-variant-playlist 選項,詳情參考 下載工具
variantplaylistcreator
mediafilesegmenter
mediastreamsegmenter
概念先寫到這吧,前面的知識夠對HSL的整體結構做一個初步的了解。
Demo配置原理:
1、 需要導入第三方庫:ASIHttpRequest,CocoaHTTPServer,m3u8(其中ASI用於網絡請求,CocoaHTTPServer用於在ios端搭建服務器使用,m3u8是用來對返回的索引文件進行解析的)
2、導入系統庫:libsqlite3.dylib、libz.dylib、libxml2.dylib、CoreTelephony.framework、SystemConfiguration.framework、MobileCoreServices.framework、Security.framework、CFNetwork.framework、MediaPlayer.framework
3、添加頭文件
YCHLS-Demo.h
4、demo介紹
原理:
上面是HLS中服務器存儲視頻文件切片和索引文件的結構圖 整個流程就是:
總結: 整個Demo並不只是讓我們搭建一個Hls服務器或者一個支持Hls的播放器。目的在於了解Hls協議的具體實現,以及服務器端的一些物理架構。通過Demo的學習,可以詳細的了解Hls直播具體的實現流程。
開啟本地服務器:
- (void)openHttpServer { self.httpServer = [[HTTPServer alloc] init]; [self.httpServer setType:@"_http._tcp."]; // 設置服務類型 [self.httpServer setPort:12345]; // 設置服務器端口 // 獲取本地Library/Cache路徑下downloads路徑 NSString *webPath = [kLibraryCache stringByAppendingPathComponent:kPathDownload]; NSLog(@"-------------\\nSetting document root: %@\\n", webPath); // 設置服務器路徑 [self.httpServer setDocumentRoot:webPath]; NSError *error; if(![self.httpServer start:&error]) { NSLog(@"-------------\\nError starting HTTP Server: %@\\n", error); }
視頻下載:
- (IBAction)downloadStreamingMedia:(id)sender { UIButton *downloadButton = sender; // 獲取本地Library/Cache路徑 NSString *localDownloadsPath = [kLibraryCache stringByAppendingPathComponent:kPathDownload]; // 獲取視頻本地路徑 NSString *filePath = [localDownloadsPath stringByAppendingPathComponent:@"XNjUxMTE4NDAw/movie.m3u8"]; NSFileManager *fileManager = [NSFileManager defaultManager]; // 判斷視頻是否緩存完成,如果完成則播放本地緩存 if ([fileManager fileExistsAtPath:filePath]) { [downloadButton setTitle:@"已完成" forState:UIControlStateNormal]; downloadButton.enabled = NO; }else{ M3U8Handler *handler = [[M3U8Handler alloc] init]; handler.delegate = self; // 解析m3u8視頻地址 [handler praseUrl:TEST_HLS_URL]; // 開啟網絡指示器 [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; } }
播放本地視頻:
- (IBAction)playVideoFromLocal:(id)sender { NSString * playurl = [NSString stringWithFormat:@"http://127.0.0.1:12345/XNjUxMTE4NDAw/movie.m3u8"]; NSLog(@"本地視頻地址-----%@", playurl); // 獲取本地Library/Cache路徑 NSString *localDownloadsPath = [kLibraryCache stringByAppendingPathComponent:kPathDownload]; // 獲取視頻本地路徑 NSString *filePath = [localDownloadsPath stringByAppendingPathComponent:@"XNjUxMTE4NDAw/movie.m3u8"]; NSFileManager *fileManager = [NSFileManager defaultManager]; // 判斷視頻是否緩存完成,如果完成則播放本地緩存 if ([fileManager fileExistsAtPath:filePath]) { MPMoviePlayerViewController *playerViewController =[[MPMoviePlayerViewController alloc]initWithContentURL:[NSURL URLWithString: playurl]]; [self presentMoviePlayerViewControllerAnimated:playerViewController]; } else{ UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Sorry" message:@"當前視頻未緩存" delegate:self cancelButtonTitle:@"確定" otherButtonTitles:nil, nil]; [alertView show]; } }
播放在線視頻
- (IBAction)playLiveStreaming { NSURL *url = [[NSURL alloc] initWithString:TEST_HLS_URL]; MPMoviePlayerViewController *player = [[MPMoviePlayerViewController alloc] initWithContentURL:url]; [self presentMoviePlayerViewControllerAnimated:player]; }
也就是說你可以吧ADTS這個頭看作是AAC的frameheader。
ADTS 頭中相對有用的信息采樣率、聲道數、幀長度。
想想也是,我要是解碼器的話,你給我一堆得AAC音頻 ES流我也解不出來。
每一個帶ADTS頭信息的AAC流會清晰的告送解碼器他需要的這些信息。
一般情況下ADTS的頭信息都是7個字節,7*8 = 56 個bit,分為2部分:
固定頭 adts_fixed_header(); 28bit
可變頭 adts_variable_header(); 28bit
其中:
syncword:同步頭 總是0xFFF,12 bit, all bits must be 1,代表著一個ADTS幀的開始
ID:MPEG Version: 0 for MPEG-4, 1 for MPEG-2
Layer:always: '00'
profile:表示使用哪個級別的AAC,有些芯片只支持AAC LC 。
在MPEG-2 AAC中定義了3種:
sampling_frequency_index:
表示使用的采樣率下標,通過這個下標在Sampling Frequencies[ ]數組中查找得知采樣率的值。
There are 13 supported frequencies:
frame_length:
一個ADTS幀的長度包括ADTS頭和AAC原始流.
adts_buffer_fullness:0x7FF 說明是碼率可變的碼流
如果是通過嵌入式高清解碼芯片做產品的話,一般情況的解碼工作都是由硬件來完成的。所以大部分的工作是把AAC原始流打包成ADTS的格式,然後丟給硬件就行了。
通過對ADTS格式的了解,很容易就能把AAC打包成ADTS。我們只需得到封裝格式裡面關於音頻采樣率、聲道數、元數據長度、aac格式類型等信息。然後在每個AAC原始流前面加上個ADTS頭就OK了。
貼上ffmpeg中添加ADTS頭的代碼,就可以很清晰的了解ADTS頭的結構: