最近要做一个判断flv文件信息的程序,使用php对flv文件进行解析判断,百度了半天也没有对应的信息,后来又去csdn发帖子,得到的答复是目前还没有直接可以对flv文件进行处理的方法,于是决定放弃这个功能。不过后来终于让我在google上搜出一个牛人的blog,这哥们对flv的格式相当有研究。于是盯着看了好久,终于让我找到了一些的思路。尽管这个功能已经不做了,但是把思路写下来,总还是有用处的。

        不过我是第一次搞关于flv视频相关的东西,因此如果有说的不对的地方,希望有看到的同人不要骂我。年轻人嘛,总要有犯错误的机会。我犯了再改,改了再犯…………千锤百炼嘛。


        废话少说,对于flv文件,相信许多前辈已经研究了很多了。flv文件除了头只外,是由连续的tag组成的。每一个tag代表一个视频祯或一个音频祯或metadata,这些都不细说了。既然是要获取视频的尺寸,那么我们对视频进行下研究就ok了。


        首先第一个问题是如何定位一个视频tag,我们假定各个祯的尺寸都是一样的,那么只要找到第一个tag就ok了。


flv tags有下面的格式:

tag类型   1个字节:
   8 音频
   9 视频
   18(0x12) 脚本数据
   其它 保留


         先粘一个图,这个图是对一个flv文件进行二进制转换后的片段。




从第一行开始看,前12个字节是flv文件的头,具体的东西有人讲过我就不细说了。可以参考http://www.roading.net/blog/article.asp?id=104这个blog就可以了。

文件头之后,是以12开头的一段,这一段就是一个初始tag了。这个tag主要包含了一些基本的信息具体也可以参考上面的blog。我们要关心的是我选定的那部分。这部分就是一个视频的tag。视频的tag是以09开头的,且09前面的三个字节表示了前一个祯的大小。那么我们看一下09前的三个字节是000101,也就是257个字节。数一下就知道从第一行12开始到这三个字节之前,恰好是257个字节,因此可以断定000101之后就是一个视频tag了。

一个视频tag包含的信息如下:

//—————————————————————————
tag类型 0x09

tag数据大小 3个字节的视频数据大小

tag时间戳 3个字节tag数据应用的时间(毫秒)

tag时间戳扩展 1个字节的时间戳扩展,让时间戳变成4字节,本字节作为时间戳的高位.

streamID 3个字节的类id,总是0

视频tags的数据

//———————————————————————————————————–
视频tags的数据:

视频tags数据和swf文件格式中的VideoFrame是相似的.他们的数据是一样的

视频格式的数据的组成如下:

帧类型 4bit

1: 关键帧keyframe(视频中的关键帧,数据存储的是整个画面完整的数据,可以提取它来生成图片)
2: 中间帧inter frame(关键帧之间的状态,不完整的画面数据,需要依靠前面帧的数据生成)
3: 可任意使用的中间帧disposable inter frame(H.263 only)

视频编码id 4bit

2: Sorenson H.263(mencoder转换所使用的视频编码)
3: Screen video
4: On2 VP6
5: On2 VP6 with alpha channel
6: Screen video version 2

//—————

视频数据

If CodecID = 2
H263VIDEOPACKET
If CodecID = 3
SCREENVIDEOPACKET
If CodecID = 4
VP6FLVVIDEOPACKET
If CodecID = 5
VP6FLVALPHAVIDEOPAC
KET
If CodecID = 6
SCREENV2VIDEOPACKET

接下来的内容是关于视频编码的。也是我们需要关注的内容,因为我们需要获取的视频文件信息就在其中!!!

通过分析我们可以获取到CodecID为2,也就是说使用的是H263VIDEOPACKET的数据结构下面讲一下

H263VIDEOPACKET数据结构(其中UB代表usebit):

PictureStartCode UB[17]   和H.263 5.1.1相似
     0000 0000 0000 0000 1

Version   UB[5]   视频格式版本
     Flash Player 6 supports 0 and 1
TemporalReference UB[8]   察看 H.263 5.1.2

PictureSize UB[3]   图像尺寸:
     000: custom, 1 byte
     001: custom, 2 bytes
     010: CIF (352×288)
     011: QCIF (176×144)
     100: SQCIF (128×96)
     101: 320×240
     110: 160×120
     111: 保留

CustomWidth    If PictureSize = 000 UB[8]
     If PictureSize = 001 UB[16]
     否则不存在
     注意:UB[16]不一样UI16,这里不是字节交换的
     单位是像素

CustomHeight    If PictureSize = 000 UB[8]
     If PictureSize = 001 UB[16]
     否则不存在
     注意:UB[16]不一样UI16,这里不是字节交换的
     单位是像素
如果你仔细观察,就会发现,我选中的那段数据,恰好是与这个视频tag完全对应上的。因此通过php使用一定的位运算,就可以获取到flv文件的播放尺寸了。


第一次发这样的技术文章加上时间比较紧迫,只能先简单的写这么多。有兴趣的朋友可以参考我上面给出的那个blog地址,那位老兄才是真正的牛

 

原文:http://hi.baidu.com/pejaq/blog/item/0d17e9503bc9e25d1138c210.html

Comments are closed.

Post Navigation