手游脚本源码哪个文件-在Mac上编译基于Android平台的FFmpeg源码

这段时间开始学习音视频编解码的相关知识手游脚本源码哪个文件,自然少不了学习FFmpeg这个开源项目。 网上有很多关于如何编译FFmpeg源代码的教程,而且大部分都已经过时了。 编译的时候你会遇到很多错误,也会遇到很多陷阱。 因此,总结本文,以方便大家后续参考。

1.下载NDK和FFmpeg

编译Android平台的FFmpeg需要下载NDK和FFmpeg源代码:

首先下载NDK。 官方最新稳定版本为r20版本,建议不要下载最新版本。 这里为了编译顺利,我们可以下载r17及以下版本。 这里我们下载的是r17c版本。 为什么? 请参阅前面的错误处理链接。

然后去FFmepg官网下载最新的源码。 最新版本是ffmpeg-4.1.3.tar.bz2。

2.编写configure配置脚本

编译FFmpeg源码需要通过configure脚本进行配置。 FFmpeg后期可以根据项目需求进行各种裁剪,所以我们可以通过配置脚本来实现。 我们可以通过命令./configure--help来查看支持的配置项。 网上很多文章都有介绍,这里不再赘述。

新建一个build_android.sh文件,输入以下脚本内容,帮助我们编译FFmpeg。 注意,更新第一行的NDK路径可以改为你本地下载的r17c路径

#!/bin/bash
NDK=/Users/codezjx/Android/android-ndk-r17c
SYSROOT=$NDK/platforms/android-21/arch-arm
ISYSROOT=$NDK/sysroot
ASM=$ISYSROOT/usr/include/arm-linux-androideabi
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
PREFIX=$(pwd)/android/armv7-a
CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-
build_android()
{
    ./configure 
    --prefix=$PREFIX 
    --enable-shared 
    --disable-static 
    --disable-doc 
    --disable-ffmpeg 
    --disable-ffplay 
    --disable-ffprobe 
    --disable-avdevice 
    --disable-symver 
    --cross-prefix=$CROSS_PREFIX 
    --target-os=android 
    --arch=arm 
    --enable-cross-compile 
    --sysroot=$SYSROOT 
    --extra-cflags="-I$ASM -isysroot $ISYSROOT -D__ANDROID_API__=21 -Os -fpic -marm -march=armv7-a"
    make clean
    make
    make install
}
build_android

手游脚本源码哪个文件-在Mac上编译基于Android平台的FFmpeg源码

3.执行编译并生成.so文件

执行以下指令开始编译FFmpeg

$ chmod +x build_android.sh
$ ./build_android.sh

如果最终没有报错,并显示如下日志,则证明编译成功,并且会在android/armv7-a下生成我们需要的.so库及相关头文件。 这个路径也是我们在--prefix中配置的路径。

...
INSTALL libavutil/twofish.h
INSTALL libavutil/version.h
INSTALL libavutil/xtea.h
INSTALL libavutil/tea.h
INSTALL libavutil/lzo.h
INSTALL libavutil/avconfig.h
INSTALL libavutil/ffversion.h
INSTALL libavutil/libavutil.pc

最终android/armv7-a的目录结构大致如下:

├── include
│   ├── libavcodec
│   ├── libavfilter
│   ├── libavformat
│   ├── libavutil
│   ├── libswresample
│   └── libswscale
├── lib
│   ├── libavcodec.so
│   ├── libavfilter.so
│   ├── libavformat.so
│   ├── libavutil.so
│   ├── libswresample.so
│   ├── libswscale.so
│   └── pkgconfig
└── share
    └── ffmpeg

4. 踩陷阱

因为我们这里编译的是最新的FFmpeg源码,网上很多脚本都已经过时了,或者与NDK版本不匹配,所以我们在编译的时候会遇到很多问题。 这里列出我在编译时遇到的一些问题,以便大家也可以更清楚的理解为什么里面的build_android.sh是这样配置的。

手游脚本源码哪个文件-在Mac上编译基于Android平台的FFmpeg源码

Tips:编译FFmpeg时,难免会遇到很多问题。 控制台中的错误消息可能不够详细。 这时,我们可以打开日志文件ffbuild/config.log来查看更详细的日志信息,这可以帮助我们加快定位问题。

4.1 错误1:Ccompilertest失败。

/Users/codezjx/Android/android-sdk-macosx/ndk-bundle/toolchains/arm-linux-androideabi-4.9/
prebuilt/darwin-x86_64/bin/arm-linux-androideabi-gcc is unable to create an executable file.
C compiler test failed.

NDK升级到r18及更高版本后,官方迁移不仅使用Clang作为GCC的默认交叉编译器,详细信息请参见此处的Changelog-r18。 FFmpeg默认编译选择GCC进行编译,所以当configure脚本根据路径搜索可执行文件arm-linux-androideabi-gcc时,发现找不到。 这也是我们之前选择r17c版本的原因。 NDK来编译激励。

4.2 错误2:未知选项“--disable-ffserver”

Unknown option "--disable-ffserver".
See ./configure --help for available options.

FFmpeg4.0.x版本之后删除了--disable-ffserver配置项。 如果使用网上的旧脚本,会报这个错误,去掉即可。

4.3 错误3:错误:requestformember's_addr'insomethingnotastructorunion

libavformat/udp.c: In function 'udp_set_multicast_sources':
libavformat/udp.c:290:28: error: request for member 's_addr' in something not a structure or union
         mreqs.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
                            ^
libavformat/udp.c:292:32: error: incompatible types when assigning to type '__be32' from type 'struct in_addr'
             mreqs.imr_interface= ((struct sockaddr_in *)local_addr)->sin_addr;
                                ^
libavformat/udp.c:294:32: error: request for member 's_addr' in something not a structure or union
             mreqs.imr_interface.s_addr= INADDR_ANY;
                                ^
libavformat/udp.c:295:29: error: request for member 's_addr' in something not a structure or union
         mreqs.imr_sourceaddr.s_addr = ((struct sockaddr_in *)&sources[i])->sin_addr.s_addr;
                             ^
make: *** [libavformat/udp.o] Error 1

如果build_android.sh脚本中使用的NDK版本是r15c或者r16b,就会报这个错误,所以解决办法是升级到r17及以上。

4.4 错误4:没有这样的文件或目录

CC  libavfilter/aeval.o
In file included from libavfilter/aeval.c:26:0:
./libavutil/avassert.h:30:20: fatal error: stdlib.h: No such file or directory
 #include 
                    ^
compilation terminated.
make: *** [libavfilter/aeval.o] Error 1

这个错误是新版本NDK的机制导致的。 由于NDK将头文件和库文件分开,所以指定--sysroot只有库文件,头文件放在NDK目录下的sysroot中。 只需添加 --extra 只需将 -isysroot$NDK/sysroot 添加到 -cflags 即可。 另外,汇编相关的头文件也被分离出来,需要根据目标平台指定 -I$NDK/sysroot/usr/include/arm-linux-androideabi。 只需将arm-linux-androideabi更改为所需的平台即可。 ,前一个也可以添加到--extra-cflags中。

如何免费获取C++音视频学习资料:关注音视频开发T哥,点击“链接”即可免费获取2023年最新C++音视频开发进阶专属免费学习礼包!

4.5 错误5:expectedidentifier'('beforenumericconstant

libavcodec/aaccoder.c: In function 'search_for_ms':
libavcodec/aaccoder.c:803:25: error: expected identifier or '(' before numeric constant
                     int B0 = 0, B1 = 0;
                         ^
libavcodec/aaccoder.c:865:28: error: lvalue required as left operand of assignment
                         B0 += b1+b2;
                            ^
libavcodec/aaccoder.c:866:25: error: 'B1' undeclared (first use in this function)
                         B1 += b3+b4;
                         ^
libavcodec/aaccoder.c:866:25: note: each undeclared identifier is reported only once for each function it appears in
make: *** [libavcodec/aaccoder.o] Error 1

这个错误比较混乱,与NDK版本的变量名定义冲突。 在较低版本的 NDK 中不会出现此错误。 我在网上看到有一些解决方案是直接更改变量名称-_-|||。 这些方法过于暴力,后续更新FFmpeg源码时极有可能造成代码冲突。 我认为这不是一个可靠的解决方案。 我在FFmpeg官方报告中找到了这个错误的描述和解决方案。 虽然很简单,只要把--target-os=linux改成--target-os=android就可以了。 原因还有待检验。 有关详细信息,请参阅此处#7103。

5.将.so文件导入到Android项目中

编译成功后,我们将得到.so库和相关头文件,可以导出到Android项目中使用。 简单来说,有以下几个步骤:

5.1AS新建一个NativeC++类型的Project

这里为了方便测试,我们直接新建一个C++ Project,Android Studio会帮我们生成Native项目的目录结构和CMakeLists.txt文件。

5.2 导出.so并包含头文件

将.so和include头文件分别复制到src对应的目录下。 最终app的目录结构大致如下:

├── CMakeLists.txt
├── app.iml
├── build.gradle
├── proguard-rules.pro
└── src
    └── main
        ├── AndroidManifest.xml
        ├── cpp
        │   ├── include
        │   │   ├── libavcodec
        │   │   ├── libavfilter
        │   │   ├── libavformat
        │   │   ├── libavutil
        │   │   ├── libswresample
        │   │   └── libswscale
        │   └── native-lib.cpp
        ├── java
        ├── jniLibs
        │   └── armeabi-v7a
        │       ├── libavcodec.so
        │       ├── libavfilter.so
        │       ├── libavformat.so
        │       ├── libavutil.so
        │       ├── libswresample.so
        │       └── libswscale.so
        └── res

5.3 更改CMakeLists.txt

首先通过include_directories导出FFmpeg相关的头文件,然后通过add_library()和set_target_properties()添加需要导出的.so库,指定其具体位置。 最后,需要链接的库也在target_link_libraries()中声明。

add_library(...)
include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/include)
add_library(avcodec SHARED IMPORTED)
set_target_properties( avcodec 
        PROPERTIES
        IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libavcodec.so)
add_library(avformat SHARED IMPORTED)
set_target_properties( avformat
        PROPERTIES
        IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libavformat.so)
add_library(avfilter SHARED IMPORTED)
set_target_properties( avfilter
        PROPERTIES
        IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libavfilter.so )
add_library(avutil SHARED IMPORTED)
set_target_properties( avutil
        PROPERTIES
        IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libavutil.so )
add_library(swresample SHARED IMPORTED)
set_target_properties( swresample
        PROPERTIES
        IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libswresample.so )
add_library(swscale SHARED IMPORTED)
set_target_properties( swscale
        PROPERTIES
        IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libswscale.so )
...
target_link_libraries( # Specifies the target library.
        native-lib
        # Links the target library to the log library
        # included in the NDK.
        ${log-lib}
        avcodec
        avformat
        avfilter
        avutil
        swresample
        swscale
        )

手游脚本源码哪个文件-在Mac上编译基于Android平台的FFmpeg源码

Tips:注意${CMAKE_SOURCE_DIR}代表CMakeLists.txt当前所在的路径。 别设置错了。

最后,不要忘记在 build.gradle 中声明 abiFilters。 目前我们只编译了armeabi-v7a架构的.so库。

defaultConfig {
    ...
    ndk {
        abiFilters 'armeabi-v7a'
    }
}

5.4 更改native-lib.cpp并调用FFmpeg相关函数

演示代码中,我们随意导出一个FFmpeg函数手游脚本源码哪个文件,看看能否正常运行。 这里在原来的基础上添加一个avcodec_configuration()函数调用,看看是否可以复制config信息。 请务必在此处包含相应的头文件。

#include 
#include 
extern "C" {
#include "libavcodec/avcodec.h"
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_codezjx_ffmpegproject_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = avcodec_configuration();
    return env->NewStringUTF(hello.c_str());
}

运行项目,最后在MainActivity界面中应该输出如下信息,整个FFmpeg编译导出过程就结束了:

--prefix=/Users/codezjx/AndroidProjects/ffmpeg-4.1.3/android/armv7-a 
--enable-shared --disable-static --disable-doc --disable-ffmpeg 
--disable-ffplay --disable-ffprobe --disable-avdevice --disable-symver 
--cross-prefix=/Users/codezjx/Android/android-ndk-r17c/toolchains/
arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi- 
--target-os=android --arch=arm --enable-cross-compile --sysroot=/Users/codezjx/
Android/android-ndk-r17c/platforms/android-21/arch-arm --extra-cflags='-I/Users
/codezjx/Android/android-ndk-r17c/sysroot/usr/include/arm-linux-androideabi 
-isysroot /Users/codezjx/Android/android-ndk-r17c/sysroot -D__ANDROID_API__=21 
-Os -fpic -marm -march=armv7-a'

原文链接:在Mac上编译基于Android平台的FFmpeg源码 | codezjx的首页

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 手游资源 手游脚本源码哪个文件-在Mac上编译基于Android平台的FFmpeg源码 https://www.wkzy.net/game/198892.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务