一、背景介绍
FFmpeg是一款超级强大的开源多媒体编解码框架,提供了录制、转换以及流化音视频的完整解决方案,包含了libavcodec、libavformat等多个多媒体库。FFmpeg是基于linux平台下开发的,同样可以运行于android(其实也是linux,你懂得!)、windows、Mac等平台。
FFmpeg有多重要?列举一下我们常用的多媒体处理软件:暴风影音、QQ影音、KMP(这个牛掰啊)、格式工厂……都使用了FFmpeg,可是他们都被FFmpeg刻上了耻辱柱:理由是把开源的东西改造成不开源的去赚钱!
说到播放器,千万不要把FFmpeg和播放器等同,这也是我这篇博文重点介绍的:FFmpeg处理的数据我们看不到,要想看到数据处理的结果,还需要借助另一套多媒体处理框架的帮助,这里就用surface代替吧。
图一
那么在不同平台下应该如何搭配FFmpeg与surface呢?我采用如下方案实现:
linux平台:FFmpeg + SDL。
Android平台:FFmpeg + surface(jni注入)。
Windows:FFmpeg + D3D。
以上三种平台的搭配本人全部实现(代码陆续上传到github中,欢迎大家批评指正)。实现难度么,个人感觉Android最难,linux其次,windows较为简单。本人是从事linux平台开发的,按道理说linux衍生出的Android不应该有太大困难的,这里强烈喷一下GFW,你把谷歌禁了也就罢了,Android相关资源也禁?Android源码、ADT这些资源找了十天半月,浪费了博主我大把青春岁月。
闲话少说,下面切入正题。
二、FFmpeg + surface(jni注入)
平台资源:adt-bundle-windows-x86-20140702、android-ndk-r4b、libffmpeg、cygwin。
具备知识:JNI、FFmpeg、Android surface。
1、 adt-bundle-windows-x86-20140702:windows上的Android开发环境,由eclipse、Android SDk、Android模拟器组成。
2、 android-ndk-r4b:交叉编译器,用来在Android开发环境下编译C系语言的交叉编译器。
3、 libffmpeg 经过修改的可以由android-ndk-r4b编译的ffmpeg源码。
4、 JNI :JAVA调用C、C++的技术。
5、 Android surface:android显示技术。
6、 Cygwin:因为交叉编译器是在linux上才能运行的,所以需要cygwin在windows上模拟一个linux环境。
参考网址:
http://www.cnblogs.com/bjzhanghao/archive/2012/11/14/2769409.html
(开发资源下载,解决了android官网被墙的不便)
http://blog.csdn.net/buleriver/article/details/26139109
(java调用C、C++的实现方法)
http://www.cnblogs.com/android100/p/android-surfaceView.html
(android surface 实现方法)
https://github.com/havlenapetr/FFMpeg
(超级大牛,ffmpeg在android上实现的鼻祖)
http://blog.csdn.net/conowen/article/details/7526398
(针对鼻祖的讲解)
https://github.com/dongguadan/surfaceDraw
(博主的DEMO)
开发步骤
1、搭建环境。
初学者不建议使用原生态的eclipse加上各种复杂的配置来进行环境搭建,那只会让你失去学习的乐趣,直接使用配套产品adt-bundle-windows-x86比较简洁。解压准备好adt-bundle-windows-x86、ndroid-ndk-r4b,装好cygwin,进行工程配置,主要是配置交叉编译器(eclipse是不能直接编译C系的,需要外部编译器),如图2、3。
图2
图3
2、编译工程
可以先使用android-ndk-r4b自带的hello-jni,也可以使用博主根据havlenapetr裁剪的surfaceDraw(一个简单的播放器,实现对SD卡中的视频文件进行播放)。相比于havlenapetr,surfaceDraw功能简洁,没有涉及C++、java中一些复杂的技术,可以清晰的看出android调用C++封装的ffmpeg接口的过程。
3、创建、运行模拟器
首先创建模拟器(必须基于API2.2的,后面会说明这样做的原因),然后运行,导入视频文件到SD卡,运行APP,如图4、图5、图6。
图4
图5
图6
其实Android平台是内置多媒体处理的API的,例如MediaPlayer,只需短短的几行代码就可以实现上面整个工程的功能。但是读者可以仔细想想,如果是这样简单的话,那么岂不是谁都可以开发一个简洁的手机版暴风影音?另一方面,如果开发者想用播放器播放一段流媒体,这段流媒体的接收参数是一段网址(就想优酷在线观看一样),而不是本地视频路径,MediaPlayer可以么?当然不可以。所以我们需要开发一套可以满足自己需求的API。
这就涉及到了Android framework层的知识了。Android简单说是运行在linux上的虚拟机,用过虚拟机的人都知道,那是相当的消耗资源,在虚拟机上在跑一个复杂的多媒体处理软件,效率可想而知。那么如何才能提高效率呢?在linux上运行C语言的程序效率当然是最高的,业内公认。所以需要有一种方法使Android 应用绕过虚拟层直接调用linux层的接口进行处理,这就是JNI技术的精髓,也是havlenapetr、surfaceDraw的实现原理。MediaPlayer其实也是用的这种技术,但是基于MediaPlayer的多媒体处理能力、灵活性当然是无法满足我们的需求的。
图7
唯一可惜的是目前为止的surfaceDraw只能在Android 2.X上运行,因为工程最重要的两个库libjniaudio.so、libjnivideo.so是基于Android2.X的源码编译的。基于Android4.X源码的编译博主尚位编译通过,主要原因是Android4.X对编译的环境要求比较高。后面有时间博主会提供给相关版本的libjniaudio.so、libjnivideo.so。
Android平台上的FFMpeg移植介绍到这里,下一篇会介绍linux平台上的FFMpeg与SDL的组合应用。