W3C home > Mailing lists > Public > public-webrtc@w3.org > August 2012

Re: [Bug 18485] Change DTMF API to be on PeerConnection

From: Cullen Jennings (fluffy) <fluffy@cisco.com>
Date: Mon, 13 Aug 2012 14:19:21 +0000
To: Adam Bergkvist <adam.bergkvist@ericsson.com>
CC: Martin Thomson <martin.thomson@gmail.com>, Justin Uberti <juberti@google.com>, Stefan Håkansson LK <stefan.lk.hakansson@ericsson.com>, "public-webrtc@w3.org" <public-webrtc@w3.org>
Message-ID: <C15553A1-6EF8-4692-8C21-89151EF5CF3E@cisco.com>

I think I proposed something along these lines long ago and the general feeling was to just give these capablities to all audio tracks and if the an applicaiton never uses DTMF, it won't matter. I can go either way.

On Aug 10, 2012, at 6:49 AM, Adam Bergkvist <adam.bergkvist@ericsson.com> wrote:

> On 2012-08-09 01:40, Martin Thomson wrote:
>> On 8 August 2012 14:26, Justin Uberti <juberti@google.com> wrote:
>>> Option D seems like a good way to get what we need without spending too much
>>> effort on this legacy use case.
>> 
>> The problem with all of these - D included - is that DTMF is not
>> prearranged at the point that the track is added to the
>> PeerConnection, so either all streams have DTMF negotiated or none do.
>>  The former ensures that some negotiations will fail (or remove DTMF),
>> but will ensure that the DTMF is available everywhere it can be.  The
>> latter forces applications to add DTMF themselves, probably by SDP
>> bashing.
>> 
>> Given how much we care for this legacy use case - and I care even less
>> than most - I would suggest the API that minimizes impact on existing
>> APIs.  Randell's basic suggestion is good, the choice of
>> implementation point is not:
>> 
>>> Personally, I'd have SendDTMF() operate on a MediaStreamTrack, and be an
>>> event.  This would mean that if you have a MediaStreamTrack connected to two
>>> PeerConnections (quite possible), the event would be cloned and bubble up to
>>> both PeerConnections, which would then send DTMF (if possible).  I'd have
>>> PlayDTMF() operate on a track in remote or localstream via PeerConnection,
>>> and it would insert tones.
>> 
>> As I described separately, I'm not convinced that adding more stuff to
>> PeerConnection is the right answer, and I'm interested in learning why
>> this choice is considered superior to the current proposal, or
>> something even more explicit as I outlined.
>> 
>> That is, send:
>> 
>> var track = new DtmfAudioStreamTrack(stream.audioTracks[0]);
>> stream = new MediaStream(track);
>> track.sendTones('12');
>> 
>> Receive:
>> 
>> var track = pc.remoteStreams[0].audioTracks[0];
>> if (track instanceof DtmfAudioStreamTrack) {
>>     track.addEventListener('tone', function(dtmfEvent) {
>>         if (dtmfEvent.state === 'start') {
>>             dtmfTones[dtmfEvent.tone].enable();
>>             keyLog += dtmfEvent.tone;
>>         } else if (dtmfEvent.state === 'end') {
>>             dtmfTones[dtmfEvent.tone].disable();
>>         }
>>     });
>> }
>> 
> 
> Included the idl from Martins mail in another thread.
> 
> [Constructor(MediaStreamTrack audioTrack)]
> interface DtmfAudioStreamTrack : MediaStreamTrack, EventTarget {
>    void playTones (DOMString tones,
>            optional unsigned long duration = 100);
>    void startTone (DOMString tone);
>    void endTone ();
> 
>    attribute DtmfCallback? ontone;
> };
> 
> ----
> 
> I like this approach since it doesn't pollute the general part of the MediaStream API with DTMF functionality at same time as it doesn't add more functions to the PeerConnection API.
> 
> Since we need methods like startTone() and endTone() to emulate a dial pad as well as the convenience method to simply send a few tones for a duration of time, we need more than one or two functions. I think it's nicer to have these in a separate interface compared to adding them directly to PeerConnection. Also, if we decide to support incoming DTMF tones, it's more straight forward to have an object to register event listeners on compared to the approach with "static-like" functions on PeerConnection (e.g. pc.incomingDTMF(track, function (dtmf) {...});).
> 
> One thing that might be confusing for developers is how the original MediaStreamTrack and the new DtmfAudioStreamTrack relate to each other since they are both MediaStreamTrack objects. Do I need to add the DtmfAudioStreamTrack to the same stream that provided the MediaStreamTrack (passed to the constructor) and send that stream with PeerConnection. Should it go into a MediaStream on it's own? If the tracks are in the same stream and transmitted with PeerConnection, what happens if I remove the MediaStreamTrack that was used to create the DtmfAudioStreamTrack? The DtmfAudioStreamTrack could also be added to another stream that is sent somewhere else than the MediaStreamTrack used to create the DtmfAudioStreamTrack. Should the DtmfAudioStreamTrack be in the MediaStream.audioTracks list? It doesn't really behave as a normal MediaStreamTrack.
> 
> I don't see any reason why the DtmfAudioStreamTrack needs to be a MediaStreamTrack. We could simply have an object that's used as a remote to insert and receive DTMF on associated MediaStreamTrack objects.
> 
> [Constructor(MediaStreamTrack outgoingAudioTrack,
>    optional MediaStreamTrack incomingAudioTrack)]
> interface DtmfTransceiver : EventTarget {
>    void playTones (DOMString tones,
>            optional unsigned long duration = 100);
>    void startTone (DOMString tone);
>    void endTone ();
> 
>    attribute Function? ontone;
> };
> 
> --- Example ---
> // we have a connected PeerConnection, pc
> var outgoingAudioTrack = pc.localStreams[0].audioTracks[0];
> var incomingAudioTrack = pc.remoteStreams[0].audioTracks[0];
> 
> var dtmf = new DtmfTransceiver(outgoingAudioTrack, incomingAudioTrack);
> 
> dtmf.playTones("1 2 3"); // could be played back in "incomingAudioTrack"
> 
> dtmf.ontone = function (evt) { ... };
> ------
> 
> We could initially skip the ontone stuff and add it back if we decide that we need to be able to receive DTMF as well.
> 
> /Adam
> 
> 
> 
Received on Monday, 13 August 2012 14:19:53 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Monday, 13 August 2012 14:19:54 GMT