FreeSWITCH+H264+Wireshark分析

1,012 阅读4分钟

FreeSWITCH H264

FreeSWITCH默认支持H263 H264 VP8 VP9等视频编码,这里先只讨论H264

mod_avmod_openh264都支持H264编解码,这里只介绍mod_avmod_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-ASTAP-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支持的很完善。

image.png

如上图所示,如果抓包包含SIP信令,Wireshark Protocol直接显示为H264,可以直观的看到每个包的类型。如果没有SIP信令,只显示UDP,可以右键Decode As选择RTP,如果还是不显示H264,可以看一下RTP头中的PT值,依次选择编辑-首选项-Protocol-H264,添加PT值即可。

image.png

同时也可以在电话-RTP-RTP流中查看每个方向的流信息,可以直接看到丢包,最大延迟等。

image.png

如果包看起来没有丢,但是终端看到的视频问题,有没有办法能导出H264流呢?看这里:volvet/h264extractor: wireshark plugin to extract h264 or opus stream from rtp packets (github.com)。照着README中How to操作一下,工具这里就可以直接使用了。

image.png

防止不同方向的H264包互相影响,可以先根据端口过滤下包(udp.srcport==12345或者udp.dstport==12345),然后选择文件-导出特定分组保存一个干净的包再导出H264。

包的同级目录下会产生一个xxx.h264文件,可以直接通过ffplay xxx.h264进行播放。

其他

后面想到了其他的再补充。