虽然plan b已经过期了,unified plan已经成为了标准,但是很多遗留系统还在使用plan
b,为了更好地理解,还是需要把plan b也好好学习一下
1. 简介
2. 设计目标
3. 设计细节
3.1 每个[media-type, content]每个m行
不管提供或使用多少的源,默认情况,每一个媒体类型(例如audio video application)只使用一个m行。如果应用希望这样,它可以通过设置media stream track的content属性,把给定的媒体源放置到一个m行。Content的属性值定义在RFC4796。这有助于一些遗留案例的互通,例如,一个终端希望它的m=video行传递屏幕共享视频源。这个属性设置场景一般很有限。
通过每种媒体类型使用一个m行而不是每一个媒体源使用一个m行,这种方式在复杂的音频/视频场景当中把所需要的Transport数量减小到2。注意在单 audio和video的通用案例中,结果和每个source一个m行是完全一样的。因此这种场景当中遗留设备不会有问题。在更复杂的案例当中,应用可以选择m行当中的哪一个源用来发送,用来和遗留设备进行交互。
3.2 传递在信令当中通过ssrc标识的source。
媒体源是通过信令中的SSRC进行标识的。参见RFC5576的SSRC属性。MST(MediaStreamTrack)的每一个提供者,在信令消息中表明他们想要发送的MST。当使用类似Simulcast或者RTX技术的时候,一个媒体源可以跨多个SSRC。MST和SSRC之间的关联性通过MSID属性来表示。SSRC属性包含MST的ID属性,就这样表明了MST关联到这个SSRC。在下面的例子中,SDP公告了三个独立的audio source,每一个都是通过一个单独的SSRC表标识
m=audio 49170 RTP/AVP 101 // main audio
a=ssrc:1 msid:left-mic // declare 3 outgoing audio sources
a=ssrc:2 msid:center-mic
a=ssrc:3 msid:right-mic
注意,由于ssrc的信令发布,SSRC冲突不是一个大问题。每个终端能够确保它是选择的SSRC不会冲突。因为它已经知道它所有使用的SSRC还有远端信令发送过来的SSRC。在极少数场景下也可能会发生---可能由于两端并行的发送信令,一端一感知到冲突,它能够更新它发送的source而不冲突。如果冲突发生在媒体流进行时,或者一个Endpoint出于任何原因需要修改SSRC,RFC5576的previous SSRC属性能够被用来修改已经存在的SSRC为一个新的值。同时保持媒体的连续播放。
3.3 接收通过使用remote ssrc请求的媒体源
当提供者公告他的媒体流时,远端能够在回答消息当中选择他想要接受的媒体。通过I-D.lennox-mmusic-sdp-source-selection表示,这个RFC介绍了remote-SSRC属性的概念。通过使用这个属性远端设置源的开和关,来选择提供者提供的源。并且可选地指定接收者建议的特定source的解析度,帧率和优先级。
这也可以用于选择Simulcast streams。或者开启和关闭类似rtx或FEC的技术。在下面的例子中,接收者发送的SDP只请求源当中的一个。
m=audio 39170 RTP/AVP 101 // main audio
a=remote-ssrc:1 recv:on // just turn on the center mic
这个逻辑的运行的准确规则在前文的草案当中指定。
3.4 rtx fec simulcast
在一个媒体源需要关联不止一个RTP流的场景当中,例如RTX,FEC或者Simulcast。RFC5576的SSRC-group概念被用于为单个MST创建一组SSRC.。每一个SSRC通过使用a=ssrc属性声明。SSRC之间共享相同的MSID。a=ssrc-group属性定义了这些分组的SSRC之间的行为。当许多流在一个单独的rtp session当中多路复用时,这些分组被用于接收的FTP流的解复用,并且关联到他们的primary flow。这是RTX或者FEC流能够被关联到他们当primary flow的唯一方式。一个RTP会话当中的RTX和FEC多路复用已经被良好定义。分别定义在RFC4588和RFC5956。
对于多解析度的Simulcast,我们创建一个类似的ssrc-group,并且为每一个SSRC行调整imageattr(定义在RFC6236)。在下面的例子中,SDP公告了两个不同解析度的同一个摄像头source和一个支持RTX的屏幕共享source。ssrc-group用来关联单一媒体源的不同SSRC。
m=video 62537 RTP/SAVPF 96 // main video
a=ssrc:5 msid:center-cam // one source is simulcasting at two resolutions
a=ssrc:5 imageattr:* [1280, 720]
a=ssrc:51 msid:center-cam // different SSRC, same MSID for simulcasts
a=ssrc:51 imageattr:* [640, 360]
a=ssrc-group:SIMULCAST 5 51
a=ssrc:8 msid:slides
a=ssrc:9 msid:slides // RTX SSRC
a=ssrc-group:FID 8 9
正如I-D.lennox-mmusic-sdp-source-selection规范的。FEC和RTX可以基于media-source开启或者关闭。因为接收者可以在SDP当中关闭这些secondary flow。然而,不可处理未定义的场景下,例如不接收primary flow而接收FEC flow。
注意在链路层RTP flow和bundle的session级多路复用的RTP flow是一样的。这些flow都是在一个单一的RTP会话中多路复用。这意味着SSRC一定被用于把RTX或者FEC flow关联到他们的primary flow。【译者注。RTX flow或者是FEC flow都是一个secondary flow,他们都是一个备选辅助的flow,而他们的primary flow是原本的主flow。】
尽管在某些简单的例案例当中,有可能是使用payload type来作为关联,但是不适用于多个媒体源的通用场景。因为每一个pt都会用于声明每一个元祖[Codec, media source, primary/RTX/FEC],这样会很快无法工作。
4. 信令行为。
4.1 新旧协商。
为了知道是否一个应用支持plan b,必须提供一个属性。有多种选项可以使用:
- a=ssrc属性是不够的,因为你可能没有发送的礼物,因此没有SSRC属性。
- a=max-*-ssrc属性有效,但是这有额外的语义。
- a=msid-semantic表示你能够理解MSID
因为理解MSID是使用plan b的前置条件,所以推荐第三个选择。
4.2 新的信令流
如果两端都支持plan b,为了让两边能够正确地表示他们使用哪些MST,并且让远端选择他们希望接收的MST,需要三趟握手。呼叫人发送它的source的offer,被叫人发回一个带有他希望呼叫人发送的source的answer,并且立即跟着带有被叫人可以发送的source的offer【译者注,这是在一趟报文当中携带的】,最后回答者发回它想从被叫人处接受的源。整个过程在1.5个RTT中完成。
一般接收被叫人的answer和接收被叫人的媒体存在竞争。然而这在plan b中通过三路握手避免。另外,由于接收source之前已经知道source。通过ssrc解复用,不会有任何的信令媒体竞争。
4.3 遗留的信令流
在遗留案例中,plan b优雅的降级回单一的offer answer序列。由于不知道哪一个流应该被发送,“新的”endpoint选择每个m行的默认媒体源发送。一旦收到表明不支持plan b的answer,就只发送默认的source到遗留的endpoint。当从遗留的endpoint接收媒体时,新的endpoint为每一个m行创建一个默认的media stream(包含单个media stream track)。就像和其他的遗留的endpoint通话一样,如MSID草案当中规范。
一般这会导致一个单audio和单video mediastreamtrack的协商。然而,如果content属性在上面被使用,为了和遗留的设备进行通信。可以协商额外的audio或者video media stream track。
4.4 和BUNDLE的交互。
既然plan b已经把相同的媒体类型划分到同一个单一的mline,BUNDLE没有那么关键。不管怎样,BUNDLE可以通过把多个媒体类型多路复用到一起,从而减少到只使用一个单一的transport,从而Plan b和BUNDLE一起也可以工作。既然所有的stream通过他们的SSRC属性来提前标识,他们的RTP flow使用相同的五元组也能够轻易的解复用。
5. 全面的例子
5.1 新的endpoint
下面的例子显示两个新的endpoint,A和B,建立了一个带有audio video screensharing,Simulcast和RTX的plan b呼叫。B决定选择A公告的source的一个子集合。
5.1.1 Offer 1(a->b):(A向B发布stream)
a=msid-semantics:WMS // I understand SSRCs and MSTs
m=audio 49170 RTP/AVP 101 // main audio
a=ssrc:1 msid:left-mic // declare 3 outgoing audio sources, each with unique MSID
a=ssrc:2 msid:center-mic
a=ssrc:3 msid:right-mic
[Candidates]
m=video 62537 RTP/SAVPF 96 // main video
a=ssrc:4 msid:left-cam // declare 3 outgoing video sources
a=ssrc:5 msid:center-cam // one source is simulcasting at two resolutions, same codec
a=ssrc:5 imageattr:* [1280, 720]
a=ssrc:51 msid:center-cam // different SSRC, same MSID for simulcasts
a=ssrc:51 imageattr:* [640, 360]
a=ssrc:6 msid:right-cam
a=ssrc-group:SIMULCAST 5 51
[Candidates]
m=video 62538 RTP/SAVPF 96 // presentation
a=content:slides // [media, content] tuples must be unique in m= lines
a=ssrc:8 msid:slides // app decision to do this; could have been put in the m=video line above
a=ssrc:9 msid:slides // RTX SSRC
a=ssrc-group:FID 8 9 // declaration that SSRC 9 is a repair flow for 8
[Candidates]
5.1.2 Answer 1(B->A):(B从A请求stream)
a=msid-semantics:WMS // I understand SSRCs and MSTs
m=audio 39170 RTP/AVP 101 // main audio
a=remote-ssrc:1 recv:on // just turn on the center mic
[Candidates]
m=video 52537 RTP/SAVPF 96 // main video
a=remote-ssrc:5 recv:off // explicitly turn off the 720p feed
a=remote-ssrc:51 recv:on // explicitly turn on the 360p feed
a=remote-ssrc:51 priority:1 // lower priority than slides (in this application)
[Candidates]
m=video 52538 RTP/SAVPF 96 // presentation
a=content:slides
a=remote-ssrc:8 recv:on // turn on the slides feed with higher priority
// FID is sent implicitly, unless explicitly rejected
a=remote-ssrc:8 priority:2 // (sender uses priority when making BW decisions)
[Candidates]
5.1.3 Offer 2(B->A):(B向A发布Stream)
a=msid-semantics:WMS // I understand SSRCs and MSTs
m=audio 39170 RTP/AVP 101 // main audio
a=ssrc:101 msid:center-mic
a=remote-ssrc:1 recv:on // just turn on the center mic
[Candidates]
m=video 52537 RTP/SAVPF 96 // main video
a=ssrc:105 msid:center-cam
a=remote-ssrc:5 recv:off // explicitly turn off the 720p feed
a=remote-ssrc:51 recv:on // explicitly turn on the 360p feed
a=remote-ssrc:51 priority:1 // lower priority than slides (in this application)
[Candidates]
m=video 52538 RTP/SAVPF 96 // presentation
a=content:slides
a=remote-ssrc:8 recv:on // turn on the slides feed with higher priority
// FID is sent implicitly (unless explicitly rejected)
a=remote-ssrc:8 priority:2 // (sender uses priority when making BW decisions)
[Candidates]
5.1.4 Answer 2(A->B):(A从B请求stream)
a=msid-semantics:WMS // I understand SSRCs and MSTs
m=audio 49170 RTP/AVP 101 // main audio
a=ssrc:1 msid:left-mic // declare 3 outgoing audio sources, each with unique MSID
a=ssrc:2 msid:center-mic
a=ssrc:3 msid:right-mic
a=remote-ssrc:101 on
[Candidates]
m=video 62537 RTP/SAVPF 96 // main video
a=ssrc:4 msid:left-cam // declare 3 outgoing video sources
a=ssrc:5 msid:center-cam // one source is simulcasting at two resolutions, same codec
a=ssrc:5 imageattr:* [1280, 720]
a=ssrc:51 msid:center-cam // different SSRC, same MSID for simulcasts
a=ssrc:51 imageattr:* [640, 360]
a=ssrc:6 msid:right-cam
a=ssrc-group:SIMULCAST 5 51
a=remote-ssrc:105 on
[Candidates]
m=video 62538 RTP/SAVPF 96 // presentation
a=content:slides // [media, content] tuples must be unique in m= lines
a=ssrc:8 msid:slides // app decision to do this; could have been put in the m=video line above
a=ssrc:9 msid:slides // RTX SSRC
a=ssrc-group:FID 8 9 // declaration that SSRC 9 is a repair flow for 8
[Candidates]
5.2 遗留的endpoint
下面的例子展示了一个新的endpint A和一个遗留的endpoint B,建立带有audio video 和screensharing的planb呼叫。尽管A支持audio和video的多source,B只接收A的默认stream。然而,screensharing是通过它自己的mline完成,它仍然对遗留endpoint有效。
5.2.1 Offer1 (A->B):(A向B发布stream)
a=msid-semantics:WMS // I understand SSRCs and MSTs
m=audio 49170 RTP/AVP 101 // main audio
a=ssrc:1 msid:left-mic // declare 3 outgoing audio sources, each
// with unique MSID
a=ssrc:2 msid:center-mic
a=ssrc:3 msid:right-mic
[Candidates]
m=video 62537 RTP/SAVPF 96 // main video
a=ssrc:4 msid:left-cam // declare 3 outgoing video sources
a=ssrc:5 msid:center-cam // one source is simulcasting at two
// resolutions, same codec
a=ssrc:5 imageattr:* [1280, 720]
a=ssrc:51 msid:center-cam // different SSRC, same MSID for simulcasts
a=ssrc:51 imageattr:* [640, 360]
a=ssrc:6 msid:right-cam
a=ssrc-group:SIMULCAST 5 51
[Candidates]
m=video 62538 RTP/SAVPF 96 // presentation
a=content:slides // [media, content] tuples must be unique
// in m= lines
a=ssrc:8 msid:slides // app decision to do this; could have been
// put in the m=video line above
a=ssrc:9 msid:slides // RTX SSRC
a=ssrc-group:FID 8 9 // declaration that SSRC 9 is a repair
// flow for 8
[Candidates]
5.2.2 Answer 1(B->A):(A接收B的offer)
// Since endpoint doesn't understand a=ssrc or MSTs, A must decide
// on a single media source to send for each m=line, e.g. center-mic,
// center-cam (360p), slides
m=audio 39170 RTP/AVP 101 // main audio
[Candidates]
m=video 52537 RTP/SAVPF 96 // main video
[Candidates]
m=video 52538 RTP/SAVPF 96 // presentation
a=content:slides
[Candidates]