這裏是微軟的官方介紹,mss和hls出現都比較久了,應用的也非常多。
1、微軟SmoothStreamIndexing協議規定了四種消息:
(The IIS Smooth StreamIndexing Transport Protocol defines four types of messages: )
1.Manifest Request
2.Manifest Response
3.Fragment Request
4.Fragment Response
把HTTP cache proxies 的角色放進去:
不同的client,同樣請求同一塊fragment,第二次直接從cache返回。
自己搭建了一個SS web server,抓包看了一下消息的內容,以BigBuckBunny舉例吧。抓包軟件最開始用的wireshark,可是不知道爲什麼總是收不到本來期望能收到的包,後來改用Windows network monitor,很容易上手很好用,還會列出哪些消息是在哪些進程裏面。
1. Manifest request
在瀏覽器中輸入http://[server_name]/[virtual_addr]/bigbuckbunny.ism/manifest,client向server發送HTTP請求。
協議中要求的(manifest/fragment request):HTTP方法必須是GET,HTTP協議版本必須是HTTP/1.1
2. Manifest response
Server 將bigbuckbunny.ismc 發回給client,可以在瀏覽器中顯示出來。(用了另外的URL展示)
協議中要求的(manifest/fragment response):HTTP 狀態碼必須是200,HTTP協議版本必須是HTTP/1.1。payload中就是ismc文件的內容了。
這時如果再次請求(在瀏覽器中刷新頁面),得到的響應卻是304:
304 not modified,數據內容跟上一次比沒有變化。這個應該跟cache-control的值有關,沒研究過不深究了。這篇先不研究manifest文件的具體element和attribute,只看消息交互。
3. Fragment request
在瀏覽器中輸入:http://[server_name]/[virtual_add]/SmoothStreamingPlayer.html
server的響應:
client收到的第一個響應,會是manifest,然後才能根據manifest裏面的信息來構建fragment request。
URL裏面包含了具體的QualityLevels 和Fragments 值。client向server請求bit rate是2962000,fragments偏移是400000000的video chunk。
4. Fragment response
由於之前已經執行過,播放過了,所以得到的響應時304。Server說還是老數據,自己從cache裏面拿吧。
5. Continue
下一個Fragment request 請求的offset是420000000。
終於等到一個不是304的響應。
返回的狀態碼是200,類型是video/mp4。HTTPPayloadLine是空的,內容包含在下一個響應中:
一般在200 ok響應之後,要接着發好幾個帶有HTTPPayloadLine的包,見下圖,一對一的都是304響應。
用Microsoft Network Monitor 抓包,協議列,請求都是PCCRTP,在wireshark中直接是HTTP。PCCRTP:Peer Content Caching and Retrieval: HTTP extension.
有時候client會收到 412 響應,代表fragment not yet available。
1. Manifest Request
ManifestRequest = [ "/" VirtualPath ] "/" PublishingPointName "." "ism" / VendorExtensionFileExtension "/" "Manifest"
注意上面的式子中有一個斜槓是沒有引號的,也就是VendorExtensionFileExtension前面那個,也就是說這個斜槓不是要出現在Request中的,這個斜槓表示或者的意思。
也就是說,"."後面既可以跟ism也可以跟提供商自己的擴展名,"ism"跟VendorExtensionFileExtensions是或的關係。
看來ManifestRequest中必須包含".",就是"/" "Manifest"的前一級必須包含"."。這樣看來我自己在lighttpd上搞的目錄實際是不符合協議的。
http://ak.xbox.c4assets.com/ondemand/CH4_29_02_29_65973003001001_001_SQ.ism/Manifest
這個URL就是一個Request Manifest。
2. Manifest Response (Manifest 文件的格式)
Manifest文件是個XML文本,遵循XML標準。注:XML 標籤對大小寫敏感,XML 的屬性值須加引號。
Manifest的根元素必須是<SmoothStreamIndexingMedia>,這個元素的意思是“客戶端爲了播放節目(Presentation)所需的所有元數據”。
這個元素有4個屬性:MajorVersion,MinorVersion,TimeScale,Duration。
2011版新加入3個屬性:IsLive,LookaheadCount ,DVRWindowLength。這三個屬性都是直播相關的。
其中除了TimeScale之外都是必須的,TimeScale之所以不是必須,是因爲他有默認值————10000000(1個1,7個0)。
TimeScale的意思是每秒鐘Duration屬性的增量,Duration就是節目長度的意思。也就是每一秒,Duration加幾,TimeScale就是個這數。
可以理解爲TimeScale是劃分時間的粒度,10000000代表每秒鐘節目時長加10的7次方那麼多,反過來理解就是,每10的負7次方秒,節目長度就要加1。
默認值把視頻劃分的夠細的啊。(比hls分得更細,hls是官方推薦的10s)
另外兩個屬性,描述版本用的:MajorVersion必須等於2,MajorVersion必須等於0,這沒啥好說的,規定。
這個元素屬性挺少的,到這兒就說完了。下邊說說這個元素的內容:
內容=[ ProtectionElement S?] 1* StreamIndexElement 注: *元素 表示0或多個元素,1*元素 表示1或多個元素,2*3元素 表示2或3個元素。
上面是協議裏寫的,翻譯成漢語就是,由一個可選的<Protection>元素和若干個<StreamIndex>元素組成。接下來的任務就是看看這倆元素分別是啥了。
先看<StreamIndex>元素。
<StreamIndex>元素的意思“客戶端爲了播放Stream所需的所有元數據”,跟前邊<SmoothStreamIndexingMedia>比,把節目(Presentation)換成了Stream。
其實一個節目一般可以分爲兩個Stream,即視頻流和音頻流。以後就管Stream叫“流”了,漢語方便。
這 個元素有以下這12個屬 性:Type,Subtype,TimeScale,Name,Chunks,QualityLevels,Url,MaxWidth,MaxHeight,DisplayWidth,DisplayHeight,VendorExtension。
其 中Type是必須的,並且,如果這個<StreamIndex>元素中沒有插入<QualityLevel>元素,那麼這3個元 素也是必須的:NumberOfFragments, NumberOfTracks,Url。當然,常見的場景是<StreamIndex>元素中都插入 了<QualityLevel>元素。
下邊來看看這12個屬性都什麼意思:
Type:流的類型,可以是video, audio, or text。text有點特殊和不常見,今天先不說。
MaxWidth, MaxHeight, DisplayWidth, DisplayHeight:這4個屬性就是字面意思。注意只有當Type屬性的值爲video時,這4個屬性纔可以出現。
Subtype:當Type屬性的值爲text時,這個屬性必須出現。這個屬性稍微複雜並不常用,今天先不說。
Name :流的名稱,沒啥好說的。
Chunks :流中Fragment的個數,Fragment就是分片。
QualityLevels :流中Track的個數,目前理解是,一個碼率就叫一個Track(對於視頻)。協議裏說Track元素的名字就是QualityLevel。
Url:客戶端用以產生FragmentRequest的格式,這個屬性的值必須是UrlPattern:
UrlPattern = QualityLevels("{bitrate}" / "{Bitrate}" ["," "{CustomAttributes}"] )"/"Fragments(TrackName "=" "{start time}" / "{start_time}" )
TimeScale:這個流中的TimeScale,跟前面的TimeScale具有相同的意義。
VendorExtension:內容提供商自己開發擴展用。
下邊說說這個元素的內容:
StreamContent = 1*(TrackElement S?) *(StreamFragment S?)
翻譯成漢語就是,此元素的內容是一到多個Track元素(<QualityLevel>)與0到多個StreamFragment元素(<c>)組成的。下面正好開始看這兩個元素。
<QualityLevel>元素(Track元素)的意思是“客戶端爲了播放Track所需的所有元數據”,跟前邊比,把stream換成了track。
這 個元素有以下這些屬 性:Index,Bitrate,MaxWidth,MaxHeight,CodecPrivateData,SamplingRate,Channels,BitsPerSample,PacketSize,AudioTag,NALUnitLengthField
這些屬性都是啥意思今天先不說。
這個元素的內容如下:
TrackContent = CustomAttributes?
這個內容協議裏描述的沒太看明白,而且也不咋重要,今天先不說。
<c>元素(StreamFragment元素)的意思是“分片(Fragments)元數據的集合”。這個元素很重要,今天好好說說。
這個元素有3個屬性:n,d,t。其中d和t至少要出現一個。
n:分片在流中的序號,隨時間遞增。非必須屬性。
d:(FragmentDuration)分片的持續時間。由包含這個分片的流的TimeScale屬性的值顯示的或隱含的指明。如果d屬性沒有出現,那麼他的隱含值要由客戶端按如下規則計算:
用本<c>元素的t屬性的值減去後面那個<c>元素的t屬性的值。翻譯成漢語就是,當前分片的開始時間減去後面分片的開時間。
如果一個分片沒有後續分片,那麼他的d屬性隱含值爲0.(注:這裏協議原文貌似寫的有問題,我覺着只有按我這麼理解才能解釋通)
t:(FragmentTime)分片(開始)時間(點)。由包含這個分片的流的TimeScale屬性的值顯示的或隱含的指明。如果t屬性沒有出現,那麼他的隱含值要由客戶端按如下規則計算:
用本<c>元素前面那個<c>元素的d的值加上t的值。
如果一個分片前面沒有其他分片,那麼他的t屬性隱含值爲0.
下邊是個例子:
<c t = "0" d = "19680000" />
<c t = "19680000" d="19680000" />
<c t = "39360000" d="19680000" />
爲了支持直播,新版協議給視頻分片加了兩個新的box(type=uiid):tfxdBox(本分片的t和d封裝在裏面),tfrfBox(下一個或幾個分片的t和d封裝在裏面)。