技术

发布一条旧闻

本来写了一个 Python 2.4.x 的 patch,让 Python 可以 native 支持 IrDA socket。但是 Python 的维护者告诉我 Python 2.5 早就 freeze,除非 bugfix 否则不考虑接受新的 feature。因此就做了一个 Python 扩展,至于维护人员认可会这个 patch 并加入到 2.6 里面去就看我的努力吧。

扩展大约一周前就做好,在邮件列表上发布了,但是无人响应,似乎是 Python-CN 的用户有红外设备的不多。所以还是在 Blog 上贴出来:如果你希望用脚本语言对红外设备(手机、PALM、PDA)通信编程,请考虑我的这个扩展

扩展这部分的代码大部分是修改 Python 的 socket 模块的,所以 License 当然也是 Python 的。

代码 checkout 地址:
http://pymobilesync.googlecode.com/svn/trunk/irdasocket/

预编译好的 Py2.4 for Win32 的包下载:
http://www.dup2.org/files/irda-0.1.win32-py2.4.exe

该 win32 版本是在 Visual C++ Toolkit 2003 + .NET SDK 1.1 + Windows Platform SDK 环境编译。感谢Compiling Python 2.4 extensions with Microsoft VC Toolkit 2003这篇文章教我们如何让 distutils 和这些免费工具一起工作。

下面是测试代码:

  1. from irda import *
  2. irdaobject = irda()
  3. devicelist = irdaobject.discover()
  4. print devicelist
  5. firstHint(devicelist[0][3])
  6. secondHint(devicelist[0][4])
  7. irdaobject.connect('OBEX')
  8. irdaobject.close()
Topic: 技术

XviD 压缩后文件大小不符合预期结果的原因和解决方法

Oversized/Undersized explanations - Doom9's Forum 翻译而来

XviD 论坛有一个问题被反复提出:压缩后的文件大小和和指定的大不相同。本文试图解释文件大小不一致的原因,并指出解决之道。

让我们从基础知识开始,要知道弄明白问题发生的根源后就离解决它很近了。

基础知识

1. 量化
XviD 属于有损压缩,即它会把一些认为无用的画面细节忽略掉。每一帧画面会指定一个 quantizer (中文翻译为"量化因子"),然后据此进行压缩。
那么:
量化因子为 1("Q1") 意味着最高质量的图象和最大的文件(高码流)

量化因子为 31("Q31") 意味着最低质量的图象和最小的文件(低码流)

我们的目标是尽可能高的质量,以及尽可能低的码流...
=> 通常不用 Q1 做压缩,因为码流太高了(如果要备份 DVD,还不如保留原始的 MPEG-2 流)

Q2 则能得到很好质量的图像,而且比 Q1 来要小很多(quality/bitrate并不是线型的)。MPEG-4 被设计为低码流应用(相比较 MPEG-2 而言),我们可以假定对于 XviD 压缩来说,Q2 就是最高质量的压缩了。

2. 文件大小

相同的量化因子前提下,不同的视频源压缩后的大小也是不一样的。有的容易压缩,而高分辨率、大量细节、快速动作、明暗变化大的电影则很难压缩。

3. two-pass 压缩(或写成 2-pass)
为了在指定文件大小的情况下得到最大的质量,XviD 提供了 two-pass 处理模式。
- 首先固定量化因子为 2 压缩一遍,产生一组参考数据(stat 文件)

- 根据参考数据进行二次压缩,编码器不断调整码流来优化整体质量

那么就产生了三种情况:
● 1st pass 得到的文件比预料的大,在 2nd pass 压缩中编码器就不得不采取更高的量化因子
● 1st pass 得到的文件比预料的小,那么 2nd pass 中编码器就会在某些帧用 Q1 进行压缩

● 1st pass 得到的文件和预料的一模一样...当然从统计学上来说这是不可能发生的,而且这种情况下我们也不用再继续讨论了

现在问题发生了

有的视频太容易被压缩了(或者说 1st pass 得到的文件比指定的要小很多),于是过多的 Q1 帧被产生,但这会扰乱编码器的码流控制系统,最后就得到了一个 oversized 结果。

oversize的解决方案

1. overflow treatment 设置的调整
该设置被用于在 2nd pass 压缩中,设定码流控制进行调整的强度。取值越大,越能有效平衡 Q1 帧。
那么我的建议值是:
("Encoding type" > Two-pass - 2nd pass > "more...")
- overflow control strength: try 10 or 20
- Max overflow improvement: try 10 or 20

- Min overflow degradation: try 10 or 20

2. Quantizer capping
很简单,就是避免 XviD 用 Q1 压缩。
把每种帧类型[I/P/B]的最小量化因子都设成 2 (最大值还是保留 31)
1.1.0-final 之前是
("Advanced option" > Quantization),
从它以后是
("Quality preset" > Userdefined > "more..." > Quantization)

这样就不再会得到一个超大文件了。但...这种方式也导致根本不再有提高质量以得到预期码流的余地了。

除了上述两种编码器相关的解决方案,其实还有更好的思路:我们的目的是填充剩余的空间,那么就可以用更高的分辨率,更高的音频质量,更高质量的定制矩阵...等等

undersize的解决方案

从上面说的去举一反三吧...

如何提前预料到文件大小无法控制呢?

上面已经提到,1st pass 将产生一个日志文件,里面就包括 Q2 压缩结果的大小。那么如果这个数字和你预期的相差非常远,就很可能发生该问题了。

怎么看到 "size" 信息呢?

用 StatReader 打开该日志文件就可以看到了。该程序被包含在 official release 里面(比如 Koepi build)

Topic: 技术

今天看 slashdot

gnome 2.16 发布、MIPS/IRIX 即将退出舞台。

感觉最近 solidot 的人气下降了很多. 也没有什么心情把这些新闻贴出来了。

其实 100k 确实便宜,但委实没有太好的商业模式,而且团队前段时间的彷徨会让社区成员更加迷茫。即使它有了新主人,想挽回颓势也是相当的困难。

昨晚和老冒在 gtalk 上聊了好多东西,深深感到,管理团队太重要了。

Topic: 技术

DV-2-XviD 0.6 发布

见本站项目DV-2-XviD

0.6 版本解决了老版本只能同 XviD-1.1-beta2 协同工作的问题... 这个让人尴尬的 bug 拖到现在才解决实在是抱歉. 也因此觉得这个软件的可用性现在高了很多,这才敢放出来公开供人下载.

计划下面需要解决的问题依次是:
a. 文件大小/码流的精确控制
b. 对目标文件各项参数的配置

c. wxPython 相关问题

不过以上目标暂时要搁置了....

下面要集中精力, 早日完成我的手机同步程序。最近又免费弄了一部早期的 S60 机 (Nokia 3650), 正好又多一个测试设备.

Topic: 技术

男人得掌握一门手艺

很久很久以前,大概也有十好几年了。看 PC Magazine 里面的一篇专栏文章,说的是作者的小孩回外婆家玩,看到一台很久没有使用的 PC,于是问他老爹(也就是作者)能不能想办法让机器运行起来。作者本来以为这机器只是一台 286,结果居然是 386! 而且还有 4M 内存!!于是换了一块新硬盘,装了一套 Windows 3.1 和 WordPerfect (都是厂商送来评测的),于是小孩的假期就很快乐的和这台电脑为伴了..

接着作者充满感情的回忆到他父亲有一次给家里的旧车更换化油器的事情,然后感叹: 几十年前男人以自己修理汽车为荣,现在的男人则负责给家里的电脑升级(没错,有谁听说过女生帮自己男朋友修理电脑的??),虽然时代在变,但男人干起这种手工活来还是很自豪的..

下面是我本周末的经历:老婆的妹妹刚刚毕业,分配到北京某事业单位,住集体宿舍。但宿舍内的上网条件很不好,因为宿舍楼位于军队大院,整栋楼只有一个人接入了 512K 的线路,然后同宿舍楼有另外三个屋子从那里接入,4个人均分网络费用。我这小姨子还没有男朋友,于是这"布线"的责任就义无反顾的落在了俺的身上。

我这个周六的任务就是去把同一层的一个接入点那里再引一根线到她们屋内。具体这活怎么弄的就不细说了,总之得益于在网络中心工作时的经验,虽然以前没怎么动手干活(最难忘的一次是在墙上钻眼,结果怎么也把不住钻),但没见过猪跑总吃过猪肉。宿舍楼内的环境和我事先预料的没有什么太大差异,工具也准备齐全,很顺利的就搞定了。

在该上级接入点的称赞俺办事利落的时候,就想起了 PC Magazine 上的这篇故事. 再联想起上周电梯里听两个程序员讨论做 RJ-45 头的对话。遂有感叹:时代在继续前进,我们男人不仅仅需要会更换硬盘,还需要能压头、布线、跑管.. 下一步偶就要学习怎么利用铁锅或漏勺来研发 wifi 增益天线了.

写到这里,想起当年我父亲大修我们家自行车的情景了. sigh.. 我们就这样在手工活里慢慢长大、成熟、老去

远程控制 PC

刚工作的时候,接触网管系统,就知道先进的系统都支持报警模式。最初很不明白,软件怎么去向人报警呢?后来韩爽姐姐和冰河哥哥教育我,这个东西可以接一个modem,然后向寻呼机发一条呼叫(估计只能支持自动台了)。立时做顿悟状,幻想某天晚上睡梦中被一条寻呼信息惊醒,然后直扑图书馆或化学楼的 5505

后来接触湖南的项目,局方有一变态的需求,要邮件系统的监控程序可以实现声光报警。我看了需求很诧异这个东西是怎么答应下来的,于是问 ray 同学,回答是计划调用 mpg123 之类的东西放首歌,至于光报警的实现方式,还没有太想好(后来看到的 MIT 学生自制的 Disco Dance Floor 到是一个不错的方案)。

上面说的是利用 PC 的声卡/音箱、串口来产生信息的方案,但是有谁考虑过怎样远程控制 PC 产生动能呢??

请看 Engadget 的自动猫咪喂食器

Topic: 技术

Python ctypes 里使用 create_string_buffer, addressof, string_at

已经写了一篇 blog 里面介绍了如何传入结构体指针的方法,而前不久发现了另外一种传入一整块 buffer 的方案,不用定义 Structure class,直接类似 malloc 那样的方法去执行,就是 create_string_buffer addressof string_at 系列函数,感觉更接近底层调用.

首先修正上篇文档里面的一个问题,就是 load 这个方法已经取消了(当时我使用的好像是 0.9.9.3 版的 ctypes),LoadLibrary 这个接口随着 ctypes 1.0 的发布并被集成进 python 2.5,应该是正式确定了名称。

其次注意的是根据源代码里面对函数不同的声明,还得选择采用 cdll 还是 windll 来实例化一个动态库,用 WINAPI 声明的函数需要用 windll.LoadLibrary(dll_file_path)。因为不同的声明导致参数传递的方法不一样,我自己就是费了好长时间的尝试,才搞清楚为什么总是报错"rocedure called with not enough arguments (xx bytes missing) or wrong calling convention"。ctypes 的手册里面还提到另外有 oledll, pydll 两种类型.

如果一个 dll 里面即有普通方法定义的函数,也有 WINAPI 定义的函数,而你只希望只 Load 一次动态库,那么就需要 WINFUNCTYPE 或者 CFUNCTYPE 这样的方法来指定不同的函数类型了。

大家都应该机器上安装 XviD 解码器了吧,:)
现在我们分别用两个不同的方法取出 XviD 编码器的缺省配置(C 源代码参考 xvidcore-x.y.z\vfw\src\driverproc.c)

  1. from ctypes import *
  2. DriverProc = windll.LoadLibrary("c:\\windows\\system32\\xvidvfw.dll").DriverProc
  3.  
  4. configsize = DriverProc(c_int(0), c_int(0), c_int(0x5000), c_voidp(0), c_voidp(0))  
  5. # 获取结构体大小 configsize
  6.  
  7. did = DriverProc(c_int(0), c_int(0), c_int(0x0003), c_voidp(0), c_voidp(0))
  8. # 获取访问句柄 did
  9.  
  10. config = create_string_buffer(configsize, configsize)
  11. # 创建 buffer, 返回一个 Python 对象
  12.  
  13. pconfig = addressof(config)
  14. # buffer 的地址,让我想起了 C 里面的 &
  15.  
  16. DriverProc(c_int(did), c_int(0), c_int(0x5000), pconfig, c_voidp(0))
  17. # 这次调用就是把缺省配置复制到传入的内存区域内
  18.  
  19. s = string_at(pconfig, configsize)
  20. # 最后我们从 pconfig 地址里的内容生成一个字符串对象出来

上面的代码通过 cdll + WINFUNCTYPE 来写就是

  1. from ctypes import *
  2. from ctypes.wintypes import *
  3. xvidvfw = cdll.LoadLibrary("c:\\windows\\system32\\xvidvfw.dll")
  4. # 看好了,这里可用的是 cdll
  5.  
  6. prototype = WINFUNCTYPE(LONG, DWORD, DWORD, UINT, LPARAM, LPARAM)
  7. # LONG 是返回值,DWORD, DWORD, UINT, LPARAM, LPARAM 是参数列表
  8.  
  9. paramflags = (1, "driverid", 0), \
  10.              (1, "hdriver", 0), \
  11.              (1, "umsg", 0), \
  12.              (1, "para1", 0), \
  13.              (1, "para2", 0)
  14. # 设定一下参数表,以及缺省参数,就可以用 key=value 的方式来传递了
  15.  
  16. x = prototype(("DriverProc", xvidvfw), paramflags)
  17. # ...
  18. configsize = x(umsg=0x5000)
  19. # 这里只传入一个参数,其它的就自动用缺省的了;而且无需 c_int 这样来转换
  20. did = x(umsg=0x0003)
  21. # .... 以下就不需要注释了吧
  22. config = create_string_buffer(configsize, configsize)
  23. pconfig = addressof(config)
  24. y = x(driverid=did, umsg=0x5000, para1=pconfig)
  25. s = string_at(pconfig, configsize)

最后要说的是通过 dumpbin.exe /exports dll_file_path,就可以查看一个 dll 里面有哪些函数是被 export 出来,可以给我们来调用的(我自己猜测) . dumpbin.exe 可以从 masm32 里面免费获得

update: 在上述第一个例子里面,传入的参数用 addressof 去做一次转换并不是必须的. 可能 ctypes 会在内部自动处理

Topic: 技术

Win32 下的音视频软件(开源的和免费的)

下面是科普时间...

LAME
lame 号称是这个星球上 MP3 编码音质最佳的编码器,而且是 GPL 的.

在我的 DV-2-XviD 里面也是采用 lame.exe 来压缩 DV 的音频的。除了 lame .exe 这个命令行工具外,这里可以找到很多基于 lame 的程序。我现在使用的是 winLAME,它除了支持文件转换外,还可以 rip CD,包括去 freedb.org 上寻找 CD 信息,至少我刚从卓越买来的《Unplugged in New York》和《时光漫步》都能被正确识别出来

ffdshow 和 FFmpeg
FFmpeg是一款强大到有些变态的多媒体编码库。它是在 Linux 下开发的,核心是 libavcodec(就是win32下说的Codecs) 和 libavformat(用于文件格式的处理),ffmpeg 只是其前端命令行程序。由于专利权问题(大部分影音编码都是有专利的),Linux 发行版本通常不会把 ffmpeg 作为发行缺省部分。
ffdshow 从其命名来看应该是脱胎于 ffmpeg,主要的解码库也用的是 libavcodec,可以说是 ffmpeg 的 DirectShow 版本。当然随着发展,它已经远远不限于 livavcodec 了,还增加了许多后处理的特性以增强低质量视频的播放效果。要说的是这些特性也多半来自 Mplayer——另一个 Linux 下开发的媒体播放器项目,其实 Linux 下多媒体处理还是很棒的。

BTW,从 Youtube 下载的 flv 格式的文件就是用 ffdshow 来enable相应的 decoder filter 就可以了.

AviSynth
AviSynth 简直可以用神奇来形容。首先解释一下 Frame Server 的概念,通常我们所谓的多媒体处理都是直接处理文件,处理网络媒体流的现在也很常见,那么 Frame Server 就可以说是生成"程序媒体流 or 来自程序的媒体流"的程序。再举一个例子,我们访问 http 服务器请求的只是一个 URL,但是这个 URL 里面可能囊括了图片、视频,现在还有 AJAX 程序... 最终组织成一个丰富多彩的页面;AviSynth 就是一种这样的服务器,它对外展示的只是一个 .avs 脚本,但这个脚本则可以把原视频文件做各种各样的处理,打开这个 .avs 文件得到的就是做过处理以后的视频流。
通常那些压缩 DVD 的人都要写 avs 脚本来去拉丝修改分辨率,渲染一下比如加亮度.. 后,再调用 Codecs 来压缩 avs 流.
AviSynth 目前只能在 Win32 上工作,不过支持 Linux 的 AviSynth 3.0 正在开发中,3.0 还将包括一个 Gstreamer 插件.

另一个有关的消息是 AviSynth 似乎打算放弃维护自己的脚本引擎,而会改用 Python

VirtualDubMod 和 VirtualDub
由于专利问题,VirtualDub 一直拒绝直接支持 MPEG-2 文件的处理,但人们的需求是压缩 DVD,于是就有了一票修改版本们的出现,VirtualDubMod 便是其中的佼佼者,它除了支持 MPEG2 以外,还增加了支持 VBR MP3 等特性。
虽然 VirtualDub/VDubMod 号称是一个视频捕获和处理程序(包括视频编辑),但我一直都用的是它的命令行功能:和 avs 类似,写一段小的 vdub 脚本,然后交给 vdub 去执行。在我的 DV-2-XivD 程序里面,整套执行流程如下:
 1. 写一个 vdub 脚本,将 PCM/Wav 格式的音频从 DV avi 里面分离出来
 2. 调用 lame,将声音压缩成 mp3
 3. 写一个 vdub 脚本,将 DV avi 做 XviD 的 1-pass 压缩,生成 stat 文件

 4. 写一个 vdub 脚本,执行 2-pass 压缩,并且和 mp3 文件 合并到最后的 avi 文件里.

AutoGK 和 DVDdecrypter
上面介绍的全都是 GPL or LGPL 的软件,现在来介绍两个免费软件(freeware)
虽然已经有了很多工具,但把一张 DVD 制作成一张 700M 的 XviD/DivX 还是很麻烦的,于是就有了 Gordian Knot 这个软件包,但我实在搞不明白 Gordian Knot 这个名字是自嘲,还是标榜自己是亚历山大之剑那样的解决方案。
事实上 AutoGK 才是真正的亚历山大之剑,它和 DVDdecrypter(原站点 DVDDecrypter.com 已经在压力下关闭了)的配合可以说天衣无缝,很轻松就能把 DVD 压缩好。我家那些宝宝反复看的 DVD 全都是这么处理的,而且不再担心盘片被宝宝弄坏.

我的 DV-2-XviD 也是来源于 AutoGK,包括 vdub 脚本,我也是学着 autogk 的中间处理结果来生成的.

Celtic Druid
这个不是软件,而是一个网名。这个家伙最擅长的就是在 win32 下 build 从 cvs 里 checkout 出来的代码并发布,doom9 这样的论坛经常可以看到大家谈论 Celtic_Druid build,AutoGK 通常就用他编译的 XviD。

原始站点(celticdruid.no-ip.com/)被 GFW 了,不明白为什么.. 不过还是有很多 mirror 可以访问,很容易可以搜索到。他编译的包括:Media Player Classic、ffdshow、XviD、x264...

====================================

最后是广告时间...

DV-2-XviD
用 Python 写成,GPL
功能是合并多个 DV avi 文件,在画面底部增加拍摄时间码,压缩成 XviD.
目前已知的问题包括:
 1. 只能和 xvid-1.1-test2 一起工作 :(
 2. 压缩 XviD 的文件大小控制有问题

 3. wxPython 窗口在压缩过程中会失去响应

原来我的 DV 是压缩成 MPEG2/SVCD 保存的(而且是用的没有合法许可的软件),最近一年多以来,开始用 XviD 压缩,感觉不错。计划修补完上述缺陷后,再考虑是不是改成 MPEG4 AVC 方案,比如 x264,如果这样的话,这个项目的名字可能也需要改成 DV-2-MPEG4,或者 DVgk?

Topic: 技术

AVI 文件格式(dv_info.py 的文档)

首先声明:本文的内容都是我从开发过程中总结出来的,以我的理解在尽可能短的篇幅里对 DV AVI 文件的分析作介绍。真要作开发还需要参考原始的文档。

AVI 文件总是以 12 个字节开始的,就是 'RIFF' + size + 'AVI '。这里 size 是一个 4 字节的整数,声明其后的字节数(包括'AVI '这4个字节数)

现在问题就出来了,这样的格式就是限定了 size 的最大取值只能是 4G,后来人们就扩展了 AVI 的结构——当分析到声明的字节数后,如果后面是扩展格式,那么就继续分析。

扩展部分类似 AVI 的格式,只不过从 'AVI ' 变成了 'AVIX',而且可能有多个扩展部分。因此这一部分的分析代码就是:

head = struct.unpack('<4sI4s', avifile.read(12))
if head[0] != 'RIFF' or head[2] != 'AVI ':
return None
while True:
xread = readChunk(avifile, head[1]-4, 0) # 分析剩余的数据
s = avifile.read(12)
if 0 == len(s): # 如果没有什么可读的了,自然是分析完了
break
head = struct.unpack('<4sI4s', s)
if head[0] != 'RIFF' or head[2] != 'AVIX':
break

由于 AVI 内部嵌套的数据块的格式也类似 4bytes info + size + data 这样的结构,因此 readChunk 被设计成一个递归函数,返回值为 0 或 -1,中途解析失败就返回 -1,根据此返回值退出嵌套调用。(回过头来看这样一段程序,递归调用分析的可读性很糟糕,主要是因为开始编程的时候对 Python 没有太多的认识所致)

可能是为了便于编程,各个数据块被设计成 4 字节对齐的,但 data 的大小未必是 4 的整数倍,从文件中读出来的 size 只是表示 data 的长度,有时候必须计算对齐。下面两行语句就是作这个的:

page = (head[1] - 1)/4
chunksize = (page + 1) * 4

为了便于播放器去 seek 一个特定的位置,比如从文件的第 12 分 32 秒开始播放,需要一个索引方案可以快速定位到相应的数据。这就是 'idx1' chunk 里面定义的东东。但传统的定义里面偏移量最大只能为 4G,因此扩展格式里面增加了 super index,或者说 index 的 index,里面可以放 longlong 的 64 位整数来避免这种寻址困境,估计在我有生之年都不会有这么大个的数据文件问世。

readChunk 函数的主要功能就是生成一个 index 列表,然后从这个列表的最前面和最后面分别 seek 到相应的数据存储区域,找出时间码。如果发现 AVI 里面有 super index,就在 readChunk 返回后,再根据 super index 生成 index 列表。程序里面这个列表变量名为 offset

分析 DV 格式获取时间的函数是 readtime。DV 可能是每次记录 12000 字节数据(类似磁盘扇区的概念??),因此在每 12000 字节数据里面都会存储一个时间码。我的当时参考的代码里面在每个 index 指向的数据块里循环了 15 次还是 10 次,但我发现我这里只能循环 12 次就碰到了数据的尽头,后来估计是 PAL/NTSC 的差异,也就没有继续追究下去。

Topic: 技术

AVI 介绍

计划把这一年多以来业余作 Python 相关开发的一些知识整理一下,这是第一篇。

迄今还记得第一次看到的 AVI 文件,在 windows 3.1 上,一个邮票大小的窗口里,一个人(男女实在看不清楚)在滑帆板。那是我们不知道从哪里弄来的一个软件包(当然现在知道是一个 VFW 驱动)里面附带的一个 sample,宣称装了这个东东后计算机就进入多媒体时代;随着后来 .dat/.mpg (VCD) 的流行,对比下 avi 给我的印象就成了落后,低质量的代名词。

进入 BT 时代后,突然就发现下载来的电影文件几乎都是 avi 文件,通常是 700MB,就拥有不输于 DVD 4G 容量的数据所包括的音视频质量。就有了这么一个疑问——AVI,它到底是个什么玩意儿。

专业的回答是这样的:AVI 是一种容器(container)格式。通常来说没有把音视频一起编码的方案(用大脚趾都能想到同时编码的效率一定不高),而是独立编码,然后打包在这样一个容器里面,做成一个单独的文件供人使用。播放的时候首先将容器里包含的不同的数据流分离出来(splitter),再交给不同的引擎(Codecs)去解码(decode),播放器还得根据容器包装的规则让视频音频能同步起来。我们现在使用的那些 avi 文件准确说是包括了 XviD/DivX 压缩的视频流和 AC-3 or MP3 音频流的 container .. 随 XP/2000 提供的缺省多媒体附件包括一个 avi 的 splitter,以及一个 mp3 的 decoder。只要再安装一个 XviD 的解码器和一个 AC-3 的解码器基本上就可以看所有的影片了。

事实上 rmvb 也是一个 container,无需 real 播放器,有一个 rmvb splitter 和合适的 codecs,就可以在任何支持 dshow 的播放器欣赏 rmvb 了;DVD 上的 .vob 就是另外一种容器,里面除了 MPEG-2 图象和 DTS/Dolby 音频外,还会包括 n 条字幕流。

言归正传,qyb 为什么要研究 AVI 格式呢?因为在 DV-2-XviD 这个软件的功能里面,有个需求就是从 DV 抓取的 AVI 文件里面,获取拍摄该视频当时的时间。我要作的事情一是把视频流从 AVI 里面分离出来,然后再从视频流里面获得保存在里面的时间戳。

网上很容易可以搜索到一篇关于 AVI 格式的文档(链接是一个 pdf 文件!),它组织的很好,是我一开始起步时的主要参考,但后来处理 >1G AVI 文件的时候感觉这篇文档描述并不清楚。最后还是依靠这篇完成了 avi 分析部分。

本期科普工作到这里结束,计划下一期简单汉化一下 AVI 相关文档... 可能更类似程序文档吧。

Topic: 技术
订阅 RSS - 技术 | BT的花