FFMpeg系列二:Android集成ffmpeg cmake编译

嗨~,大家好!
我是石头~
由于工作有点忙,有段时间没更新文章了.
这个系列的文章都是验证过的,大家在阅读的时候可以放心的实践。


xxx

这篇文章主要介绍的是:

  1. 环境搭建--FFmpeg在Android中的开发(CMake)
  2. 相关技术理论:CMake,so版本

先介绍下我的运行环境

ffmpeg编译环境

  • mac系统版本:10.13.6

  • NDK版本: r16b版本

  • ffmpeg版本:4.0.2

    对应自己的系统选择ndk

选择自己系统对应的ndk

Android studio版本

IDE版本

等等,你们可能在想,~what? 我们之前不是都用mk去编译的吗,咋又用上了cmake?

首先,Android studio默认的编译方式就是CMake
其次,cmake具有一些其他的优势,后面介绍.


CMake入门

现在我们先稍稍了解一下CMake,这样才能对我们的集成,或者开发得心应手。

CMake 是一个开源的跨平台自动化构建系统。官网地址:CMake

1.1 CMake 的特点

  • 1)跨平台,并可生成 native 编译配置文件,在 Linux/Unix 平台,生成 makefile,在
    Mac 平台,可以生成 xcode,在 Windows 平台,可以生成 MSVC 的工程文件。
    2)能够管理大型项目;
    3)简化编译构建过程和编译过程。Cmake 的工具链非常简单:cmake+make。
    4)可扩展,可以为 cmake 编写特定功能的模块,扩充 cmake 功能。
    好了,我们先了解一些特性就好了,讲多了概念的东西你们就迷糊了,所以我们先实践,在搭建完工程之后我们再来想想使用这些东西的原理,语法等等其他的东西,现在蠢蠢欲动的我们开始吧 (^ v ^)~~~.

实战篇

Android CMake 的使用

先决条件

  1. 在打开的项目中,从菜单栏选择 Tools > Android > SDK Manager
  2. 点击 SDK Tools 标签。
  3. 选中 LLDBCMakeNDK 旁的复选框,如下图所示所示。
    从 SDK 管理器中安装 LLDB、CMake 和 NDK
  1. 点击 Apply,然后在弹出式对话框中点击 OK
  2. 安装完成后,点击 Finish,然后点击 OK

step1:新建一个项目

创建一个包含CMake新工程

之后一直Next,直到Finish
这样我们生成了一个带有CMake编译文件的项目。
在Android模式下带有CMake文件的项目

step2:把我们之前的编译好的库放进去

添加编译好的库

为什么要建立armeabi-v7a文件夹呢?
这是因为Android studio编译的时候是通过文件夹的名字去区别是x86,还是v7a等不同型号的so库的。

step3:修改app模块下的build.gradle

添加框住的2部分代码

因为我们我们在上一次编译FFmpeg的时候就是指定了编译的CPU型号,现在我们也要编译我们的c或者c++对应的so库,所以要指定对应的CPU型号,不然会编译所有的型号的so库
所以现在我们只编译了abi是armeabi-v7a的.so文件
现在我们对比下加了abiFilters "armeabi-v7a"跟没加的区别.

没有过滤会编译所有版本的so
加了abiFilters

step4:修改CMakeLists.txt

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.
# 用来指定 CMake 最低版本为3.4.1,如果没指定,执行 cmake 命令时可能会出错
cmake_minimum_required(VERSION 3.4.1)

# 添加在native层log库
find_library( # Sets the name of the path variable.
              log-lib
              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

set(distribution_DIR ${CMAKE_SOURCE_DIR}/../libs)
include_directories(libs/include)

# FFmpeg编译出了6个库,这里添加----avutil
add_library( avutil
             SHARED
             IMPORTED )
set_target_properties( avutil
                       PROPERTIES IMPORTED_LOCATION
                       ${distribution_DIR}/armeabi-v7a/libavutil.so )

# FFmpeg编译出了6个库,这里添加----swresample
add_library( swresample
             SHARED
             IMPORTED )
set_target_properties( swresample
                       PROPERTIES IMPORTED_LOCATION
                       ${distribution_DIR}/armeabi-v7a/libswresample.so )

# FFmpeg编译出了6个库,这里添加----avcodec
add_library( avcodec
             SHARED
             IMPORTED )
set_target_properties( avcodec
                       PROPERTIES IMPORTED_LOCATION
                       ${distribution_DIR}/armeabi-v7a/libavcodec.so )

# FFmpeg编译出了6个库,这里添加----avfilter
add_library( avfilter
             SHARED
             IMPORTED)
set_target_properties( avfilter
                       PROPERTIES IMPORTED_LOCATION
                       ${distribution_DIR}/armeabi-v7a/libavfilter.so )

# FFmpeg编译出了6个库,这里添加----swscale
add_library( swscale
             SHARED
             IMPORTED)
set_target_properties( swscale
                       PROPERTIES IMPORTED_LOCATION
                       ${distribution_DIR}/armeabi-v7a/libswscale.so )

# FFmpeg编译出了6个库,这里添加----avformat
add_library( avformat
             SHARED
             IMPORTED)
set_target_properties( avformat
                       PROPERTIES IMPORTED_LOCATION
                       ${distribution_DIR}/armeabi-v7a/libavformat.so )


set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

add_library( native-lib
             SHARED
             src/main/cpp/native-lib.cpp
             # TODO 我们之后自己编写的cpp文件都会添加在这里比如
             # src/main/cpp/test1.cpp
             # src/main/cpp/test2.cpp
            )

target_link_libraries( # Specifies the target library.
                       native-lib
                       GLESv2 EGL
                       OpenSLES
                       android
                       # 这里需要注意下,下面这些ffmpeg的so库编译是有先后顺序的
                       # 下面的顺序是没问题的,如果想验证编译顺序,可以自己变换顺序试试.
                       avutil avformat avcodec swscale  swresample avfilter

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

至此,我们终于把环境搭好了(^ v ^).
如果没有搭好就不要灰心,先clone一下这个项目继续后面的学习,到后面自己重新再搭一遍.
不要因为在这里卡太久而放弃了入门音视频的路,加油~~~,记得继续学习后面的部分哟
你们是不是感觉项目搭建起来了就可以开干了呢~~
兄弟呀~~~~冷静,一开始我就说过,我们先动手做,有印象之后再讲原理,你不能学会了实战,就不要原理了吧 (^ v ^),下面来讲讲上面的技术所涉及的一些原理和理论的部分.


理论篇--CMake

1.2 CMake学习

在Android Developers有加上CMake的相应文章
Google 官方网站上有对 CMake 的使用示范,可以参考 官方指南
CMake基本语法

  • 使用#号作为注释;
  • 变量使用 ${}方式取值,但是在 IF 控制语句中是直接使用变量名
  • 指令名(参数1 参数2 …),其中参数之间使用空格或分号隔开;
  • 指令与大小写无关,但参数和变量是大小写相关的;

CMake常用指令

---------------------------------------------------------------

1. set 指令
语法:set(VAR [VALUE])
这个指令是用来显式地定义变量,多个变量用空格或分号隔开
例如:set(distribution_DIR ${CMAKE_SOURCE_DIR}/../libs)
Tips: 当需要用到定义的 distribution_DIR 变量时,需要用${var}的形式来引用,
如:${distribution_DIR}
不过,在 IF 控制语句中可以直接使用变量名。
---------------------------------------------------------------

2. add_library 指令
语法:add_library(libname [SHARED | STATIC | MODULE] [EXCLUDE_FROM_ALL] [source])
将一组源文件 source 编译出一个库文件,并保存为 libname.so (lib 前缀是生成文件时 CMake自动添加上去的)。
其中有三种库文件类型,不写的话,默认为 STATIC:

SHARED: 表示动态库,可以在(Java)代码中使用 System.loadLibrary(name) 动态调用;
STATIC: 表示静态库,集成到代码中会在编译时调用;
MODULE: 只有在使用 dyId 的系统有效,如果不支持 dyId,则被当作 SHARED 对待;
EXCLUDE_FROM_ALL: 表示这个库不被默认构建,除非其他组件依赖或手工构建
#将compress.c 编译成 libcompress.so 的共享库
add_library(compress SHARED compress.c)
add_library 命令也可以用来导入第三方的库:
add_library(libname [SHARED | STATIC | MODULE | UNKNOWN] IMPORTED)
如,导入 libjpeg.so

add_library(libjpeg SHARED IMPORTED)
导入库后,当需要使用 target_link_libraries 链接库时,可以直接使用该库
---------------------------------------------------------------

3. set_target_properties 指令
语法: set_target_properties(target1 target2 … PROPERTIES prop1 value1 prop2 value2 …)
这条指令可以用来设置输出的名称(设置构建同名的动态库和静态库,或者指定要导入的库文件的路径),对于动态库,还可以用来指定动态库版本和 API 版本。
如,set_target_properties(hello_static PROPERTIES OUTPUT_NAME “hello”)
设置同名的 hello 动态库和静态库:

set_target_properties(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)
set_target_properties(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
指定要导入的库文件的路径

add_library(jpeg SHARED IMPORTED)
#注意要先 add_library,再 set_target_properties
set_target_properties(jpeg PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/libs/${ANDROID_ABI}/libjpeg.so)
设置动态库 hello 版本和 API 版本:
set_target_properties(hello PROPERTIES VERSION 1.2 SOVERSION 1)

和它对应的指令:
get_target_property(VAR target property)
如上面的例子,获取输出的库的名字

get_target_property(OUTPUT_VALUE hello_static OUTPUT_NAME)
message(STATUS "this is the hello_static OUTPUT_NAME:"${OUTPUT_VALUE})
---------------------------------------------------------------

4. find_library 指令
语法:find_library( name1 path1 path2 …)
VAR 变量表示找到的库全路径,包含库文件名 。例如:

find_library(libX  X11 /usr/lib)
find_library(log-lib log)  #路径为空,查找系统环境变量路径
---------------------------------------------------------------
5. include_directories 指令
语法:include_directories([AFTER | BEFORE] [SYSTEM] dir1 dir2…)
这个指令可以用来向工程添加多个特定的头文件搜索路径,路径之间用空格分割,
如果路径中包含了空格,可以使用双引号将它括起来,
默认的行为是追加到当前的头文件搜索路径的后面。
---------------------------------------------------------------
6. target_link_libraries 指令
语法:target_link_libraries(target library library2…)
这个指令可以用来为 target 添加需要的链接的共享库,
同样也可以用于为自己编写的共享库添加共享库链接。
如:
#指定 compress 工程需要用到 libjpeg 库和 log 库
target_link_libraries(compress libjpeg ${log-lib})
同样,link_directories(directory1 directory2 …) 可以添加非标准的共享库搜索路径。
---------------------------------------------------------------

到这里,我们学习了实战里面技术的理论部分.
下一次,我们开始真正的ffmpeg学习

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,367评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,959评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,750评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,226评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,252评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,975评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,592评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,497评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,027评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,147评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,274评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,953评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,623评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,143评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,260评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,607评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,271评论 2 358

推荐阅读更多精彩内容