修正wme输出的ASF流数据
?
前言
Windows Media Encoder是Microsoft Media Serial中的編碼、轉(zhuǎn)換工具,其支持將不同的文件轉(zhuǎn)換成wmv/a格式,同時他也支持直接通過硬件設備(如聲卡、攝像頭等)采集數(shù)據(jù),輸出wmv/a格式。在輸出方面wme支持直接存入文件,推送到wms(Microsoft Media Service),或推送到本地端口功能。然而推送到本地端口的數(shù)據(jù)并不完全符合asf 規(guī)范。
問題提出
在ASF Specfication中定義ASF文件的package的大小是固定的,這就導致有一部分(實際上是大部分)package達不到package的標準尺寸,因此需要一些填充字節(jié)來增長package的大小,使其符合header object中定義的package size。?我們知道,在wme的向本地推送數(shù)據(jù)時,實際上其數(shù)據(jù)包采用的是wms Http Streaming protocol,為了減少網(wǎng)絡占用,wme推送http streaming數(shù)據(jù)時并沒有推送這些填充字節(jié),因為如果我們自己編寫程序?qū)ttp streaming數(shù)據(jù)轉(zhuǎn)存到文件時,就必須對這些數(shù)據(jù)進行修正,這正在本文所關(guān)注的問題。
方案
首先,我們需要分析asf文件的頭數(shù)據(jù),找出其package的大小,然后,逐個分析每個package,如果其大小小于頭中設定的大小,就需要進行修正。
對數(shù)據(jù)進行修復,就必須理解asf specification中的相關(guān)說明,根據(jù)5.2ASF Data package definition一節(jié)可知,數(shù)據(jù)包的組成如下:
我們所要做的就是根據(jù)Error Correction Data和Payload Parsing Information填充Padding Data,并修改data package中相應的數(shù)據(jù)(主要是Padding Length和Package Length字段)。實際上,Erro Corection Data都是存在的。
根據(jù)asf specification可知:
Error Correction Data?
Payload parsing information
首先,我們要根據(jù)Error Correction Data的第一個字節(jié)(Error Correction Data Flags)了解Error Correction Data是否存在,以及其長度。檢查Flags第8位是否為1(flags & 0x80 = 0x80),即可確定是否存在;如果存在,其低4位保存了Error Correcton Data Length(flags & 0x0f)。
然后跳過Error Correction Data,開始分析Payload parsing information。逐個分析Packet Length、Sequence、Padding Length的類型和大小。通常情況下,sequence是不存在的,其Length type flags中的值為00,Packet Length在某些情況下存在。分析方法如下:
Packet Length Type:flags & 0x60 >> 5
Sequence Type:flags & 0x06 >> 1
Padding Length Type: flags & 0x18 >>3
Type定義如下:
?
雖然這個圖是針對Sequence的,但這個定義對三個字段的含義是相同。
經(jīng)過以上分析,即可確定Packet Length字段、Padding Length字段是否存在,其類型是什么(BYTE、WORD、DWORD?),對應的修改Packet Length字段為asf header中定義的長度,然后修改Padding Length為asf header中的長度-本package的長度,在package后邊添加填充字節(jié)即可。
示例代碼(C#)
if (data.Length < AsfHeader.MaxPacketSize) //需要修正
?????????????????????????? {
?????????????????????????????? int iPaddingOffset = 0;
?????????????????????????????? int iPaddingLength = 0;
?????????????????????????????? int iParserStart = 0;
?????????????????????????????? //Error Correction
?????????????????????????????? if ((data[0] & 0x80) == 0x80) //Error Correction 存在
?????????????????????????????? {
?????????????????????????????????? iPaddingOffset += (data[0] & 0x0f) + 1/*first byte.error correction flags*/;
?????????????????????????????????? iParserStart = iPaddingOffset;
?????????????????????????????? }
?????????????????????????????? int c;
?????????????????????????????? //取得Packet Length type
?????????????????????????????? c = (data[iParserStart] & 0x60) >> 5;
?????????????????????????????? switch (c)
?????????????????????????????? {
?????????????????????????????????? case 0: // does not exist
?????????????????????????????????????? break;
?????????????????????????????????? case 1: // byte
?????????????????????????????????????? iPaddingOffset += 1;
?????????????????????????????????????? //fix length
?????????????????????????????????????? break;
?????????????????????????????????? case 2: //word
?????????????????????????????????????? iPaddingOffset += 2;
?????????????????????????????????????? //fix length
?????????????????????????????????????? Array.Copy(BitConverter.GetBytes((ushort)mHeader.AsfHeader.MaxPacketSize), 0,data,iPaddingOffset,2);
?????????????????????????????????????? break;
?????????????????????????????????? case 3: //dword
?????????????????????????????????????? iPaddingOffset += 4;
?????????????????????????????????????? //fix length
?????????????????????????????????????? Array.Copy(BitConverter.GetBytes(mHeader.AsfHeader.MaxPacketSize), 0, data, iPaddingOffset -2, 4);
?????????????????????????????????????? break;
?????????????????????????????? }
?????????????????????????????? //取得Sequence type
?????????????????????????????? c = (data[iParserStart] & 0x06) >> 1;
?????????????????????????????? switch (c)
?????????????????????????????? {
?????????????????????????????????? case 0: // does not exist
?????????????????????????????????????? break;
?????????????????????????????????? case 1: // byte
?????????????????????????????????????? iPaddingOffset += 1;
?????????????????????????????????????? break;
?????????????????????????????????? case 2: //word
?????????????????????????????????????? iPaddingOffset += 2;
?????????????????????????????????????? break;
?????????????????????????????????? case 3: //dword
?????????????????????????????????????? iPaddingOffset += 4;
?????????????????????????????????????? break;
?????????????????????????????? }
?????????????????????????????? //取得Padding Length type
?????????????????????????????? c = (data[iParserStart] & 0x18) >> 3;
?????????????????????????????? switch (c)
?????????????????????????????? {
?????????????????????????????????? case 0: // does not exist
?????????????????????????????????????? break;
?????????????????????????????????? case 1: // byte
?????????????????????????????????????? iPaddingLength = 1;
?????????????????????????????????????? break;
?????????????????????????????????? case 2: //word
?????????????????????????????????????? iPaddingLength = 2;
?????????????????????????????????????? break;
?????????????????????????????????? case 3: //dword
?????????????????????????????????????? iPaddingLength = 4;
?????????????????????????????????????? break;
?????????????????????????????? }
?????????????????????????????? int iPaddings = (int)(AsfHeader.MaxPacketSize - data.Length);
?????????????????????????????? iPaddingOffset += 2;//skip payload parser information
?????????????????????????????? switch (iPaddingLength)
?????????????????????????????? {
?????????????????????????????????? case 0:
?????????????????????????????????????? break;
?????????????????????????????????? case 1:
?????????????????????????????????????? data[iPaddingOffset] = (byte)iPaddings;
?????????????????????????????????????? break;
?????????????????????????????????? case 2:
?????????????????????????????????????? Array.Copy(BitConverter.GetBytes((ushort)iPaddings), 0, data, iPaddingOffset, iPaddingLength);
?????????????????????????????????????? break;
?????????????????????????????????? case 3:
?????????????????????????????????????? Array.Copy(BitConverter.GetBytes((uint)iPaddings), 0, data, iPaddingOffset, iPaddingLength);
?????????????????????????????????????? break;
?????????????????????????????? }
?????????????????????????????? chunk.Data = new byte[AsfHeader.MaxPacketSize];
?????????????????????????????? //chunk.Data.Initialize();
??????????????????????????????? Array.Copy(data, chunk.Data, data.Length);
??????????????????????????????? chunk.Length = (ushort)chunk.Data.Length;
?????????????????????????? }
?????????????????????????? else
?????????????????????????? {
?????????????????????????????? chunk.Data = data;
?????????????????????????? }
參考資料
ASF Specification?
轉(zhuǎn)載于:https://www.cnblogs.com/Ankh/archive/2007/08/09/849019.html
總結(jié)
以上是生活随笔為你收集整理的修正wme输出的ASF流数据的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Cisco 3750文件系统学习总结
- 下一篇: SQL Server 2000从入门到精