回 帖 发 新 帖 刷新版面

主题:[原创]mpg文件的数据结构以及获取其图像尺寸的代码

mpg文件的数据结构以及获取其图像尺寸的代码

mpg文件格式是运动图像压缩算法的国际标准,它采用有损压缩方法减少运动图像中的冗余信息,以每秒30帧左右的图像动态刷新,已被几乎所有的计算机平台共同支持。
mpg文件是以包的形式来储存信息和数据的,包中有包,大包套小包,它是若干个包的集合。
mpg文件中的长度字段采用高位在前的方式,长度从字段以后开始计算,不包括长度字段本身。


一、名词解释

基本流(ES:Elementary Streams):对视频、音频信号及其它数据进行编码压缩后的数据流,它只包含单一信源编码的数据流,就是说,ES要么是已编码的视频数据流,要么是已编码的音频数据流,要么是其它已编码的数据流。每个ES都由若干个存取单元(简称为AU)组成,每个视频AU或音频AU都是由头部和编码数据两部分组成。每个AU实际上是编码数据流的播放单元,即相当于解码的1个视频或音频帧的取样。

打包基本流(PES:Packetized Elementary Stream):将基本流数据分组为长度可变的数据包。简而言之,PES就是打包形式的基本流。PES包数据在通常情况下,就是1个AU。

标识码(start code):也可译成“起始码”。不论是包或者子包,前面都是4字节的标识码:3字节的标识码前缀0x000001+1字节的流ID(数据流识别码),这二者合成为专用的包标识码,用于识别数据包所属的数据流的性质(视频、音频、或其它)及序号。


二、包的结构
包由3部分组成,见表1。

表1 包的结构
--------------------------
字段   描述
--------------------------
包头   标识码
系统头  标识码0x000001BB
包数据
--------------------------
说明:
①包以0x000001BA或0x000001B3作为标识码,前者表示同时包含音频数据和视频数据,后者表示只有视频数据。
②包头标识码后紧跟着头信息。头信息有的为10字节(笔者的摄像机拍摄的 mpg文件),也有的为8字节(格式工厂转换的 mpg文件)。头信息是关于系统时钟基准的,本文不解析。
③文件中的第一个包才有系统头。
④包数据可以是多个PES子包的集合。PES子包的结构见表4。
⑤根据包头识别码中的流ID,可以判断当前包数据的具体内容是什么,见表2。
⑥包和子包都没有结束码,遇到下一个包标识码,就意味着此包结束。

表2 包的流ID表示的内容
-------------------------------
流ID  描述
-------------------------------
B2   用户数据
B3   视频ES
B5   本文件视频为MPEG-2编码
B8   图像组头
BA   视/音频ES
BB   系统头
BD   音频PES(AC3音频)
BE   填充字节流
BF   填充字节流
C0—CF 音频PES(MP3音频)
E0—EF 视频PES
-------------------------------
说明:
①在图像组头的后面还有流ID为00、01的图像头,图像头的后面是图像数据。图像数据可分为多个片(slice),每个片又分为多个微片(Microblock),每个微片可继续分为块(Block),不解析了。
②除了ES包,其它包都是子包。多数子包的标识码后面有长度字段,ES包没有。
③流ID为BE的包使用FF填充,流ID为BF的包使用00填充。
④笔者的摄像机拍摄的 mpg文件,流ID=BD时,包数据的前面有“MVI_DATA SONY HDR-CX180E”字符串。


三、系统头
文件的第一个包才有系统头。系统头的标识码后面是2字节的头信息长度字段,之后是头信息。系统头的结构见表3。
mpg文件的图像宽、高信息不在系统头中,而在流ID=B3的视频ES包中,其结构见表6。

表3 系统头结构
-------------------
字段    字节数
-------------------
标识码   4
信息长度  2
最大比率  3
音频范围  1
视频范围  1
保留的   1
流ID    1
PSTD范围  1
PSTD参数  6
-------------------
说明:
①系统头的信息长度不是固定的:格式工厂转换的为12字节,有的软件转换的为9字节,笔者的摄像机拍摄的为18字节。
②实际上,除了标识码和信息长度字段外,其它字段并不是以完整的字节来储存参数数据,而是用“位”来储存参数数据的,我们无须过细解析。


四、PES数据子包的结构
PES包的结构见表4。

表4 PES子包的结构
-----------------------
字段    字节数
-----------------------
包头    6
ES信息   最小为3
PES包数据 最大为65526
-----------------------
说明:
①包头由包标识码和包长度组成。注意包长度不包括包头本身的6字节。
②包头和ES信息二者可合成为1个数据头,所以可以认为 PES包是由数据头和包数据两个部分组成的。ES信息如果扩展数据长度>0,那么它占用的字节就会>3。
③包的最大长度为65535字节。包数据的最大长度=包的最大长度-数据头长度=65535-9。
④ES信息包含:
⑴2字节的PES包头识别位,16位表示了13个标记,其余3位保留,它的结构见表5。
⑵1字节的扩展数据长度,这个长度是指下面2项之和。
⑶最大46位的扩展数据信息区,当PTS和DTS标记为1时这里也是PTS和DTS的数据区。
⑷用于调整信息区长度的填充字节。

表5 ES信息的PES包头识别位
-----------------------------------------------
顺号 描述
-----------------------------------------------
⑴ PES加扰控制信息
⑵ PES优先级别指示
⑶ 数据适配定位标记
⑷ 版权指示
⑸ 原版或拷贝标记
⑹ 显示时间标记(PTS)
⑺ 解码时间标记(DTS)
⑻ 基本流时钟基准标志(ESCR)
⑼ 基本流速率标志
⑽ 数字存储媒体特技模式标志(DSM)
⑾ 附加的拷贝信息标志
⑿ 循环冗余校验信息标志(CRC)
⒀ PES扩展标志
-----------------------------------------------
说明:
①有扩展标志,表明还存在其它信息。如,在有传输误码时,通过数据包计数器,使接收端能以准确的数据恢复数据流,或借助计数器状态,识别出传输时是否有数据包丢失。


五、视频基本流包的结构
视频ES包的结构见表6。

表6 视频ES包的结构
-------------------
字段   字节数
-------------------
标识码  4字节
图像宽  1.5字节
图像高  1.5字节
宽高比  0.5字节
帧率   0.5字节
比特率  1字节

-------------------
说明:
①第5、6、7字节是视频图像的宽、高信息,以像素为单位,前面1个半字节是宽度,后面1个半字节是高度。例如:2D 02 40,宽度=2D0=720,高度=240=576。
②第8字节的前半字节之值表示图像的纵横比,见表7,后半字节之值表示帧率(每秒帧数),见表8。


表7 纵横比
-------------
值  比率
-------------
1
3  9:16
8
C  3:4
-------------
说明:
①注意图像尺寸数据是宽度在前高度在后,而纵横比数据是高度在比号前,宽度在比号后。
②QQ影音在播放mpg文件时,画面尺寸以高度为基准,再应用纵横比,获得画面宽度。例如某mpg文件中的图像尺寸为720*576,纵横比为9:16,那么QQ影音播放的画面尺寸为1024*576。


表8 帧率
-------------
值  帧率
-------------
1  23.976
2  24
3  25
4  29.97
5  30
6  50
7  59.94
8  60
-------------


六、DAT文件与MPG文件的异同
用电脑播放软件播放的时候,这两个扩展名好像没有什么区别,互相改名也没关系,但是如果要刻录到光盘还有区别的,有些可以播放有些不能播放。它们的异同如下:
①压缩标准相同:dat文件和mpg文件都是符合MPEG-1压缩标准的音视频数据流。
②显示格式不同:dat文件显示格式是CD Mode 2/CDXA/MPEG-1PS ,MPG文件显示格式是MPEG-1 Program。
③数据分包大小不同:dat文件是刻在VCD盘片上的数据,为了方便光盘数据的存取,所以就要 VCD刻录的标准,每个数据子包的大小为2324个字节,也就是正好一个扇区存储空间的大小。mpg 文件不是为了刻成VCD盘而准备的数据,所以数据子包可大可小,甚至整个 mpg文件就是一个数据包。
④文件头不同。DAT文件以“RIFF…CDXAfmt”开头,mpg文件以“000001BA”开头。


七、获取mpg文件图像宽高的代码

Private Sub Command1_Click()
Dim mpgData(7999) As Byte, startCode(3) As Byte
Dim mpgName As String
Dim mpgWidth As Long     '图像宽
Dim mpgHeight As Long    '图像高
Dim k As Long, st1 As String, st2 As String, st3 As String

startCode(2) = 1
startCode(3) = 179
mpgName = "全路径文件名"
Open mpgName For Binary As #1
Get #1, , mpgData
Close #1

k = InStrB(mpgData, startCode) '查找视频ES包
If k = 0 Then Exit Sub

st1 = Right("0" & Hex(mpgData(k + 3)), 2)
st2 = Right("0" & Hex(mpgData(k + 4)), 2)
st3 = Right("0" & Hex(mpgData(k + 5)), 2)
mpgWidth = Val("&H" & st1 & Left(st2, 1))
mpgHeight = Val("&H" & Right(st2, 1) & st3)
MsgBox "图像宽高:" & mpgWidth & "×" & mpgHeight

End Sub

回复列表 (共1个回复)

沙发

对一江秋水锲而不舍的研究精神表式深深地敬意

我来回复

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