对比了RTSP、SRT、RIST几个协议之后,最终选用RIST作为我们的设备音视频传输协议;ffmpeg在4.4以后才支持rist,OBS也要2.8.0以后才行,VLC要4.0版本才能支持;
因为rist是一个比较新的流媒体传输协议,所以在使用的时候遇到了不少问题,这里记录一下编译rist进ffmpeg遇到的问题;
librist官网:https://code.videolan.org/rist/librist
* 设置rist环境路径
将librist.pc放在/usr/local/lib/pkgconfig路径下,这个librist.pc是rist build的产物,终端输入以下命令可以下载并编译librist,执行完之后,会在/usr/local/lib下生成一个librist.a静态库,/usr/local/include目录下产生头文件;
git clone https://code.videolan.org/rist/librist.git && \
cd librist && \
mkdir build && \
cd build && \
meson .. --default-library=static --buildtype=release -Db_lto=true && \
ninja install
设置环境变量,终端输入:
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH
修改librist.pc,因为cjson是可选的库,所以为了保证顺利编译成功,libs先干掉-lcjson;修改完成后的如下;
// 第一次踩坑
1、编译ffmpeg+rist
脚本下载地址: https://github.com/kewlbear/FFmpeg-iOS-build-script
macOS 解决 No package 'openssl' found 错误
configure删除openssl、librist的require_pkg_config判断;
暂时没用到audiotoolbox,全部先注释了; --disable-audiotoolbox --disable-videotoolbox
metal也不需要用到,删了就可以;
需要重新配置openssl路径信息,需要在/usr/local目录下创建opt目录,把brew install的openssl拖进该目录下;
Mac 操作系统 fatal error: 'openssl/ssl.h' file not found
简单解决:fatal error: ‘openssl/***.h‘ file not found等综合疑难问题-pudn.com
Makefile删除下面的:
OBJS-$(CONFIG_YADIF_VIDEOTOOLBOX_FILTER) += vf_yadif_videotoolbox.o \
metal/vf_yadif_videotoolbox.metallib.o \
metal/utils.o \
yadif_common.o
2、使用Rist
编译得到FFmpeg-iOS,直接拖入工程中,配置头文件目录,静态库地址;
编译:
尝试引入rist、openssl源码
设置header search path
新的问题
因为之前是把audiotoolbox.m的文件都注释了,所以此处找不到,放开ff_audiotoolbox_muxer,然后重新输入./build-ffmpeg.sh编译,导入新的库,编译通过;
跑起来了,可以open成功;
但是崩溃在find_stream了,怀疑是没有加入ff_audiotoolbox_muxer的原因,又绕回来了;
断言在avpriv_packet_list_put;
前面暴力删除audiotoolbox的办法看来不可行,只能针对audiotoolbox缺什么补什么了
问题点:修复audiotoolbox的报错,新增以下代码
typedef UInt32 AudioObjectID;
typedef AudioObjectID AudioDeviceID;
struct AudioObjectPropertyAddress
{
UInt32 mSelector;
UInt32 mScope;
UInt32 mElement;
};
typedef struct AudioObjectPropertyAddress AudioObjectPropertyAddress;
UInt32 kAudioHardwarePropertyDevices = 'dev#';
UInt32 kAudioObjectPropertyScopeGlobal = 'glob';
UInt32 kAudioObjectPropertyElementMaster = 0;
UInt32 kAudioObjectSystemObject = 1;
UInt32 kAudioDevicePropertyScopeInput = 'inpt';
UInt32 kAudioDevicePropertyDeviceUID = 'uid ';
UInt32 kAudioDevicePropertyDeviceNameCFString = 'lnam';
extern OSStatus
AudioObjectGetPropertyDataSize( AudioObjectID inObjectID,
const AudioObjectPropertyAddress* inAddress,
UInt32 inQualifierDataSize,
const void* __nullable inQualifierData,
UInt32* outDataSize) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0);
extern OSStatus
AudioObjectGetPropertyData( AudioObjectID inObjectID,
const AudioObjectPropertyAddress* inAddress,
UInt32 inQualifierDataSize,
const void* __nullable inQualifierData,
UInt32* ioDataSize,
void* outData) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0);
新增完以上内容之后,可以成功open_input,不会出现闪退问题;
新的问题,初始化重采样上下文失败
尝试修改配置参数,写死ch_layout、rate、sample_fmt等;
AVChannelLayout src_ch_layout = AV_CHANNEL_LAYOUT_STEREO, dst_ch_layout = AV_CHANNEL_LAYOUT_SURROUND;
int src_rate = 48000, dst_rate = 44100;
enum AVSampleFormat src_sample_fmt = AV_SAMPLE_FMT_DBL, dst_sample_fmt = AV_SAMPLE_FMT_S16;
acodecContext->sample_rate = src_rate;
acodecContext->ch_layout = src_ch_layout;
acodecContext->sample_fmt = src_sample_fmt;
desPcm->sample_rate = dst_rate;
desPcm->ch_layout = dst_ch_layout;
desPcm->format = dst_sample_fmt;
经过以上修改,swr_init成功;
但是又遇到了新的问题,在接收音频数据的时候崩溃了
很明显的,编的库有问题,换个思路再试试吧;
* 重新出发
之前使用的现成库:FFmpegKit自定义library
脚本下载地址:https://github.com/arthenica/ffmpeg-kit/
1、编译脚本
./ios.sh --enable-custom-library-1-name=librist --enable-custom-library-1-repo=https://code.videolan.org/rist/librist --enable-custom-library-1-repo-tag=v0.2.7 --enable-custom-library-1-package-config-file-name=librist --enable-custom-library-1-ffmpeg-enable-flag=librist --enable-custom-library-1-license-file=README.md
注:编译带x264、openssl、gpl的,不加入x264,会导致编码的时候找不到264编码器
./ios.sh --enable-custom-library-1-name=librist --enable-custom-library-1-repo=https://code.videolan.org/rist/librist --enable-custom-library-1-repo-tag=v0.2.7 --enable-custom-library-1-package-config-file-name=librist --enable-custom-library-1-ffmpeg-enable-flag=librist --enable-custom-library-1-license-file=README.md --enable-x264 --enable-openssl --enable-gpl
error1:x264 not found using pkg-config
enabled libx264 && require_pkg_config libx264 x264 "stdint.h x264.h" x264_encoder_encode &&
require_cpp_condition libx264 x264.h "X264_BUILD >= 118" && {
[ "$toolchain" != "msvc" ] ||
require_cpp_condition libx264 x264.h "X264_BUILD >= 158"; } &&
check_cpp_condition libx262 x264.h "X264_MPEG2"
ERROR: OpenSSL <3.0.0 is incompatible with the gpl
enabled openssl && { { check_pkg_config openssl "openssl >= 3.0.0" openssl/ssl.h OPENSSL_init_ssl &&
{ enabled gplv3 || ! enabled gpl || enabled nonfree || die "ERROR: OpenSSL >=3.0.0 requires --enable-version3"; }; } ||
{ enabled gpl && ! enabled nonfree && die "ERROR: OpenSSL <3.0.0 is incompatible with the gpl"; } ||
check_pkg_config openssl openssl openssl/ssl.h OPENSSL_init_ssl ||
check_pkg_config openssl openssl openssl/ssl.h SSL_library_init ||
check_lib openssl openssl/ssl.h OPENSSL_init_ssl -lssl -lcrypto ||
check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto ||
check_lib openssl openssl/ssl.h SSL_library_init -lssl32 -leay32 ||
check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto -lws2_32 -lgdi32 ||
die "ERROR: openssl not found"; }
libavformat/hlsenc.c:33:10: fatal error: 'openssl/rand.h' file not found
libavcodec/allcodecs.c:789:10: fatal error: 'x264.h' file not found
解决:将x264、openssl拖入libavformat同级目录;
Undefined symbols for architecture arm64:
将libx264.a库放入当前配置的libs路径下,并在终端输入:
export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig"
error2: 'librist/librist.h' file not found
比较简单的方法就把librist头文件放在libavformat同一级目录下,因为librist.c是在该目录下面;
此处因为官方编出来的.a库不支持iOS arm64(忘截图了),所以需要自己编库;
2、编译支持iOS架构的rist静态库
创建静态库工程
既然rist官方提供的方法编译出来的静态库不支持iOS,我们只能自己动手,丰衣足食了;
将rist源码拖入library工程中;配置Search Paths
bitcode支持
ffmpeg编译默认开启bitcode支持,所以我们编译的库也要支持bitcode才行;
当然我现在还没找到哪里可以关闭的,有找到的朋友可以留言互相探讨下。
找不到执行文件
需要通过下载librist资源文件,同时我们自己编译生成的librist.a库也要有;
x86是mac下的架构,具体可参考下面两篇文章,选择mac,在build,是可以生成x86_64架构的静态库;
https://www.jianshu.com/p/369b84ee0fd6
但是与现在的需求不符,这个也不能直接拖过来用,因为现在是要编译iOS可以的库,除非提取这个库的x86_64架构跟iphoneos的arm64、arm64e合并才能使用,所有这里的做法是:
直接改脚本,将x86_64的架构先剔除掉
通过关键词检索ffmpegkit目录,找到在main-ios.sh进行实际编译;
找到执行main-ios.sh的地方
通过关键词检索,在function.sh中找到0..12分别代表什么意思;
有了这个认知,发现8-12都是目前不需要编译的架构,所以就把ios.sh做一番调整,修改完成后如下:
/ffmpeg-kit/src/librist/LICENSE.md: No such file or directory
值得注意的是,运行脚本的时候, --enable-custom-library-1-license-file一定要写,在librist目录下面,可以新建一个LICENSE.md ,也可以直接使用README.md,即--enable-custom-library-1-license-file=README.md
错误示范:不带--enable-custom-library-1-license-file,编出来的库不完整,不会携带librist
./ios.sh --enable-custom-library-1-name=librist --enable-custom-library-1-repo=~~~~https://code.videolan.org/rist/librist --enable-custom-library-1-repo-tag=v0.2.7 --enable-custom-library-1-package-config-file-name=librist --enable-custom-library-1-ffmpeg-enable-flag=librist
编译成功!
prebuilt目录下apple-framework-ios就是我们要的库文件;
3、导入rist到工程中
直接将编译好的库拖入工程中,配置好header search path跟library search path,cmd+B编译;
运行,动态库没有加载成功
查看.app文件,发现framesworks确实没有;
参考下面这篇文章,手动copy Files,配置Runpath Search Paths->@executable_path/Frameworks;
参考:dyld: Library not loaded: @rpath/xxx.framework 动态库
4、测试
obs输入手机ip地址,然后开始直播
手机通过rist://@0.0.0.0:8888可以成功拉取到视频流数据;
5、编译源文件
librist.a静态库编译源码:https://github.com/xghbq-yang/build-rist-lib
修改完的脚本下载地址:https://github.com/xghbq-yang/ffmpeg-rist-for-ios