Bug 1363667 - P3 - JS impl of getContributingSources;r?mjf draft
authorNico Grunbaum
Thu, 21 Sep 2017 17:46:38 -0700
changeset 675767 dcabf9e0eab3f3fa26a9da972876c8dcf11521b0
parent 675247 a8b23ecfe8a3370f8b334071bc449c8afec8d561
child 675768 fa5b497cf2d187b0a87b2d4a603af8f36b38508b
push id83237
push userna-g@nostrum.com
push dateThu, 05 Oct 2017 21:14:54 +0000
reviewersmjf
bugs1363667
milestone58.0a1
Bug 1363667 - P3 - JS impl of getContributingSources;r?mjf MozReview-Commit-ID: 3oOXMP42PSt
dom/media/PeerConnection.js
dom/media/PeerConnection.manifest
dom/webidl/PeerConnectionImpl.webidl
dom/webidl/RTCRtpContributingSource.webidl
--- a/dom/media/PeerConnection.js
+++ b/dom/media/PeerConnection.js
@@ -22,28 +22,34 @@ const PC_ICE_CONTRACT = "@mozilla.org/do
 const PC_SESSION_CONTRACT = "@mozilla.org/dom/rtcsessiondescription;1";
 const PC_MANAGER_CONTRACT = "@mozilla.org/dom/peerconnectionmanager;1";
 const PC_STATS_CONTRACT = "@mozilla.org/dom/rtcstatsreport;1";
 const PC_STATIC_CONTRACT = "@mozilla.org/dom/peerconnectionstatic;1";
 const PC_SENDER_CONTRACT = "@mozilla.org/dom/rtpsender;1";
 const PC_RECEIVER_CONTRACT = "@mozilla.org/dom/rtpreceiver;1";
 const PC_COREQUEST_CONTRACT = "@mozilla.org/dom/createofferrequest;1";
 const PC_DTMF_SENDER_CONTRACT = "@mozilla.org/dom/rtcdtmfsender;1";
+const PC_CONTRIB_SOURCE_CONTRACT = "@mozilla.org/dom/rtpcontributingsource;1";
+const PC_SYNC_SOURCE_CONTRACT = "@mozilla.org/dom/rtpsynchronizationsource;1";
 
 const PC_CID = Components.ID("{bdc2e533-b308-4708-ac8e-a8bfade6d851}");
 const PC_OBS_CID = Components.ID("{d1748d4c-7f6a-4dc5-add6-d55b7678537e}");
 const PC_ICE_CID = Components.ID("{02b9970c-433d-4cc2-923d-f7028ac66073}");
 const PC_SESSION_CID = Components.ID("{1775081b-b62d-4954-8ffe-a067bbf508a7}");
 const PC_MANAGER_CID = Components.ID("{7293e901-2be3-4c02-b4bd-cbef6fc24f78}");
 const PC_STATS_CID = Components.ID("{7fe6e18b-0da3-4056-bf3b-440ef3809e06}");
 const PC_STATIC_CID = Components.ID("{0fb47c47-a205-4583-a9fc-cbadf8c95880}");
 const PC_SENDER_CID = Components.ID("{4fff5d46-d827-4cd4-a970-8fd53977440e}");
 const PC_RECEIVER_CID = Components.ID("{d974b814-8fde-411c-8c45-b86791b81030}");
 const PC_COREQUEST_CID = Components.ID("{74b2122d-65a8-4824-aa9e-3d664cb75dc2}");
 const PC_DTMF_SENDER_CID = Components.ID("{3610C242-654E-11E6-8EC0-6D1BE389A607}");
+const PC_CONTRIB_SOURCE_CID =
+  Components.ID("{be01cd41-25fe-4da9-bd31-0dc84be42828}");
+const PC_SYNC_SOURC_CID =
+  Components.ID("{06991841-FF13-4880-88A7-192D361D5F33}");
 
 function logMsg(msg, file, line, flag, winID) {
   let scriptErrorClass = Cc["@mozilla.org/scripterror;1"];
   let scriptError = scriptErrorClass.createInstance(Ci.nsIScriptError);
   scriptError.initWithWindowID(msg, file, null, line, 0, flag,
                                "content javascript", winID);
   let console = Cc["@mozilla.org/consoleservice;1"].
   getService(Ci.nsIConsoleService);
@@ -1092,16 +1098,20 @@ class RTCPeerConnection {
   _insertDTMF(sender, tones, duration, interToneGap) {
     return this._impl.insertDTMF(sender.__DOM_IMPL__, tones, duration, interToneGap);
   }
 
   _getDTMFToneBuffer(sender) {
     return this._impl.getDTMFToneBuffer(sender.__DOM_IMPL__);
   }
 
+  _getContributingSources(receiver) {
+    return this._impl.getContributingSources(receiver.track);
+  }
+
   async _replaceTrack(sender, withTrack) {
     this._checkClosed();
     return this._chain(() => new Promise((resolve, reject) => {
       this._onReplaceTrackSender = sender;
       this._onReplaceTrackWithTrack = withTrack;
       this._onReplaceTrackSuccess = resolve;
       this._onReplaceTrackFailure = reject;
       this._impl.replaceTrack(sender.track, withTrack);
@@ -1699,16 +1709,48 @@ class RTCDTMFSender {
   }
 }
 setupPrototype(RTCDTMFSender, {
   classID: PC_DTMF_SENDER_CID,
   contractID: PC_DTMF_SENDER_CONTRACT,
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports])
 });
 
+class RTCRtpContributingSource {
+  constructor(pc, entry, receiver) {
+    Object.assign(this, {
+      _pc:pc,
+      _receiver:receiver,
+      _entry: entry,
+    });
+  }
+
+  _fetch() {
+    this._receiver._fetchContributingSources();
+  }
+
+  get source() {
+    this._entry.source();
+  }
+
+  get timestamp () {
+    this._fetch(); // Update "live" fields
+    return this._entry.timestamp;
+  }
+
+  get audioLevel () {
+    this._fetch(); // Update "live" fields
+    return this._entry.audioLevel;
+  }
+}
+setupPrototype(RTCRtpContributingSource, {
+  classID: PC_CONTRIB_SOURCE_CID,
+  contractID: PC_CONTRIB_SOURCE_CONTRACT,
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports])
+});
 class RTCRtpSender {
   constructor(pc, track, stream) {
     let dtmf = pc._win.RTCDTMFSender._create(pc._win, new RTCDTMFSender(this));
     Object.assign(this, { _pc: pc, track, _stream: stream, dtmf });
   }
 
   replaceTrack(withTrack) {
     return this._pc._async(() => this._pc._replaceTrack(this, withTrack));
@@ -1731,23 +1773,55 @@ class RTCRtpSender {
 setupPrototype(RTCRtpSender, {
   classID: PC_SENDER_CID,
   contractID: PC_SENDER_CONTRACT,
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports])
 });
 
 class RTCRtpReceiver {
   constructor(pc, track) {
-    Object.assign(this, { _pc: pc, track });
+    Object.assign(this, {
+      _pc: pc,
+      track,
+      _contributingSources: new Map(),
+      _contributingSourcesCurrent: false,
+    });
+  }
+
+  _fetchContributingSources() {
+    if (this._contributingSourcesCurrent) {
+      return;
+    }
+    this._contributingSourcesCurrent = true;
+    // Queue microtask to mark the cache as stale after this task completes
+    Promise.resolve().then(() => this._contributingSourcesCurrent = false);
+    for (let entry of this._pc._getContributingSources(this)) {
+      let cached = this._contributingSources.get(entry.source);
+      if (!cached) {
+        this._contributingSources.set(entry.source,
+            this._pc._win.RTCRtpContributingSource._create(this._pc._win,
+                new RTCRtpContributingSource(this._pc, entry, this)));
+      } else {
+        cached._entry = entry;
+      }
+    }
   }
 
   getStats() {
     return this._pc._async(
       async () => this._pc.getStats(this.track));
   }
+
+  getContributingSources() {
+    this._fetchContributingSources();
+    // Only return the values from within the last 10 seconds as per the spec
+    let cutoffTime = new Date().getTime() - 10 * 1000;
+    return [...this._contributingSources.values()].filter(
+        (cs) => cs.timestamp >= cutoffTime);
+  }
 }
 setupPrototype(RTCRtpReceiver, {
   classID: PC_RECEIVER_CID,
   contractID: PC_RECEIVER_CONTRACT,
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports])
 });
 
 class CreateOfferRequest {
--- a/dom/media/PeerConnection.manifest
+++ b/dom/media/PeerConnection.manifest
@@ -4,20 +4,25 @@ component {02b9970c-433d-4cc2-923d-f7028
 component {1775081b-b62d-4954-8ffe-a067bbf508a7} PeerConnection.js
 component {7293e901-2be3-4c02-b4bd-cbef6fc24f78} PeerConnection.js
 component {7fe6e18b-0da3-4056-bf3b-440ef3809e06} PeerConnection.js
 component {0fb47c47-a205-4583-a9fc-cbadf8c95880} PeerConnection.js
 component {4fff5d46-d827-4cd4-a970-8fd53977440e} PeerConnection.js
 component {d974b814-8fde-411c-8c45-b86791b81030} PeerConnection.js
 component {74b2122d-65a8-4824-aa9e-3d664cb75dc2} PeerConnection.js
 component {3610C242-654E-11E6-8EC0-6D1BE389A607} PeerConnection.js
+component {be01cd41-25fe-4da9-bd31-0dc84be42828} PeerConnection.js
+component {06991841-FF13-4880-88A7-192D361D5F33} PeerConnection.js
 
 contract @mozilla.org/dom/peerconnection;1 {bdc2e533-b308-4708-ac8e-a8bfade6d851}
 contract @mozilla.org/dom/peerconnectionobserver;1 {d1748d4c-7f6a-4dc5-add6-d55b7678537e}
 contract @mozilla.org/dom/rtcdtmfsender;1 {3610C242-654E-11E6-8EC0-6D1BE389A607}
 contract @mozilla.org/dom/rtcicecandidate;1 {02b9970c-433d-4cc2-923d-f7028ac66073}
 contract @mozilla.org/dom/rtcsessiondescription;1 {1775081b-b62d-4954-8ffe-a067bbf508a7}
 contract @mozilla.org/dom/peerconnectionmanager;1 {7293e901-2be3-4c02-b4bd-cbef6fc24f78}
 contract @mozilla.org/dom/rtcstatsreport;1 {7fe6e18b-0da3-4056-bf3b-440ef3809e06}
 contract @mozilla.org/dom/peerconnectionstatic;1 {0fb47c47-a205-4583-a9fc-cbadf8c95880}
 contract @mozilla.org/dom/rtpsender;1 {4fff5d46-d827-4cd4-a970-8fd53977440e}
 contract @mozilla.org/dom/rtpreceiver;1 {d974b814-8fde-411c-8c45-b86791b81030}
 contract @mozilla.org/dom/createofferrequest;1 {74b2122d-65a8-4824-aa9e-3d664cb75dc2}
+contract @mozilla.org/dom/rtpcontributingsource;1
+{be01cd41-25fe-4da9-bd31-0dc84be42828}
+contract @mozilla.org/dom/rtpsynchronizationsource;1 {06991841-FF13-4880-88A7-192D361D5F33}
--- a/dom/webidl/PeerConnectionImpl.webidl
+++ b/dom/webidl/PeerConnectionImpl.webidl
@@ -45,16 +45,19 @@ interface PeerConnectionImpl  {
   [Throws]
   void removeTrack(MediaStreamTrack track);
   [Throws]
   void insertDTMF(RTCRtpSender sender, DOMString tones,
                   optional unsigned long duration = 100,
                   optional unsigned long interToneGap = 70);
   [Throws]
   DOMString getDTMFToneBuffer(RTCRtpSender sender);
+  sequence<RTCRtpContributingSourceEntry>
+  getContributingSources(MediaStreamTrack track);
+
   [Throws]
   void replaceTrack(MediaStreamTrack thisTrack, MediaStreamTrack withTrack);
   [Throws]
   void setParameters(MediaStreamTrack track,
                      optional RTCRtpParameters parameters);
   [Throws]
   RTCRtpParameters getParameters(MediaStreamTrack track);
   [Throws]
--- a/dom/webidl/RTCRtpContributingSource.webidl
+++ b/dom/webidl/RTCRtpContributingSource.webidl
@@ -8,9 +8,15 @@
  */
 
 [Pref="media.peerconnection.enabled",
     JSImplementation="@mozilla.org/dom/rtpcontributingsource;1"]
 interface RTCRtpContributingSource {
     readonly attribute DOMHighResTimeStamp timestamp;
     readonly attribute unsigned long       source;
     readonly attribute byte?               audioLevel;
+};
+
+dictionary RTCRtpContributingSourceEntry {
+  DOMHighResTimeStamp timestamp;
+  unsigned long source;
+  byte? audioLevel;
 };
\ No newline at end of file