win10编译Android可用的FFmpeg

说明

之前编译的忘记怎么编译的了只能根据资料整理下,罪过罪过。今后要及时整理

应用场景:Qt For Android 平台需要使用拉流功能

编译过程

##下全是复制的其他人写的博客。为了防止原作者删除,我在这里复制了一份。原文链接:https://blog.csdn.net/qq_34902522/article/details/87879145
进入FFmpeg官网,或者github上面把源码下载到本地.
下载地址:
(1) ffmpeg官网下载地址
(2)github上FFmpeg的下载地址

准备好NDK
去官网下载好ndk,版本的话,推荐r17以下(包括r17c),为什么不用最新版本的r19b呢?这个问题稍后再回答.
Android NDK 下载地址

编写build for Android 脚本
进去FFmpeg目录内,会找到一个configure脚本文件,执行 ./configure --help 命令,你会看到一大串的帮助文档,慢慢看,根据你的项目需要来对编译的FFmpeg进行enable or disable.
这里要说一点的,如果你想编译FFmpeg动态库的话,就是.so库,需要对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)'

修改的目的是为了生成的动态库命名方式可以被Android平台理解,识别.
如果要是编译FFmpeg静态库的话,那就没必要进行上面的修改了.
下面我们在与configure脚本同级目录的地方,创建一个build_android.sh脚本来帮助编译FFmpeg. build_android.sh内容如下:

#!/bin/bash
set -x
API=14
NDK=/NDK安装位置/android-ndk-r15c
SYSROOT=$NDK/platforms/android-$API/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
function function_one
{
./configure \
  --prefix=$PREFIX \
  --disable-shared \
  --enable-static \
  --disable-doc \
  --disable-ffplay \
  --disable-ffprobe \
  --disable-symver \
  --disable-ffmpeg \
  --cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \
  --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
  --target-os=linux \
  --arch=arm \
  --enable-cross-compile \
  --sysroot=$SYSROOT \
  --extra-cflags="-fPIC -DANDROID -D__thumb__ -mthumb -Wfatal-errors -Wno-deprecated -mfloat-abi=softfp -marm -march=armv7-a" \
  --enable-neon

make clean all
make 
make install
}
CPU=armv7-a
PREFIX=$(pwd)/android/$CPU
function_one
现在libavresample 和 libpostproc 默认不启用,已经deprecated,如果想编译这两个库需要设置:
–enable-avresample
–enable-gpl
–enable-nonfree
–enable-postproc

上面的编译脚本编译出来的FFmpeg库还是很完整,挺大的,我们现实项目中一般不需要这么功能齐全,只需要使用其中的部分功能,这里可以根据需要,自行对FFmpeg裁剪,自定义.具体可自定义内容,执行 ./configure.sh --help命令自行查看研究.这里就不细说了.
理想状态下,经过上面的步骤后,会成功的生成android/armv7-a/ 文件,里面会有lib,include目录,lib文件夹里面就是需要的编译好的,适用于Android平台的库文件.
但是往往事实没那么顺利.上面也说了,理想状态下…接下来,坑来了…

遇到的坑
(一)
上面演示的build_android.sh 脚本中使用的ndk版本是r15c,那在FFmpeg 4.1版本中,你应该会遇到这个error:

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
网上很少关于这个错误的描述,官方的回复也没看出来啥子有用的价值.
https://trac.ffmpeg.org/ticket/7741
解决方法:
有两种解决方案
1.ndk版本升到r17c
2.如果不想升ndk版本的,那就修改libavformat/udp.c 文件,把报错的相关代码注释掉就好.前提是你的项目中用不到这块功能.
在低版本的ndk应该都会有这个问题,我有试过r9b版本的,也有这个问题.

(二)
如果使用ndk版本是r17c的话,那上面的问题就不会遇到,但是会遇到新的问题.
CC libavdevice/alldevices.o
In file included from ./libavformat/internal.h:24:0,
from libavdevice/alldevices.c:23:
/opt/andorid_sdk/adt-bundle-linux-x86-20131030/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/include/stdint.h:9:26: fatal error: stdint.h: No such file or directory
出现这个错误是因为NDK r17c版本将头文件和库文件进行了分离,我们指定的sysroot文件夹下只有库文件,而头文件放在了NDK目录下的sysroot内.
解决方法: 需在–extra-cflags中添加 “-isysroot N D K / s y s r o o t ”还有有关汇编的头文件也进行了分离 . 解决方法 : 根据目标平台进行指定“ − I NDK/sysroot” 还有有关汇编的头文件也进行了分离. 解决方法:根据目标平台进行指定 “-I NDK/sysroot还有有关汇编的头文件也进行了分离.解决方法:根据目标平台进行指定INDK/sysroot/usr/include/arm-linux-androideabi”,将 “arm-linux-androideabi” 改为需要的平台就可以
修改之后的build_android.sh :

#!/bin/bash
set -x
API=14
NDK=/opt/andorid_sdk/adt-bundle-linux-x86-20131030/android-ndk-r17c
SYSROOT=$NDK/platforms/android-$API/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
function function_one
{
./configure \
  --prefix=$PREFIX \
  --disable-shared \
  --enable-static \
  --disable-doc \
  --disable-ffplay \
  --disable-ffprobe \
  --disable-symver \
  --disable-ffmpeg \
  --cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \
  --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
  --target-os=linux \
  --arch=arm \
  --enable-cross-compile \
  --sysroot=$SYSROOT \
  --extra-cflags="-I$NDK/sysroot/usr/include/arm-linux-androideabi -isysroot $NDK/sysroot -fPIC -DANDROID -D__thumb__ -mthumb -Wfatal-errors -Wno-deprecated -mfloat-abi=softfp -marm -march=armv7-a" \
  --enable-neon

make clean all
make 
make install
}
CPU=armv7-a
PREFIX=$(pwd)/android/$CPU
function_one

(三)

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;
^
这是由于定义冲突导致的一个error,和ndk
版本有关,我在使用r15c和r9b版本的时候都没有遇到这个问题.
解决方法:修改libavcodec/aaccoder.c 文件 B0改成b0(ps:就是把int型变量名改一下,避免冲突,名字随便起)

(四)

libavcodec/hevc_mvs.c: In function ‘derive_spatial_merge_candidates’:
libavcodec/hevc_mvs.c:208:15: error: ‘y0000000’ undeclared (first use in this function)
((y ## v) >> s->ps.sps->log2_min_pu_size))
^
解决方法:将libavcodec/hevc_mvs.c文件的变量B0改成b0,xB0改成xb0,yB0改成yb0

(五)

libavcodec/opus_pvq.c: In function ‘quant_band_template’:
libavcodec/opus_pvq.c:498:9: error: expected identifier or ‘(’ before numeric constant
int B0 = blocks;
^
解决方法:将libavcodec/opus_pvq.c文件的变量B0改成b0

结语
除了上面的问题外,中间也遇到过configure.sh脚本没执行成功的问题,原因大都是空格键,一些久的参数过时了,等问题.比如-ffserver这个参数已经不用了.
上面提到说推荐ndk版本是r17c以下的,是因为我们的build_android.sh,编译脚本用用的编译工具是gcc,但是ndk r17c以后的版本,把gcc给移除了.所以如果现在用最新的版本r19b的话,会出现关于gcc的error.考虑更换编译工具不用gcc,应该就能解决问题,但是不知道又会不会出现其他的问题…这个还需要研究,后续有发现,还会持续更新补充.
————————————————
版权声明:本文为CSDN博主「宇宝守护神(rainyang)」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_34902522/article/details/87879145

不同

.sh文件我记得和上文中的不同。我使用的.sh文件为(应该是这个,有大佬看到错误的话请留言谢谢):

#!/bin/bash
#设置编译中临时文件目录,不然会报错 unable to create temporary file
export TMPDIR=C:/Progect/UVCamera/Data/OpencvFFmpeg/ffmpegTemp
# NDK的路径,根据实际安装位置设置
NDK=C:/Qt/android-ndk-r12b
# 编译针对的平台,这里选择最低支持android-14, arm架构,生成的so库是放在libs/armeabi文件夹下的,若针对x86架构,要选择arch-x86
PLATFORM=$NDK/platforms/android-14/arch-arm
# 工具链的路径,arm-linux-androideabi-4.9与上面设置的PLATFORM对应,4.9为工具的版本号
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64
PREFIX=$(pwd)/android/$CPU
CPU=arm
ADDI_CFLAGS="-Os -fpic -marm"
 
function build_one
{
./configure \
    --prefix=$PREFIX \
    --target-os=linux \
    --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
    --arch=arm \
    --sysroot=$PLATFORM \
    --extra-cflags="-I$PLATFORM/usr/include" \
    --cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \
    --nm=$TOOLCHAIN/bin/arm-linux-androideabi-nm \
    --enable-shared \
    --enable-runtime-cpudetect \
    --enable-gpl \
    --enable-small \
    --enable-cross-compile \
    --disable-debug \
    --enable-static \
    --disable-doc \
    --disable-asm \
    --disable-ffmpeg \
    --disable-ffplay \
    --disable-ffprobe \
    --disable-postproc \
    --disable-avdevice \
    --disable-symver \
    --disable-stripping \
 
make clean
make -j4
make install
}
build_one

你可能感兴趣的:(Qt,For,Android,android,android,studio,ide)