一次RTP多播测试

1 在本机推流与播放

音视频推流的时候,ffmpeg分别绑定本地一个端口A、B,然后把视频和音频都推送到同一个组播端口C

播放时从组播端口C拉取数据,因为RTP协议的Payload可以区分视频数据和音频数据。

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
# 推流视频
.\ffmpeg.exe -re -i demo.h264 -vcodec copy -f rtp rtp://233.5.5.5:23466
# 推流音频
.\ffmpeg.exe -re -i demo.mp3 -acodec copy -f rtp rtp://233.5.5.5:23466

# SDP文件
# all.sdp
v=0
o=- 0 0 IN IP4 127.0.0.1
s=White Butterfly
c=IN IP4 233.5.5.5
t=0 0
a=tool:libavformat 57.56.101
m=audio 23466 RTP/AVP 14
b=AS:128

v=0
o=- 0 0 IN IP4 127.0.0.1
s=No Name
c=IN IP4 233.5.5.5
t=0 0
a=tool:libavformat 57.56.101
m=video 23466 RTP/AVP 96
a=rtpmap:96 H264/90000

# 播放
.\ffplay.exe -protocol_whitelist file,udp,rtp all.sdp

也可以单独播放视频、音频,只需要将SDP分开写就好。

tips 1· Payload

RTP协议中使用Payload标识数据类型,占用7bits,范围0~127。

其中,0~95有明确的定义,比如PT=14为MPEG-1 or MPEG-2 音频audio;PT=32为MPEG-1 or MPEG-2 视频video;PT=33为MPEG-2 Transport Stream(MP2T)包含音频audio和视频video。

96以后是用户自定义的动态负载,上面方式中,ffmpeg默认将H264数据设为PT=96。

一种数据类型使用一种PT,RTP只能携带一种负载(头结构决定了只有一个PT段),所以,音频和视频裸流要分开发送;MP2T中是ts格式的容器,包含音视频的封装格式。

使用mp2t:

1
2
3
4
5
#推流 输出格式必须使用muxer封装为container,rtp_mpegts
.\ffmpeg.exe -re -i .\demo.mp4 -c copy -f rtp_mpegts rtp://233.5.5.5:7788

#播放 可以同时播放声音和画面
\ffplay.exe rtp://233.5.5.5:7788

tips 2· url ~ sdp

使用RTP协议规定的PT值时,可以直接用url方式播放,如.\ffplay.exe rtp://233.5.5.5:23466\vlc.exe rtp://233.5.5.5:23466
使用自定义动态负载时,如PT=96的h264裸流,必须用Session Description Protocol-SDP文件明确说明负载属性。

PT≥96时使用URL,会播放失败:

  • ffmpeg出现错误:
1
Unable to receive RTP payload type 96 without an SDP file describing it
  • VLC出现错误:
1
2
SDP required:
A description in SDP format is required to receive the RTP stream. Note that rtp:// URIs cannot work with dynamic RTP payload format (96).

2 在局域网的组播

和本机组播一样,在一台电脑上推流,在另一台电脑上就可以观看。

推流电脑:

1
2
3
4
# 推流视频
.\ffmpeg.exe -re -i demo.h264 -vcodec copy -f rtp rtp://233.5.5.5:23466
# 推流音频
.\ffmpeg.exe -re -i demo.mp3 -acodec copy -f rtp rtp://233.5.5.5:23466

拉流电脑:

1
2
 # 播放
.\ffplay.exe -protocol_whitelist file,udp,rtp all.sdp

3 VLC播放失败的问题

我在测试过程中发现wireshark可以抓取到rtp包,但是vlc就是不能播放。换成ubuntu系统就可以用VLC播放,很奇怪。

这个问题困扰了好久终于发现原因了。是因为虚拟机网卡导致的。

3.1 解决方案

当客户端电脑上安装了 Oracle VM VirtualBox 的网卡 VirtualBox Host-Only Ethernet Adapter ,必须禁用这个适配器才能接收到rtp数据,否则vlc、ffplay等不能正常接收,不能播放。

禁用VirtualBox Host-Only Ethernet Adapter后,VLC就可以正常接收到多播数据了。

如果还不能播放,可能是Windows防火墙阻止了,需要去防火墙添加规则,放行VLC的所有数据。

3.2 还有个问题

我所在的局域网网络拓扑如下

用一个路由器组成的192.168.1.0/24的局域网,所有设备都是一个网段。

RTP服务器接有无线网卡和有线网卡,RTP推流两路信号分别到233.2.2.2 和 233.4.4.4 两个地址。

用有线连接的电脑都能接收到多播数据包,并且能够在VLC上播放

但是只用无线WiFi连接的电脑收不到多播数据包,更谈不上播放了。在笔记本上用Wireshark抓不到ip为233.x.x.x的包,暂时不知道什么原因。

4 在本机的单播

因为单播的本地端口A、B都推送到本地端口C,当有进程和C端口建立连接后,会阻止其他进程再去链接C端口。因此推流时需要把音视频分别推送到不同的端口,然后播放时在不同的端口拉取数据。

即推送时 :

视频 本地端口A 推送到 本地端口 C

音频 本地端口B 推送到 本地端口 D

播放时:

视频 本地端口E 拉取 本地端口 C

音频 本地端口F 拉取 本地端口 D

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
# 推流视频
.\ffmpeg.exe -re -i demo.h264 -vcodec copy -f rtp rtp://localhost:23477
# 推流音频
.\ffmpeg.exe -re -i demo.mp3 -acodec copy -f rtp rtp://localhost:23488

# SDP文件
# all.sdp
v=0
o=- 0 0 IN IP4 127.0.0.1
s=White Butterfly
c=IN IP4 localhost
t=0 0
a=tool:libavformat 57.56.101
m=audio 23488 RTP/AVP 14
b=AS:128

v=0
o=- 0 0 IN IP4 127.0.0.1
s=No Name
c=IN IP4 localhost
t=0 0
a=tool:libavformat 57.56.101
m=video 23477 RTP/AVP 96
a=rtpmap:96 H264/90000

# 播放
.\ffplay.exe -protocol_whitelist file,udp,rtp all.sdp

ffmpeg vlc

ffmpeg的播放效果很好,音视频都能流畅播放。VLC可以流畅播放音频,视频总是卡在某一帧,不能更新数据,不知道为什么。

用Wireshark抓包数据是一直更新的

虽然很不要脸,但是还请您多多打赏 ^_^