网站导航免费论文 原创论文 论文搜索 作业答案 网学软件 学术大家 资料中心 会员中心 问题解答 原创论文 论文素材 设计下载 最新论文 下载排行 论文上传 在线投稿 联系我们
返回网学首页
最新论文 推荐专题 热门论文 素材专题
当前位置: 网学 > 交易代码 > Delphi精品代码 > 正文
Delphi写的RM文件分析器源代码
来源:Http://myeducs.cn 联系QQ:点击这里给我发消息 作者: 用户投稿 来源: 网络 发布时间: 10/11/06

最近在研究RM格式文件,我想自己设计一个RM文件编辑器,先设计了这个分析器,界面做的很简单,不过已经具有简单的编辑功能:

以下是可执行文件
点击下载该文件

以下是该程序的源代码,其中的RealMediaFile.pas文件是核心代码
点击下载源代码

PS:设计中发现的一个问题:如何判断最尾部数据包的时间长度?对于音频数据包的时间长度都是116毫秒,也就是说每个音频数据包保存了116毫秒的音频数据,但是对于视频数据包呢?特别是VBR压缩格式的视频数据包,由于我无法判断最尾部数据包的时间长度,所以用这个程序连接RM文件时生成的文件在播放时会出现错误。如果有那位高手知道的一定告诉我,谢谢啦。

从逻辑上讲,RM文件由不同的流组成,每个流由一个MDPR头、零个或多数据包、一个INDX索引块组成,每个流都有一个唯一的媒体流标识。RM文件的实际存储结构由各种格式的块组成,每个块又可以包含子块,每个块都有一个size成员以确定块的长度,各个块在文件中的基本顺序如下:

.RMF块
PROP块,其中num_streams成员决定了会有几个MDPR块和INDX块
MDPR块,这个块会有多个
CONT块
DATA块,这个块中包含了多个数据包子块,不同流的数据包以时间为顺序交差存放
INDX块,这个块也会有多个,每个块中包含索引记录子块

PROP块的data_offset成员指出了DATA块在文件中的位置,DATA块中的5个成员之后就是第1个数据包,DATA块中前5个成员占18字节,也就是说PROP块的data_offset成员加上18就是第1个数据包在文件中的位置。数据包长度都不一样,由数据包length成员可以确定数据包的长度,读取第1个数据包确定其长度,计算出下一个数据包在文件中的位置,读取下一个数据包,以此类推可以实现数据包的历遍。

MDPR块、数据包子块、INDX块,都有一个stream_number成员来确定媒体流标识,INDX块中包含了多条记录,每条记录包含该媒体流的数据包在文件中的位置,但并不是所有的数据包都有对应的索引记录,相隔一定的时间差才对应一条索引记录,我设计的这个程序是相隔一定的时间(音频流1857毫秒,视频流83毫秒)后的关键帧数据包才建立一条索引记录(数据包的flags成员为2时表明这个数据包为关键帧数据包)。试用不同的编辑器后发现:时间差多少、是否是关键帧并不重要,只要相隔一定的时间建立一条索引记录,播放器都可以正常播放。

利用我这个程序打开一个RM格式文件,左边的树形窗口就可以看到各个块在RM文件中的情况,使用菜单“工具/读取数据包”可以历遍查看文件中的所有数据包,使用菜单“工具/索引时间差”可以查看建立索引记录时的最小时间差,使用菜单“工具/导出索引记录”可以将索引记录导出成用空格分隔的文本数据文件,这种文件可以用Excel或记事本打开查看。

说一下RM文件的基本数据格式,RM文件的基本数据由:无符号32位整型(UINT32)、无符号16位整型(UINT16)、无符号8位整型(UINT8)、ASCII字符串组成。需要注意的是整型数据写入文件的方向与Delphi的数据写入方向不一致,这种情况在很多文件格式中都会遇到,比如说十进制整型值2904000,在RM文件中为002C4FC0,如果用Delphi的读写函数将整型值2904000写入文件,就会变为C04F2C00,所以从RM文件中读取或写入整型数据时需要将数据调一个头,具体的代码可以参考RealMediaFile.pas文件中593行开始的代码,这些代码负责从TStream流中读取写入数据,其它方法都是调用这几个函数来完成对RM文件中基本数据的读取。

基本的数据文件格式有两种,一种是文本格式,一种是二进制数据格式,RM文件是二进制数据格式。

随便找了一个RM文件,它的第一个INDX块在16进制编辑器中如下:

002a43f0h: F2 37 C5 11 F2 37 C5 11 F2 49 4E 44 58 00 00 02 ; ?????INDX
002a4400h: 1A 00 00 00 00 00 25 00 00 00 2A 46 13 00 00 00 ; %*F.
002a4410h: 00 00 00 00 00 03 76 00 00 00 00 00 00 00 00 07 ; v
002a4420h: 42 00 01 2E EB 00 00 00 83 00 00 00 00 0E 83 00 ; B?..?.?
002a4430h: 02 50 97 00 00 00 FD 00 00 00 00 15 C5 00 03 79 ; .P?..?.?.y
002a4440h: CA 00 00 01 76 00 00 00 00 1D 07 00 04 5A 24 00 ; ?..v..Z$.
002a4450h: 00 01 E8 00 00 00 00 24 48 00 05 66 A2 00 00 02 ; ..?$H..f?..
002a4460h: 61 00 00 00 00 2B 8A 00 06 8D 79 00 00 02 D9 00 ; a.+?.峺?

从002a43f9开始的4个字节49 4E 44 58是object_id,固定为INDX;紧接的4个字节00 00 02 1A是size,转换为十进制为538表明这个INDX块的总长度为538字节;紧接的2个字节00 00是object_version,一般为0;紧接的4个字节00 00 00 25是num_indices,表明这个INDX块中有37条记录;紧接的2个字节00 00是stream_number,表明这个INDX块对标识为0的媒体流数据包进行索引;紧接的4个字节00 2A 46 13是next_index_header,表明下一个INDX块从文件的2770451字节处开始。

接下来就是索引记录,开始的2个字节00 00是object_version,一般为0;紧接的4个字节00 00 00 00是timestamp,表明该索引记录对应的数据包时间戳为0毫秒;紧接的4个字节00 00 03 76是offset,表明该索引记录对应的数据包在文件的886字节处;紧接的4个字节00 00 00 00是packet_count_for_this_packet,表明该索引记录对应的数据包是该媒体流中的第1个数据包(编号从0开始)。

接下来是第2条索引记录,开始的2个字节00 00是object_version,一般为0;紧接的4个字节00 00 07 42是timestamp,表明该索引记录对应的数据包时间戳为1858毫秒;紧接的4个字节00 01 2E EB是offset,表明该索引记录对应的数据包在文件的77547字节处;紧接的4个字节00 00 00 83是packet_count_for_this_packet,表明该索引记录对应的数据包是该媒体流中的第132个数据包。

以此类推,可以读出所有的索引记录。

确定INDX在文件的位置

有两种方法:第一种,PROP块的index_offset成员指出第一个INDX块在文件中的位置,每个INDX块的next_index_header成员指出下一个INDX块的位置。第二种方法,在INDX块之前是:.RMF块、PROP块、多个MDPR块、CONT块、DATA块,这些块都有size成员指出块的大小,依次读取这些块,将它们的size成员加起来就是第一个INDX块在文件中的位置,这种方法适合那些PROP块的index_offset成员有错误的RM文件格式。

网学推荐

免费论文

原创论文

浏览:
设为首页 | 加入收藏 | 论文首页 | 论文专题 | 设计下载 | 网学软件 | 论文模板 | 论文资源 | 程序设计 | 关于网学 | 站内搜索 | 网学留言 | 友情链接 | 资料中心
版权所有 电话:013574892963 QQ:3710167 邮箱:Educs@163.com 网学网 [Myeducs.cn] 您电脑的分辨率是 像素
Copyright 2008-2015 Www.myeducs.Cn All Rights Reserved
湘ICP备09003080号