Chinaunix首页 | 论坛 | 博客
  • 博客访问: 466282
  • 博文数量: 62
  • 博客积分: 1742
  • 博客等级: 中尉
  • 技术积分: 859
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-06 00:13
个人简介

这是一句很长很长而且又很啰嗦并且很无聊的废话...

文章分类

全部博文(62)

文章存档

2013年(1)

2012年(13)

2011年(48)

分类: WINDOWS

2012-02-26 19:29:27

首先到Ffmpeg和MinGW官网下载所需的包.
MingGW 
Ffmpeg 

我使用的Ffmpeg是0.6.3,用Git下或者直接下他的压缩包.MinGW安装完毕后直接打开MinGW32\MSYS\msys.bat(Win7下需要管理员权限),在MinGW控制台下cd到ffmpeg的解压文件夹根目录.接着就是配置编译选项,笔者这里只用到H264的解码器单元,所以其他音视频编码器一律关掉.

笔者的编译选项:
  1. 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功能实现的影响,如有高人知道,望指点.

修改后的编译选项:
  1. 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缩小后黑块问题,望不略赐教.

下面是一些解码调用的简单流程:
  1. avcodec_init(); //初始化编解码器
  2. avcodec_register_all(); //注册在编译选项中所有可用的视音频编解码器
  3. avcodec_find_decoder(CODEC_ID_H264); //查找所需的解码器
  4. avcodec_alloc_context(); //申请一个上下文对象
  5. avcodec_alloc_frame(); //申请一个帧对象用于存放解码后的YUV数据
  6. avcodec_open(); //打开编解码器
  7. alloc_picture(); //申请一个帧对象用于存放色彩空间转换后的数据,如RGB.(该方法是自己实现的,不是Ffmpeg库的API)
  8. sws_getContext(); 获取一个缩放器的上下文(用于一个色彩空间到另一个色彩空间转换并且缩放画面).
  9. ...
  10. avcodec_decode_video(); //解码
  11. avcodec_decode_video2(); //解码(取代avcodec_decode_video的新接口)
  12. sws_scale(); //颜色转换,画面缩放
  13. ...

由于调用Ffmpeg编译出来的解码库需要几个动态库文件,这样文件一多会显得麻烦.所以我们需要将几个编译好的解码器静态库文件静态连接到我们的一个动态库中,然后导出所需的API调用(注意:XXX.dll.a是使用动态的一个符号描述静态连接库,并不是真正的代码实现,XXX.a才是真正的代码实现).
下面是笔者的动态库MakeFile关键句:
  1. all:$(objs)
  2.     gcc $(objs) -shared -o libxxx_codec.dll -static -lavcodec -lavutil -lswscale
  3.         
  4. %.o:%.c
  5.     gcc -c -o $@ $< -I$(ffmpeg_root)
在Make之前,我们需要设置一下Ffmpeg的库文件路径到MinGW环境变量中, 在环境变量->系统变量->新建
  1. LIBRARY_PATH=x:\xxx\ffmpeg\libavcodec; x:\xxx\ffmpeg\libavutil; x:\xxx\ffmpeg\libswscale
OK,Make,出来的库大概是1.1M左右.

接着就把用VC或Delphi做好的Ocx控件跟解码库打包到一起.我们还需要一个控件的安装信息文件.用来描述控件版本,文件列表等信息.例如:
  1. [Add.Code]
  2. XXX.ocx=XXX.ocx
  3. XXX.inf=XXX.inf
  4. libXXX_codec.dll=libXXX_codec.dll

  5. [XXX.ocx]
  6. file=XXX.cab
  7. clsid={E873427E-0454-447B-878C-AAD905A1178D}
  8. RegisterServer=yes
  9. FileVersion=1,0,0,0

  10. [XXX.inf]
  11. file=XXX.cab

  12. [libXXX_codec.dll]
  13. file-win32-x86=thiscab
  14. file=liXXX_codec.dll
  15. RegisterServer=yes
  16. FileVersion=1,0,0,0
用记事本创建,把后缀改成.inf即可.用cabarc程序打包成CAB文件,没有的话到网上下一个.使用命令:
  1. cabarc n XXX.cab XXX.ocx XXX.inf libXXX_codec.dll
编译好的OCX控件有800KB左右的大小,加上解码库是2MB左右,在cabarc归档打包后,文件包只有600多KB大小,还算能接受.

最后,再写个简单的HTML测试页面,如下代码:
  1. </HTML>
  2. <!d_oCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "">
  3. <html xmlns="">
  4. <head>
  5. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  6. <title>XXX video</title>
  7. </head>
  8. <body>
  9.   <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>
  10. </body>
  11. </html>
在15帧率的常速运动下,画面还算流畅,呵呵.(与上面内容无关),
贴一张效果图:
阅读(7800) | 评论(5) | 转发(3) |
给主人留下些什么吧!~~

yurius_a2012-05-02 14:54:43

czysocket_dara: 让它再小一点的话就要平台指令优化选项关掉,会小一半大小.
我没用SDL,我用Delphi直接调GDI+画RGB的.
avcodec_decode_video->解成YUV->sws_scale->转RG.....
博主,我又来了,问题被我用可耻的办法解决了,就是用url_set_interrupt_cb(decode_interrupt_cb),在回这个回调函数中判断超过一定时间就退出。这个url_set_interrupt_cb一被设置就会在一直运行回调。我实在没办法只好这样了。。。

czysocket_dara2012-04-30 20:11:17

yurius_a: 博主您好!又来打扰您了,搞了一个星期,总算是有点成果,跟您的性能上差得多,下面汇报一下
1 之前说的找不到svq3那些函数,可能是一个BUG吧,因为没有.....
让它再小一点的话就要平台指令优化选项关掉,会小一半大小.
我没用SDL,我用Delphi直接调GDI+画RGB的.
avcodec_decode_video->解成YUV->sws_scale->转RGB,就算是用RTP,你把帧抽出来,等第一个I帧后才开始解码,来一帧解一帧.

yurius_a2012-04-29 12:13:39

czysocket_dara: 没找到的函数不是Linux下面的库,是FFmpeg的,你看看在哪个库定义的,-l 把他引用进来.

没有用RTP,是网络流,只是我们自己做协议......
博主您好!又来打扰您了,搞了一个星期,总算是有点成果,跟您的性能上差得多,下面汇报一下
1 之前说的找不到svq3那些函数,可能是一个BUG吧,因为没有编译相关的函文件(貌似是没开启什么优化),我在h264.c里将使用到这些函数的地方直接注释掉了。
2 因为我要使用rtp传视频,所以开了好多选项,最后配置如下
./configure --disable-everything --disable-muxers --disable-avdevice --disable-armv5te --disable-armv6 --disable-armv6t2 -

czysocket_dara2012-04-23 15:10:03

yurius_a: 您好博主,我需要您的帮助!您写的这篇博文http://blog.chinaunix.net/uid-24875436-id-3083409.html
对我非常有帮助!但我有一些问题,想请您有时间的话指点我.....
没找到的函数不是Linux下面的库,是FFmpeg的,你看看在哪个库定义的,-l 把他引用进来.

没有用RTP,是网络流,只是我们自己做协议.

yurius_a2012-04-23 12:17:15

您好博主,我需要您的帮助!您写的这篇博文http://blog.chinaunix.net/uid-24875436-id-3083409.html
对我非常有帮助!但我有一些问题,想请您有时间的话指点我一下,非常谢谢了!
1 我编译ffmpeg(也用的mingw),都是动态篇译 --enable-shared --disable-static,这样vs能用这些库文件,而静态编译出来的库,则 vc会找不到一些只有linux 才有的函数。但我用动态编译(按您这个配置),则会出错,错误如下:
libavcodec/h264.o:h264.c:(.text+0x4f20): undefined reference to `ff_svq3_add_idc               &n