测试FFmpeg的RTSP转MP4功能
环境:Win7
工具:ffmpeg-win-2.2.2
命令行运行
VLC播放
功能正常。
测试FFmpeg4Android项目
环境
- Win7
- Android Studio 3.1
- NDK r16b
参考剑西的博客《编译Android下可执行命令的FFmpeg》
修改命令
编译运行
测试压缩MP4,成功。
第一次转显示OK,没看到输出文件,第二次开搞直接闪退,报错
A/libc: Fatal signal 11 (SIGSEGV) at 0x00000099 (code=1), thread 18656 (Thread-1957)
发现电脑查看不了,但是手机文件管理器可以看到压缩后的文件。这步成功了。
添加网络权限
<uses-permission android:name="android.permission.INTERNET" />
测试保存MP4文件,用这个命令
String cmd_transcoding = String.format("ffmpeg -i rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov -acodec copy -vcodec copy %s",
basePath+"/"+"abc.mp4");
原版是精简版的ffmpeg库,不能解析RTSP流,要用增强版的库。否则会闪退。
保存成功
编译FFmpeg
Windows编译环境配置比较麻烦,我选择在Ubuntu虚拟机编译FFmpeg。
环境
- Ubuntu 16.04
- NDK r14b
- jdk1.8.0_144
- ffmpeg 3.2.5
修改ffmpeg-3.2.5、fdk-aac-0.1.5、libx264目录下的sh脚本
NDK=${ANDROID_NDK_HOME}
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
允许生成静态库
--enable-static
先编译x264和aac,再编译ffmpeg
FFmpeg4Android/ffmpeg-3.2.5/fdk-aac-0.1.5$ ./fdk_aac_arm_build.sh
FFmpeg4Android/ffmpeg-3.2.5/libx264$ ./x264_arm_build.sh
$ ./jianxi_ffmpeg_arm_v7a_build_more.sh
编译成功
这里为什么编译成静态库而不是动态库呢?静态库可以把内容编译到待会儿要编译 ffmpeg 的so库里去,不需要单独加载 libx264.so 了,如果你硬要编译成动态库也可以,加载 ffmpeg.so 的时候加载 libx264.so 就可以。
–enable-static –disable-shared这两个是看编译出来的库是静态库(.a)还是动态库(.so),如果要编译成动态库就–enable-shared –disable-static。或者两个都编译出来。
运行安卓版FFmpeg
还是用前面的项目,把android_more目录下arm-v7a的静态库.a文件复制到jniLibs目录,不要忘了libx264-148.a和libfdk-aac.a
写脚本提取头文件,放到cpp目录下
修改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_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
jxffmpegrun
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/cmdutils.c
src/main/cpp/ffmpeg.c
src/main/cpp/ffmpeg_filter.c
src/main/cpp/ffmpeg_opt.c
src/main/cpp/jx_ffmpeg_cmd_run.c
)
add_library(
avcodec
SHARED
IMPORTED
)
add_library(
avfilter
STATIC
IMPORTED
)
add_library(
avformat
STATIC
IMPORTED
)
add_library(
avutil
STATIC
IMPORTED
)
add_library(
swresample
STATIC
IMPORTED
)
add_library(
swscale
STATIC
IMPORTED
)
add_library(
fdk-aac
STATIC
IMPORTED
)
add_library(
x264
SHARED
IMPORTED
)
set_target_properties(
avcodec
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libavcodec.a
)
set_target_properties(
avfilter
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libavfilter.a
)
set_target_properties(
avformat
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libavformat.a
)
set_target_properties(
avutil
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libavutil.a
)
set_target_properties(
swresample
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libswresample.a
)
set_target_properties(
swscale
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libswscale.a
)
set_target_properties(
fdk-aac
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libfdk-aac.a
)
set_target_properties(
x264
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libx264-148.so
)
include_directories(
../ffmpeg-3.2.5/
)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
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 )
find_library(
z-lib
z )
find_library(
m-lib
m )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
jxffmpegrun
avfilter
avformat
avcodec
swresample
swscale
avutil
fdk-aac
x264
# Links the target library to the log library
# included in the NDK.
${log-lib}
${z-lib}
${m-lib} )
注意添加libm和libz。link的顺序是有要求的,查看MakeFile的needs to be in linking order。
准备完成之后点击Build——>Make project,完成后就会在app mould下的build——>intermediates——>cmake下生成对应的.so库了,可以把这些.so拷贝到libs或者jniLibs下使用即可
这里不复制so文件也可以运行。
修改过cmake文件后最好执行Refresh Linked C++ Projects。
注意编译前要停止调试。
refresh、make、run成功。
GitHub地址 linux分支
附录
ffmpeg编译参数对比
精简版 | 增强版 |
---|---|
--enable-gpl | + |
--enable-shared | + |
--disable-static | + |
--enable-version3 | + |
--enable-pthreads | + |
--enable-small | + |
--disable-vda | + |
--disable-iconv | + |
--disable-encoders | --enable-encoders |
--enable-libx264 | + |
--enable-neon | + |
--enable-yasm | + |
--enable-libfdk_aac | + |
--enable-encoder=libx264 | + |
--enable-encoder=libfdk_aac | + |
--enable-encoder=mjpeg | + |
--enable-encoder=png | + |
--enable-nonfree | + |
--enable-muxers | + |
--enable-muxer=mov | - |
--enable-muxer=mp4 | - |
--enable-muxer=h264 | - |
--enable-muxer=avi | - |
--disable-decoders | --enable-decoders |
--enable-decoder=aac | - |
--enable-decoder=aac_latm | - |
--enable-decoder=h264 | - |
--enable-decoder=mpeg4 | - |
--enable-decoder=mjpeg | - |
--enable-decoder=png | - |
--disable-demuxers | --enable-demuxers |
--enable-demuxer=image2 | - |
--enable-demuxer=h264 | - |
--enable-demuxer=aac | - |
--enable-demuxer=avi | - |
--enable-demuxer=mpc | - |
--enable-demuxer=mpegts | - |
--enable-demuxer=mov | - |
--disable-parsers | --enable-parsers |
--enable-parser=aac | - |
--enable-parser=ac3 | - |
--enable-parser=h264 | - |
--enable-protocols | + |
--enable-zlib | + |
--enable-avfilter | + |
--disable-outdevs | + |
--disable-ffprobe | + |
--disable-ffplay | + |
--disable-ffmpeg | + |
--disable-ffserver | + |
--disable-debug | + |
--disable-postproc | + |
--disable-avdevice | + |
--disable-symver | + |
--disable-stripping | + |
编译aac报错
Makefile:1269: recipe for target 'libSYS/src/genericStds.lo' failed
make: *** [libSYS/src/genericStds.lo] Error 1
CXX libSYS/src/cmdl_parser.lo
libSYS/src/cmdl_parser.cpp:96:19: fatal error: stdio.h: No such file or directory
#include <stdio.h>
^
compilation terminated.
Makefile:1269: recipe for target 'libSYS/src/cmdl_parser.lo' failed
make: *** [libSYS/src/cmdl_parser.lo] Error 1
解:改用ndk-r14b,因为r16b目录结构改了。
configure: creating ./config.status
config.status: creating Makefile
config.status: creating fdk-aac.pc
config.status: executing depfiles commands
config.status: executing libtool commands
configure: WARNING: unrecognized options: --disable-asm, --enable-pic, --enable-strip
CDPATH="${ZSH_VERSION+.}:" && cd . && /bin/bash /home/rong/AndroidStudioProjects/FFmpeg4Android/ffmpeg-3.2.5/fdk-aac-0.1.5/missing aclocal-1.15 -I m4
/home/rong/AndroidStudioProjects/FFmpeg4Android/ffmpeg-3.2.5/fdk-aac-0.1.5/missing: line 81: aclocal-1.15: command not found
WARNING: 'aclocal-1.15' is missing on your system.
You should only need it if you modified 'acinclude.m4' or
'configure.ac' or m4 files included by 'configure.ac'.
The 'aclocal' program is part of the GNU Automake package:
<http://www.gnu.org/software/automake>
It also requires GNU Autoconf, GNU m4 and Perl in order to run:
<http://www.gnu.org/software/autoconf>
<http://www.gnu.org/software/m4/>
<http://www.perl.org/>
Makefile:695: recipe for target 'aclocal.m4' failed
make: *** [aclocal.m4] Error 127
CDPATH="${ZSH_VERSION+.}:" && cd . && /bin/bash /home/rong/AndroidStudioProjects/FFmpeg4Android/ffmpeg-3.2.5/fdk-aac-0.1.5/missing aclocal-1.15 -I m4
/home/rong/AndroidStudioProjects/FFmpeg4Android/ffmpeg-3.2.5/fdk-aac-0.1.5/missing: line 81: aclocal-1.15: command not found
WARNING: 'aclocal-1.15' is missing on your system.
You should only need it if you modified 'acinclude.m4' or
'configure.ac' or m4 files included by 'configure.ac'.
The 'aclocal' program is part of the GNU Automake package:
<http://www.gnu.org/software/automake>
It also requires GNU Autoconf, GNU m4 and Perl in order to run:
<http://www.gnu.org/software/autoconf>
<http://www.gnu.org/software/m4/>
<http://www.perl.org/>
Makefile:695: recipe for target 'aclocal.m4' failed
make: *** [aclocal.m4] Error 127
CDPATH="${ZSH_VERSION+.}:" && cd . && /bin/bash /home/rong/AndroidStudioProjects/FFmpeg4Android/ffmpeg-3.2.5/fdk-aac-0.1.5/missing aclocal-1.15 -I m4
/home/rong/AndroidStudioProjects/FFmpeg4Android/ffmpeg-3.2.5/fdk-aac-0.1.5/missing: line 81: aclocal-1.15: command not found
WARNING: 'aclocal-1.15' is missing on your system.
You should only need it if you modified 'acinclude.m4' or
'configure.ac' or m4 files included by 'configure.ac'.
The 'aclocal' program is part of the GNU Automake package:
<http://www.gnu.org/software/automake>
It also requires GNU Autoconf, GNU m4 and Perl in order to run:
<http://www.gnu.org/software/autoconf>
<http://www.gnu.org/software/m4/>
<http://www.perl.org/>
Makefile:695: recipe for target 'aclocal.m4' failed
make: *** [aclocal.m4] Error 127
解:
sudo apt install autoreconf
autoreconf -f -i
编译ffmpeg报错
C compiler test failed.
解:查看config.log知道-march=arm-v7a
是不对的,应该用armv7-a
。
编译APP报错
截取一部分报错
../../../../src/main/jniLibs/armeabi-v7a/libavcodec.a(cscd.o):cscd.c:function decode_frame: error: undefined reference to 'uncompress'
../../../../src/main/jniLibs/armeabi-v7a/libavcodec.a(dxa.o):dxa.c:function decode_frame: error: undefined reference to 'uncompress'
../../../../src/main/jniLibs/armeabi-v7a/libavcodec.a(exr.o):exr.c:function decode_block: error: undefined reference to 'uncompress'
../../../../src/main/jniLibs/armeabi-v7a/libavcodec.a(exr.o):exr.c:function decode_block: error: undefined reference to 'uncompress'
../../../../src/main/jniLibs/armeabi-v7a/libavcodec.a(flashsv.o):flashsv.c:function flashsv_decode_end: error: undefined reference to 'inflateEnd'
../../../../src/main/jniLibs/armeabi-v7a/libavcodec.a(flashsv.o):flashsv.c:function flashsv_decode_init: error: undefined reference to 'inflateInit_'
../../../../src/main/jniLibs/armeabi-v7a/libavcodec.a(flashsv.o):flashsv.c:function flashsv_decode_frame: error: undefined reference to 'deflateInit_'
../../../../src/main/jniLibs/armeabi-v7a/libavcodec.a(flashsv.o):flashsv.c:function flashsv_decode_frame: error: undefined reference to 'deflateBound'
../../../../src/main/jniLibs/armeabi-v7a/libavcodec.a(flashsv.o):flashsv.c:function flashsv_decode_frame: error: undefined reference to 'deflateEnd'
../../../../src/main/jniLibs/armeabi-v7a/libavformat.a(concatdec.o):concatdec.c:function match_streams: error: undefined reference to 'av_bitstream_filter_init'
../../../../src/main/jniLibs/armeabi-v7a/libavformat.a(concatdec.o):concatdec.c:function concat_read_packet: error: undefined reference to 'av_bitstream_filter_filter'
../../../../src/main/jniLibs/armeabi-v7a/libavformat.a(utils.o):utils.c:function av_apply_bitstream_filters: error: undefined reference to 'av_bitstream_filter_filter'
../../../../src/main/jniLibs/armeabi-v7a/libavformat.a(http.o):http.c:function http_read_header: error: undefined reference to 'inflateInit2_'
../../../../src/main/jniLibs/armeabi-v7a/libavformat.a(http.o):http.c:function http_read_header: error: undefined reference to 'zlibCompileFlags'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.
解:补齐缺的include文件。添加libm和libz。
添加libm.h到x264编译报错
In file included from encoder/analyse.c:34:0:
./libavutil/libm.h:444:41: error: static declaration of 'round' follows non-static declaration
static av_always_inline av_const double round(double x)
^
In file included from ./common/osdep.h:43:0,
from ./common/common.h:117,
from encoder/analyse.c:28:
/home/rong/Android/android-ndk-r14b/platforms/android-19/arch-arm/usr/include/math.h:280:8: note: previous declaration of 'round' was here
double round(double);
^
In file included from encoder/analyse.c:34:0:
./libavutil/libm.h:451:40: error: static declaration of 'roundf' follows non-static declaration
static av_always_inline av_const float roundf(float x)
^
In file included from ./common/osdep.h:43:0,
from ./common/common.h:117,
from encoder/analyse.c:28:
/home/rong/Android/android-ndk-r14b/platforms/android-19/arch-arm/usr/include/math.h:341:7: note: previous declaration of 'roundf' was here
float roundf(float);
^
In file included from encoder/analyse.c:34:0:
./libavutil/libm.h:458:41: error: static declaration of 'trunc' follows non-static declaration
static av_always_inline av_const double trunc(double x)
^
In file included from ./common/osdep.h:43:0,
from ./common/common.h:117,
from encoder/analyse.c:28:
/home/rong/Android/android-ndk-r14b/platforms/android-19/arch-arm/usr/include/math.h:284:8: note: previous declaration of 'trunc' was here
double trunc(double);
^
In file included from encoder/analyse.c:34:0:
./libavutil/libm.h:465:40: error: static declaration of 'truncf' follows non-static declaration
static av_always_inline av_const float truncf(float x)
^
In file included from ./common/osdep.h:43:0,
from ./common/common.h:117,
from encoder/analyse.c:28:
/home/rong/Android/android-ndk-r14b/platforms/android-19/arch-arm/usr/include/math.h:367:7: note: previous declaration of 'truncf' was here
float truncf(float);
^
<builtin>: recipe for target 'encoder/analyse.o' failed
make: *** [encoder/analyse.o] Error 1
make包含libx264.a的工程 报错
../../../../src/main/jniLibs/armeabi-v7a/libx264.a(set.o):set.c:function x264_sps_init: error: undefined reference to 'log2f'
../../../../src/main/jniLibs/armeabi-v7a/libx264.a(encoder.o):encoder.c:function x264_validate_parameters: error: undefined reference to 'log2f'
../../../../src/main/jniLibs/armeabi-v7a/libx264.a(encoder.o):encoder.c:function x264_validate_parameters: error: undefined reference to 'log2f'
../../../../src/main/jniLibs/armeabi-v7a/libx264.a(analyse.o):analyse.c:function x264_analyse_init_costs: error: undefined reference to 'log2f'
../../../../src/main/jniLibs/armeabi-v7a/libx264.a(ratecontrol.o):ratecontrol.c:function x264_ratecontrol_new: error: undefined reference to 'log2'
../../../../src/main/jniLibs/armeabi-v7a/libx264.a(ratecontrol.o):ratecontrol.c:function x264_ratecontrol_new: error: undefined reference to 'log2'
../../../../src/main/jniLibs/armeabi-v7a/libx264.a(ratecontrol.o):ratecontrol.c:function x264_ratecontrol_new: error: undefined reference to 'log2'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.
放弃把libx264.a打包进去,最后保留一个libx264-148.so。
马赛克和花屏
丢包
参考
编译Android下可用的全平台FFmpeg(包含libx264与libfdk-aac) - CSDN博客
编译Android下可执行命令的FFmpeg - CSDN博客