项目需要,网上也有现成的FFmpeg Android动态库,但是本着亲力亲为的宗旨,做了不断地尝试,最终也是成功了,在此做一个笔记,以备日后查阅。

附上给我帮助的资料链接:
王英豪大神的博客
雷霄骅大神的博客

因为FFmpeg,虽未谋面,但是有了第一个年龄相仿的励志偶像,那就是雷霄骅,给了我无限的正能量,努力!

我们开始正题,上边的两位大神的博客,整个编译过程描述的非常详细了,但是因为我第一次尝试,对c的编译不是很熟悉,所以碰到的很多比较低级细节问题,上述博客中没有提及,在此做一下记录。

1、Android 端集成 FFmpeg 需要掌握哪些基础知识呢?个人认为以下内容是需要了解的:

JNI
CPU架构
交叉编译
NDK
FFmpeg 简介

这些内容,王英豪大神描述的很清楚,在开始编译之前,需要细细琢磨,理解。

2、我的编译环境:

Linux 环境(Ubuntu 14.04 ,x86_64)
NDK 版本(android-ndk-r13b)
FFmpeg 版本(ffmpeg-3.3.7): 官网下载链接:https://ffmpeg.org/download.html

3、工具,环境准备完毕,我们开始编译动态库
3.1 将FFmpeg源码解压到文件夹中

解压方法:tar -xzvf ffmpeg-3.3.7.tar.gz (解压到当前文件夹)
3.2 修改FFmpeg 配置文件
进入解压后的 ffmpeg-3.3.7 文件夹

vim configure 

替换操作(建议用 #号注释掉被替换部分):

#注释掉原来的
#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)'#替换为下边的形式
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'

3.3 执行配置文件:

在FFmpeg根目录下,执行 ./configure
如果不执行这句,后边执行脚本时,可能会出现某些配置项不存在的提示

3.4 下载并解压ndk
ndk 是什么,用来干什么,看文章开头王英豪大神链接。
下载:
ndk 下载可能需要翻墙,为了方便,我在文章末尾会附上资源链接。
解压:
下载下来之后是 .zip 文件,所以我们使用以下方法解压:

unzip *.zip

3.5 编写编译脚本
网上有好多脚本,我尝试过几个,觉得雷霄骅这份不错,我使用这份:
FFmpeg类库完整功能脚本
下面这个脚本可以生成一套功能完整,体积比较大的类库。

注意事项:
1、路径相关的信息,一定认真比对,保证无误
2、因为编辑器的原因,直接复制粘贴,脚本每一行最后都会有多余的空格,执行之前,一定要将每一行最后的空格删除掉,否则会出现很多莫名的错误。
3、有时候也会出现一些权限的问题,这个,赋予合适的权限就好了。
4、我觉得最好也不要有中文

make clean
#自己的ndk路径(相对路径或绝对路径都可以)
export NDK=/home/shoppingchen/work/ffmpeg_for_android/android-ndk-r13b
export PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt
# 支持的最低 android 版本
export PLATFORM=$NDK/platforms/android-14/arch-arm
#最终的库生成位置为上一级目录的 simplefflib
export PREFIX=../simplefflib
build_one(){
./configure --target-os=linux --prefix=$PREFIX \
--enable-cross-compile \
--enable-runtime-cpudetect \
--disable-asm \
--arch=arm \
--cc=$PREBUILT/linux-x86_64/bin/arm-linux-androideabi-gcc \
--cross-prefix=$PREBUILT/linux-x86_64/bin/arm-linux-androideabi- \
--disable-stripping \
--nm=$PREBUILT/linux-x86_64/bin/arm-linux-androideabi-nm \
--sysroot=$PLATFORM \
--enable-gpl --enable-shared --disable-static --enable-small \
--disable-ffprobe --disable-ffplay --disable-ffmpeg --disable-ffserver --disable-debug \
--extra-cflags="-fPIC -DANDROID -D__thumb__ -mthumb -Wfatal-errors -Wno-deprecated -mfloat-abi=softfp -marm -march=armv7-a"
}#make
#make install
build_one

在这儿,有一个建议,就是 make 命令和make install 命令,对正在尝试的人来说,不要把他写到脚本中,建议执行完脚本之后再手动执行比较好。因为我们在执行脚本或命令之后,需要密切关注屏幕上打出来的log,如果有异常,应立即停止编译,对log进行分析。
在我自己编译过程中,刚开始,直接复制脚本执行,完成之后是不会出现 fail 或者 success 的提示,在此处浪费了很多时间。
3.6、执行完make 和 make install 命令之后,我们就可以看到生成的 simplefflib 文件夹,下图所示:

如果没有该文件夹生成,那么详细检查上一步操作,详细阅读log,看哪儿出了异常,无外乎注意事项中的三点。

如果一切顺利,那么到这儿,我们的动态库就完成了。但是要使用到 Android 项目中,我们还需要 jni
5、搞定 jni
5.1 jni 步骤

编写带有 native 方法的 Java 类
生成该类扩展名为 .h 的头文件
创建该头文件的 C/C++ 文件,实现 native 方法
将该 C/C++ 文件编译成动态链接库
在Java 程序中加载该动态链接库

5.2 编写带有 native 方法的 Java 类

package com.jni;
public class FFmpeg {public static native void run();
}

位置可以是任何地方,我是在 ubantu下边,看图

就是创建了类似结构的文件夹树结构
5.3 生成该类扩展名为 .h 的头文件
在图中 ffmpeg_for_android 文件夹下执行以下命令:

javah -classpath .  com.jni.FFmpeg

执行完之后,我们就发现在当前目录下边,生成了 com_jni_FFmpeg.h 如下图所示

5.4 创建该头文件的 C/C++ 文件,实现 native 方法
此处建议,新建一个目录来编译jni 的动态库,我这儿新建了一个 ndkBuild 目录,然后把上一步生成的头文件复制到该目录下,并在该目录下创建 com_jni_FFmpeg.c 文件,文件内容如下:

#include <android/log.h>
#include "com_jni_FFmpeg.h"
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavfilter/avfilter.h"
JNIEXPORT void JNICALL Java_com_jni_FFmpeg_run(JNIEnv *env, jclass obj) {char info[40000] = {0};av_register_all();AVCodec *c_temp = av_codec_next(NULL);while(c_temp != NULL){if(c_temp->decode!=NULL){sprintf(info,"%s[Dec]",info);}else{sprintf(info,"%s[Enc]",info);}switch(c_temp->type){case AVMEDIA_TYPE_VIDEO:sprintf(info,"%s[Video]",info);break;case AVMEDIA_TYPE_AUDIO:sprintf(info,"%s[Audio]",info);break;default:sprintf(info,"%s[Other]",info);break;}sprintf(info,"%s[%10s]\n",info,c_temp->name);c_temp=c_temp->next;}
__android_log_print(ANDROID_LOG_INFO,"myTag","info:\n%s",info);
}

这段程序用于输出 FFmpeg 支持的编解码信息,通过 < android/log.h > 的 __android_log_print 方法可以直接将信息输出到 Android Studio 的 logcat 。
5.5 将该 C/C++ 文件编译成动态链接库
首先在 jni 目录下创建 Application.mk 文件 :

APP_ABI := armeabi
APP_PLATFORM=android-14

APP_ABI 表示编译生成 armeabi 架构的 so 库,APP_PLATFORM 表示最低支持的 Android 版本。

然后在 jni 目录下创建 Android.mk 文件:

LOCAL_PATH:= $(call my-dir)
INCLUDE_PATH:=../jniLibs/include
FFMPEG_LIB_PATH:=../jniLibs/libinclude $(CLEAR_VARS)
LOCAL_MODULE:= libavcodec
LOCAL_SRC_FILES:= $(FFMPEG_LIB_PATH)/libavcodec-57.so
LOCAL_EXPORT_C_INCLUDES := $(INCLUDE_PATH)
include $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)
LOCAL_MODULE:= libavformat
LOCAL_SRC_FILES:= $(FFMPEG_LIB_PATH)/libavformat-57.so
LOCAL_EXPORT_C_INCLUDES := $(INCLUDE_PATH)
include $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)
LOCAL_MODULE:= libswscale
LOCAL_SRC_FILES:= $(FFMPEG_LIB_PATH)/libswscale-4.so
LOCAL_EXPORT_C_INCLUDES := $(INCLUDE_PATH)
include $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)
LOCAL_MODULE:= libavutil
LOCAL_SRC_FILES:= $(FFMPEG_LIB_PATH)/libavutil-55.so
LOCAL_EXPORT_C_INCLUDES := $(INCLUDE_PATH)
include $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)
LOCAL_MODULE:= libavfilter
LOCAL_SRC_FILES:= $(FFMPEG_LIB_PATH)/libavfilter-6.so
LOCAL_EXPORT_C_INCLUDES := $(INCLUDE_PATH)
include $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)
LOCAL_MODULE:= libswresample
LOCAL_SRC_FILES:= $(FFMPEG_LIB_PATH)/libswresample-2.so
LOCAL_EXPORT_C_INCLUDES := $(INCLUDE_PATH)
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libpostproc
LOCAL_SRC_FILES:= $(FFMPEG_LIB_PATH)/libpostproc-54.so
LOCAL_EXPORT_C_INCLUDES := $(INCLUDE_PATH)
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavdevice
LOCAL_SRC_FILES:= $(FFMPEG_LIB_PATH)/libavdevice-57.so
LOCAL_EXPORT_C_INCLUDES := $(INCLUDE_PATH)
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := ffmpeg
LOCAL_SRC_FILES := com_jni_FFmpeg.c
LOCAL_C_INCLUDES := /home/shoppingchen/work/ffmpeg_for_android/ffmpeg-3.3.7
LOCAL_LDLIBS := -lm -llog
LOCAL_SHARED_LIBRARIES := libavcodec libavfilter libavformat libavutil libswresample libswscale libavdevice
include $(BUILD_SHARED_LIBRARY)

注意:Android.mk 文件中
INCLUDE_PATH:=../jniLibs/include
FFMPEG_LIB_PATH:=../jniLibs/lib
这两个路径为,我们第四步中生成的两个文件夹的路径,看图

LOCAL_C_INCLUDES := /home/shoppingchen/work/ffmpeg_for_android/ffmpeg-3.3.7
这个路径为 ffmpeg 源码路径,在3.1中提到过

然后在 ndkBuild 目录下边执行命令:

ndk-build

这个命令其实就是一个可执行文件,这个文件在 3.4 提到的ndk 解压根目录下边,
如果执行上述命令系统提示找不到,说明我们没有配置环境变量,此时我们有两种选择
①配置环境变量(自行百度)
②通过路径来直接调用(我是通过相对路径找到这个可执行文件来调用的)

执行完毕后,在当前目录下边,会生成两个文件夹,目录结构如下所示:

5.6 在Java 程序中加载该动态链接库
5.6.1 在Android_studio 中新建一个 Android 工程
5.6.2 将5.5 中生成的libs 下的armeabi-v7a 文件夹复制到工程的 libs 目录下边

5.6.3 将我们写的 FFmpeg.java 文件复制到下图中位置(注意,路径不能错):

5.6.4 尝试进行编译

如果编译不通过,提示说run 方法找不到,按下图操作
去掉 Android NDK Support 勾选

到此,我们Android 动态库的编译就完成了,本博客是参考雷霄骅和王英豪两位大神博客而写,记录了一下自己编译的“坎坷“过程,如有侵犯版权,请告知,如有错误之处,请告知,非常感谢

FFmpeg编译成Android动态库相关推荐

  1. linux下ffmpeg编译成so文件,一、ffmpeg编译成android使用的so库

    1.在https://ffmpeg.org/中下载ffmpeg源码(目前版本为ffmpeg-3.2.1) 2.下载ndk 3.分别解压ffmpeg和ndk, 路径如 : ffmpeg路径: /home ...

  2. 【Android 逆向】修改运行中的 Android 进程的内存数据 ( Android 系统中调试器进程内存流程 | 编译内存调试动态库以及调试程序 )

    文章目录 一.Android 系统中调试器进程内存流程 二.编译内存调试动态库以及调试程序 三.博客资源 一.Android 系统中调试器进程内存流程 修改游戏运行中的内存 , 游戏运行之后 , 游戏 ...

  3. 【Android NDK 开发】Ubuntu 函数库交叉编译 ( Android 动态库交叉编译 | Android 静态库交叉编译 )

    文章目录 I . Ubuntu 中交叉编译 Android 动态库 II . Ubuntu 中交叉编译 Android 静态库 I . Ubuntu 中交叉编译 Android 动态库 1 . 要编译 ...

  4. 使用VS2019开发调试Android动态库

    1. 环境准备 1.1 安装JDK:jdk1.8.0_112 1.2 安装Android SDK SDK可以安装指定的platforms和ndk-bundle.为了兼容性考虑,单独安装了版本比较老的a ...

  5. ViSP安装之Windows系统基于VS2019编译器编译获得VISP动态库

    Windows系统基于VS2019编译器编译获得VISP动态库 官网地址: Installation from source for Windows with Visual C++ 2019 (vc1 ...

  6. MATLAB算法(函数)编译为C++动态库遇到的问题

    MATLAB算法(函数)编译为C++动态库遇到的问题 今天在编译MATLAB函数为C++的动态链接库时遇到了几个问题,在网上搜索了很多资料都没有解决我遇到的问题,特此分享出来供大家参考. 环境: Wi ...

  7. COCOS2D-X编译成android的项目

    今天对cocos2d-x编译成android做个笔记,本文使用的是2.2.1版本.这里指记录如何编译.本文主要参考http://blog.csdn.net/sttyytw/article/detail ...

  8. unity3d android包太大了,unity/unity3d编译成android apk包瘦身方法

     unity/unity3d编译成android apk包瘦身方法 本文系原创,请转发的朋友带上我的链接. 相信用unity开发的同学都会遇到类似的经历:明明资源图片不大,但是发现打包后apk文件 ...

  9. Ijkplayer编译成Android的so库的详细步骤

    Ijkplyer简介 本人在做网络摄像头的时候遇到的一个需求就是要做一个手机app能够实时看rtsp流传过来的视频,首先当然是用MediaPlayer去播放视频,结果是延时的要命,自己写一个播放器框架 ...

最新文章

  1. wxWidgets:wxArchiveClassFactory类用法
  2. 计算机语言XML,在计算机中有一门语言叫“XML”,请问它的全称是什么?是什么含义?...
  3. 从架构到源码:一文了解Flutter渲染机制
  4. LiveVideoStack线上分享第三季(九):《街舞》《长安十二时辰》背后的文娱大脑...
  5. 详解list容器(应用+模拟实现)
  6. 10_Influxdb+Grafana监控Mysql
  7. C++中公有继承、保护继承、私有继承
  8. 河北省计算机2018单招试题答案,2018年河北省普通高职单招考试十类和高职单招对口电子电工类、计算机类联考命题、考试与评卷...
  9. JavaScript学习(四十三)—构造方法创建对象的图解和注意事项
  10. mysql 跳过授权表_跳过授权表登录后使用replace into创建root权限用户
  11. 中比较两个时间的月份差值_测量血压时,一天中什么时间测比较准?控制血压又有哪些好方式?...
  12. c语言模糊pid算法实例,模糊PID的c语言算法.docx
  13. python 画笔画一些形状(八卦图、小鸭子、五角星等)
  14. 知网研学不同电脑端同步无效问题
  15. 美团O2O供应链系统架构设计解析
  16. Android 自定义高德地图比例尺
  17. Windows开机加速实战之开机设置优…
  18. 洛谷 P1160 队列安排
  19. linux unzip 包括目录,Linux 命令(目录管理 - zip/unzip)
  20. TensorFlow 2.9的零零碎碎(六)-模型训练和评价

热门文章

  1. Mysql设置初始化密码和修改密码
  2. 作为通信人,我们究竟该如何看待AI?
  3. 计算机专业的高级称呼,软考高级和中级全称~~
  4. 大数据架构师之路-大数据框架大全
  5. IDEA: 自动优化导包 Auto Import
  6. 特征值和奇异值(svd)
  7. 初中语文古诗词作者生平归纳
  8. DSP(f2812/28335/28377/28388)TZ功能说明
  9. 前端关于自己模拟接口做测试
  10. 除尘机器人毕业_一种除尘机器人的制作方法