- From: Bernard Aboba <Bernard.Aboba@microsoft.com>
- Date: Fri, 30 May 2014 05:29:42 +0000
- To: "public-ortc@w3.org" <public-ortc@w3.org>, "pthatcher@google.com" <pthatcher@google.com>
Peter Thatcher said: "1. Allow passing in RtpCapabilities into RtpSender.send and RtpReceiver.receive. That way, the signalling could just exchange capabilities and not have to create RtpParameters for the simple case. 2. Send and receive with the preferredPayloadType. The sender just picks some SSRC, and the receiver automatically locks onto them, as if the JS had listened to "onunsignalledrtp" and added SSRCs manually. That doesn't support header extensions (since the receiver wouldn't know the IDs) or layering or FEC, but that might be OK for the simple use case. Are there dragons that I'm not thinking of that would make this not work?" [BA] In addition to the preferredPayloadtype, it would appear to me that the capabilities also need to include the full RTP extension information as well as an RTCP-mux preference. To help us find potential dragons (I didn't notice any), here is a take on all the changes needed to make this work, and also what the sample code might look like. dictionary RTCRtpCapabilities { sequence<RTCRtpCodec> audioCodecs; sequence<RTCRtpCodec> videoCodecs; sequence<RTCRtpHeaderExtensionParameters> headerExtensionPreferences; boolean rtcpMux = true; Capabilities features; Capabilities rtcpFeedback; }; [Constructor(MediaStreamTrack track, RTCDtlsTransport transport, optional RTCDtlsTransport rtcpTransport)] interface RTCRtpSender { readonly attribute MediaStreamTrack track; readonly attribute RTCDtlsTransport transport; readonly attribute RTCDtlsTransport rtcpTransport; void setTransport (RTCDtlsTransport transport, optional RTCDtlsTransport rtcpTransport); void setTrack (MediaStreamTrack track); static RTCRtpCapabilities getCapabilities (optional DOMString kind); void send (optional RTCRtpParameters parameters, optional RTCRtpCapabilities remoteCaps); void stop (); }; [Constructor(RTCDtlsTransport transport, optional RTCDtlsTransport rtcpTransport)] interface RTCRtpReceiver { readonly attribute MediaStreamTrack? track; readonly attribute RTCDtlsTransport transport; readonly attribute RTCDtlsTransport rtcpTransport; void setTransport (RTCDtlsTransport transport, optional RTCDtlsTransport rtcpTransport); static RTCRtpCapabilities getCapabilities (optional DOMString kind); void receive (optional RTCRtpParameters parameters, optional RTCRtpCapabilities capabilities); void stop (); }; SAMPLE CODE EXAMPLE 5 // This is an example of how to utilize distinct ICE transports for RTP and RTCP. // Assume we have an audioTrack and a videoTrack to send. // //create the RTP and RTCP ICE transports for audio and video var audioRtpIceTransport = new RTCIceTransport(...); var audioRtcpIceTransport = audioRtpIceTransport.createAssociatedTransport(); var videoRtpIceTransport = new RTCIceTransport(...); var videoRtcpIceTransport = audioRtpIceTransport.createAssociatedTransport(); //create the DTLS transports var audioRtpDtlsTransport = new RTCDtlsTransport(audioRtpIceTransport); var audioRtcpDtlsTransport = new RTCDtlsTransport(audioRtcpIceTransport); var videoRtpDtlsTransport = new RTCDtlsTransport(videoRtpIceTransport); var videoRtcpDtlsTransport = new RTCDtlsTransport(videoRtcpIceTransport); // ... start the ICE and DTLS transports var controller = new RTCIceTransportController(); controller.addTransport(audioRtpIceTransport); controller.addTransport(videoRtpIceTransport); var audioSender = new RtpSender(audioTrack, audioRtpDtlsTransport, audioRtcpDtlsTransport); var videoSender = new RtpSender(videoTrack, videoRtpDtlsTransport, videoRtcpDtlsTransport); var audioReceiver = new RtpReceiver(audioRtpDtlsTransport, audioRtcpDtlsTransport); var videoReceiver = new RtpReceiver(videoRtpDtlsTransport, videoRtcpDtlsTransport); var audioRecvCaps = RTCRtpReceiver.getCapabilities("audio"); var videoRecvCaps = RTCRtpReceiver.getCapabiltiies("video"); // Initiator can disable RTCP mux to start, to see if the responder will enable it. audioRecvCaps.rtcpMux = false; videoRecvCaps.rtcpMux = false; // At this point, receiver capabilities can be exchanged. // It is assumed that the responder receiver capabilities are stored in // remoteAudioRecvCaps and remoteVideoRecvCaps. // The initiator then adjusts its own rtcpMux capabilities based on the remote receive capabilities. // If the initiator leaves rtcpMux disabled, or enables it, either way it works. audioSender.send(remoteAudioRecvCaps); videoSender.send(remoteVideoRecvCaps); audioRecvCaps.rtcpMux = remoteAudioRecvCaps.rtcpMux; videoRecvCaps.rtcpMux = remoteVideoRecvCaps.rtcpMux; audioReceiver.receive(audioRecvCaps); videoReceiver.receive(videoRecvCaps); // If the initiator does enable RTCP-mux, we need to remember to // stop the unused ICE transports, or else they will go to the // failed state when the remote endpoint blows theirs away. if (audioRecvCaps.rtcpMux) { audioRtcpIceTransport.stop(); audioRtpDtlsTransport.stop(); } if (videoRecvCaps.rtcpMux) { videoRtcpIceTransport.stop(); videoRtcpDtlsTransport.stop(); } EXAMPLE 8 // Assume we already have a way to signal, a transport // (RTCDtlsTransport), and audio and video tracks. This is an example // of how to offer them and get back an answer with audio and // video tracks, and begin sending and receiving them. // The example assumes that RTP and RTCP are multiplexed. function initiate(signaller, transport, audioTrack, videoTrack) { var audioSender = new RTCRtpSender(audioTrack, transport); var videoSender = new RTCRtpSender(videoTrack, transport); var audioReceiver = new RTCRtpReceiver(transport); var videoReceiver = new RTCRtpReceiver(transport); // Retrieve the audio and video receiver capabilities var recvAudioCaps = RTCRtpReceiver.getCapabilities("audio"); var recvVideoCaps = RTCRtpReceiver.getCapabilities("video"); signaller.offerTracks({ // The initiator offers its receiver capabilities. "rtpAudioCaps": recvAudioCaps, "rtpVideoCaps": recvVideoCaps }, function(answer) { // The responder answers with its receiver capabilities audioSender.send(answer.rtpAudioCaps); videoSender.send(answer.rtpVideoCaps); audioReceiver.receive(recvAudioCaps); videoReceiver.receive(recvVideoCaps); // Now we can render/play // audioReceiver.track and videoReceiver.track. }); } EXAMPLE 9 // Assume we already have a way to signal, a transport (RTCDtlsTransport) // and audio and video tracks. This is an example of how to answer an // offer with audio and video tracks, and begin sending and receiving them. // The example assumes that RTP and RTCP are multiplexed. function accept( signaller, remote, transport, audioTrack, videoTrack) { var audioSender = new RTCRtpSender(audioTrack, transport); var videoSender = new RTCRtpSender(videoTrack, transport); var audioReceiver = new RTCRtpReceiver(transport); var videoReceiver = new RTCRtpReceiver(transport); // Retrieve the audio and video receive capabilities var recvAudioCaps = RTCRtpReceiver.getCapabilities("audio"); var recvVideoCaps = RTCRtpReceiver.getCapabilities("video"); audioSender.send(remote.rtpAudioCaps); videoSender.send(remote.rtpVideoCaps); audioReceiver.receive(recvAudioCaps); videoReceiver.receive(recvVideoCaps); signaller.answerTracks({ "rtpAudioCaps": recvAudioCaps, "rtpVideoCaps": recvVideoCaps }); // Now we can render/play // audioReceiver.track and videoReceiver.track. }
Received on Friday, 30 May 2014 05:30:17 UTC