美文网首页Android FFMPEGFFMpegFFmpeg
FFMpeg系列二:Android集成ffmpeg cmake编

FFMpeg系列二:Android集成ffmpeg cmake编

作者: 噬魂Miss | 来源:发表于2018-11-03 17:49 被阅读17次

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


    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学习

    相关文章

      网友评论

        本文标题:FFMpeg系列二:Android集成ffmpeg cmake编

        本文链接:https://www.haomeiwen.com/subject/gkitbftx.html