Does RTCPeerconnection correctly handle 'a=sendonly', 'a=inactive', 'a=recvonly' sdp attributes?

3,293 views
Skip to first unread message

José Luis Millán

unread,
Apr 10, 2013, 8:16:33 AM4/10/13
to discuss...@googlegroups.com
Hi,

I'm getting stuck with this since I haven't managed to make it work nor seen it working.

In a scenario where 'pc2'  receives a sdp offer with any of those three attributes, it always responds with a 'a=sendrecv' attribute in the sdp answer, which is not compliant with RFC 3264.

I have slightly modified pc1.html so the local media is attached to pc2 instead of pc1, and pc2 is offered a sdp with a 'a=inactive' attribute. The response from pc2 is always the same: 'a=sendrecv'. Such response is the same regardless the offer comes with 'a=inactive', 'a=sendonly' or 'a=recvonly'.

I would like to know if RTCPeerconnection does handle properly such different attributes and appreciate any comment if I'm doing something wrong.

For anyone interested, I attach a modified pc1.html.


Best regards



--
José Luis Millán
pc1_inactive.html

José Luis Millán

unread,
Apr 10, 2013, 4:11:32 PM4/10/13
to discuss...@googlegroups.com
I'm just trying to implement the classic HOLD feature to the classic way: offerer sending an offer with 'a=sendonly' and offered responding with 'a=recvonly'.

As per RFC3264

```
5.1 Unicast Streams

   If the offerer wishes to only send media on a stream to its peer, it
   MUST mark the stream as sendonly with the "a=sendonly" attribute.
```

```
6.1 Unicast Streams

   If a stream is offered as sendonly, the corresponding stream MUST be
   marked as recvonly or inactive in the answer.  If a media stream is
   listed as recvonly in the offer, the answer MUST be marked as
   sendonly or inactive in the answer.

```

So, if RTCPeerconnection wont react upon reception of a 'a=sendonly' attribute, I would need inspect the sdp myself. Just wondering if it does react or there are plans to do it in the future.


Thanks a lot.


2013/4/10 José Luis Millán <jmi...@aliax.net>



--
José Luis Millán

Vikas

unread,
Apr 10, 2013, 4:56:12 PM4/10/13
to discuss-webrtc
Hi Jose,

I think if you want to implement call-hold, then probably you have to
mute the tracks & then send updated offer with sendonly direction. I
have not tried it, but will test it with pc1 demo.
Also, in regards to a= 'inactive' attribute you can check the pranswer
demo :- http://webrtc.googlecode.com/svn/trunk/samples/js/demos/html/pranswer.html

/Vikas

On Apr 10, 1:11 pm, José Luis Millán <jmil...@aliax.net> wrote:
> I'm just trying to implement the classic HOLD feature to the classic way:
> offerer sending an offer with 'a=sendonly' and offered responding with
> 'a=recvonly'.
>
> As per RFC3264
>
> ```
> 5.1 Unicast Streams
>
>    If the offerer wishes to only send media on a stream to its peer, it
>    MUST mark the stream as sendonly with the "a=sendonly" attribute.
> ```
>
> ```
> 6.1 Unicast Streams
>
>    If a stream is offered as sendonly, the corresponding stream MUST be
>    marked as recvonly or inactive in the answer.  If a media stream is
>    listed as recvonly in the offer, the answer MUST be marked as
>    sendonly or inactive in the answer.
>
> ```
>
> So, if RTCPeerconnection wont react upon reception of a 'a=sendonly'
> attribute, I would need inspect the sdp myself. Just wondering if it does
> react or there are plans to do it in the future.
>
> Thanks a lot.
>
> 2013/4/10 José Luis Millán <jmil...@aliax.net>

Vikas

unread,
Apr 10, 2013, 5:40:18 PM4/10/13
to discuss-webrtc
Hi Jose,

I tested after modifying pc1.html and it seems to work fine. Just set
enabled to false for the audio and video tracks and then renegotiate
with sendonly stream.

/Vikas

On Apr 10, 1:56 pm, Vikas <vikasmarw...@webrtc.org> wrote:
> Hi Jose,
>
> I think if you want to implement call-hold, then probably you have to
> mute the tracks & then send updated offer with sendonly direction. I
> have not tried it, but will test it with pc1 demo.
> Also, in regards to a= 'inactive' attribute you can check the pranswer
> demo :-http://webrtc.googlecode.com/svn/trunk/samples/js/demos/html/pranswer...

José Luis Millán

unread,
Apr 10, 2013, 5:43:36 PM4/10/13
to discuss...@googlegroups.com
Hi Vikas,

2013/4/10 Vikas <vikasm...@webrtc.org>
Hi Jose,

I tested after modifying pc1.html and it seems to work fine. Just set
enabled to false for the audio and video tracks and then renegotiate
with sendonly stream.


Would you be so kind to attach the modified pc1.html for testing?

Thanks
 
--

---
You received this message because you are subscribed to the Google Groups "discuss-webrtc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to discuss-webrt...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.





--
José Luis Millán

José Luis Millán

unread,
Apr 10, 2013, 5:52:35 PM4/10/13
to discuss...@googlegroups.com
Hi Vikas,


2013/4/10 Vikas <vikasm...@webrtc.org>
Hi Jose,


I think if you want to implement call-hold, then probably you have to
mute the tracks & then send updated offer with sendonly direction.
 
Yes, that is the way to go in the 'offerer'. There is no problem at all on this. Can be perfectly done.

What I mean is: should the 'offered' react upon reception of a 'a=sendonly' parameter (setRemoteDescription)?

Since sendonly means that the offerer wishes to only send media (so not receive), I would expect that the offered would stop sending media.

I have tested that such an attribute doesn't generate any stimulus at all in RTCPeerconnection. Should it or should I inspect myself the sdp in the offered and stop sending media if receive a sendonly?

I guess, that the way to go by now is, as you advanced:

Offerer:
- Mute the tracks
- Send updated offer with sendonly direction

Offered:
- Receive offer -> inspect sdp looking for 'a=sendonly' attribute
- Mute the tracks (or detach the localStream from RTCPeerconnection)
- Send answer with recvonly direction
--

---
You received this message because you are subscribed to the Google Groups "discuss-webrtc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to discuss-webrt...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.





--
José Luis Millán

Vikas Marwaha

unread,
Apr 10, 2013, 6:06:48 PM4/10/13
to discuss...@googlegroups.com
Hi,

attached modified pc1 application. 

/Vikas
hold.html

José Luis Millán

unread,
Apr 10, 2013, 6:56:14 PM4/10/13
to discuss...@googlegroups.com
Hi,

Thanks a lot for the example.

The followed process for hold is:

Offerer:
- Mute the tracks
- Send updated offer with sendonly direction

Offered:
- Do nothing. It will respond allways with recvonly since it has not localStream attached.


The followed process for unhold is:

Offerer:
- Un-Mute the tracks
- Send updated offer with sendrecv direction

Offered:
- Do nothing. It will respond allways with recvonly since it has not localStream attached.


In a p2p scenario, both pc1 and pc2 will have a localStream each, and here the offered will not automatically respond with recvonly buy allways respond with sendrecv regardless the offer came with sendonly, inactive or recvonly. This is the scenario I'm referring to, and where my questions where pointed on.

Since the offered (having this a locaStream attrached) does not react upon sendonly, inactive or recvonly attributes in the offer, I guess this parameters and their significance must be taken manually as said before.

Thanks a million.






2013/4/11 Vikas Marwaha <vikasm...@webrtc.org>



--
José Luis Millán

José Luis Millán

unread,
Apr 11, 2013, 5:16:24 AM4/11/13
to discuss...@googlegroups.com
Found a couple of references regarding to mute and hold:


The conclusion I take is that the 'signaling' of the hold/mute is application dependent.

Regards.



2013/4/11 José Luis Millán <jmi...@aliax.net>



--
José Luis Millán

Iñaki Baz Castillo

unread,
Apr 11, 2013, 7:26:33 AM4/11/13
to discuss...@googlegroups.com
I've commented in the open issue:

https://www.w3.org/Bugs/Public/show_bug.cgi?id=20816

I cannot imagine we are the only guys having real problems with SDP
usage for basic hold/unhold operations within WebRTC.

2013/4/11 José Luis Millán <jmi...@aliax.net>:
Iñaki Baz Castillo
<i...@aliax.net>

Vikas

unread,
Apr 11, 2013, 1:01:01 PM4/11/13
to discuss-webrtc
Hi Jose,

Thanks for the feedback, According to RFC 3264 section 6.1, If a
stream is offered as sendonly, the corresponding stream MUST be marked
as recvonly or inactive in the answer. That looks like a bug that we
are not responding to sendonly stream with recvonly. I will file one
in the issue tracker.

/Vikas
> 2013/4/11 Vikas Marwaha <vikasmarw...@webrtc.org>
>
>
>
>
>
>
>
>
>
> > Hi,
>
> > attached modified pc1 application.
>
> > /Vikas
>
> > On Wed, Apr 10, 2013 at 2:43 PM, José Luis Millán <jmil...@aliax.net>wrote:
>
> >> Hi Vikas,
>
> >> 2013/4/10 Vikas <vikasmarw...@webrtc.org>
> >>> For more options, visithttps://groups.google.com/groups/opt_out.
>
> >> --
> >> José Luis Millán
>
> >> --
>
> >> ---
> >> You received this message because you are subscribed to the Google Groups
> >> "discuss-webrtc" group.
> >> To unsubscribe from this group and stop receiving emails from it, send an
> >> email to discuss-webrt...@googlegroups.com.
> >> For more options, visithttps://groups.google.com/groups/opt_out.
>
> >  --
>
> > ---
> > You received this message because you are subscribed to the Google Groups
> > "discuss-webrtc" group.
> > To unsubscribe from this group and stop receiving emails from it, send an
> > email to discuss-webrt...@googlegroups.com.
> > For more options, visithttps://groups.google.com/groups/opt_out.
>
> --
> José Luis Millán

Iñaki Baz Castillo

unread,
Apr 11, 2013, 1:08:46 PM4/11/13
to discuss...@googlegroups.com
Hi Vikas, don't you think that this stuff should be more clarified at
WebRTC spec level?

Regards.

2013/4/11 Vikas <vikasm...@webrtc.org>:

Iñaki Baz Castillo

unread,
Apr 19, 2013, 4:32:49 AM4/19/13
to discuss...@googlegroups.com
2013/4/18 Wolfgang Beck <wolfgan...@googlemail.com>:
> It's quite a mess.
>
> - The offering browser doesn't care about a=inactive/recvonly attributes in
> SDP. It still sends RTP
> - The answering browser doesn't care about a=inactive either. It keeps
> sending RTP.
> - Disabling the local stream is fine for mute, but doesn't work for 'hold'
> as the local stream will be muted for all ongoing calls.
> Cloning the local stream and selectively muting them doesn't work either.

So SDP is chosen as "media information exchange unit" but then there
is no a real API for inspecting an SDP at JS level (i.e. how to know
whether a "m" line has "a=sendonly"?) and there is no API for setting
common SDP attributes (i.e. "a=sendonly", "a=inactive"...). And no
events when a peer receives the same remote SDP but with "a=inactive"
or whatever... and RTP still is sent which is even worse...

Not sure if this is a bug in the spec or in the implementation.
Hopefuly all these needs will be addressed.

Regards.

Dennis E. Dowhy

unread,
Apr 19, 2013, 8:32:29 AM4/19/13
to discuss...@googlegroups.com
AFAIK this is how webRTC works:

  1. Muting the video/audio HTML elements themselves only affects local playback. RTP/RTCP/STUN is still transmitted.
  2. Setting the video/audio tracks's enabled flag to 'false' still transmits RTP/RTCP/STUN, but it changes the contents of the RTP media streams to 'zeros' for for audio (silence) and black video frames.
  3. Changing the local description SDP to 'inactive' halts the RTP media stream completely.  STUN & RTCP is still transmitted.  but for this to work, you need to do something like:
var tmp = pc1.localDescription;
tmp.sdp = setInactiveFunc(tmp.sdp);// where setInactiveFunc returns the modified SDP with 'a=inactive'
pc1.setLocalDescription(tmp);
pc1.setRemoteDescription(pc1.remoteDescription); // completes the offer/answer

Also, I didn't have any issues cloning media streams.  When I cloned a stream, and set the cloned stream's enabled flag to false, "zeros" are transmitted as expected.  If the cloned stream's enabled flags are "true" while the parent's stream's enabled flag is "false", the local playout is muted, but the media itself is still transmitted and played out successfully on the receiver.

For #3, if you're doing more advanced work, when you resume, I think RTP sequence numbers might be reset, but .roll over counters continue since RTCP is still active. 

One question I have regarding #3 ... from my understanding reading specs the ROC increments every time the sequence number increments past modulo 2^16, e.g. 65535.  In this situation for local 'on hold', If the sequence numbers are resetting when you resume, how does the receiver keep track of when the next ROC increment occurs?  When a sender sets local description to inactive & does the setLocal and setRemote, do you also need to do this on the receiver's side in order for the ROC to stay in sync?  How does ROC work in this situation?  My guess would be that if the receiver is not also setting their remote description to inactive, the receiver might know know when the next ROC increment occurs, then ROC might get out of sync and thus eventually fail to decrypt and playout.  I haven't toyed around enough to figure this one out yet.  Does anyone know the answer to that?


Wolfgang Beck

unread,
Apr 19, 2013, 9:26:19 AM4/19/13
to discuss...@googlegroups.com
That's how it is supposed to work. But at least in Chrome 26.0.1410.63. it's broken:
- setting the 'enable' flag of the localStream's tracks to 'false' has no effect at all. Just tested
pc.getLocalStreams()[0].getAudioTracks()[0].enabled = false
pc.getLocalStreams()[0].getVideoTracks()[0].enabled = false
the remote browser still shows the video.

- browserA.pc.localDescription and browserB.pc.remoteDescription both show 'a=inactive' (after I made the prescribed setLocalDescription / setRemoteDescription call). Still, browserA sends the complete video stream.
The only way is calling pause() on the receiving video element. But that's not useful outside of demos.

Vikas

unread,
Apr 22, 2013, 5:19:54 PM4/22/13
to discuss-webrtc
Hi,

It looks like the enabled property for MediaStreamTrack was fixed for
M27 release. See issue https://code.google.com/p/chromium/issues/detail?id=114163.
So in your case you should test with at least M27. Also you if you are
observing issues related to sdp attributes (inactive/sendonly/
recvonly) i would suggest add information to this issue:-
https://code.google.com/p/webrtc/issues/detail?id=1640.

/Vikas

On Apr 19, 6:26 am, Wolfgang Beck <wolfgang.bec...@googlemail.com>
wrote:
> That's how it is supposed to work. But at least in Chrome 26.0.1410.63.
> it's broken:
> - setting the 'enable' flag of the localStream's tracks to 'false' has no
> effect at all. Just tested
> pc.getLocalStreams()[0].getAudioTracks()[0].enabled = false
> pc.getLocalStreams()[0].getVideoTracks()[0].enabled = false
> the remote browser still shows the video.
>
> - browserA.pc.localDescription and browserB.pc.remoteDescription both show
> 'a=inactive' (after I made the prescribed setLocalDescription /
> setRemoteDescription call). Still, browserA sends the complete video stream.
> The only way is calling pause() on the receiving video element. But that's
> not useful outside of demos.
>
>
>
>
>
>
>
> On Friday, April 19, 2013 2:32:29 PM UTC+2, Dennis wrote:
>
> > AFAIK this is how webRTC works:
>
> >    1. Muting the video/audio HTML elements themselves only affects local
> >    playback. RTP/RTCP/STUN is still transmitted.
> >    2. Setting the video/audio tracks's enabled flag to 'false' still
> >    transmits RTP/RTCP/STUN, but it changes the contents of the RTP media
> >    streams to 'zeros' for for audio (silence) and black video frames.
> >    3. Changing the local description SDP to 'inactive' halts the RTP
> >    media stream completely.  STUN & RTCP is still transmitted.  but for this
> >    to work, you need to do something like:
>
> > var tmp = pc1.localDescription;
> > tmp.sdp = *setInactiveFunc*(tmp.sdp);// where *setInactiveFunc *returns
> > the modified SDP with 'a=inactive'
> > pc1.setLocalDescription(tmp);
> > pc1.setRemoteDescription(pc1.remoteDescription); // completes the
> > offer/answer
>
> > Also, I didn't have any issues cloning media streams.  When I cloned a
> > stream, and set the cloned stream's enabled flag to false, "zeros" are
> > transmitted as expected.  If the cloned stream's enabled flags are "true"
> > while the parent's stream's enabled flag is "false", the local playout is
> > muted, but the media itself is still transmitted and played out
> > successfully on the receiver.
>
> > For #3, if you're doing more advanced work, when you resume, I think RTP
> > sequence numbers might be reset, but .roll over counters continue since
> > RTCP is still active.
>
> > *One question I have regarding #3* ... from my understanding reading
> > specs the ROC increments every time the sequence number increments past
> > modulo 2^16, e.g. 65535.  In this situation for local 'on hold', If the
> > sequence numbers are resetting when you resume, how does the receiver keep
> > track of when the next ROC increment occurs?  When a sender sets local
> > description to inactive & does the setLocal and setRemote, do you also need
> > to do this on the receiver's side in order for the ROC to stay in sync?
> >  How does ROC work in this situation?  My guess would be that if the
> > receiver is not also setting their remote description to inactive, the
> > receiver might know know when the next ROC increment occurs, then ROC might
> > get out of sync and thus eventually fail to decrypt and playout.  I haven't
> > toyed around enough to figure this one out yet.  Does anyone know the
> > answer to that?
>
> > On Fri, Apr 19, 2013 at 4:32 AM, Iñaki Baz Castillo <i...@aliax.net<javascript:>
> > > wrote:
>
> >> 2013/4/18 Wolfgang Beck <wolfgan...@googlemail.com <javascript:>>:
> >> > It's quite a mess.
>
> >> > - The offering browser doesn't care about a=inactive/recvonly
> >> attributes in
> >> > SDP. It still sends RTP
> >> > - The answering browser doesn't care about a=inactive either. It keeps
> >> > sending RTP.
> >> > - Disabling the local stream is fine for mute, but doesn't work for
> >> 'hold'
> >> > as the local stream will be muted for all ongoing calls.
> >> > Cloning the local stream and selectively muting them doesn't work
> >> either.
>
> >> So SDP is chosen as "media information exchange unit" but then there
> >> is no a real API for inspecting an SDP at JS level (i.e. how to know
> >> whether a "m" line has "a=sendonly"?) and there is no API for setting
> >> common SDP attributes (i.e. "a=sendonly", "a=inactive"...). And no
> >> events when a peer receives the same remote SDP but with "a=inactive"
> >> or whatever... and RTP still is sent which is even worse...
>
> >> Not sure if this is a bug in the spec or in the implementation.
> >> Hopefuly all these needs will be addressed.
>
> >> Regards.
>
> >> --
> >> Iñaki Baz Castillo
> >> <i...@aliax.net <javascript:>>
>
> >> --
>
> >> ---
> >> You received this message because you are subscribed to the Google Groups
> >> "discuss-webrtc" group.
> >> To unsubscribe from this group and stop receiving emails from it, send an
> >> email to discuss-webrt...@googlegroups.com <javascript:>.

Iñaki Baz Castillo

unread,
Apr 23, 2013, 11:43:32 AM4/23/13
to discuss...@googlegroups.com
2013/4/22 Vikas <vikasm...@webrtc.org>:
> It looks like the enabled property for MediaStreamTrack was fixed for
> M27 release. See issue https://code.google.com/p/chromium/issues/detail?id=114163.
> So in your case you should test with at least M27. Also you if you are
> observing issues related to sdp attributes (inactive/sendonly/
> recvonly) i would suggest add information to this issue:-
> https://code.google.com/p/webrtc/issues/detail?id=1640.

IMHO the problem is more at WebRTC spec level. Still missing how to
set a media stream with a=inactive or how to inspect
a=sendonly/recvonly/inactive/sendrecv attributes in an SDP once it has
been given to a PC as remote descriptor.

Vikas

unread,
May 15, 2013, 8:02:58 PM5/15/13
to discuss-webrtc
Hi,
Have you already tested with offerToReceiveVideo constraint set to
false in CreateAnswer? Something like below :-
var sdpConstraints = {'mandatory': {
                        'OfferToReceiveAudio':true,
                        'OfferToReceiveVideo':false }};

pc2.createAnswer(gotDescription2, null, sdpConstraints);

/Vikas

On May 14, 7:46 pm, Thiago Hirai <thiago.hi...@gmail.com> wrote:
> I agree with Iñaki. While one can edit the SDP strings by hand to get the
> desired behavior, that seems hacky and inelegant.
>
> Consider the following scenario:
>
> User A calls user B, offering audio and video
> User B doesn't want to see the incoming video, and therefore doesn't want
> to receive the bytes associated with that
>
> There's no clean way for User B to tell RTCPeerConnection to refuse video.
> The constraints only talk about what each side wants to send, not about
> what they want to receive.
>
>
>
>
>
>
>
> On Tuesday, April 23, 2013 8:43:32 AM UTC-7, Iñaki Baz Castillo wrote:
>
> > 2013/4/22 Vikas <vikasm...@webrtc.org <javascript:>>:
> > <i...@aliax.net <javascript:>>

Martin Ekblom

unread,
Jun 17, 2014, 10:47:33 AM6/17/14
to discuss...@googlegroups.com
Hi,

yes, setting OfferToReceiveVideo: false in Chrome works, which makes absolutely no sense to me. Don't know if this is in agreement with the specification but does not seem logical.

If the offer you receive offers to accept but not send video with a=recvonly the SDP answer should contain a=sendonly if you are prepared to send video or a=inactive if you decline to send video. In this case OfferToSendVideo: true | false would make more sense, but even this is unnecessary since we already know that we either have a local stream or not. As it happens, Firefox gets this right, but not Chrome.

Sending a an offer to receive video (I want to see video from the remote party if possible but not send it) would look something like (simplified SDP offer):
m=video 54310 RTP/SAVPF 100 116 117
c=IN IP4 192.168.6.72
a=recvonly
a=rtcp-mux
a=rtpmap:100 VP8/90000
a=rtpmap:116 red/90000
a=rtpmap:117 ulpfec/90000

If the remote party declines to send video (not able device or user denied access) it may send an a=inactive, example from Firefox (working properly):
m=video 54313 RTP/SAVPF 100
c=IN IP4 192.168.6.72
a=rtpmap:100 VP8/90000
a=inactive
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtcp-fb:100 ccm fir
a=setup:active
a=rtcp-mux

In Chrome 35, what happens is that it creates a SDP answer with a=sendonly despite the fact that there is no video media stream available:
m=video 51230 RTP/SAVPF 120
a=setup:active
a=mid:video
a=sendonly
a=rtcp-mux
a=rtpmap:120 VP8/90000
a=rtcp-fb:120 ccm fir
a=rtcp-fb:120 nack
a=rtcp-fb:120 nack pli


To me this must be considered to be a bug in Chrome (if nobody can give a sensible explanation for this behaviour) - it has no video to send but creates an answer with sendonly... Hacking the SDP with adding a=inactive fixes the issue (fixing this by adding OfferToReceiveVideo makes no sense to me, OfferToSendVideo would make sense but is redundant since the application already knows we have no video stream to send). This may be a reported bug but I didn't find any.

Justin Uberti

unread,
Jun 17, 2014, 9:21:56 PM6/17/14
to discuss-webrtc
I agree with your assessment - if there is no local video track, we should answer with a=recvonly. Can you file a bug?


--

---
You received this message because you are subscribed to the Google Groups "discuss-webrtc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to discuss-webrt...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages