Bug 1324545 - Implement AudioContext getOutputTimestamp(). r=baku
authorPaul Adenot <paul@paul.cx>
Fri, 12 Jul 2019 11:27:25 +0000
changeset 482585 de7190bf40fd3c940929365df71cfc2401f47cac
parent 482584 718a301a0c6c387a56f236ea88f5f3da6cf9381d
child 482586 c96e81ba64f307b402fc6df24a3e7c256ea854a3
push id89849
push userpadenot@mozilla.com
push dateFri, 12 Jul 2019 11:29:28 +0000
treeherderautoland@c96e81ba64f3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1324545
milestone70.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1324545 - Implement AudioContext getOutputTimestamp(). r=baku Differential Revision: https://phabricator.services.mozilla.com/D37281
dom/media/webaudio/AudioContext.cpp
dom/media/webaudio/AudioContext.h
dom/webidl/AudioContext.webidl
testing/web-platform/meta/webaudio/idlharness.https.window.js.ini
testing/web-platform/meta/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-getoutputtimestamp.html.ini
--- a/dom/media/webaudio/AudioContext.cpp
+++ b/dom/media/webaudio/AudioContext.cpp
@@ -31,16 +31,17 @@
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "mozilla/dom/MediaElementAudioSourceNodeBinding.h"
 #include "mozilla/dom/MediaStreamAudioSourceNodeBinding.h"
 #include "mozilla/dom/MediaStreamTrackAudioSourceNodeBinding.h"
 #include "mozilla/dom/OfflineAudioContextBinding.h"
 #include "mozilla/dom/OscillatorNodeBinding.h"
 #include "mozilla/dom/PannerNodeBinding.h"
 #include "mozilla/dom/PeriodicWaveBinding.h"
+#include "mozilla/dom/Performance.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/StereoPannerNodeBinding.h"
 #include "mozilla/dom/WaveShaperNodeBinding.h"
 #include "mozilla/dom/Worklet.h"
 
 #include "AudioBuffer.h"
 #include "AudioBufferSourceNode.h"
 #include "AudioChannelService.h"
@@ -520,16 +521,38 @@ AudioListener* AudioContext::Listener() 
   if (!mListener) {
     mListener = new AudioListener(this);
   }
   return mListener;
 }
 
 double AudioContext::OutputLatency() { return Graph()->AudioOutputLatency(); }
 
+void AudioContext::GetOutputTimestamp(AudioTimestamp& aTimeStamp) {
+  if (!Destination()) {
+    aTimeStamp.mContextTime.Construct(0.0);
+    aTimeStamp.mPerformanceTime.Construct(0.0);
+    return;
+  }
+
+  // The currentTime currently being output is the currentTime minus the audio
+  // output latency.
+  aTimeStamp.mContextTime.Construct(
+      std::max(0.0, CurrentTime() - OutputLatency()));
+  nsPIDOMWindowInner* parent = GetParentObject();
+  Performance* perf = parent ? parent->GetPerformance() : nullptr;
+  if (perf) {
+    // Convert to milliseconds.
+    aTimeStamp.mPerformanceTime.Construct(
+        std::max(0., perf->Now() - (OutputLatency() * 1000.)));
+  } else {
+    aTimeStamp.mPerformanceTime.Construct(0.0);
+  }
+}
+
 Worklet* AudioContext::GetAudioWorklet(ErrorResult& aRv) {
   if (!mWorklet) {
     mWorklet = AudioWorkletImpl::CreateWorklet(this, aRv);
   }
 
   return mWorklet;
 }
 
--- a/dom/media/webaudio/AudioContext.h
+++ b/dom/media/webaudio/AudioContext.h
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef AudioContext_h_
 #define AudioContext_h_
 
 #include "AudioParamDescriptorMap.h"
 #include "mozilla/dom/OfflineAudioContextBinding.h"
+#include "mozilla/dom/AudioContextBinding.h"
 #include "MediaBufferDecoder.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/dom/TypedArray.h"
 #include "mozilla/RelativeTimeline.h"
 #include "mozilla/TypedEnumBits.h"
 #include "mozilla/UniquePtr.h"
@@ -195,16 +196,18 @@ class AudioContext final : public DOMEve
   double BaseLatency() const {
     // Gecko does not do any buffering between rendering the audio and sending
     // it to the audio subsystem.
     return 0.0;
   }
 
   double OutputLatency();
 
+  void GetOutputTimestamp(AudioTimestamp& aTimeStamp);
+
   Worklet* GetAudioWorklet(ErrorResult& aRv);
 
   bool IsRunning() const;
 
   // Called when an AudioScheduledSourceNode started or the source node starts,
   // this method might resume the AudioContext if it was not allowed to start.
   void StartBlockedAudioContextIfAllowed();
 
--- a/dom/webidl/AudioContext.webidl
+++ b/dom/webidl/AudioContext.webidl
@@ -9,23 +9,28 @@
  * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
 dictionary AudioContextOptions {
              float        sampleRate = 0;
 };
 
+dictionary AudioTimestamp {
+  double contextTime;
+  DOMHighResTimeStamp performanceTime;
+};
+
 [Pref="dom.webaudio.enabled",
  Constructor(optional AudioContextOptions contextOptions = {})]
 interface AudioContext : BaseAudioContext {
 
-    // Bug 1324545: AudioTimestamp                  getOutputTimestamp ();
     readonly        attribute double               baseLatency;
     readonly        attribute double               outputLatency;
+    AudioTimestamp                  getOutputTimestamp();
 
     [Throws]
     Promise<void> suspend();
     [Throws]
     Promise<void> close();
 
     [NewObject, Throws]
     MediaElementAudioSourceNode createMediaElementSource(HTMLMediaElement mediaElement);
--- a/testing/web-platform/meta/webaudio/idlharness.https.window.js.ini
+++ b/testing/web-platform/meta/webaudio/idlharness.https.window.js.ini
@@ -15,19 +15,16 @@
     expected: FAIL
 
   [MediaStreamAudioSourceNode interface: attribute mediaStream]
     expected: FAIL
 
   [AudioParam interface: calling cancelAndHoldAtTime(double) on new AudioBufferSourceNode(context).playbackRate with too few arguments must throw TypeError]
     expected: FAIL
 
-  [AudioContext interface: context must inherit property "getOutputTimestamp()" with the proper type]
-    expected: FAIL
-
   [AudioListener interface: context.listener must inherit property "forwardX" with the proper type]
     expected: FAIL
 
   [Stringification of worklet_node.parameters]
     expected: FAIL
 
   [AudioListener interface: attribute positionX]
     expected: FAIL
@@ -39,19 +36,16 @@
     expected: FAIL
 
   [AudioListener interface: context.listener must inherit property "positionY" with the proper type]
     expected: FAIL
 
   [MediaElementAudioSourceNode interface: new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) must inherit property "mediaElement" with the proper type]
     expected: FAIL
 
-  [AudioContext interface: operation getOutputTimestamp()]
-    expected: FAIL
-
   [Stringification of new AudioProcessingEvent('', {\n        playbackTime: 0, inputBuffer: buffer, outputBuffer: buffer\n      })]
     expected: FAIL
 
   [OfflineAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "suspend(double)" with the proper type]
     expected: FAIL
 
   [AudioParam interface: operation cancelAndHoldAtTime(double)]
     expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-getoutputtimestamp.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[audiocontext-getoutputtimestamp.html]
-  expected: ERROR