安卓RTSP转MP4

本文链接:https://blog.csdn.net/obarong/article/details/80009362

测试FFmpeg的RTSP转MP4功能

环境:Win7
工具:ffmpeg-win-2.2.2

命令行运行
ffmepg rtsp to mp4.jpg

VLC播放
win7测试.jpg

功能正常。

测试FFmpeg4Android项目

环境
- Win7
- Android Studio 3.1
- NDK r16b

参考剑西的博客《编译Android下可执行命令的FFmpeg》

修改命令
压缩MP4.jpg

编译运行
FFmpeg4Android.jpeg

测试压缩MP4,成功。
压缩成功.jpeg

第一次转显示OK,没看到输出文件,第二次开搞直接闪退,报错

扫描二维码关注公众号,回复: 3131852 查看本文章
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流,要用增强版的库。否则会闪退。
FFmpeg4Android下载中.jpeg
FFmpeg4Android下载完成.jpeg

保存成功
保存成功.jpeg

增强版v7a安装包大小.jpg

编译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编译成功.jpg

这里为什么编译成静态库而不是动态库呢?静态库可以把内容编译到待会儿要编译 ffmpeg 的so库里去,不需要单独加载 libx264.so 了,如果你硬要编译成动态库也可以,加载 ffmpeg.so 的时候加载 libx264.so 就可以。

–enable-static –disable-shared这两个是看编译出来的库是静态库(.a)还是动态库(.so),如果要编译成动态库就–enable-shared –disable-static。或者两个都编译出来。

运行安卓版FFmpeg

ffmpeg静态库a文件.jpg

还是用前面的项目,把android_more目录下arm-v7a的静态库.a文件复制到jniLibs目录,不要忘了libx264-148.a和libfdk-aac.a

写脚本提取头文件,放到cpp目录下
include.jpg

修改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。

link.jpg

准备完成之后点击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

参考 installation stops with WARNING: ‘aclocal-1.15’ is missing on your system · Issue #97 · apereo/mod_auth_cas

编译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。

马赛克和花屏

视频失真.jpg

视频失真2.jpg

丢包

ffmpeg rtsp2.jpg

参考

Android下玩JNI的新老三种姿势 - CSDN博客

编译Android下可用的全平台FFmpeg(包含libx264与libfdk-aac) - CSDN博客

编译Android下可执行命令的FFmpeg - CSDN博客

向您的项目添加 C 和 C++ 代码 | Android Studio

在Android上使用FFmpeg压缩视频 - 简书

最纯粹的直播技术实战01-FFmpeg的编译与运行 - CSDN博客

猜你喜欢

转载自blog.csdn.net/obarong/article/details/80009362