0. 版本确定:
最近需要以NativeC方式编译OpenCV2.0. 其中用到ffmpeg.
(OpenCV 目录树下,有interfaces/ffopencv).
但ffmpeg版本一直在升级,在不同的版本中,接口也有所变化,如何判断OpenCV2.0使用的哪个版本的ffmpeg是个关键。
首先观察interfaces/ffopencv/ffopencv.cpp. 其中包含:
#ifdef WIN32
#include //ffmpeg_/avformat.h
#include
//ffmpeg_/avcodec.h
#include
//ffmpeg_/imgconvert.h
#else
说明Windows编译时使用这几个ffmpeg头文件。
打开:3rdparty/include/ffmpeg_/avcodec.h
有如下代码:
#define LIBAVCODEC_VERSION_MAJOR 52
#define LIBAVCODEC_VERSION_MINOR 20
#define LIBAVCODEC_VERSION_MICRO 0
所以,确认应该找对应的ffmpeg 版本。
在ffmpeg官网(http://ffmpeg.org/) 分别下载了:
ffmpeg-2.2.4.tar.gz(当前最新版本)
ffmpeg-1.0.9.tar.gz,ffmpeg-0.6.7.tar.gz,ffmpeg-0.5.13.tar.gz
分别打开其avcodec.h,结果0.5.13最为接近:
#define LIBAVCODEC_VERSION_MAJOR 52
#define LIBAVCODEC_VERSION_MINOR 20
#define LIBAVCODEC_VERSION_MICRO 1
所以说明:OpenCV2.0所使用的FFMpeg库是0.5.13.
1.
开始编译ffMpeg-0.5.13:
以下编译方法,是借鉴网络上已有的ffmpeg
NDK编译之方法。只是针对各个特定ffmpeg版本做了一点微调。在此感谢分享这些编译经历的朋友。
1.1:目录建立:
创建jni目录。将ffmpeg-0.5.13.tar.gz copy到其中并解压缩。
最终目录结构如下:
jni/ffmpeg-0.5.13
1.2: 建立config_android.sh并生成config.h文件:
在编译X86 Linux环境下ffmpeg, 是通过configure来创建config.h
和config.mk.
决定编译哪些模块,以及程序中用到的一些宏定义(关系到程序向哪方向走)。
我们也需要一个config.h. 所以要利用configure来生成它。
在jni/ffmpeg-0.5.13/目录内,创建config_android.sh
内容如下:
NDK_ROOT=/opt/android-ndk-r9d
PREBUILT=${NDK_ROOT}/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64
PLATFORM=${NDK_ROOT}/platforms/android-8/arch-arm
./configure --target-os=linux \
--arch=arm \
--enable-small \
--enable-static \
--disable-yasm \
--enable-armv5te \
--enable-cross-compile \
--disable-stripping \
--disable-ffplay \
--disable-ffserver \
--disable-devices \
--disable-devices \
--enable-swscale \
--cc=$PREBUILT/bin/arm-linux-androideabi-gcc \
--cross-prefix=$PREBUILT/bin/arm-linux-androideabi- \
--nm=$PREBUILT/bin/arm-linux-androideabi-nm \
--extra-cflags="-fPIC -DANDROID" \
--extra-ldflags='-L$PLATFORM/usr/lib -nostdlib' \
echo "#undef restrict" >> config.h
echo "#define restrict __restrict__" >> config.h
echo "#undef HAVE_LRINT" >> config.h
echo "#define HAVE_LRINT 1" >> config.h
echo "#undef HAVE_LRINTF" >> config.h
echo "#define HAVE_LRINTF 1" >> config.h
echo "#undef HAVE_ROUND" >> config.h
echo "#define HAVE_ROUND 1" >> config.h
echo "#undef HAVE_ROUNDF" >> config.h
echo "#define HAVE_ROUNDF 1" >> config.h
echo "#undef HAVE_TRUNCF" >> config.h
echo "#define HAVE_TRUNCF 1" >> config.h
注意:NDK_ROOT,PREBUILT 要按照本机实际地址配置。
之后修改其权限:
chmod 777 config_android.sh
运行:
./config_android.sh
生成了config.h
1.3: 微调config.h和几个文件:
1.3.1: config.h微调:
在config.h中,找到:
#define restrict restrict
#define restrict __restrict__
修改为:
#define restrict
#define restrict
因为restrict关键字是C99才引入的。
1.3.2:libavutil/internal.h微调:
#if 0
static av_always_inline av_const long long llrint(double
x)
{
return rint(x);
}
#endif
如果不去掉,llrint会重定义。(llrint是C函数)
1.3.3:libavcodec/utils.c微调:
fd = open(*filename, O_RDWR | O_BINARY