一个RTP会话中有多个H.264视频流

时间:2020-03-06 15:02:33  来源:igfitidea点击:

我想在流视频应用程序中动态切换视频源。但是,不同的视频源具有唯一的图像尺寸。我可以为每个视频源生成单独的SDP文件,但是我想将它们合并为一个SDP文件,以便查看客户端可以在视频源更改时自动调整显示窗口的大小。这是两个示例SDP文件:

640x480.sdp:

v=0
o=VideoServer 305419896 9876543210 IN IP4 192.168.0.2
s=VideoStream640x480
t=0 0
c=IN IP4 192.168.0.2
m=video 8000/2 RTP/AVP 96
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=0; profile-level-id=4D4033; sprop-parameter-sets=Z01AM5ZkBQHtCAAAAwAIAAADAYR4wZU=,aO48gJ==
a=control:trackID=1

960x480.sdp:

v=0
o=VideoServer 305419896 9876543210 IN IP4 192.168.0.2
s=VideoStream960x480
t=0 0
c=IN IP4 192.168.0.2
m=video 8000/2 RTP/AVP 96
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=0; profile-level-id=4D4033; sprop-parameter-sets=J01AM5WwPA9sBAIA,KO4G8gA=
a=control:trackID=1

如何将这些单独的文件合并为一个SDP文件?

解决方案

我已经遍历了RFC(RFC2327 SDP:会话描述协议),看来我们可以将两个SDP文档串联起来。该文件明确指出:

When SDP is conveyed by SAP, only one session description is allowed per packet.  When SDP is conveyed by other means, many SDP session descriptions may be concatenated together (the `v=' line indicating the start of a session description terminates the previous description).

我认为这取决于解码器。如果它支持在流中更改参数,那么如果我们可以告诉编码器在更改分辨率时放置相应的标头,则解码器应自动切换。

我们到底要问什么?
是:如何在不停止/重新启动流的情况下更改分辨率?

我认为我们无法提前告诉解码器,这是一些sdp魔术所能看到的潜在分辨率。解码器能够理解H264参数的变化,然后就可以了,或者我们必须停止重新启动整个过程,然后使用动态sdp就足够了。

我知道,例如,VLC能够检测MP4编码的变化(例如,从可变比特率变为恒定比特率),但是如果我们更改分辨率,则会崩溃
使用sdp唯一可以做的就是结合不同的媒体描述,例如,使用不同的动态有效负载类型和不同的control-id属性。

两个sdp示例中的参数非常接近,流名称和sprop-parameter-sets不同。我假设我们不在乎流名称。如果我们需要单独的属性参数集,并且客户端很好地支持标准,则可以为每个分辨率使用单独的动态有效载荷类型,并具有单个SDP,如下所示:

v=0
    o=VideoServer 305419896 9876543210 IN IP4 192.168.0.2
    s=VideoStream640x480
    t=0 0
    c=IN IP4 192.168.0.2
    m=video 8000/2 RTP/AVP 96 <B>97
    a=rtpmap:96 H264/90000
    a=fmtp:96 packetization-mode=0; profile-level-id=4D4033; sprop-parameter-sets=Z01AM5ZkBQHtCAAAAwAIAAADAYR4wZU=,aO48gJ==
    a=rtpmap:97 H264/90000
    a=fmtp:97 packetization-mode=0; profile-level-id=4D4033; sprop-parameter-sets=J01AM5WwPA9sBAIA,KO4G8gA=
    a=control:trackID=1

与其他答案类似,如果我们实际上不需要其他流名称或者不同的属性参数集,则应该能够使用第一个SDP并在中间流中切换格式。我不知道H.264或者特定解码器的实际有效负载是否足以确保它可以在应用程序中正常工作,但是在视频会议应用程序中它很常见,它允许在分辨率之间动态切换而无需发出更改或者发出单独的动态信号。有效负载类型。

尽管我们可以按照另一个答案中的说明连接两个SDP文档,但在这种情况下它不会有帮助。我相信,H.264解码器一次只能使用单个属性参数集参数。由于两个SDP具有相同的有效负载类型,源端口等,因此接收器将不知道何时使用哪个sprop-parameter-sets参数。更新:请注意,某些实现是在带内而不是从SDP(或者仅最初是从SDP)获得它们的道具。如果在环境中适用,则可以在带内更新SDP prop参数集

参考:

  • H.264视频的RFC 3984 RTP有效负载格式
  • 新提议的H.264 RTP有效负载格式RFC 6184
  • RFC 4566 SDP:会话描述协议

[对不起,没有给出完整的引用,请随时进行纠正]

我们可以进行动态有效负载更改或者流内参数集更改,也可以进行SIP重新邀请。

有效负载更改存在一个问题,即如果我们不控制编码器和解码器,则需要确保另一端接受两个有效负载,并且它们将正确切换有效负载(对我们而言足够快,这方面没有要求)。

如果参数集数据包丢失,则流内更改会出现问题。我们可以使用另一组参数集(更改时从参数集1切换到参数集2),以避免在丢失参数集时误解码,我们应该只得到冻结的图片或者空白图片。我建议重传它们几次(不要以太快的顺序)。

SIP re-INVITE是带外和握手的,因此很安全,但是会增加任何切换的延迟,并且可能会因接收器而出现毛刺,因此可能被拒绝。

(注意:我是RFC 3984bis(RFC 3984的更新)的作者)