首先到Ffmpeg和MinGW官网下载所需的包.
MingGW
Ffmpeg
我使用的Ffmpeg是0.6.3,用Git下或者直接下他的压缩包.MinGW安装完毕后直接打开MinGW32\MSYS\msys.bat(Win7下需要管理员权限),在MinGW控制台下cd到ffmpeg的解压文件夹根目录.接着就是配置编译选项,笔者这里只用到H264的解码器单元,所以其他音视频编码器一律关掉.
笔者的编译选项:
- configure --disable-armv5te --disable-armv6 --disable-armv6t2 --disable-armvfp --disable-iwmmxt --disable-mmi --disable-neon --disable-amd3dnowext --disable-mmx2 --disable-ssse3 --disable-vis --disable-yasm --disable-altivec --disable-zlib --disable-bzlib --disable-debug --disable-ffmpeg --disable-ffserver --disable-ffplay --disable-avdevice --disable-avformat --disable-network --disable-muxers --disable-filters --disable-demuxers --disable-devices --disable-protocols --disable-bsfs --disable-parsers --disable-encoders --disable-decoders --disable-hwaccels --disable-everything --enable-static --enable-memalign-hack --enable-small --enable-decoder=h264
配置完毕后即可Make.编译出来的264解码器库不到700K,但是笔者在上面的选项编译出来的解码库使用上遇到一个问题,帧解码没问题,问题出在色彩空间转换和缩放上,一旦调用sws_scale函数,程序马上崩溃.后来几番尝试下,把编译选项的平台指令优化选项打开,重新编译,问题才解决.笔者没有深入去搞清楚平台指令优化对sws_scale功能实现的影响,如有高人知道,望指点.
修改后的编译选项:
- configure --disable-armv5te --disable-armv6 --disable-armv6t2 --disable-armvfp --disable-zlib --disable-bzlib --disable-debug --disable-ffmpeg --disable-ffserver --disable-ffplay --disable-avdevice --disable-avformat --disable-network --disable-muxers --disable-filters --disable-demuxers --disable-devices --disable-protocols --disable-bsfs --disable-parsers --disable-encoders --disable-decoders --disable-hwaccels --disable-everything --enable-static --enable-memalign-hack --enable-small --enable-decoder=h264
这样编译出来的库加起来大概是1.1MB左右的大小.但是,在缩放的使用上还是有点问题,图像放大OK,但是缩小的话,会出现有一半画面是黑块,Ffmpeg试了0.6.5,0.7.11,0.8.10,0.9.1,0.10几个版本还是一样缩小就是黑块,然后再到Google神一番还是无果,最后在缩小的问题上是在控件上用二次线性插值算法实现的,如有大神知道Ffmpeg缩小后黑块问题,望不略赐教.
下面是一些解码调用的简单流程:
- avcodec_init(); //初始化编解码器
-
avcodec_register_all(); //注册在编译选项中所有可用的视音频编解码器
-
avcodec_find_decoder(CODEC_ID_H264); //查找所需的解码器
-
avcodec_alloc_context(); //申请一个上下文对象
-
avcodec_alloc_frame(); //申请一个帧对象用于存放解码后的YUV数据
-
avcodec_open(); //打开编解码器
-
alloc_picture(); //申请一个帧对象用于存放色彩空间转换后的数据,如RGB.(该方法是自己实现的,不是Ffmpeg库的API)
-
sws_getContext(); 获取一个缩放器的上下文(用于一个色彩空间到另一个色彩空间转换并且缩放画面).
-
...
-
avcodec_decode_video(); //解码
-
avcodec_decode_video2(); //解码(取代avcodec_decode_video的新接口)
-
sws_scale(); //颜色转换,画面缩放
-
...
由于调用Ffmpeg编译出来的解码库需要几个动态库文件,这样文件一多会显得麻烦.所以我们需要将几个编译好的解码器静态库文件静态连接到我们的一个动态库中,然后导出所需的API调用(注意:XXX.dll.a是使用动态的一个符号描述静态连接库,并不是真正的代码实现,XXX.a才是真正的代码实现).
下面是笔者的动态库MakeFile关键句:
- all:$(objs)
-
gcc $(objs) -shared -o libxxx_codec.dll -static -lavcodec -lavutil -lswscale
-
-
%.o:%.c
-
gcc -c -o $@ $< -I$(ffmpeg_root)
在Make之前,我们需要设置一下Ffmpeg的库文件路径到MinGW环境变量中, 在环境变量->系统变量->新建
- LIBRARY_PATH=x:\xxx\ffmpeg\libavcodec; x:\xxx\ffmpeg\libavutil; x:\xxx\ffmpeg\libswscale
OK,Make,出来的库大概是1.1M左右.
接着就把用VC或Delphi做好的Ocx控件跟解码库打包到一起.我们还需要一个控件的安装信息文件.用来描述控件版本,文件列表等信息.例如:
- [Add.Code]
-
XXX.ocx=XXX.ocx
-
XXX.inf=XXX.inf
-
libXXX_codec.dll=libXXX_codec.dll
-
-
[XXX.ocx]
-
file=XXX.cab
-
clsid={E873427E-0454-447B-878C-AAD905A1178D}
-
RegisterServer=yes
-
FileVersion=1,0,0,0
-
-
[XXX.inf]
-
file=XXX.cab
-
-
[libXXX_codec.dll]
-
file-win32-x86=thiscab
-
file=liXXX_codec.dll
-
RegisterServer=yes
-
FileVersion=1,0,0,0
用记事本创建,把后缀改成.inf即可.用cabarc程序打包成CAB文件,没有的话到网上下一个.使用命令:
- cabarc n XXX.cab XXX.ocx XXX.inf libXXX_codec.dll
编译好的OCX控件有800KB左右的大小,加上解码库是2MB左右,在cabarc归档打包后,文件包只有600多KB大小,还算能接受.
最后,再写个简单的HTML测试页面,如下代码:
- </HTML>
-
<!d_oCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "">
-
<html xmlns="">
-
<head>
-
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-
<title>XXX video</title>
-
</head>
-
<body>
-
<object classid="clsid:E873427E-0454-447B-878C-AAD905A1178D" codebase="XXX.cab" width="100" height="100" hspace="0" vspace="0" id="XXX" name="XXX" style="border:0px;padding:0px; margin:0xp; background:#F00;"></object>
-
</body>
-
</html>
在15帧率的常速运动下,画面还算流畅,呵呵.(与上面内容无关),
贴一张效果图:
阅读(7806) | 评论(5) | 转发(3) |