解决wmv文件在vista下无法播放的问题

因为工作关系,同事解决wmv文件经过libasf解析重组后在vista下无法播放问题。
处理后的wmv在windows xp下工作正常,但是在vista平台,wmp显示无法识别此文件。比较微妙,可以大致推断,应该是对wmv文件处理后,丢失了某些必要的属性,而这些属性在windows xp下不需要,而vista对wmv格式要求比较严格,因此出现了问题。
在MS 的ASF spec 文档的描述中,有几个object是必须的:
HEADER OBJECT
FILE PROPERTIES OBJECT
STREAM PROPERTIES OBJECT
HEADER EXTENSION OBJECT
四个Object是必须的,看看原来的wmv解析重组代码,没有HEADER EXTENSION OBJECT这个对象,好的,问题应该在这里!
首相将HEADER EXTENSION OBJECT对象中所有的子对象都加入到处理后的文件中,测试通过!随后小心翼翼的进行HEADER EXTENSION OBJECT子对象的删除,经过一番简单的 重试-测试 之后, 最终只要保存HEADER EXTENSION OBJECT对象中的Extended Stream Properties Object即可。
好了,我们的ASF头部由原来的5K,降低到了600字节。

使用erlang进行text和binary文件的解析(parsing text and binary files)

parsing text and binary files
(form: http://wagerlabs.com/ openpoker author)
Erlang最初主要是针对电信应用开发,因此一个必须要完成的工作就是text和binary数据的转化。
在我们的通讯服务器开发课程中,解析text和binary数据,是我们经常要做的事情。再这里我要向大家讲述如何用erlang高效的处理这些事情。
选择Strings 或 binaries
Erlang本身没有string类型,其采用integer list来表现string,比如:”a string”,对应的list为[$a, $ , $s, $t, $r, $i, $n, $g]。在32位的Erlang虚拟机中,integer为4字节,因此在list的实现内部,每个元素除去4字节存储自身Value,同时还需要4字节作为指针指向下一个元素,因此要表现一个string的字符,我们需要付出8字节的代价,而在64位的erlang虚拟机中,这个代价还要翻倍。
为什么要关心这些呢?
在实际的开发中,每个同服务器的连接都需要分配一定的内存,用来发送接收数据。很多的互联网协议,比如XML其通过字符来表现。比如我们接收10K的XML消息,如果将这些消息转化为String进行解析,那么消息所占用的内存将为80K或者160左右,显然这是非常低效的。
当服务器的并发连接为成百上千时,减少每个连接所消耗的内存,将变的非常有意义。任何数据再经过我们的代码处理成另一种Erlang的数据结构后,原有的数据将进行垃圾回收。如果我们产生的垃圾越少,那么我们的垃圾回收越高效,我们的服务器也就越高效。
因此我们需要把我们通过socket接收的binary保持原样,不要尝试将其转化为strings。binary的解析是非常迅速的,并且具有非常方便的构造和匹配语法。而String却没有这些好处。
Erlang中所有的输入输出函数都可以操作binary数据。同一个程序,采用binary作为内部数据处理的程序肯定比采用String要高效。
好了,让我们用锤子将Erlang String牢牢的钉在坟墓里吧。

将文本文件作为binary处理
假设我们要解析一个以逗号分割的文本文件。我们将解析每一行中的文本,将分割出的各个内容放入list,同时所有的行也放入一个list。我们要处理的文件不是很大,因此我们可以一次加载整个文件。下面是代码的一个最初样子:

-module(act).
-compile([export_all]).

parse(Filename) when is_list(Filename) ->
{ok, Bin} = file:read_file(Filename),
parse(Bin); %% 作者此处原为”.”,应该为”;”

parse(Bin) when is_binary(Bin) ->
parse(Bin, [], [], []).

上面代码中的元素为空的list,作为初始参数,其用来保存累积的值(称为Accumulator,在Erlang这样的FP编程中,其作为参数也用来保存状态)。三个[],分别对应Field,Line和Acc,Field用来保存我们正在处理的字段(一个string),Line用来保存我们正在处理行的field 列表,Acc则是保存我们处理的Line的列表。
上面的代码中有两个parse函数(确切的说是一个parse函数,两个clause):第一个parse的参数为要操作的文件名称(string, a list of integers), 第二个parse函数的参数为binary,即我们读取的文件内容。这两个完成不同功能函数同样的名称,仅仅是通过guard来进行区别。你也可以将第二个函数命名为parse1或do_parse,这样更清晰一些。
Erlang中的函数通过函数名和参数个数来进行区分,采用fun_name/num_args的形式来表示一个函数。由此可知,parse/0, parse/1是不同的函数。我们上面代码中两个parse函数其实是一个函数,仅仅通过guard [...]