回 帖 发 新 帖 刷新版面

主题:(原创)wmv和asf文件数据结构以及提取常用信息的代码

wmv和asf文件数据结构以及提取常用信息的代码

在大多数情况下,WMV文件都是用ASF容器格式来封装的。ASF是微软专门针对流媒体开发的容器格式。ASF格式的文件中,如果使用微软的WMV编解码器,文件扩展名就用wmv,如果使用非微软的编解码器,则用asf扩展名。所以也可以说,wmv文件和asf文件的区别在于它们的媒体压缩数据使用的编解码器不同,而它们的封装格式是相同的,所以下面的解析对asf和wmv都是适用的。
WMV文件的所有对象和语法都是小端字节序。即低位在前。但是数据包中的媒体流数据的字节序可以随意。


一、对象
WMV文件的基本单位是“对象”,也就是说,WMV是由许许多多的对象组成的。顶层的对象常用的有3个,按照它们在文件中的排列顺序是:头对象(HeaderObject)、数据对象(DataObject)、索引对象(Index Object)或者简单索引对象(Simple Index Object)。前两个对象是必须的,索引对象是可选的,但索引对象对于查找和快进快退的操作非常重要。数据对象和索引对象之间还可以插入用户自定义对象。
所有的对象都由32位的GUID来区分,GUID是全局唯一对象标识符,以下称“对象ID”。
常用对象名称及对象ID对照见表1。
对象的结构见表2。


表1:常用对象名称及对象ID对照
------------------------------------------------------------------------------------
名称                         对象ID
------------------------------------------------------------------------------------
****顶层对象****
头对象   (Header Object)           3026B2758E66CF11A6D900AA0062CE6C
数据对象    (Data Obiect)            3626B2758E66CF11A6D900AA0062CE6C
简单索引对象(Simple Index Object)         90080033B1E5CF1189F400A0C90349CB

索引对象  (Index Object)            D329E2D6DA35D111349000A0C90349BE
媒体对象索引对象(Media Object Index Object)   F803B1FEAD12644C0F842A1D2F7AD48C
时间码索引对象(Time Code Index Obiect)      D03FB73C4A0C03483D95EDF7B6DD8F0C

****二层对象****
文件属性对象(file properties Object)       A1DCAB8C47A9CF118EE400C00C205365
流属性对象 (stream properties Object)      9107DCB7B7A9CF118EE600C00C205365
头扩展对象 (header extension Object)      B503BF5F2EA9CF118EE300C00C205365
编解码器列表对象(Codec List Object)       4052D1861D31D011A3A400A0C90348F6
扩展目录描述(Extended Content Description Object)40A4D0D207E3D21197F000A0C95EA850

高级目录加密(Advanced Content Encryption Object) 338505438169E649749BAD12CB86D58C
高级互斥对象(Advanced Mutual Exclusion Object)  CF4986A075477046168A6E35357566CD
带宽分享对象(Bandwidth Sharing Object)      E60996A67B51D211AFB600C04FD908E9
兼容性对象 (Compatibility Object)        5D8BF126844547EC5F9F0E654F0452C9
目录品牌对象(Content Branding Object)      FAB3112223BDD211B7B400A0C955FC6E
目录描述对象(Content Description Object)     3326B2758E66CF11A6D900AA0062CE6C
目录加密对象(Content Encryption Object)       FBB3112223BDD211B7B400A0C955FC6E
数字签名对象(Digital Signature Object)      FCB3112223BDD211B7B400A0C955FC6E
扩展目录加密(Extended Content Encryption Object) 14E68A292226174CB935DAE07EE9289C
扩展流属性 (Extended Stream Properties Object) CBA5E61472C632439983A96952065B5A
群互斥对象 (Group Mutual Exclusion Object)    405A46D1795A38431BB7E36B8FD6C249
索引参数对象(Index Parameters Object)      DF29E2D6DA35D111349000A0C90349BE
语言列表对象(Language List Object)        A946437CE0EFFC4B29B2696EDE415C85
书签对象  (Marker object)           01CD87F451A9CF118EE600C00C205365
媒体索引参数(Media Object Index Parameters Object)AD3B206B443FE448A8ACD7613DE2CFA7
元数据库对象(Metadata Library Object)      941C23449894D14941A11D134E457054
元数据对象 (Metadata Object)          EACBF8C5AF5B77486784AA8C44AF4CCA
相互排斥对象(Mutual Exclusion Object)      DC29E2D6DA35D111349000A0C90349BE
填充对象  (Padding Object)           74D40618DFCA0945BAA49AABCB96AAE8
脚本命令对象(Script command object)       301AFB1E620BD0119BA300A0C90348F6
流比特率属性(Stream Bitrate Properties Object)  CE75F87B8D46D1118D82006097C9A2B2
流优先次序 (Stream prioritization Object)      5BD1FED4D3884F45F081ED5C45999E24
时间码索引参数(Timecode Index Parameters Object) 6D495EF597975D4B888C604DFE9BFB24

****三层对象****
音频媒体对象(Audio Media Obiect)         409E69F84D5BCF11A8FD00805F5C442B
视频媒体对象(Video Media Obiect)         C0EF19BC4D5BCF11A8FD00805F5C442B
二元媒体对象(Binary Media Obiect)          E265FB3AEF47F240AC2C70A90D71D343
指令媒体对象(Command Media Obiect)        C0CFDA59E65911D0A3AC00A0C90348F6

可降解JPEG媒体(Degradable JPEG Media Obiect)   E07D903515E4CF1117A900805F5C442B
误差校正对象(Error Correction Object)      3526B2758E66CF11D9A600AA0062CE6C
视频误差校正类型(Error Correction Type Object)  0057FB20555BCF11A8FD00805F6C442B
音频误差校正类型(Error Correction Type Object)  50CDC3BF8F61CF118BB200AA00B4E220
文件传输媒体(File Transfer Media Obiect)     2C22BD911CF27A496D8B5AA86BFC0185
JPEG交换媒体(JFIF Media Obiect)         00E11BB64E5BCF11FDA800805F5C442B
保留对象(Reserved Object)              4152D1861D31D011A3A400A0C90348F6
------------------------------------------------------------------------------------
说明:
1.顶层对象中,前3个是常用对象。但只有前2个是必需的。
2.二层对象中,前5个是常用对象,但只有前3个是必需的。
3.三层对象中,前4个是常用对象,但只有前2个是必需的。


表2:对象的结构
----------------
名称  占用字节
----------------
对象ID  16
对象大小 8
对象数据 不定
----------------
说明:
1.对象大小=对象数据大小+24,即该值包括对象ID字段和对象大小字段本身所占用的字节数。


二、头对象
头对象描述了所有媒体流的一些信息。例如作者,曲目信息,用户加入的命令信息,码流的码率等。头对象也是顶层对象中唯一能够包含二层子对象的,每个子对象相当于一个信息描述符。在使用数据对象的媒体流数据之前,必须先要解析头对象中的信息。头对象的结构见表3。

表3:头对象结构
------------------------------------------------------------------
名称     占用字节  描述
------------------------------------------------------------------
对象ID      16
对象大小     8    >30字节
子对象数     4    二层子对象数目
保留1      1    固定值=1
保留2      1    固定值=2

    ****以下是6个常见的二层子对象****
文件属性对象   104  包含全局文件信息,如文件大小、播放时长等
流属性对象    129  包含视频流的基本信息,如图像宽高等
流属性对象    114  包含音频流的基本信息,如音频采样率等
头扩展对象    不定  支持为文件添加新功能,以便向后兼容
编解码器列表对象 122  包含视频和音频编解码器格式名称
扩展目录描述对象 100  包含所有的目录信息
------------------------------------------------------------------
说明:
1.头对象中必有的二层子对象有:1个文件属性对象,1个头扩展对象,和至少1个流属性对象。
2.二层子对象的排列次序可随意,但必有的对象一般排在前面。
3.表中列出的二层子对象占用的字节只是典型值,实际可能会有出入。

三、文件属性对象
文件属性对象是二层对象,是头对象中的必有对象,它的结构见表4。

表4:文件属性对象的结构
-----------------------------------------------------------------
名称    占用字节    描述
-----------------------------------------------------------------
对象ID     16
对象大小    8
文件ID     16     必须与数据对象中的文件ID相同
文件大小    8      wmv文件的字节总数
创建日期    8
数据包数目   8      数据对象中的数据包数目
播放时长    8      单位:100ns(纳秒)
发送时长    8      单位:100ns(纳秒)
缓冲时长    8      单位:ms(毫秒)
标志      4      把此4字节化为连续的32位二进制
播放标志    1(位)  低1位
查找标志    1(位)  低2位
保留的     30(位)
最小数据包大小 4
最大数据包大小 4
最大比特率   4
-----------------------------------------------------------------
说明:
1.理论上每个wmv文件的文件ID都不相同。但笔者查看了多个wmv文件后发现,此ID多为0。
2.1秒(s)=1,000毫秒(ms)=1,000,000微秒(μs)=1,000,000,000纳秒(ns)
3.文件实际播放时间=播放时长-缓冲时长,计算时要注意它们的单位不同。
4.以下两种情况须设置查找标志位=1:
①只有单一音频流时。
②有音频流和视频流时,必须有针对视频流的索引对象。


四、流属性对象
流属性对象是二层对象,是头对象中的必有对象。它定义了文件中媒体数据的属性,有多少个流就有多少个流属性对象。它的结构见表5。

表5:流属性对象结构
--------------------------------------------------------------
名称      占用字节   描述
--------------------------------------------------------------
对象ID       16
对象大小      8
流类型对象ID    16    必是下面说明 1.中的一个
误差校正类型对象ID 16
时间偏移量     8
特定类型数据长度  4
误差校正数据长度  4
标志        2     把此2字节化为连续的16位二进制
流编号       7(位) 低7位
保留的       8(位) 中8位
目录加密标志    1(位) 高1位
保留的       4
特定类型数据    不定    当特定类型数据长度>0才有此项
误差校正数据    不定    当误差校正数据长度>0才有此项
--------------------------------------------------------------
说明:
1.每个流属性对象只能是以下4个流类型中的1个:①视频媒体;②音频媒体;③指令媒体;④二元媒体
2.4个流类型只有视频媒体和音频媒体是必须的,所以wmv文件中一般有2个流属性对象。
3.特定类型数据必须根据流类型来解析:
①如果是视频媒体,特定类型数据的结构见表6。
②如果是音频媒体,特定类型数据的结构见表7。
③如果是指令媒体,不须再解析。
④如果是二元媒体,特定类型数据的结构见表8。
4.如果设置了目录加密标记,这个流里的数据就不需解析,因为加密了。
    5.将标志的16位 AND 7F(“与”运算),就得到流编号,即以后可能会用到的视频或音频 pid。


表6:视频特定类型数据结构(共51或55字节)
-----------------------------------------------------------------------
名称     占用字节 描述
-----------------------------------------------------------------------
图像宽      4
图像高      4
保留的      1
格式数据大小   2

****以下为格式数据****
biSize      4  结构长度,40(或44)字节
biWidth     4  图像宽度,与表中第1项图像宽相同
biHeight     4  图像高度,与表中第2项图像高相同
biPlanes     2  位面板数,≡1
biBitCount    2  颜色深度:1=单色,4=16色,8=256色,24=真彩
biCompression  4  图像压缩方式,即视频编码格式,一般为wmv2
biSizeImage   4  图像数据占用的字节数
biXPelsPerMeter 4  目标设备的水平分辨率,单位是每米的象素个数
biYPelsPerMeter 4  目标设备的垂直分辨率,单位是每米的象素个数
biClrUsed    4  图象实际用到的颜色数,0表示全要使用
biClrImportant  4  图象中重要的颜色数,0表示所有颜色都重要
****         4  格式工厂转换的wmv文件,最后多了4字节,未知用途
-----------------------------------------------------------------------
说明:
1.格式数据是BITMAPINFOHEADER类型结构。
2.格式数据大小一般为40字节,但用格式工厂转换的wmv有44字节。


表7:音频特定类型数据结构(WAVEFORMATEX类型结构)
-----------------------------------------------------------------------
名称         占用字节 描述
-----------------------------------------------------------------------
Coder ID/Format Tag    2  音频编码格式,一般为&H0161(wma2)
Number of Channels    2  声道数
Samples Per Second    4  采样率,单位:kHz
Average Bytes Per Second 4  平均数据传输率,单位:字节/秒
Block Alignment      2  块对齐,最小数据的原始大小。单位:字节
Bits Per Sample      2    每次采样样本的大小(位深),单位:位
Extra Data Size      2    额外数据大小,单位:字节

****以下为额外数据(额外数据大小>0才有)****
wValidBitsPerSample    2  每个样本有效位
wSamplesPerBlock     2  每个样本块
wReserved         2  保留的
dwChannelMask       4  声道掩码
-----------------------------------------------------------------------
说明:
1.音频特定类型数据是WAVEFORMATEX类型结构。
2.根据音频编码格式的值在对照表中可查得对应的编码格式名称,但这样很麻烦(要将对照表的一百多项列出来,并遍历该表),所以不须理睬这个字段,而是在编解码器列表对象中获知,参见下文的“五、编解码器列表对象”。WMV文件中的音频编码一般是WMA。
    3.采样率常用值有:8.0、11.025、22.05、44.1。例如11025对应采样率为11.025。
4.平均数据传输率可以看作是比特率,要换算成常用的单位kbps,其值要÷1000×8。
5.额外数据是WAVEFORMATEXTENSIBLE类型结构,用于存放编解码器特定数据,专用于音频媒体,解决多声道排序和高精度数据的问题,提供自我注册新数据格式的机制。通过每个样本有效位和声道掩码可以获得编码方式码。通过编码方式码,可以确定一帧的数据大小和最终的编码方式。
6.块对齐=(声道数×位深)÷8。


表8:二元媒体特定类型数据结构
--------------------------------------------
名称               占用字节
--------------------------------------------
主流媒体类型ID(Major media type) 16
媒体过程类型ID(Media sub type)  16
固定大小样本(Fixed-size samples) 4
时间压缩(Temporal compression)  4
样本大小(Sample size)       4
格式类型(Format type)       16
格式数据大小(Format data size)  4
格式数据
--------------------------------------------
说明:
1.二元媒体特定类型数据一般不解析,除了主流媒体类型ID为9D8C1731E103284582B53DF9DB22F503的时候,其类型为音频,才去解析这个结构体之后的格式数据,以音频媒体方式解析,见表7。


五、编解码器列表对象
编解码器列表对象是二层对象,是头对象中可选的对象,它的结构见表9。

表9:编解码器列表对象结构
---------------------------------------
名称      占用字节 描述
---------------------------------------
对象ID      16
对象大小     8
保留对象ID    16
编解码器记录数  4  一般为2条记录

****以下为记录****
序号       2  0001,这是视频的
字串1的字符数目 2
字串1     不定
....
字串n的字符数目 2
字串n     不定

序号       2  0002,这是音频的
字串1的字符数目 2
字串1     不定
....
字串n的字符数目 2
字串n     不定
---------------------------------------
说明:
1.每条记录都有可能跟着几个字符串,每个字符串前都有2字节的字符数目。字符串以0结尾。
2.字符串一般是UTF-8编码的字符(每个字符2字节),也有Ansi字符串。
3.字符数目不包括该字段本身占用的2字节。


六、数据对象
数据对象是顶层对象,由若干个固定长度的数据包(data packet)组成。每个数据包携带一个或多个数字媒体流。数据包按照发送时间顺序保存。一个数据包中可能包含来自不同码流中的数据,数据包通过条目对象(entry objects)来组织管理不同码流的数据。数据对象结构见表10。

表10:数据对象结构
--------------------------------------------------------------
名称  占用字节 描述
--------------------------------------------------------------
对象ID   16
对象大小  8
文件ID   16  必须与文件属性对象中的文件ID相同
数据包总数 8
保留    2  值=0101
数据包1  不定 结构见表11
……
数据包n  不定 大小与数据包1相同,结构见表11
---------------------------------------------------------------
说明:
1.文件ID在一个ASF文件中是唯一的。当ASF文件修改时,这个值也会改变。这个值和文件属性对象中的文件ID相同。
2.数据包总数必须和头对象的文件属性对象中的数据包数相等。
3.数据包结构见表11。


表11:数据包结构
-------------------------------------------
项号 名称        描述
-------------------------------------------
1   误差校正数据    结构见表12
2   有效负载解析信息  结构见表13
3   有效负载数据    结构见表14、表15
4   填充数据      使数据包大小相同
-------------------------------------------
说明:
1.第1项和第4项是可选的。
2.一个数据包中可有多个有效负载,但这些有效负载必须是同一种媒体流。
3.数据包在开始传输的时候,在数据对象中自动排序,这种排序来自于交叉存储的文件格式。在网络上播放时,它和带宽紧密相关。
4.数据包还有一种结构:第2、3项合为一项:不透明数据
5.每个数据包的大小都必须≤64K,且与文件属性对象中指定的“最大数据包大小”相同,如果小于这个值,就用填充数据补充。


表12:误差校正数据(Error correction data)结构
-------------------------------------------------------------------
项号 名称                       长度
-------------------------------------------------------------------
1 误差校正标记(Error correction Flags)        8(位)
1-1 误差校正数据长度(Error correction data length)   4(低位)
1-2 不透明数据呈现(Opaque Data Present)         1
1-3 误差校正数据长度类型(Error correction length type) 2
1-4 误差校正呈现(Error correction present)       1

2 误差校正数据(Error correction data)         2(字节)
-------------------------------------------------------------------
说明:
1.误差校正标记为1个字节(8位),这8位代表着4项。
2.误差校正数据长度类型用于编码误差校正数据的大小。这个值一般=00。当误差校正长度类型=00时,误差校正数据长度值才有效,其值=0010(表明后面有2字节误差校正数据)。如果类型值≠00,这个值=0000。
3.不透明数据呈现值如果=1,表示误差校正数据是不透明数据,否则这个值=0
4.误差校正呈现值如果=1,表示有误差校正信息。


表13:有效负载解析信息结构
--------------------------------------------
项号 名称         占用二进制位
--------------------------------------------
1 长度类型标记        8
1-1 多重有效负载呈现      1(最低位)
1-2 序列类型          2
1-3 填充长度类型        2
1-4 包长度类型         2
1-5 误差校正呈现        1

2 属性标记          8
2-1 重复数据长度类型      2(最低位)
2-2 偏移信息媒体对象长度类型  2
2-3 媒体对象编号长度类型    2
2-4 流编号长度类型       2

3 包长度           0、8、16、32
4 序列            0、8、16、32
5 填充长度          0、8、16、32
6 发送时间          32
7 持续时间          16
--------------------------------------------
说明:
1.如果1-1项=1,表示该数据包不止1个流。
2.如果1-2项的值=00/01/10/11,表示4项占用的二进制位=0/8/16/32,其中0表示不存在。
3.5项对应1-3项,其值的意义同上。
4.3项对应1-4项,其值的意义同上。


表14:有效负载数据的结构
--------------------------------
名称      占用二进制位
--------------------------------
流数目和关键帧  8
流数目      7(低位)
关键帧      1
媒体对象数目   0、8、16、32
偏移信息媒体对象 0、8、16、32
重复数据长度   0、8、16、32
重复数据     不定
有效负载长度   8、16、32
有效负载     不定
--------------------------------
说明:
1.如果关键帧标志=1,表示这个数据包有关键帧,否则没有。
    2.如果表13中的1-1项=1,那么有效负载的结构见表15。


表15:多重有效负载的结构
--------------------------------
名称       占用二进制位
--------------------------------
有效负载标志    8
有效负载数目    6(低位)
有效负载长度类型  2
有效负载      不定
--------------------------------


七、索引对象
存放数据对象中数据包的时间索引。这些索引不用于流化数据,而是为了加快数据查找和维护。每一索引进入表现的时间间隔是在制作时设置的,存储在索引对象中。有了索引,通过对关键帧的查找,可以向前、向后或跳到某个指定的位置。
索引对象有两种方式,一个wmv文件只能有其中一种方式:
1.索引对象(index object)。包含索引对象和媒体对象索引对象。
2.简单索引对象(simple index object):结构见表16。由于没有必要为每个媒体流建立一个索引,因此,通常利用一个时间间隔表来索引一系列的媒体流。每个视频流都应该有一个简单索引对象。简单索引对象出现的顺序和视频流在文件中出现的顺序一致。


表16:简单索引对象结构
---------------------------------------------
名称      占用字节  描述
---------------------------------------------
对象ID      16
对象大小     8
文件ID      16
索引入口时间间隔 8    单位:微秒(μs)
最大包数     4
索引入口数目   4    假设有n个入口

****以下是索引入口表****
第1个索引入口
包编号     4
包计数     2
……
第n个索引入口
包编号     4
包计数     2
---------------------------------------------
说明:
1.文件ID与文件属性对象中的文件ID、数据对象中的文件ID是相同的。

2.索引入口中指出了关键帧所在的包编号。



回复列表 (共6个回复)

沙发


八、实例解析
以下是XP系统自带的wmv文件《小男孩》头对象的部分数据:
-------------------------------------------------------------------------
0000: 30 26 B2 75 8E 66 CF 11 A6 D9 00 AA 00 62 CE 6C   0&瞮巉.....b蝜
0010: 53 04 00 00 00 00 00 00 09 00 00 00 01 02 CE 75   S.............蝩
0020: F8 7B 8D 46 D1 11 8D 82 00 60 97 C9 A2 B2 26 00   鴞岶..崅.`椛⒉&.
0030: 00 00 00 00 00 00 02 00 01 00 0F 86 00 00 02 00   ................
0040: D6 FC 02 00 A1 DC AB 8C 47 A9 CF 11 8E E4 00 C0   贮..≤珜G┫.庝..
0050: 0C 20 53 65 68 00 00 00 00 00 00 00 9E 61 CD E5   . Seh.......瀉湾
0060: C7 3B FA 43 91 EB 66 4D F3 C3 D8 8D 9D A3 05 00   .;鶦戨fM竺貚潱..
0070: 00 00 00 00 30 21 C7 A3 7A CF C0 01 80 00 00 00   ....0!牵z侠.....
0080: 00 00 00 00 40 B8 6C 09 00 00 00 00 30 9E DE 07   ....@竘.....0炥.
0090: 00 00 00 00 1C 0C 00 00 00 00 00 00 02 00 00 00   ................
00A0: 3D 0B 00 00 3D 0B 00 00 E5 82 03 00 B5 03 BF 5F   =...=...鍌....縚
00B0: 2E A9 CF 11 8E E3 00 C0 0C 20 53 65 2E 00 00 00   .┫.庛... Se....
00C0: 00 00 00 00 11 D2 D3 AB BA A9 CF 11 8E E6 00 C0   .....矣┫.庢..
00D0: 0C 20 53 65 06 00 00 00 00 00 91 07 DC B7 B7 A9   . Se........芊珐
00E0: CF 11 8E E6 00 C0 0C 20 53 65 72 00 00 00 00 00   ..庢... Ser.....
00F0: 00 00 40 9E 69 F8 4D 5B CF 11 A8 FD 00 80 5F 5C   ..@瀒鳰[...._\
0100: 44 2B 50 CD C3 BF 8F 61 CF 11 8B B2 00 AA 00 B4   D+P兔繌a..嫴...粹
0110: E2 20 00 00 00 00 00 00 00 00 1C 00 00 00 08 00     ..............
0120: 00 00 01 00 20 1B E1 00 61 01 02 00 00 7D 00 00   .... ...a....}..
0130: A0 0F 00 00 00 03 10 00 0A 00 00 88 00 00 17 00   ................
0140: 00 1E 00 00 01 00 03 00 03 01 00 00 91 07 DC B7   ..............芊
0150: B7 A9 CF 11 8E E6 00 C0 0C 20 53 65 81 00 00 00   珐..庢... Se....
0160: 00 00 00 00 C0 EF 19 BC 4D 5B CF 11 A8 FD 00 80   ....里.糓[....
0170: 5F 5C 44 2B 00 57 FB 20 55 5B CF 11 A8 FD 00 80   _\D+.W. U[....
0180: 5F 5C 44 2B 00 00 00 00 00 00 00 00 33 00 00 00   _\D+........3...
0190: 00 00 00 00 02 00 20 1B E1 00 40 01 00 00 F0 00   ...... ...@.....
01A0: 00 00 02 28 00 28 00 00 00 40 01 00 00 F0 00 00   ...(.(...@......
01B0: 00 01 00 18 00 57 4D 56 31 00 00 00 00 00 00 00   .....WMV1.......
01C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 40 A4 D0   .............@
01D0:D2 07 E3 D2 11 97 F0 00 A0 C9 5E A8 50 8C 00 00   ..阋.楌.犐^≒...
01E0: 00 00 00 00 00 02 00 1C 00 57 00 4D 00 46 00 53   .........W.M.F.S
01F0: 00 44 00 4B 00 56 00 65 00 72 00 73 00 69 00 6F   .D.K.V.e.r.s.i.o
0200: 00 6E 00 00 00 00 00 1A 00 38 00 2E 00 30 00 30   .n.......8...0.0
0210: 00 2E 00 30 00 30 00 2E 00 34 00 33 00 38 00 33   ...0.0...4.3.8.3
0220: 00 00 00 1A 00 57 00 4D 00 46 00 53 00 44 00 4B   .....W.M.F.S.D.K
0230: 00 4E 00 65 00 65 00 64 00 65 00 64 00 00 00 00   .N.e.e.d.e.d....
0240: 00 16 00 30 00 2E 00 30 00 2E 00 30 00 2E 00 30   ...0...0...0...0
0250: 00 30 00 30 00 30 00 00 00 40 52 D1 86 1D 31 D0   .0.0.0...@R褑.1.
0260: 11 A3 A4 00 A0 C9 03 48 F6 D2 00 00 00 00 00 00   .¥.犐.H鲆......
0270: 00 41 52 D1 86 1D 31 D0 11 A3 A4 00 A0 C9 03 48   .AR褑.1..¥.犐.H
0280: F6 02 00 00 00 02 00 17 00 57 00 69 00 6E 00 64   .........W.i.n.d
0290: 00 6F 00 77 00 73 00 20 00 4D 00 65 00 64 00 69   .o.w.s. .M.e.d.i
02A0: 00 61 00 20 00 41 00 75 00 64 00 69 00 6F 00 20   .a. .A.u.d.i.o. 
02B0: 00 56 00 38 00 00 00 19 00 20 00 33 00 32 00 20   .V.8..... .3.2. 
02C0: 00 6B 00 62 00 70 00 73 00 2C 00 20 00 33 00 32   .k.b.p.s.,. .3.2
02D0: 00 20 00 6B 00 48 00 7A 00 2C 00 20 00 73 00 74   . .k.H.z.,. .s.t
02E0: 00 65 00 72 00 65 00 6F 00 00 00 02 00 61 01 01   .e.r.e.o.....a..
02F0: 00 17 00 57 00 69 00 6E 00 64 00 6F 00 77 00 73   ...W.i.n.d.o.w.s
0300: 00 20 00 4D 00 65 00 64 00 69 00 61 00 20 00 56   . .M.e.d.i.a. .V
0310: 00 69 00 64 00 65 00 6F 00 20 00 56 00 37 00 00   .i.d.e.o. .V.7..
0320: 00 01 00 00 00 04 00 57 4D 56 31 33 26 B2 75 8E   .......WMV13&瞮巉
-------------------------------------------------------------------------

板凳

解析:
0000-000F:头对象ID
0010-0017:头对象大小=&H453字节
0018-001B:头对象中包含9个二层子对象
001C-001D:保留的
001E-0043:第1个子对象:流比特率属性对象(略)
0044-00AB:第2个子对象:文件属性对象
0044-0053:对象ID
0054-005B:对象大小=&H68
005C-006B:文件ID
006C-0073:文件总字节=&H5A39D
0074-007B:文件创建日期和时间
007C-0083:数据包数目=&H80
0084-008B:播放时长=&H96CB840,注意其单位是100ns
008C-0093:发送时长=&H7DE9E30
0094-009B:缓冲时长=&HC1C,实际播放时长=&H96CB840/10000-&HC1C=12712(ms)
009C-009F:标志:可播放、可查找
00A0-00A3:最小数据包大小=&HB3D
00A4-00A7:最大数据包大小=&HB3D
00A8-00AB:最大比特率=&H682E5=230.117(kbps)
00AC-00D9:第3个子对象:头扩展对象
00AC-00BB:对象ID
00BC-00C3:对象大小=&H2E
00C4-00D9:对象内容
00DA-014B:第4个子对象:流属性对象(音频)
00DA-00E9:对象ID
00EA-00F1:对象大小=&H72
00F2-0101:流类型对象ID(音频)
0102-0111:误差校正类型对象ID
0112-0119:时间偏移量=0
011A-011D:特定类型数据长度=&H1C=28(字节)
011E-0121:误差校正数据长度=&H8=8(字节)
0122-0123:标志
0124-0127:保留的
0128-0143:特定类型数据
0128-0129:音频编码格式=&H161
012A-012B:声道数=2
012C-012F:音频采样率=&H7D00=32(kHz)
0130-0133:音频比特率=&HFA0*8=32(kbps)
0134-0135:块对齐=&H300
0136-0137:音频位数=&H10=16(bits)
0138-0139:额外数据大小=&HA=10(字节)
013A-0143:额外数据
0144-014B:误差校正数据
014C-01CC:第5个子对象:流属性对象(视频)
014C-015B:对象ID
015C-0163:对象大小=&H81
0164-0173:流类型对象ID(视频)
0174-0183:误差校正类型对象ID
0184-018B:时间偏移量=0
018C-018F:特定类型数据长度=&H33=51(字节)
0190-0193:误差校正数据长度=0
0194-0195:标志=&H2
0196-0199:保留的
019A-01CC:特定类型数据
019A-019D:图像宽=&H140=320(像素)
019E-01A1:图像高=&HF0=240(像素)
01A2:   保留的
01A3-01A4:格式数据大小=&H28=40(字节)
01A5-01CC:格式数据
01A5-01A8:结构长度=&H28=40(字节)
01A9-01AC:图像宽=&H140=320(像素)
01AD-01B0:图像高=&HF0=240(像素)
01B1-01B2:位面板数=1
01B3-01B4:颜色深度=&H18=24(真彩)
01B5-01B8:图像压缩方式=WMV1
01B9-01BC:图像数据占用的字节=0
01BD-01C0:目标设备水平分辨率=0
01C1-01C4:目标设备垂直分辨率=0
01C5-01C8:图像中用到颜色数=0
01C9-01CC:图像中重要的颜色数=0
01CD-0258:第6个子对象:扩展目录描述对象(略)
0259-032A:第7个子对象:编解码器列表对象
0259-0268:对象ID
0269-0270:对象大小=&HD2
0271-0280:保留对象ID
0281-0284:编解码器记录数目=&H2
0285-02EE:第1条记录
0285-0286:序号=0002(一般序号0001在先,0002在后)。
0287-0288:第1个字符串的字符数目=&H17。注意每个UTF-8字符占用2字节
0289-02B6:UTF-8字符串“Windows Media Audio V8”,最后2个00是结束标记
02B7-02E8:第2个字符串的字符数目=&H19
02E9-02EA:UTF-8字符串“32kbps,32kHz,stereo”
02EB-02EC:第3个字符串的字符数目=2
02ED-02EE:这2字节实际是数值&H0161,代表音频编码格式wma2
02EF-032A:第2条记录
02EF-02F0:序号=0001
02F1-02F2:第1个字符串的字符数目=&H17
02F3-0320:UTF-8字符串“Windows Media Video V7”,最后2个00是结束标记
0321-0322:第2个字符串的字符数目=1
0323-0324:UTF-8字符0000(空字符)
0325-0326:第3个字符串的字符数目=4
0327-032A:Ansi字符串“WMV1”

第8个子对象是目录描述对象,第9个子对象是书签对象,这里都从略。

3 楼


九、提取常用信息的代码
提取的信息有:①图像宽;②图像高;③播放时长;④视频比特率;⑤声道数;⑥音频采样率;
⑦音频比特率;⑧音频位深;⑨视频编码格式;⑩音频编码格式。
代码如下:

Option Explicit

Private WithEvents CD As VBControlExtender

Private Sub Form_Load()
Licenses.Add "MSComDlg.CommonDialog"
Set CD = Controls.Add("MSComDlg.CommonDialog", "CD") '创建公用对话框
End Sub

Private Sub Command1_Click()
Const fObject = "A1DCAB8C47A9CF118EE400C00C205365" '文件属性对象ID
Const vObject = "C0EF19BC4D5BCF11A8FD00805F5C442B" '视频媒体对象ID
Const aObject = "409E69F84D5BCF11A8FD00805F5C442B" '音频媒体对象ID
Const cObject = "4052D1861D31D011A3A400A0C90348F6" '编解码器列表对象ID

Dim wmvWidth As Long       '图像宽
Dim wmvHeight As Long      '图像高
Dim mcoms As Double        '播放时长(秒)
Dim vBitRate As Double     '视频比特率(kbps)
Dim Channel As Integer     '声道数
Dim Sample As Double       '音频采样率(kHz)
Dim aBitRate As Double     '音频比特率(kbps)
Dim BitsSample As Integer  '音频位深(bit)
Dim vCodec As String       '视频编码格式
Dim aCodec As String       '音频编码格式
Dim i As Integer, j As Integer, L As Integer, k As Integer, k2 As Integer
Dim ObjectID(15) As Byte, wmvData(2999) As Byte
Dim tem1() As String, tem2(1) As Byte
Dim fName As String, st As String

With CD.object
  .Filter = "wmv"
  .CancelError = True
  .DialogTitle = "打开"
  .showopen
  fName = .FileName
End With

Open fName For Binary As #1
Get #1, , wmvData
Close #1

For i = 0 To 15: ObjectID(i) = Val("&H" & Mid(fObject, i * 2 + 1, 2)): Next '文件属性对象
k = InStrB(wmvData, ObjectID)
If k Then
  ReDim tem1(5)
  For i = 0 To 5: tem1(i) = Right("0" & Hex(wmvData(k + 68 - i)), 2): Next '播放时长
  mcoms = BaseChange(Join(tem1, "")) / 10000000 '播放时长化为秒
  For i = 0 To 5: tem1(i) = Right("0" & Hex(wmvData(k + 84 - i)), 2): Next '缓冲时长
  mcoms = CInt(mcoms - BaseChange(Join(tem1, "")) / 1000) '获取播放时长
  ReDim tem1(3)
  For i = 0 To 3: tem1(i) = Right("0" & Hex(wmvData(k + 102 - i)), 2): Next '视频比特率
  vBitRate = BaseChange(Join(tem1, "")) / 1000 '获取比特率
End If

For i = 0 To 15: ObjectID(i) = Val("&H" & Mid(vObject, i * 2 + 1, 2)): Next '视频流属性对象
k = InStrB(wmvData, ObjectID)
If k Then
  ReDim tem1(1)
  For i = 0 To 1: tem1(i) = Right("0" & Hex(wmvData(k + 54 - i)), 2): Next
  wmvWidth = Val("&H" & Join(tem1, ""))  '获取图像宽
  For i = 0 To 1: tem1(i) = Right("0" & Hex(wmvData(k + 58 - i)), 2): Next
  wmvHeight = Val("&H" & Join(tem1, "")) '获取图像高
End If

For i = 0 To 15: ObjectID(i) = Val("&H" & Mid(aObject, i * 2 + 1, 2)): Next '音频流属性对象
k = InStrB(wmvData, ObjectID)
If k Then
  Channel = wmvData(k + 55) '获取声道数
  ReDim tem1(3)
  For i = 0 To 3: tem1(i) = Right("0" & Hex(wmvData(k + 60 - i)), 2): Next
  Sample = BaseChange(Join(tem1, "")) / 1000   '音频采样率
  For i = 0 To 3: tem1(i) = Right("0" & Hex(wmvData(k + 64 - i)), 2): Next
  aBitRate = BaseChange(Join(tem1, "")) / 1000 * 8 '音频比特率
  For i = 0 To 1: tem1(i) = Right("0" & Hex(wmvData(k + 68 - i)), 2): Next
  BitsSample = Val("&H" & tem1(0) & tem1(1))   '音频位深
End If

For i = 0 To 15: ObjectID(i) = Val("&H" & Mid(cObject, i * 2 + 1, 2)): Next '编解码器列表对象
k = InStrB(wmvData, ObjectID)
If k Then
  tem2(0) = 1
  GoSub 200
  vCodec = Join(tem1, "")
  tem2(0) = 2
  GoSub 200
  aCodec = Join(tem1, "")
End If

st = "图 像宽 度(像素):" & wmvWidth & vbCrLf & "图 像高 度(像素):" & wmvHeight & vbCrLf & _
     "播 放 时 长(秒) :" & mcoms & vbCrLf & "视频比特率(kbps):" & vBitRate & vbCrLf & _
     "音频比特率(kbps):" & aBitRate & vbCrLf & "音频采样率(kHz) :" & Sample & vbCrLf & _
     "采样精度(bits)  :" & BitsSample & vbCrLf & "声   道   数    :" & Channel & vbCrLf & _
     "视 频 编 解码器 :" & vCodec & vbCrLf & "音 频 编 解码器 :" & aCodec
Text1 = st
Exit Sub

4 楼


200
k2 = InStrB(k, wmvData, tem2) '查找编号
If wmvData(k2 + 1) = 0 Then k2 = InStrB(k2 + 1, wmvData, tem2) '跳过编解码器记录数
L = -1: j = wmvData(k2 + 1): ReDim tem1(j * 2 - 1)
For i = 0 To j * 2 - 1
  If wmvData(k2 + 3 + i) Then L = L + 1: tem1(L) = Chr(wmvData(k2 + 3 + i))
Next
ReDim Preserve tem1(L)
Return
End Sub

Private Function BaseChange(Num As String) As Double '16进制转为10进制
Dim A#, B#
Dim t3 As String, i As Integer, L As Integer

L = Len(Num)
For i = 0 To L - 1
  t3 = Mid(Num, L - i, 1)
  A = Asc(t3) - 48: If A > 9 Then A = A - 7
  B = B + A * 16 ^ i
Next

BaseChange = B
End Function

5 楼

更正:本文中讲的UTF-8编码字符,应为UTF-16BE编码字符(将Unicode码的两字节顺序颠倒),请更正。

6 楼

111

我来回复

您尚未登录,请登录后再回复。点此登录或注册