Re: Issue 80: filterParameters

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