安卓RTSP转MP4

本文链接:https://www.jianshu.com/p/38894c45daf0

测试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,没看到输出文件,第二次开搞直接闪退,报错

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博客

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容