从ffmpeg中提取wma pro解码器

http://blog.csdn.net/xcgspring/article/details/5107932


经过一周半的努力,终于从ffmpeg中提取了一个包含asf解析功能和wmapro解码功能,并能在VC2005上运行的工程,当然现在还很简陋,呵呵。

这个是我第一次从ffmpeg中提取解码器模块,ffmpeg是个相当大的工程,这给提取工作带来了很大的麻烦,更大的麻烦其实在于ffmpeg遵循了C99的标准,而VC不支持。以前没怎么接触C99,经过这次移植对它稍稍了解了一下,也许是我C的水平不够,我感觉有些规定像是败笔,引用国外牛人的话就是——“stop adding shits to C”。

总之,不论C99给C语言带来了什么影响,它给我的提取移植工作带来了很多的麻烦。

 

谈谈我的提取经验吧:

1.       首先,是确定你的解码器依赖哪些文件。

理论上讲,要知道依赖的文件,最好是将源代码过一遍,建立一个测试工程,将找出来的那些文件添加进去,编译,看看有没有缺失函数的错误,再寻找缺失的文件,一直这样做下去,直至测试通过。

但ffmpeg是个很大的工程,内部的依赖关系很复杂,用上面的方法,估计即使能成功,耗时也肯定很多。当初我浏览了一遍ffmpeg的源码,搞清楚大体架构之后,我觉得上面的方法对于第一次使用ffmpeg的我来说,可能还不如直接看懂解码器原理,然后自己写一个来得快。

当我苦苦的啃代码的时候,别人教给了我一个简便的方法——就是使用ffmpeg自己的configure命令来定制编解码器,然后通过生成的.o文件来判断需要的.c文件。这是一个很快也很保险的方法,于是我定制了一个只包含asf解析、wmapro解码、pcm_s16le编码和wav封装的ffmpeg工程,其他没用的都disable掉。试了几次,直至测试解码通过,然后根据生成的.o文件轻易的就确定了相关的.c源文件,当然,为了得到一个clean的针对wmapro解码的工程,还有很多冗余代码要删除,不过相对于原来面对整个ffmpeg工程来说是简单多了。

还有最好使用libavcodec和libavformat库里面的API自己写一个main函数,这样不仅可以加深对ffmpeg架构和解码流程的理解,还能大大提高删减工作的效率。

2.       然后,就是向VC 2005移植了。

为什么要移植到VC呢?一是我想做一个兼容VC、Linux和VDSP的工程,以后的定点和优化工作就能很便利。还有最好在VC 2005以上的版本,VC 6会遇到额外的问题。

将源文件添加到VC的工程中,编译会遇到很多问题。

 

C99相关:

01.   首先很多问题是关于stdint.h和inttypes.h,在gcc的标准库中找到这两个文件,对照它们的对使用了的类型进行相应的定义即可。注意64位数据的定义VC上为__int64。

02.   还有就是结构体全局变量初始化,C99中支持比较灵活的初始化方式,改成C89的方式就行。

03.   C99的数组初始化大小可以是变量,改为动态内存分配malloc。

04.   数字后缀,如”ll”之类,我感觉作用和原来的强制类型转换差不多,如100ll等价于(int64_t)100。

05.   宏可以带变元,在宏定义中用省略号(...)表示。内部预处理标识符__VA_ARGS__决定变元将在何处得到替换。例:#define MySum(...) sum(__VA_ARGS__),没想到替换方法,程序中用到的地方就av_log和dprintf两个信息输出函数,可以去掉。

 

平台相关:

01.   关于inline关键字,VC中对应__inline,snprintf函数,VC中对应_snprintf。

02.   使用了strings.h文件中的一些函数,如strcasecmp()函数,VC没有此头文件和相应函数,得自己添加。Google了一下,解决方法如下:

int strcasecmp(char *s1, char *s2)

{

   while  (toupper((unsigned char)*s1) == toupper((unsigned char)*s2++))

       if (*s1++ == '/0') return 0;

   return(toupper((unsigned char)*s1) - toupper((unsigned char)*--s2));

}

 

int strncasecmp(char *s1, char *s2, register int n)

{

  while (--n >= 0 && toupper((unsigned char)*s1) == toupper((unsigned char)*s2++))

      if (*s1++ == '/0')  return 0;

  return(n < 0 ? 0 : toupper((unsigned char)*s1) - toupper((unsigned char)*--s2));

}

03.   字节对齐设置

GCC:

struct unaligned_64 { uint64_t l; } __attribute__((packed));

VC:

#ifdef WIN32

#pragma pack(1)

#endif

struct unaligned_16 { uint16_t l; };

#ifdef WIN32

#pragma pack()

#endif

大概就这些了,具体的C89和C99的标准可以参见这几篇文章。

http://www.kuro5hin.org/?op=displaystory;sid=2001/2/23/194544/139

http://blog.csdn.net/ustcgy/archive/2009/12/17/5024944.aspx

http://blog.csdn.net/phlexii/archive/2006/06/30/855263.aspx

(……写起来没多少,当时做还是比较难的,还有一些地方想不起来了,记忆力不行)


你可能感兴趣的:(c,工作,struct,gcc,测试,Google)