北京理工大学 20981 陈罡
上一篇,大致分析了一下目前比较有名的开源的flash播放器的构成以及大致需要的技术和
移植到symbian、win mobile平台的可行性。最后,我们还是选择flirt做为入手的起点,
毕竟它是不借助外部的库,自己自成体系进行swf文件的解码、计算的。(当然,这里的
自成体系是指不借助direct 3d和open gl之类的库,以及boost之类的库;其实本质上,flirt
仍然要依赖三个主要的库,jpeglib,zlib和libmad)。
尽管有了nokia symbian的open c的强力支持,移植起来也并非一件很容易的事情。偶就
把移植的过程以及遇到的难点整理一下,一来为了备忘,二来为后来者铺平一些道路。
下面的全部移植过程均采用flirt20060121的最新版本来做的,到source forge上面下载源代码
自然是必不可少的预先准备工作,以及symbian 3rd sdk,open c安装这些就不赘述了。
(1)将代码放入symbian项目中
这一步主要是把代码拷贝到新建的symbian工程目录,然后修改mmp文件,将所有的.c文件的后缀
改为.cpp,然后添加open c所需要的lib和include路径,例如:
systeminclude /epoc32/include/stdapis
library libc.lib // 这个是open c的library
library libm.lib // 这个是math.h需要的一些数学库函数
(有用过偶的测试代码的朋友反映还需要加入estlib.lib,才能编译过去。这一点很奇怪,
偶采用vs2005+carbide.vs 3.0.1+s60 3rd sdk fp1是没有加这个lib也可以运行的)
(2)尝试编译一次
呵呵,这一次必然是编译不过去的。偶第一次编译竟然出了980多处错误,已经足以让偶处于
半昏迷状态。不过这次编译,可以让偶从宏观上了解一下,整个项目目前都在哪些地方存在问题。
例如某些linux相关的头文件找不到,某些linux专用的函数,某些跟硬件接口有关的,例如mixer
某些库有关的jpeglib, zlib, libmad之类的接口和头文件等等。这样会把问题暴露得比较彻底一些
为了下一步开始动手做port有一个整体的overview。
(3)从全局的定义开始入手
主要就是types.h和dd.h这两个文件了。从功能上来看,dd.h主要负责debug log输出的,这些是
采用stdio库的文件操作函数来完成的,在这个地方可以考虑采用RFileLogger类来完成log日志操作
替换。然后就是关于一些数学库函数的处理了,例如有下面这一段:
#ifdef WIN32
#include
#define rint(a) floor((a)+0.5)
#define isnan(a) _isnan(a)
#define finite(a) _finite(a)
#endif
这是对ieee浮点数支持的函数,这里的nan的意思是not a number,不是一个数字,代表当前的浮点数
按照ieee的浮点数标准来说不是一个数字,还有finite之类对无穷大/小之类的定义。这些数学函数主要
是用来保证double类型的浮点数在解码和运算过程中是合法的。必需要有喔,否则symbian的模拟器就会
出现kernel exec 3的那种不知所云的错误退出。(这是偶的惨痛教训)
再有就是数据类型的定义了,这里需要说一下的就是SInt64,用的是long long。但是这个数据类型在
symbian中是没有的,arm的core通常最大只有32位,因此需要把它改为32位的即可。所幸在程序中没有
怎么用到这个变量。然后就是boolean的定义了,这些基本数据类型的定义相信有些经验的开发者都可以
很优雅地处理掉。
(4)修改变量命名以及强制类型转换
这个纯粹是浪费时间了,这个flirt是采用纯c预言编写的,因此通篇采用经过封装过的dd_malloc(),
dd_realloc(),dd_free(),这些都是void *类型的内存分配函数,在原始的代码中都是直接赋值的方式:
struct ABC * pabc = dd_malloc(sizeof(struct ABC)) ;
类似这样的代码,这在c99编译器上编译是没有任何问题的,但是对于c++的编译起来说,就严重成为一个
error,因此,需要一个个老老实实地修改为:
struct ABC * pabc = (struct ABC *)(dd_malloc(sizeof(struct ABC))) ;
这样的代码才可以,整个过程很冗长,让人乏味,把这些改完偶已经口吐白沫,又一次半昏死状态。。。
或许可以通过某些编译选项解决这个问题,不过为了防止链接的时候.c的obj与.cpp的obj发生欲哭无泪的
问题,只好忍了。再有,就是代码里面有不少地方、变量命名都是采用new, class, list之类c++保留字
做为变量名(list不是,它是stl模板保留字了,请不要嘲笑偶,这里只是举个例子)命名,因此编译的时候
肯定是过不去的。
解决方法很简单,在原有的保留字命名的后面加上个_v, _p即可。
例如:
int new ;
可以改为
int new_v ;
诸如此类,不再一一讲述。
(5)对于字节存储和表达式顺序的修改
这里就是关键了,需要非常重视。打开swfcore/format/read.cpp就会看到关于表达式的处理顺序问题
这里只举一个例子,说明一下原理:
return (long)readUInt8(r) + (readUInt8(r) << 8) + (readUInt8(r) << 16) + (readUInt8(r) << 24);
这是read.cpp文件中,long readSInt32(ddReader* r)函数的函数体。
这里采用了一个一个字节读取出来,然后拼接成32位有符号数字的方法,但是从symbian 3rd模拟器的效果
来看,这种拼接是错误的。我想可能是由于编译器对表达式各元素处理的先后顺序导致的。举个例子来说,
我希望读取的数字为:18 38,而通过上述表达式计算的结果却是38 18 00 00。这个时候就可以灵活地考虑
采用c预言里面的union(共用体)来解决这个问题,
示例代码如下:
register union {
int val ;
unsigned char a[4] ;
} data ;
data.val = 0 ;
data.a[0] = readUInt8(r) ;
data.a[1] = readUInt8(r) ;
data.a[2] = readUInt8(r) ;
data.a[3] = readSInt8(r) ;
return (long)(data.val) ;
代码看上去罗嗦了许多,肯定还有更好的解决方法,目前偶只是要确保数据正确和代码可以工作。
修改完毕read.cpp中几个文件读取函数上述问题以后,基本上剩下的工作就是小打小闹了。
(6)最后说一下解码结果格式
利用flirt在手机上解码出来的数据的存放格式是RGBA,四个字节表示一个像素。这一点在显示图像的时候
要额外注意了。可以用最简单的方式,采用flirt提供的宏COLOR_BLUE(), COLOR_RED(), COLOR_GREEN()来
获取三原色,还有一个字节就是alpha透明度通道了。在偶的测试代码中没有理会这个alpha透明通道,结果
导致有些效果显示不全。以后有时间再做调整吧。
另外,偶已经把jpeglib和zlib都移植上去了,播放flash动画应该问题不大,但是libmad还没有腾出时间来
加上去希望有兴趣的朋友可以沿着偶的思路继续做下去把libmad解码器移植到这个flash播放器上去。这样
依赖symbian 3rd就不必非要依靠adobe的flash lite也可以播放flash动画了。
还有,在这个port实验中,DestroyActionEngine()这个函数有内存泄露问题还没有解决,同样希望有兴趣的
朋友来解决这个问题。
希望这篇文章对各位后来者有用,谢谢大家。
附上模拟器上运行的效果图片:
附上源代码:
|
文件: |
FlashTest.rar |
大小: |
610KB |
下载: |
下载 | |
PS:
(1)程序编译后请把a.swf放到模拟器的c盘根目录下面
(2)选择菜单play
(3)按向下方向键,即可一帧一帧播放flash
(这里偶懒得查键值,直接写了个数字上去,如果按向下方向键不能播放的朋友清酌情修改)
(4)按stop释放资源
阅读(4082) | 评论(5) | 转发(0) |