FreeSWITCH H264
FreeSWITCH默认支持H263 H264 VP8 VP9等视频编码,这里先只讨论H264。
mod_av和mod_openh264都支持H264编解码,这里只介绍mod_av。mod_av借助FFmpeg的强大功能不仅实现了视频编解码(avcodec),同时也实现文件接口(avformat)支持视频播放及录制。
需要说明的是最新的Freeswitch master或v1.10.10已经支持FFmpeg 5.1,支持avcodec_send_frame avcodec_receive_packet等编解码接口。
除了需要加载codec模块,还需要修改sip profile增加相关的codec,参见inbound-codec-prefs outbound-codec-prefs。
FreeSWITCH H264部分细节
呼叫时也可以设置absolute_codec_string这样按照指定的编码呼叫。
通过设置rtp_force_video_fmtp这个通道可以影响H264的部分编码参数及打包方式。其中profile-level-id由3部分组成profile_idc profile_iop level_idc(如何解析自己搜索一下),其中profile_idc对应H264 profile是BP MP还是HP;level_idc对应编码的level 3.0还是4.0等,不同的分辨率一般对应不同的level,比如720P用3,1080P的用4,当然都用3也没有问题。
packetization-mode表示打包模式,取值0 1 2,常见的就0或者1。从下面列表里不同打包模式支持的类型来看,0 1模式主要区别是FU-A,可以这样理解:单一nalu不超过MTU不用分包,否则需要分包成FU-A。STAP-A常用在SPS和PPS组合成一个包。
mode 0 1 2
Payload Packet Single NAL Non-Interleaved Interleaved
Type Type Unit Mode Mode Mode
-------------------------------------------------------------
0 reserved ig ig ig
1-23 NAL unit yes yes no
24 STAP-A no yes no
25 STAP-B no no yes
26 MTAP16 no no yes
27 MTAP24 no no yes
28 FU-A no yes yes
29 FU-B no no yes
30-31 reserved ig ig ig
fmtp举例如下:
rtp_force_video_fmtp=profile-level-id=42801F;packetization-mode=1
上面的这些参数都可以通过修改av.conf来控制,配置项比较多,这里不一一说明,可以同时参考FFmpeg来看。
需要说明的是FreeSWITCH还没有解析fmtp,但是你可以外呼时指定fmtp防止某些场景视频协商失败,比如对接IMS。
视频相关APP
视频的常用的场景一般有这么几种:bridge,playback,conference。
bridge
bridge默认不转码,根据a腿的编码去呼叫b,协商失败就看到常见的488 Not Acceptable Here。如果两条腿的编码配置确实没法做到一致,那可以通过设置通道变量media_mix_inbound_outbound_codecs=true开启转码。
转码的情况下每条腿都需要解码再编码发给对方,这样bridge就需要2次解码,2次编码,如果开启录像还需要占用1路编码,资源消耗还是比较大的。
playback
播放视频编码参数根据视频文件来的,像IMS对接的话,需要控制下视频文件的码率不好太高,否则手机可能黑屏。
conference
会议profile conference-flags开启minimize-video-encoding时会共用编码器,减少资源消耗,两外profile中bandwidth的配置要小于等于rtp_video_max_bandwidth_out,否则每个成员还是用自己的编码器。
共享编码器的话,如果某个成员丢包通过RTCP请求关键帧,所有的成员都会收到关键帧,会浪费带宽,不过可以修改av.conf来限制最小关键帧间隔(key-frame-min-freq),否则某个时间段可能都是关键帧了。
如何在Wireshark中分析H264
Wireshark功能强大不用多说,并且对SIP RTP支持的很完善。
如上图所示,如果抓包包含SIP信令,Wireshark Protocol直接显示为H264,可以直观的看到每个包的类型。如果没有SIP信令,只显示UDP,可以右键Decode As选择RTP,如果还是不显示H264,可以看一下RTP头中的PT值,依次选择编辑-首选项-Protocol-H264,添加PT值即可。
同时也可以在电话-RTP-RTP流中查看每个方向的流信息,可以直接看到丢包,最大延迟等。
如果包看起来没有丢,但是终端看到的视频问题,有没有办法能导出H264流呢?看这里:volvet/h264extractor: wireshark plugin to extract h264 or opus stream from rtp packets (github.com)。照着README中How to操作一下,工具这里就可以直接使用了。
防止不同方向的H264包互相影响,可以先根据端口过滤下包(udp.srcport==12345或者udp.dstport==12345),然后选择文件-导出特定分组保存一个干净的包再导出H264。
包的同级目录下会产生一个xxx.h264文件,可以直接通过ffplay xxx.h264进行播放。
其他
后面想到了其他的再补充。