[時間:2016-06] [狀態:Open]
ASF,全稱Advanced Systems Format,是由微軟提出的開放封裝格式標准。ASF是微軟公司Windows Media的核心。這是一種包含音頻、視頻、圖像、控制命令腳本、JPEG、二進制文件的數據格式。
目前常見遵循這種標准的數據封裝格式化的后綴是.asf、.wma、.wmv。
詳細介紹建議參考
- Overview of the ASF Format https://msdn.microsoft.com/en-us/library/windows/desktop/dd757562\v=vs.85).aspx
- Advanced Systems Format-wiki
- ASF-百度百科
學習ASF容器格式的目標
讀完本文,你應該能夠回答下面問題:
- ASF中數據是如何組織的?
- 該容器包含哪些編碼格式的數據?這些數據是如何存儲的?
- 該容器包含哪些元數據信息?包含哪些節目信息?
- 對於支持多節目的容器格式,如何找到對應的音頻流、視頻流、字幕流?
- 如何確定該容器的節目播放時長?
- 如何從該容器中提取音頻、視頻、字幕數據,並交給解碼器解碼,有時間戳否?
- 該容器是否支持seek?有哪些輔助信息?
- 是否支持直接流化?
- 哪里可以找到該容器格式最標准的文檔資料?
- 有哪些可用的工具,方便分析容器格式異常或者錯誤?
1. ASF文件整體結構
ASF Object
ASF文件是有多個ASF Object構成,換個說法,ASF Object是ASF的最小組成單元。其結構如下:
Field | Size(byte) |
---|---|
Object GUID | 16 |
Object Size | 8 |
Payload | varies |
ASF object 是16個字節的GUID代表這個Object的類型,Object的類型有很多種。8個字節的 Size 代表這個Object的大小(=24+負載長度),緊接着就是Object的內容(負載)。
所有ASF Object和結構都是以小端字節序存儲的。
ASF文件頂層視圖
ASF文件通常包含三類ASF Object: Header Object、Data Object和Index Object。
- Header Object是必須位於ASF文件起始位置,一個ASF文件中有且僅有一個Header Object。
- Data Object必須緊跟在Header Object之后,有且僅有一個。
- Index Object是可選的,該對象主要提供了基於時間點的ASF隨機訪問機制(快速seek);如果Index Object存在必須是ASF文件最后一個Object。
實際結構類似下圖:
==================
Header Object
------------------
Data Object
------------------
------------------
Index Object
===================
ASF文件的解析過程中可以忽略任何無法識別的ASF Object。所有新定義或添加的ASF Object必須位於Data Object之后,Index Object之前(即上面的Other Object)。
Header Object
Header Object以ASF_Header_Object GUID object開頭,是唯一可以包含ASF Ojbect的頂層結構。它包含着一系列的ASF object,分別代表着不同類型的ASF object,由GUID區分;它們提供了關於ASF DATA 的一些解釋信息,如音視頻類型及詳細信息等, Header Object通常包含如下類型的object:
- File Properties Object:包含整個文件屬性,如文件大小、時長等
- Stream Properties Object:包含Stream特性,如音視頻格式、類型、PID等
- Header Extension Object:包含用於ASF后向兼容的機制
- Content Description Object:包含內容目錄信息
- Script Command Object:包含用於回放時執行的腳本命令
- Marker Object:Provides named jump points within a file
一般情況, Header Object必須包含1個File Properties Object, 1個Header Extension Object, 和至少一個Stream Properties Object。
並且Header Object中Object出現的順序是不固定的。
一類比較簡單的Header Object構成如下(音視頻Stream各一個):
========================
File Properties Object
------------------------
Header Extenstion Object
------------------------
Stream Properties Object
------------------------
Stream Properties Object
========================
Index Objects
Index Objects包含兩種變體:Simple Index Object和Index Object。在ASF文件中Index Object可以有多個。
Simple Index Object包含視頻流的基於時間的索引序列,其中索引之間的間隔是固定的,通常是1s。標准規定,對於ASF文件中的任意視頻流必須有一個對應的Simple Index Object,而且順序是必須以stream number出現。
Index Object指的是Index Object,Media Object Index Object和Timecode Index Object。Index Object類似Simple Index Object,保存固定時間間隔的索引序列,但可以包括非視頻流;Media Object Index Object是逐幀的索引機制,支持逐幀seek。Timecode Index Object是基於時間碼(timecode)的seek機制,主要針對有時間碼的內容。
更具體的內容建議參考“ASF Specification” section 7.3。
2. 如何解析ASF Data Object?
Data Object(GUID:ASF_Data_Object)是由多個Data Packet構成。這些Data Packet是按照發送時間順序排列的,並且可以來自多個不同的stream。
Data Object包含64位的Total Data Packets字段,用於說明當前文件包含的Data Packet數目。
Data Packet通常是等長的,長度固定(具體長度在File Properties Object中的Data Packet Size字段)。
一個Data Packet中可以包含一個或多個Payload。
Data Packet結構
ASF Data Packet的結構如下圖:
============================
Error Correction Data
----------------------------
Payload Parsing Info
----------------------------
Playload Data
----------------------------
Padding Data
============================
or
============================
Error Correction Data
----------------------------
Opaque Data
----------------------------
Padding Data
============================
其中Error Correction Data和Padding Data都是可選的,不一定每一個Data Packet都存在這些數據。
由於Error Correction Data是可選的,如何區分ASF Data Packet開始位置是Error Correction Data還是Payload Parsing Info呢?主要區分在於Data Packet中第一個字節的最高位是否的值(Error Correction Present),如果為1,則是Error Correction Data,否則是Playload Parsing Info。不管是那種數據,其中都存儲了數據長度,可以按照ASF Specification中的section 5.2解析。
其中Error Correction Data中有一個字段Opaque Data Present,表示當前Data Packet結構是第二種,負載中有Opaque Data。
Payload Parsing & data解析
Payload Parsing Info段的長度不是固定的,需要按照其實際字段含義解析。其中需要特別關注的是Multiple Payloads Present、Padding Length、Send Time字段。在解析Payload data時會參考這些字段。
一個Playload Data可以包含一個或多個Payload,需要根據Multiple Payloads Present的值判斷,如果該值為1,表示包含多個Payload。
Payload結構
ASF中定義Payload如下:
Field name | Filed Type | Size(bits) |
---|---|---|
Stream Number | BYTE | 8 |
Media Object Number | BYTE/WORD/DWORD | 0/8/16/32 |
Offset Into Media Object | BYTE/WORD/DWORD | 0/8/16/32 |
Relicated Data Length | BYTE/WORD/DWORD | 0/8/16/32 |
Replicated Data | BYTE | varies |
Payload Data | BYTE | varies |
其中Stream Number的最高位表示是否是關鍵幀(key frame),這也就限制了ASF最大能支持128個Stream Media。
另外,如果Replicated Data Length長度為1,表示payload是壓縮格式的,具體建議參考ASF Specification的section 5.2.3。
Replicated Data中包含一個DWORD用於標識Payload長度,緊跟一個DWORD表示時間戳信息(以毫秒為單位),其他數據是附加的media sample信息。
對於Multiple Payloads Present為0的情況,可以直接通過Payload的結構解析出負載數據信息。
多個Payload數據解析
理解單個Payload解析之后,多Payload解析是參考Payload Data第一個字節的信息來解析的。其定義如下:
Filed name | Field type | Size(bits) |
---|---|---|
Playload Flags | BYTE | 8 |
==Number of Payloads | - | 6(LSDB) |
==Payload Length Type | - | 2 |
Payloads | - | varies |
這里的Payload的定義包含了Payload Length字段,定義結構如下:
Field name | Filed Type | Size(bits) |
---|---|---|
Stream Number | BYTE | 8 |
Media Object Number | BYTE/WORD/DWORD | 0/8/16/32 |
Offset Into Media Object | BYTE/WORD/DWORD | 0/8/16/32 |
Relicated Data Length | BYTE/WORD/DWORD | 0/8/16/32 |
Replicated Data | BYTE | varies |
Payload Length | BYTE/WORD/DWORD | 8/16/32 |
Payload Data | BYTE | varies |
填充字節主要為了保證ASF Data Packet的定長,通常填充0數據。
3. 如何解析ASF MetaData?
ASF中有五種Object用於存儲Metadata,每個Metadata屬性存儲的順序按照下面規則選擇:
- Content Description Object:可用於存儲長度小於65535字節、與Stream無關、與語言無關的屬性值,包括:Title, Author, Copyright, Description, and Rating
- Content Branding Object:可用於存儲與Stream無關、與語言無關的以下屬性值:Banner Image Type, Banner Image Data, Banner Image URL, and Copyright URL
- Extended Content Description Object:可用於存儲任意命名的屬性值,該屬性值需要是下列類型的一種,並且長度小於65535,與Stream無關、與語言無關:WCHAR strings, BYTE arrays, Boolean values, DWORDs, QWORDs, or WORDs
- Metadata Object:可用於存儲與語言無關的任意名稱的屬性。允許數據按照Extended Content Description Object格式存儲。屬性可以用於描述特定stream,但長度必須不超過65535字節。
- Metadata Library Object:可用於存儲任意名稱的屬性。允許數據按照Extended Content Description Object格式或者GUID數據類型存儲。屬性可以用於描述特定stream,並支持指定特定語言,並且其長度可以超過65535字節(DWORD)。
至於這五種Object如何解析,建議參考ASF Specification的相關內容。
4. ASF中的節目選擇
ASF文件中用StreamID唯一的標識一個stream(音頻或者視頻,當然也支持其他數據,比如字幕、腳本命令等,目前不需要關心這個,按照傳統的音視頻處理即可,后續需要可以自己按照標准處理下),這些信息可以在Header Object中的Stream Properties Object找到。比如說音頻的聲道數、采樣率、量化位數、編碼方式,視頻的編碼寬高、編碼方式、量化位數。
如果ASF文件中只有一個音頻或者一個視頻,這是很容易選擇,但是如果存在多個音頻、視頻文件該如何選擇呢?
ASF中提供了Bitrate Mutual Exclusion Object、Advanced Mutual Exclusion Object、Group Mutual Exclusion Object,用於說明不能同時播放的視頻流。
Stream Prioritization Object用於給出流播放的優先級。
stream選擇在流媒體推流,及帶寬變化時用的比較多,正常播放文件的話,通常默認選擇最大分辨率、最大碼率的視頻,最大采樣率、最多聲道數的音頻。
具體選擇策略建議參考ASF Specification的section 7.2。
5. ASF如何實現seek?
第一部分介紹了ASF中提供的四種不同的Index Object。對於文件,比較常見的是Simple Index Object。多數seek操作時可以通過這個對象實現的。
Simple Index Object中存儲的是按照固定時間間隔seek point。先了解下Simple Index Object的結構:
Field name | Field type | Size (bits) |
---|---|---|
Object ID | GUID | 128 |
Object Size | QWORD | 64 |
File ID | GUID | 128 |
Index Entry Time Interval | QWORD | 64 |
Maximum Packet Count | DWORD | 32 |
Index Entries Count | DWORD | 32 |
Index Entries | See below | varies |
其中Index Entry Time Interval表示相鄰seek point之間的時間間隔,單位是100納秒。最常用的是10000000,表示1s。
Maximum Packet Count中存儲的是Index Entries中最大的Packet數目。
Index Entries的定義如下:
Field name | Field type | Size (bits) |
---|---|---|
Packet Number | DWORD | 32 |
Packet Count | WORD | 16 |
其中Packet Number指的是與當前時間有關的Data Packet的編號。對於視頻stream,該域總是指向具當前時間最近的關鍵幀所在的Data packet.
Packet Count表示在當前時間間隔內需要發送的Data Packet數目。
舉個例子,下面數據是一個wmv文件的Simple Index Object的二進制數據:
0000: 90 08 00 33 B1 E5 CF 11-89 F4 00 A0 C9 03 49 CB
0010: CE 00 00 00 00 00 00 00-B6 FA 97 93 D3 CB E3 4B
0020: 81 D0 F0 6B 24 96 98 A2-80 96 98 00 00 00 00 00
0030: 0F 00 00 00 19 00 00 00-01 00 00 00 01 00 01 00
0040: 00 00 01 00 01 00 00 00-01 00 01 00 00 00 01 00
0050: 38 00 00 00 08 00 38 00-00 00 08 00 38 00 00 00
0060: 08 00 77 01 00 00 0A 00-77 01 00 00 0A 00 77 01
0070: 00 00 0A 00 B2 02 00 00-0D 00 B2 02 00 00 0D 00
0080: B2 02 00 00 0D 00 E8 03-00 00 07 00 E8 03 00 00
0090: 07 00 E8 03 00 00 07 00-26 05 00 00 08 00 26 05
00A0: 00 00 08 00 26 05 00 00-08 00 66 06 00 00 0F 00
00B0: 66 06 00 00 0F 00 66 06-00 00 0F 00 69 07 00 00
00C0: 0A 00 69 07 00 00 0A 00-69 07 00 00 0A 00
解析之后的數據如下:
Simple Index Object (206 bytes) |
---|
Property |
File Position |
Object ID |
Object Size |
MMS ID |
Interval |
Max. Packets in Entry |
Index Entries |
Entry |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
這樣我們就可以通過這張表查到需要seek到的時間點對應的Data Packet的索引號,然后通過ASF Data Packet的定長邏輯跳轉到指定位置。(注意其他三種Index Object給出的是相對第一個ASF Data Packet的偏移位置)
上面表格中的Packet SCR是Packet Send Time。
6. 其他
讀到這里,相信對ASF文件格式有一定的了解了,那么剩下的就回答下沒有覆蓋的問題。
-
如何確定該容器的節目播放時長?
在Header Object中的File Properties Object中有一個字段Duration,可以通過這個直接讀出節目時長(有時候不准確,這就是文件生成方的責任了)。 -
哪里可以找到該容器格式最標准的文檔資料?
通常在微軟的官網上是可以下載到ASF標准文檔的,但是不行的話可以谷歌(百度基本找不到)。
我現在參考的是“Advanced Systems Format (ASF) Specification Revision 01.20.05 Microsoft Corporation June 2010” -
有哪些可用的工具,方便分析容器格式異常或者錯誤?
比較經典的分析ASF、wmv、wma文件的工具是ASFViewer,也是微軟提供的碼流輔助分析工具,當然你也可以使用開源的demuxer分析(比如ffmpeg asf_demuxer)。
小結
本文主要是參考:
- “Advanced Systems Format (ASF) Specification Revision 01.20.05 Microsoft Corporation June 2010”
- 【多媒體封裝格式詳解】---ASF(WMV/WMA)
這里主要整理我對於ASF文件格式一些疑惑的地方。算是基本上可以解析了。了解了基本的文件結構,清楚了如何選擇音頻、視頻,時間戳信息、seek索引文件的使用。