1 在本机推流与播放
音视频推流的时候,ffmpeg分别绑定本地一个端口A、B,然后把视频和音频都推送到同一个组播端口C
播放时从组播端口C拉取数据,因为RTP协议的Payload可以区分视频数据和音频数据。
1 | 推流视频 |
也可以单独播放视频、音频,只需要将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 | 推流 输出格式必须使用muxer封装为container,rtp_mpegts |
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 | SDP required: |
2 在局域网的组播
和本机组播一样,在一台电脑上推流,在另一台电脑上就可以观看。
推流电脑:
1 | # 推流视频 |
拉流电脑:
1 | 播放 |
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 | 推流视频 |
ffmpeg vlc
ffmpeg的播放效果很好,音视频都能流畅播放。VLC可以流畅播放音频,视频总是卡在某一帧,不能更新数据,不知道为什么。
用Wireshark抓包数据是一直更新的