修正wme输出的ASF流数据

 

前言

Windows Media Encoder是Microsoft Media Serial中的编码、转换工具,其支持将不同的文件转换成wmv/a格式,同时他也支持直接通过硬件设备(如声卡、摄像头等)采集数据,输出wmv/a格式。在输出方面wme支持直接存入文件,推送到wms(Microsoft Media Service),或推送到本地端口功能。然而推送到本地端口的数据并不完全符合asf 规范。

问题提出

在ASF Specfication中定义ASF文件的package的大小是固定的,这就导致有一部分(实际上是大部分)package达不到package的标准尺寸,因此需要一些填充字节来增长package的大小,使其符合header object中定义的package size。 我们知道,在wme的向本地推送数据时,实际上其数据包采用的是wms Http Streaming protocol,为了减少网络占用,wme推送http streaming数据时并没有推送这些填充字节,因为如果我们自己编写程序将http streaming数据转存到文件时,就必须对这些数据进行修正,这正在本文所关注的问题。

方案

首先,我们需要分析asf文件的头数据,找出其package的大小,然后,逐个分析每个package,如果其大小小于头中设定的大小,就需要进行修正。

对数据进行修复,就必须理解asf specification中的相关说明,根据5.2ASF Data package definition一节可知,数据包的组成如下:

clip_image001

我们所要做的就是根据Error Correction Data和Payload Parsing Information填充Padding Data,并修改data package中相应的数据(主要是Padding Length和Package Length字段)。实际上,Erro Corection Data都是存在的。

根据asf specification可知:

image

Error Correction Data 

image

Payload parsing information

首先,我们要根据Error Correction Data的第一个字节(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定义如下:

image 

虽然这个图是针对Sequence的,但这个定义对三个字段的含义是相同。

经过以上分析,即可确定Packet Length字段、Padding Length字段是否存在,其类型是什么(BYTE、WORD、DWORD?),对应的修改Packet Length字段为asf header中定义的长度,然后修改Padding Length为asf header中的长度-本package的长度,在package后边添加填充字节即可。

示例代码(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 

转载于:https://www.cnblogs.com/Ankh/archive/2007/08/09/849019.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值