Android中集成ffmpeg(一):编译ffmpeg
- 方案选择
Android中集成ffmpeg的codec功能无非两种方式:
- JNI直接调用,主要用于App开发(无权限修改系统底层),如EXOPlayer,JPlayer等。
- 集成ffmpeg到OMX,即封装ffmpeg为OMX的plugin,然后实现component接口。
考虑到性能问题,我选取的方案二即集成ffmpeg到OMX。首先第一个问题就是ffmpeg的编译。也有两种方式:
- 集成ffmpeg源码到整个Android系统工程,独立写bp或mk进行编译。(由于ffmpeg配置复杂,参考网上的一些现成mk进行修改发现工作量比较巨大)
- 独立NDK编译ffmpeg成动态库或静态库,然后通过prebuild的方式集成。(由于OMX的plugin是直接动态加载动态库,无编译上的依赖,此种方法编译跟普通的ffmpeg编译类似,故推荐该方法)
- FFmpeg配置
32bit编译配置:
- #!/bin/bash
- chmod ./configure
- #chmod ./version.sh
- NDK=/your_ndk_path/android-ndk-r16b
- SYSROOT=$NDK/platforms/android-/arch-arm
- TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
- CROSS=$TOOLCHAIN/bin/arm-linux-androideabi-
- ISYSROOT=$NDK/sysroot
- ASM=$ISYSROOT/usr/include/arm-linux-androideabi
- CC=$TOOLCHAIN/bin/arm-linux-androideabi-gcc
- NM=$TOOLCHAIN/bin/arm-linux-androideabi-nm
- CPU=arm
- PREFIX=./android/$CPU
- ADDI_CFLAGS="-marm"
- function build_one
- {
- ./configure \
- --prefix=$PREFIX \
- --target-os=linux \
- --arch=$CPU \
- --enable-cross-compile \
- --incdir=$NDK/sysroot/usr/include \
- --sysroot=$SYSROOT \
- --cross-prefix=$CROSS \
- --cc=$CC \
- --nm=$NM \
- --extra-cflags="-I$ASM -isysroot $ISYSROOT -Os -fpic $ADDI_CFLAGS" \
- --enable-shared \
- --enable-static \
- --disable-asm \
- --enable-pic \
- --disable-doc \
- --disable-ffmpeg \
- --disable-ffplay \
- --disable-ffprobe \
- --disable-ffserver \
- --disable-avdevice \
- --disable-doc \
- --disable-symver \
- --disable-debug \
- --disable-encoders \
- --disable-muxers \
- --enable-avresample \
- --disable-pthreads \
- --enable-swresample
- make
- make install
- }
- rm -rf $PREFIX
- make distclean
- build_one
说明:
1. --disable-asm选项是因为在ffmpeg-2.0的版本编译出版本运行时出现错误:libavcodec.so: has text relocation。 但是在用ffmpeg-3.3版本时没有出现。也有文章说跟NDK版本也有关系。
可以通过命令检查:readelf -a aarch64/lib/libavcodec.so |grep TEXTREL
2. 在高版本的ffmpeg(如3.3.8)中,可以直接指定--target-os=android ,否则就需要修改configure文件让输出的动态库不带版本号,修改SLIBNAME_WITH_VERSION等选项为:
- SLIBNAME='$(SLIBPREF)$(FULLNAME)$(SLIBSUF)'
- SLIBNAME_WITH_VERSION='$(SLIBNAME).$(LIBVERSION)'
- SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
- LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
- SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'
- SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)'
3. ffmpeg增加动态库导出函数,只需要修改源码所在目录的.v文件,如在libavformat/libavformat.v中增加导出ffurl_register_protocol方法供外部代码链接。
64bit编译配置:
- #!/bin/bash
- chmod ./configure
- #chmod ./version.sh
- NDK=/disk2/wuxingde/android-ndk-r16b
- SYSROOT=$NDK/platforms/android-/arch-arm64
- TOOLCHAIN=$NDK/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64
- ISYSROOT=$NDK/sysroot
- ASM=$ISYSROOT/usr/include/aarch64-linux-android
- CC=$TOOLCHAIN/bin/aarch64-linux-android-gcc
- NM=$TOOLCHAIN/bin/aarch64-linux-android-nm
- CPU=aarch64
- PREFIX=$(pwd)/android/$CPU
- #ADDI_CFLAGS="-marm"
- function build_one
- {
- ./configure \
- --prefix=$PREFIX \
- --target-os=linux \
- --arch=$CPU \
- --enable-cross-compile \
- --incdir=$NDK/sysroot/usr/include \
- --sysroot=$SYSROOT \
- --cross-prefix=$TOOLCHAIN/bin/aarch64-linux-android- \
- --cc=$CC \
- --nm=$NM \
- --extra-cflags="-I$ASM -isysroot $ISYSROOT -Os -fpic" \
- --enable-shared \
- --enable-static \
- --enable-asm \
- --enable-pic \
- --disable-doc \
- --disable-ffmpeg \
- --disable-ffplay \
- --disable-ffprobe \
- --disable-ffserver \
- --disable-avdevice \
- --disable-doc \
- --disable-symver \
- --disable-debug \
- --disable-encoders \
- --disable-muxers \
- --enable-avresample \
- --disable-pthreads \
- --enable-swresample
- make
- make install
- }
- rm -rf $PREFIX
- make distclean
- build_one
- PREBUID
如果只用64bit版本可以直接使用下面Android.mk一次性编译:
- LOCAL_PATH := $(call my-dir)
- include $(CLEAR_VARS)
- LOCAL_PREBUILT_LIBS := \
- lib/libavcodec.so \
- lib/libavformat.so \
- lib/libavutil.so \
- lib/libavfilter.so \
- lib/libswresample.so \
- lib/libavresample.so \
- lib/libswscale.so
- include $(BUILD_MULTI_PREBUILT)
如果同时需要32bit和64bit版本需要使用下面Android.mk分别编译各个库:
- LOCAL_PATH := $(call my-dir)
- include $(CLEAR_VARS)
- LOCAL_SRC_FILES_32 := \
- arm/lib/libavcodec.so
- LOCAL_SRC_FILES_64 := \
- aarch64/lib/libavcodec.so
- LOCAL_MODULE := libavcodec
- LOCAL_MODULE_SUFFIX := .so
- LOCAL_MODULE_CLASS := SHARED_LIBRARIES
- #LOCAL_MODULE_TARGET_ARCH := arm
- LOCAL_MULTILIB := both
- include $(BUILD_PREBUILT)
- include $(CLEAR_VARS)
- LOCAL_SRC_FILES_32 := \
- arm/lib/libavformat.so
- LOCAL_SRC_FILES_64 := \
- aarch64/lib/libavformat.so
- LOCAL_MODULE := libavformat
- LOCAL_MODULE_SUFFIX := .so
- LOCAL_MODULE_CLASS := SHARED_LIBRARIES
- #LOCAL_MODULE_TARGET_ARCH := arm
- LOCAL_MULTILIB := both
- include $(BUILD_PREBUILT)
- include $(CLEAR_VARS)
- LOCAL_SRC_FILES_32 := \
- arm/lib/libavutil.so
- LOCAL_SRC_FILES_64 := \
- aarch64/lib/libavutil.so
- LOCAL_MODULE := libavutil
- LOCAL_MODULE_SUFFIX := .so
- LOCAL_MODULE_CLASS := SHARED_LIBRARIES
- #LOCAL_MODULE_TARGET_ARCH := arm
- LOCAL_MULTILIB := both
- include $(BUILD_PREBUILT)
- include $(CLEAR_VARS)
- LOCAL_SRC_FILES_32 := \
- arm/lib/libavresample.so
- LOCAL_SRC_FILES_64 := \
- aarch64/lib/libavresample.so
- LOCAL_MODULE := libavresample
- LOCAL_MODULE_SUFFIX := .so
- LOCAL_MODULE_CLASS := SHARED_LIBRARIES
- #LOCAL_MODULE_TARGET_ARCH := arm
- LOCAL_MULTILIB := both
- include $(BUILD_PREBUILT)
- include $(CLEAR_VARS)
- LOCAL_SRC_FILES_32 := \
- arm/lib/libavfilter.so
- LOCAL_SRC_FILES_64 := \
- aarch64/lib/libavfilter.so
- LOCAL_MODULE := libavfilter
- LOCAL_MODULE_SUFFIX := .so
- LOCAL_MODULE_CLASS := SHARED_LIBRARIES
- #LOCAL_MODULE_TARGET_ARCH := arm
- LOCAL_MULTILIB := both
- include $(BUILD_PREBUILT)
- include $(CLEAR_VARS)
- LOCAL_SRC_FILES_32 := \
- arm/lib/libswresample.so
- LOCAL_SRC_FILES_64 := \
- aarch64/lib/libswresample.so
- LOCAL_MODULE := libswresample
- LOCAL_MODULE_SUFFIX := .so
- LOCAL_MODULE_CLASS := SHARED_LIBRARIES
- #LOCAL_MODULE_TARGET_ARCH := arm
- LOCAL_MULTILIB := both
- include $(BUILD_PREBUILT)
- include $(CLEAR_VARS)
- LOCAL_SRC_FILES_32 := \
- arm/lib/libswscale.so
- LOCAL_SRC_FILES_64 := \
- aarch64/lib/libswscale.so
- LOCAL_MODULE := libswscale
- LOCAL_MODULE_SUFFIX := .so
- LOCAL_MODULE_CLASS := SHARED_LIBRARIES
- #LOCAL_MODULE_TARGET_ARCH := arm
- LOCAL_MULTILIB := both
- include $(BUILD_PREBUILT)
编译部分就到此结束,这部分由于Android NDK版本(我用的是android-ndk-r16b)和ffmpeg版本不同,网上很多教程都没法用,花费了很多时间。特别要注意ffmpeg中--extra-cflags=配置,不要随意加额外一些定义,可能会导致链接不上的问题。
Android中集成ffmpeg(一):编译ffmpeg的更多相关文章
- Android中集成第三方库的方法和问题
Android中集成第三方库的方法和问题 声明: 1. 本文參考了网上同学们的现有成果,在此表示感谢,參考资料在文后有链接. 2. 本文的重点在第三部分,是在开发中遇到的问题及解决的方法.第一,第二部 ...
- Android中集成第三方支付
常见的第三方支付解决方案 支付宝支付 微信支付 银联支付 Ping++统一支付平台(需要继承服务器端和客户端) 短信支付 支付宝的集成流程 相关资料链接: 支付宝支付指引流程:支付指引流程 支付宝An ...
- Android中集成支付宝
手机的在线支付,被认为是2012年最看好的功能,我个人认为这也是移动互联网较传统互联网将会大放光彩的一个功能. 人人有手机,人人携带手机,花钱买东西,不再需要取钱付现,不再需要回家上网银,想买什么,扫 ...
- cocos2d-x在android中响应返回键编译报错的bug分析
先看一段代码如何在Android中加入返回按键的响应 <span style="font-size:18px;">自己派生CCKeypadDelegate的子类,然后注 ...
- Android中集成QQ登陆和QQ好友分享及QQ空间分享
extends : http://blog.csdn.net/arjinmc/article/details/38439957 相关官方文档及下载地址: 如果只用分享和登陆,用lite包就可以,体积小 ...
- Android开发学习之路--Android Studio cmake编译ffmpeg
最新的android studio2.2引入了cmake可以很好地实现ndk的编写.这里使用最新的方式,对于以前的android下的ndk编译什么的可以参考之前的文章:Android开发学习之路– ...
- OpenCV - Android Studio 中集成Opencv环境(包含opencv_contrib部分)
我在上一篇博客中说到了在Android中集成OpenCV,但是那个版本的OpenCV是没有SIFT和SURF算法的,因为这些算法是受专利保护的,所以并没有被包含在预编译库中,所以如果想要使用SIFT和 ...
- Android中的Apk的加固(加壳)原理解析和实现
一.前言 今天又到周末了,憋了好久又要出博客了,今天来介绍一下Android中的如何对Apk进行加固的原理.现阶段.我们知道Android中的反编译工作越来越让人操作熟练,我们辛苦的开发出一个apk, ...
- Android中的Apk的加固(加壳)原理解析和实现(转)
一.前言 今天又到周末了,憋了好久又要出博客了,今天来介绍一下Android中的如何对Apk进行加固的原理.现阶段.我们知道Android中的反编译工作越来越让人操作熟练,我们辛苦的开发出一个apk, ...
随机推荐
- js语法之条件语句
一.比较操作符 比较操作符包括:等于(==).大于(>).大于等于(>=).小于(<).小于等于(<=).
- css兼容性问题总结
DIV+CSS设计IE6.IE7.FF 兼容性 DIV+CSS网页布局这是一种趋势,我也开始顺应这股趋势了,不过在使用DIV+CSS网站设计的时候,应该注意css样式兼容不同浏览器问题,特别是对完全使 ...
- [agc004c]and grid
别问我为什么咕了两天 题意: 给出一个$H\times W$的网格图A,仅由'.'和'#'构成,边界上没有'#'且至少有一个'#'.构造两个网格图B和C,大小均为$H\times W$,要求A中为'# ...
- WPF内嵌WCF服务对外提供接口
要测试本帖子代码请记得管理员权限运行vs. 我写这个帖子的初衷是在我做surface小车的时候有类似的需求,感觉这个功能还挺有意思的,所以就分享给大家,网上有很多关于wcf的文章 我就不一一列举了.公 ...
- SP687 REPEATS - Repeats(后缀数组)
一个初步的想法是我们枚举重复子串的长度\(L\).然后跑一遍SA.然后我们枚举一个点\(i\),令他的对应点为\(i+L\),然后求出这两个点的LCP和LCS的长度答案就是这个点的答案就是\((len ...
- Python 中多线程之 _thread
_thread模块是python 中多线程操作的一种模块方式,主要的原理是派生出多线程,然后给线程加锁,当线程结束的 时候取消锁,然后执行主程序 thread 模块和锁对象的说明 start_new_ ...
- 紫书 例题11-8 UVa 11082(网络流最大流)
这道题的建模真的非常的秀, 非常牛逼. 先讲建模过程.源点到每一行连一条弧, 容量为这一行的和减去列数, 然后每一列到汇点连一条弧, 容量为这一列 的和减去行数, 然后每一行和列之间连一条弧, 容量为 ...
- 【Henu ACM Round#24 C】Quiz
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 肯定是这样 先放k-1个,然后空1个,然后再放k-1个.然后再空1个.. 以此类推. 然后如果(n/k)*(k-1)+n%k> ...
- Android中的AsyncTask异步任务的简单实例
在 Android中的AsyncTask异步任务的简介 一文中.已经对 安卓 异步任务操作做了简单的介绍.这里,直接将上文中的异步任务做了一个实例.实现异步操作更新UI线程,相比开启子线程更新来说逻辑 ...
- sass05 数据类型,数据运算
/*! 数字类型 */ $n1: 1.2; $n2: 12; $n3: 14px; p{ font-size: $n3; } /*! 字符串类型*/ $s1: container; $s2: 'con ...