1.error: undefined reference to ‘av_version_info()’
出错原因: ffmpeg是纯C的库,头文件没有做好C++调用的准备 用extern “C”{}套住ffmpeg头文件,用C 语言的编译规则来编译ffmpeg代码,就可以了
解决办法:
1 2 3 extern "C" { #include <libavutil/avutil.h> }
2.libavutil/log.c:186: error: undefined reference to ‘stderr’
出错原因: 代码中使用了大量的标准IO设备:stderr 等,这些在NDK15以后,这些都不被支持了,代码本身 没问题,只是编译器链接时找不到对应的静态库定义了;
解决方案: 在编译选项中添加语句-DANDROID_API=[你的android API版本号]即可; 比如我的测试手机为 android 5.1.1 对应 API = 22,编译选项中应该添加:-DANDROID_API=22 adb shell 获取 android 系统版本: adb shell getprop ro.build.version.release adb shell 获取 android 系统 API 版本: adb shell getprop ro.build.version.sdk
出错原因: 链接静态库先后顺序不正确,引起的符号定义找不到。 解决方案:
修改静态库的链接顺序。
1 2 3 4 target_link_libraries ( native-lib avfilter avformat avcodec avutil swresample swscale log )
忽略静态库的链接顺序。
1 2 3 4 5 6 target_link_libraries ( native-lib -Wl,--start-group avcodec avfilter avformat avutil swresample swscale -Wl,--end-group log )
出错原因: 找不到的z库中的函数的实现。因为 ffmpeg 依赖了z库。编译ffmpeg的时候如果仔细看编译 时输出的日志,就可以看到 External libraries: zlib 解决方案:添加z库的依赖。
1 2 3 4 5 6 7 target_link_libraries ( native-lib -Wl,--start-group avcodec avfilter avformat avutil swresample swscale -Wl,--end-group log z )
出错原因: Google have moved some of the C standard library functions like atof() from being inline functions in header files to normal functions. The latest NDKs will default to building a .so that is only compatible with the latest Android devices that have the atof() function in the device’s standard C library (libc.so). This means if you run a library on an older device that has an older version of the C library, you will get an error loading the dll as the expected atof() function will not exist. 解决方案: 修改ffmpeg编译脚本,指定Android API版本为17,重新编译。
这里又有一个问题: libavcodec/v4l2_buffers.c:434:44: error: call to ‘mmap’ declared with attribute error: mmap is not available > with _FILE_OFFSET_BITS=64 when using GCC until android-21. Either raise your minSdkVersion, disable > _FILE_OFFSET_BITS=64, or switch to Clang.
所以21版本以下,需要取消 _FILE_OFFSET_BITS宏定义。添加编译参数: -U_FILE_OFFSET_BITS
6.混合编译FFmpeg和Rtmp 6.1 下载最新库 1 2 3 4 5 6 7 wget https: unzip master wget https: tar -xvf ffmpeg-4.2 .2 .tar.bz2
6.2 单编rtmp脚本 编译androideabi架构
1 2 3 4 5 6 7 8 9 10 11 12 13 # !/bin/bash NDK_ROOT=/home/jackou/tools/android-ndk-r17c CPU=arm-linux-androideabi TOOLCHAIN=$NDK_ROOT/toolchains/$CPU-4.9/prebuilt/linux-x86_64 export XCFLAGS="-isysroot $NDK_ROOT/sysroot -isystem $NDK_ROOT/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=17" export XLDFLAGS="--sysroot=${NDK_ROOT}/platforms/android-17/arch-arm " export CROSS_COMPILE=$TOOLCHAIN/bin/arm-linux-androideabi- make install SYS=android prefix=`pwd`/result CRYPTO= SHARED= XDEF=-DNO_SSL
编译arm64-v8a架构
1 2 3 4 5 6 7 8 9 10 11 12 13 # !/bin/bash NDK_ROOT=/home/jackou/tools/android-ndk-r17c CPU=aarch64-linux-android TOOLCHAIN=$NDK_ROOT/toolchains/$CPU-4.9/prebuilt/linux-x86_64 export XCFLAGS="-isysroot $NDK_ROOT/sysroot -isystem $NDK_ROOT/sysroot/usr/include/aarch64-linux-android -D__ANDROID_API__=17" export XLDFLAGS="--sysroot=${NDK_ROOT}/platforms/android-17/arch-arm " export CROSS_COMPILE=$TOOLCHAIN/bin/aarch64-linux-android- make install SYS=android prefix=`pwd`/result CRYPTO= SHARED= XDEF=-DNO_SSL
6.2混编FFmpeg和rtmp 6.2.1 修改configure文件
6.2.1.1 最新版本的ffmpeg默认使用clang编译,可以修改configure文件来关闭
1 2 3 4 5 6 注释4210-4213行,关闭掉: 4209 4210 #set_default target_os 4211 #if test "$target_os" = android; then 4212 # cc_default="clang" 4213 #fi 4214
6.2.1.2 由于ffmpeg 默认开启librtmp需要pkgconfig,这里我们手动关闭,修改ffmpeg的configure文件:
1 2 3 4 5 6 # 6254 enabled libpulse && require_pkg_config libpulse libpulse pulse/pulseaudio.h pa_context_new 6255 enabled librsvg && require_pkg_config librsvg librsvg-2.0 librsvg-2.0/librsvg/rsvg.h rsvg_handle_render_cairo 6256 # enabled librtmp && require_pkg_config librtmp librtmp librtmp/rtmp.h RTMP_Socket 6257 enabled librubberband && require_pkg_config librubberband "rubberband >= 1.8.1" rubberband/rubberband-c.h rubberband_new -lstdc++ && append librubberband_extralibs "-lstdc++" 6258 enabled libshine && require_pkg_config libshine shine shine/layer3.h shine_encode_buffer
6.2.2 编译androideabi架构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 # !/bin/bash NDK_ROOT=/home/jackou/tools/android-ndk-r17c CPU=arm-linux-androideabi TOOLCHAIN=$NDK_ROOT/toolchains/$CPU-4.9/prebuilt/linux-x86_64 ANDROID_API=17 PREFIX=./android/armeabi-v7a/ffmpeg_rtmp # rtmp路径 RTMP=/root/KevinStudyNDK/MyFFmpeg3/librtmp/result ./configure \ --prefix=$PREFIX \ --enable-small \ --disable-programs \ --disable-avdevice \ --disable-encoders \ --disable-muxers \ --disable-filters \ --enable-librtmp \ --enable-cross-compile \ --cross-prefix=$TOOLCHAIN/bin/$CPU- \ --disable-shared \ --enable-static \ --sysroot=$NDK_ROOT/platforms/android-$ANDROID_API/arch-arm \ --extra-cflags="-isysroot $NDK_ROOT/sysroot -isystem $NDK_ROOT/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=$ANDROID_API -U_FILE_OFFSET_BITS -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -Wa,--noexecstack -Wformat -Werror=format-security -O0 -fPIC -I$RTMP/include" \ --extra-ldflags="-L$RTMP/lib" \ --extra-libs="-lrtmp" \ --arch=arm \ --target-os=android make clean make install
编译arm64-v8a架构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 # !/bin/bash NDK_ROOT=/home/jackou/tools/android-ndk-r17c CPU=aarch64-linux-android TOOLCHAIN=$NDK_ROOT/toolchains/$CPU-4.9/prebuilt/linux-x86_64 ANDROID_API=21 PREFIX=./android/arm64-v8a/ffmpeg_rtmp # rtmp路径 RTMP=/home/jackou/ndk/ffmpeg/librtmp-master/result ./configure \ --prefix=$PREFIX \ --enable-small \ --disable-programs \ --disable-avdevice \ --disable-encoders \ --disable-muxers \ --disable-filters \ --enable-librtmp \ --enable-cross-compile \ --cross-prefix=$TOOLCHAIN/bin/$CPU- \ --disable-shared \ --enable-static \ --sysroot=$NDK_ROOT/platforms/android-$ANDROID_API/arch-arm64 \ --extra-cflags="-isysroot $NDK_ROOT/sysroot -isystem $NDK_ROOT/sysroot/usr/include/aarch64-linux-android -D__ANDROID_API__=$ANDROID_API -U_FILE_OFFSET_BITS -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=arm64-v8a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -Wa,--noexecstack -Wformat -Werror=format-security -O0 -fPIC -I$RTMP/include" \ --extra-ldflags="-L$RTMP/lib" \ --extra-libs="-lrtmp" \ --arch=aarch64 \ --target-os=android make clean make install
6.2.3 集成到AS中CMakelist脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 include_directories (${CMAKE_SOURCE_DIR} /ffmpeg/include ) set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} - L${CMAKE_SOURCE_DIR}/ffmpeg/libs/${CMAKE_ANDROID_ARCH_ABI}" ) set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} - L${CMAKE_SOURCE_DIR}/rtmp/libs/${CMAKE_ANDROID_ARCH_ABI}" ) target_link_libraries ( my-player ${log-lib} -Wl, --start-group avcodec avfilter avformat avutil swresample swscale -Wl, --end-group z )
7.搭建rtmp服务器 7.1 下载Nginx和rtmp-module 1 2 3 4 5 # 下载Nginx wget http://nginx.org/download/nginx-1.15.3.tar.gz tar xvf nginx-1.15.3.tar.gz # 下载rtmp-module wget https://codeload.github.com/arut/nginx-rtmp-module/tar.gz/v1.2.1
7.2 执行配置和安装 1 2 3 4 # 生成makefile ./configure --prefix=./bin --add-module=../nginx-rtmp-module-1.2.1 # 生成结果在bin make install
成功之后,会在/bin下生成conf html logs sbin几个文件。
7.3 配置Nginx 1 2 3 # 进入到成果目录,并且配置nginx cd /bin/conf vim nginx.conf
配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 # 启动nginx服务器就会报错,权限被拒绝 user root; worker_processes 1; # 如果启动错误,这个就是错误日志详情 error_log logs/error.log debug; events { worker_connections 1024; } rtmp { server { # 注意端口占用 流媒体服务器的端口 listen 1935; # 如果不加,可能会失败 application myapp { live on; # 丢弃闲置5s的连接 drop_idle_publisher 5s; } } } # 下面就是为了测试 http://139.224.136.101:8080/stat 控制面板的意思 http { server { # 注意端口占用 listen 8080; location /stat { rtmp_stat all; rtmp_stat_stylesheet stat.xsl; } location /stat.xsl { root /home/jackou/ndk/Nginx_RTMP/nginx-rtmp-module-1.2.1/; } location /control { rtmp_control all; } location /rtmp-publisher { root /home/jackou/ndk/Nginx_RTMP/nginx-rtmp-module-1.2.1/test; } location / { root /home/jackou/ndk/Nginx_RTMP/nginx-rtmp-module-1.2.1/test/www; } } }
7.4 启动服务 1 jackou@ubuntu:~/ndk/Nginx_RTMP/nginx-1.15.3$ sudo bin/sbin/nginx
1 2 3 4 5 6 7 8 9 10 11 12 nginx: [emerg] bind() to 0.0.0.0:1935 failed (98: Address already in use) nginx: [emerg] bind() to 0.0.0.0:8080 failed (98: Address already in use) nginx: [emerg] bind() to 0.0.0.0:1935 failed (98: Address already in use) nginx: [emerg] bind() to 0.0.0.0:8080 failed (98: Address already in use) nginx: [emerg] bind() to 0.0.0.0:1935 failed (98: Address already in use) nginx: [emerg] bind() to 0.0.0.0:8080 failed (98: Address already in use) nginx: [emerg] bind() to 0.0.0.0:1935 failed (98: Address already in use) nginx: [emerg] bind() to 0.0.0.0:8080 failed (98: Address already in use) nginx: [emerg] bind() to 0.0.0.0:1935 failed (98: Address already in use) nginx: [emerg] bind() to 0.0.0.0:8080 failed (98: Address already in use) nginx: [emerg] still could not bind() # 端口被占用需要停止服务
1 2 # 停止服务 sudo bin/sbin/nginx -s stop
1 2 # 重启后输入如下域名查看是否启动成功 http://139.224.136.101:8080/stat
启动成功之后,就会出现这种情况,139.224.136.101是一个共有云服务器,需要自己买。
版权声明: 此文章版权归Jack Ou所有,如有转载,请註明来自原作者