Bug 1423241 - Move SpeechRecognition from stream listener to track listener. r=padenot
authorAndreas Pehrson <apehrson@mozilla.com>
Fri, 23 Nov 2018 15:00:08 +0000
changeset 447819 acd70715684a851db640fae307c111cc6c6b1417
parent 447818 24d6a327d6a2c8badd1082ab6791b217e7343ba4
child 447820 f7fc271746a2e216d8a6dfbb97d256bf0e156f0b
push id35090
push userbtara@mozilla.com
push dateFri, 23 Nov 2018 21:37:23 +0000
treeherdermozilla-central@2317749c5abf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs1423241
milestone65.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 1423241 - Move SpeechRecognition from stream listener to track listener. r=padenot Differential Revision: https://phabricator.services.mozilla.com/D12266
dom/media/webspeech/recognition/SpeechRecognition.cpp
dom/media/webspeech/recognition/SpeechRecognition.h
dom/media/webspeech/recognition/SpeechStreamListener.cpp
dom/media/webspeech/recognition/SpeechStreamListener.h
dom/media/webspeech/recognition/SpeechTrackListener.cpp
dom/media/webspeech/recognition/SpeechTrackListener.h
dom/media/webspeech/recognition/moz.build
--- a/dom/media/webspeech/recognition/SpeechRecognition.cpp
+++ b/dom/media/webspeech/recognition/SpeechRecognition.cpp
@@ -4,40 +4,41 @@
  * 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/. */
 
 #include "SpeechRecognition.h"
 
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 
+#include "mozilla/dom/AudioStreamTrack.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/SpeechRecognitionBinding.h"
 #include "mozilla/dom/MediaStreamTrackBinding.h"
 #include "mozilla/dom/MediaStreamError.h"
 #include "mozilla/MediaManager.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPrefs.h"
 
 #include "AudioSegment.h"
-#include "DOMMediaStream.h"
 #include "MediaEnginePrefs.h"
 #include "endpointer.h"
 
 #include "mozilla/dom/SpeechRecognitionEvent.h"
 #include "nsContentUtils.h"
 #include "nsIDocument.h"
 #include "nsIObserverService.h"
 #include "nsIPermissionManager.h"
 #include "nsIPrincipal.h"
 #include "nsPIDOMWindow.h"
 #include "nsServiceManagerUtils.h"
 #include "nsQueryObject.h"
+#include "SpeechTrackListener.h"
 
 #include <algorithm>
 
 // Undo the windows.h damage
 #if defined(XP_WIN) && defined(GetMessage)
 #undef GetMessage
 #endif
 
@@ -98,17 +99,17 @@ already_AddRefed<nsISpeechRecognitionSer
 
   nsresult rv;
   nsCOMPtr<nsISpeechRecognitionService> recognitionService;
   recognitionService = do_GetService(speechRecognitionServiceCID.get(), &rv);
   return recognitionService.forget();
 }
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(SpeechRecognition, DOMEventTargetHelper,
-                                   mDOMStream, mSpeechGrammarList)
+                                   mTrack, mSpeechGrammarList)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SpeechRecognition)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(SpeechRecognition, DOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(SpeechRecognition, DOMEventTargetHelper)
 
@@ -132,16 +133,18 @@ SpeechRecognition::SpeechRecognition(nsP
       Preferences::GetInt(PREFERENCE_ENDPOINTER_SILENCE_LENGTH, 1250000));
   mEndpointer.set_long_speech_input_complete_silence_length(
       Preferences::GetInt(PREFERENCE_ENDPOINTER_LONG_SILENCE_LENGTH, 2500000));
   mEndpointer.set_long_speech_length(
       Preferences::GetInt(PREFERENCE_ENDPOINTER_SILENCE_LENGTH, 3 * 1000000));
   Reset();
 }
 
+SpeechRecognition::~SpeechRecognition() = default;
+
 bool SpeechRecognition::StateBetween(FSMState begin, FSMState end) {
   return mCurrentState >= begin && mCurrentState <= end;
 }
 
 void SpeechRecognition::SetState(FSMState state) {
   mCurrentState = state;
   SR_LOG("Transitioned to state %s", GetName(mCurrentState));
 }
@@ -494,17 +497,17 @@ void SpeechRecognition::NotifyFinalResul
 
 void SpeechRecognition::DoNothing(SpeechEvent* aEvent) {}
 
 void SpeechRecognition::AbortSilently(SpeechEvent* aEvent) {
   if (mRecognitionService) {
     mRecognitionService->Abort();
   }
 
-  if (mDOMStream) {
+  if (mTrack) {
     StopRecording();
   }
 
   ResetAndEnd();
 }
 
 void SpeechRecognition::AbortError(SpeechEvent* aEvent) {
   AbortSilently(aEvent);
@@ -516,41 +519,43 @@ void SpeechRecognition::NotifyError(Spee
 
   DispatchEvent(*aEvent->mError);
 }
 
 /**************************************
  * Event triggers and other functions *
  **************************************/
 NS_IMETHODIMP
-SpeechRecognition::StartRecording(DOMMediaStream* aDOMStream) {
+SpeechRecognition::StartRecording(RefPtr<AudioStreamTrack>& aTrack) {
   // hold a reference so that the underlying stream
   // doesn't get Destroy()'ed
-  mDOMStream = aDOMStream;
+  mTrack = aTrack;
 
-  if (NS_WARN_IF(!mDOMStream->GetPlaybackStream())) {
+  if (NS_WARN_IF(mTrack->Ended())) {
     return NS_ERROR_UNEXPECTED;
   }
-  mSpeechListener = new SpeechStreamListener(this);
-  mDOMStream->GetPlaybackStream()->AddListener(mSpeechListener);
+  mSpeechListener = new SpeechTrackListener(this);
+  mTrack->AddListener(mSpeechListener);
 
   mEndpointer.StartSession();
 
   return mSpeechDetectionTimer->Init(this, kSPEECH_DETECTION_TIMEOUT_MS,
                                      nsITimer::TYPE_ONE_SHOT);
 }
 
 NS_IMETHODIMP
 SpeechRecognition::StopRecording() {
   // we only really need to remove the listener explicitly when testing,
-  // as our JS code still holds a reference to mDOMStream and only assigning
+  // as our JS code still holds a reference to mTrack and only assigning
   // it to nullptr isn't guaranteed to free the stream and the listener.
-  mDOMStream->GetPlaybackStream()->RemoveListener(mSpeechListener);
+  mStream->UnregisterTrackListener(this);
+  mTrack->RemoveListener(mSpeechListener);
+  mStream = nullptr;
   mSpeechListener = nullptr;
-  mDOMStream = nullptr;
+  mTrack = nullptr;
 
   mEndpointer.EndSession();
   DispatchTrustedEvent(NS_LITERAL_STRING("audioend"));
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -654,17 +659,26 @@ void SpeechRecognition::Start(const Opti
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
   MediaStreamConstraints constraints;
   constraints.mAudio.SetAsBoolean() = true;
 
   if (aStream.WasPassed()) {
-    StartRecording(&aStream.Value());
+    mStream = &aStream.Value();
+    mStream->RegisterTrackListener(this);
+    nsTArray<RefPtr<AudioStreamTrack>> tracks;
+    mStream->GetAudioTracks(tracks);
+    for (const RefPtr<AudioStreamTrack>& track : tracks) {
+      if (!track->Ended()) {
+        NotifyTrackAdded(track);
+        break;
+      }
+    }
   } else {
     AutoNoJSAPI nojsapi;
     MediaManager* manager = MediaManager::Get();
     MediaManager::GetUserMediaSuccessCallback onsuccess(
         new GetUserMediaSuccessCallback(this));
     MediaManager::GetUserMediaErrorCallback onerror(
         new GetUserMediaErrorCallback(this));
     manager->GetUserMedia(GetOwner(), constraints, std::move(onsuccess),
@@ -754,16 +768,34 @@ void SpeechRecognition::Abort() {
     return;
   }
 
   mAborted = true;
   RefPtr<SpeechEvent> event = new SpeechEvent(this, EVENT_ABORT);
   NS_DispatchToMainThread(event);
 }
 
+void SpeechRecognition::NotifyTrackAdded(
+    const RefPtr<MediaStreamTrack>& aTrack) {
+  if (mTrack) {
+    return;
+  }
+
+  RefPtr<AudioStreamTrack> audioTrack = aTrack->AsAudioStreamTrack();
+  if (!audioTrack) {
+    return;
+  }
+
+  if (audioTrack->Ended()) {
+    return;
+  }
+
+  StartRecording(audioTrack);
+}
+
 void SpeechRecognition::DispatchError(EventType aErrorType,
                                       SpeechRecognitionErrorCode aErrorCode,
                                       const nsAString& aMessage) {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aErrorType == EVENT_RECOGNITIONSERVICE_ERROR ||
                  aErrorType == EVENT_AUDIO_ERROR,
              "Invalid error type!");
 
@@ -838,17 +870,17 @@ AudioSegment* SpeechRecognition::CreateA
                           PRINCIPAL_HANDLE_NONE);
   }
 
   return segment;
 }
 
 void SpeechRecognition::FeedAudioData(already_AddRefed<SharedBuffer> aSamples,
                                       uint32_t aDuration,
-                                      MediaStreamListener* aProvider,
+                                      MediaStreamTrackListener* aProvider,
                                       TrackRate aTrackRate) {
   NS_ASSERTION(!NS_IsMainThread(),
                "FeedAudioData should not be called in the main thread");
 
   // Endpointer expects to receive samples in chunks whose size is a
   // multiple of its frame size.
   // Since we can't assume we will receive the frames in appropriate-sized
   // chunks, we must buffer and split them in chunks of mAudioSamplesPerChunk
@@ -916,16 +948,26 @@ const char* SpeechRecognition::GetName(S
                                 "EVENT_RECOGNITIONSERVICE_FINAL_RESULT",
                                 "EVENT_RECOGNITIONSERVICE_ERROR"};
 
   MOZ_ASSERT(aEvent->mType < EVENT_COUNT);
   MOZ_ASSERT(ArrayLength(names) == EVENT_COUNT);
   return names[aEvent->mType];
 }
 
+SpeechEvent::SpeechEvent(SpeechRecognition* aRecognition,
+                         SpeechRecognition::EventType aType)
+    : Runnable("dom::SpeechEvent"),
+      mAudioSegment(nullptr),
+      mRecognitionResultList(nullptr),
+      mError(nullptr),
+      mRecognition(aRecognition),
+      mType(aType),
+      mTrackRate(0) {}
+
 SpeechEvent::~SpeechEvent() { delete mAudioSegment; }
 
 NS_IMETHODIMP
 SpeechEvent::Run() {
   mRecognition->ProcessEvent(this);
   return NS_OK;
 }
 
@@ -934,17 +976,25 @@ NS_IMPL_ISUPPORTS(SpeechRecognition::Get
 
 NS_IMETHODIMP
 SpeechRecognition::GetUserMediaSuccessCallback::OnSuccess(
     nsISupports* aStream) {
   RefPtr<DOMMediaStream> stream = do_QueryObject(aStream);
   if (!stream) {
     return NS_ERROR_NO_INTERFACE;
   }
-  mRecognition->StartRecording(stream);
+  mRecognition->mStream = stream;
+  mRecognition->mStream->RegisterTrackListener(mRecognition);
+  nsTArray<RefPtr<AudioStreamTrack>> tracks;
+  mRecognition->mStream->GetAudioTracks(tracks);
+  for (const RefPtr<AudioStreamTrack>& track : tracks) {
+    if (!track->Ended()) {
+      mRecognition->NotifyTrackAdded(track);
+    }
+  }
   return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS(SpeechRecognition::GetUserMediaErrorCallback,
                   nsIDOMGetUserMediaErrorCallback)
 
 NS_IMETHODIMP
 SpeechRecognition::GetUserMediaErrorCallback::OnError(nsISupports* aError) {
--- a/dom/media/webspeech/recognition/SpeechRecognition.h
+++ b/dom/media/webspeech/recognition/SpeechRecognition.h
@@ -19,42 +19,42 @@
 #include "nsIDOMNavigatorUserMedia.h"
 #include "nsITimer.h"
 #include "MediaStreamGraph.h"
 #include "AudioSegment.h"
 #include "mozilla/WeakPtr.h"
 
 #include "SpeechGrammarList.h"
 #include "SpeechRecognitionResultList.h"
-#include "SpeechStreamListener.h"
 #include "nsISpeechRecognitionService.h"
 #include "endpointer.h"
 
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/SpeechRecognitionError.h"
 
 namespace mozilla {
 
-class DOMMediaStream;
-
 namespace dom {
 
 #define SPEECH_RECOGNITION_TEST_EVENT_REQUEST_TOPIC \
   "SpeechRecognitionTest:RequestEvent"
 #define SPEECH_RECOGNITION_TEST_END_TOPIC "SpeechRecognitionTest:End"
 
 class GlobalObject;
+class AudioStreamTrack;
 class SpeechEvent;
+class SpeechTrackListener;
 
 LogModule* GetSpeechRecognitionLog();
 #define SR_LOG(...) \
   MOZ_LOG(GetSpeechRecognitionLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
 
 class SpeechRecognition final : public DOMEventTargetHelper,
                                 public nsIObserver,
+                                public DOMMediaStream::TrackListener,
                                 public SupportsWeakPtr<SpeechRecognition> {
  public:
   MOZ_DECLARE_WEAKREFERENCE_TYPENAME(SpeechRecognition)
   explicit SpeechRecognition(nsPIDOMWindowInner* aOwnerWindow);
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SpeechRecognition,
                                            DOMEventTargetHelper)
@@ -121,32 +121,34 @@ class SpeechRecognition final : public D
     EVENT_AUDIO_DATA,
     EVENT_AUDIO_ERROR,
     EVENT_RECOGNITIONSERVICE_INTERMEDIATE_RESULT,
     EVENT_RECOGNITIONSERVICE_FINAL_RESULT,
     EVENT_RECOGNITIONSERVICE_ERROR,
     EVENT_COUNT
   };
 
+  void NotifyTrackAdded(const RefPtr<MediaStreamTrack>& aTrack) override;
+
   void DispatchError(EventType aErrorType,
                      SpeechRecognitionErrorCode aErrorCode,
                      const nsAString& aMessage);
   uint32_t FillSamplesBuffer(const int16_t* aSamples, uint32_t aSampleCount);
   uint32_t SplitSamplesBuffer(const int16_t* aSamplesBuffer,
                               uint32_t aSampleCount,
                               nsTArray<RefPtr<SharedBuffer>>& aResult);
   AudioSegment* CreateAudioSegment(nsTArray<RefPtr<SharedBuffer>>& aChunks);
   void FeedAudioData(already_AddRefed<SharedBuffer> aSamples,
-                     uint32_t aDuration, MediaStreamListener* aProvider,
+                     uint32_t aDuration, MediaStreamTrackListener* aProvider,
                      TrackRate aTrackRate);
 
   friend class SpeechEvent;
 
  private:
-  virtual ~SpeechRecognition(){};
+  virtual ~SpeechRecognition();
 
   enum FSMState {
     STATE_IDLE,
     STATE_STARTING,
     STATE_ESTIMATING,
     STATE_WAITING_FOR_SPEECH,
     STATE_RECOGNIZING,
     STATE_WAITING_FOR_RESULT,
@@ -182,17 +184,17 @@ class SpeechRecognition final : public D
         : mRecognition(aRecognition) {}
 
    private:
     virtual ~GetUserMediaErrorCallback() {}
 
     RefPtr<SpeechRecognition> mRecognition;
   };
 
-  NS_IMETHOD StartRecording(DOMMediaStream* aDOMStream);
+  NS_IMETHOD StartRecording(RefPtr<AudioStreamTrack>& aDOMStream);
   NS_IMETHOD StopRecording();
 
   uint32_t ProcessAudioSegment(AudioSegment* aSegment, TrackRate aTrackRate);
   void NotifyError(SpeechEvent* aEvent);
 
   void ProcessEvent(SpeechEvent* aEvent);
   void Transition(SpeechEvent* aEvent);
 
@@ -204,18 +206,19 @@ class SpeechRecognition final : public D
   void WaitForEstimation(SpeechEvent* aEvent);
   void DetectSpeech(SpeechEvent* aEvent);
   void WaitForSpeechEnd(SpeechEvent* aEvent);
   void NotifyFinalResult(SpeechEvent* aEvent);
   void DoNothing(SpeechEvent* aEvent);
   void AbortSilently(SpeechEvent* aEvent);
   void AbortError(SpeechEvent* aEvent);
 
-  RefPtr<DOMMediaStream> mDOMStream;
-  RefPtr<SpeechStreamListener> mSpeechListener;
+  RefPtr<DOMMediaStream> mStream;
+  RefPtr<AudioStreamTrack> mTrack;
+  RefPtr<SpeechTrackListener> mSpeechListener;
   nsCOMPtr<nsISpeechRecognitionService> mRecognitionService;
 
   FSMState mCurrentState;
 
   Endpointer mEndpointer;
   uint32_t mEstimationSamples;
 
   uint32_t mAudioSamplesPerChunk;
@@ -261,44 +264,37 @@ class SpeechRecognition final : public D
 
   const char* GetName(FSMState aId);
   const char* GetName(SpeechEvent* aId);
 };
 
 class SpeechEvent : public Runnable {
  public:
   SpeechEvent(SpeechRecognition* aRecognition,
-              SpeechRecognition::EventType aType)
-      : Runnable("dom::SpeechEvent"),
-        mAudioSegment(0),
-        mRecognitionResultList(nullptr),
-        mError(nullptr),
-        mRecognition(aRecognition),
-        mType(aType),
-        mTrackRate(0) {}
+              SpeechRecognition::EventType aType);
 
   ~SpeechEvent();
 
   NS_IMETHOD Run() override;
   AudioSegment* mAudioSegment;
   RefPtr<SpeechRecognitionResultList>
       mRecognitionResultList;  // TODO: make this a session being passed which
                                // also has index and stuff
   RefPtr<SpeechRecognitionError> mError;
 
   friend class SpeechRecognition;
 
  private:
   SpeechRecognition* mRecognition;
 
   // for AUDIO_DATA events, keep a reference to the provider
-  // of the data (i.e., the SpeechStreamListener) to ensure it
+  // of the data (i.e., the SpeechTrackListener) to ensure it
   // is kept alive (and keeps SpeechRecognition alive) until this
   // event gets processed.
-  RefPtr<MediaStreamListener> mProvider;
+  RefPtr<MediaStreamTrackListener> mProvider;
   SpeechRecognition::EventType mType;
   TrackRate mTrackRate;
 };
 
 }  // namespace dom
 
 inline nsISupports* ToSupports(dom::SpeechRecognition* aRec) {
   return ToSupports(static_cast<DOMEventTargetHelper*>(aRec));
rename from dom/media/webspeech/recognition/SpeechStreamListener.cpp
rename to dom/media/webspeech/recognition/SpeechTrackListener.cpp
--- a/dom/media/webspeech/recognition/SpeechStreamListener.cpp
+++ b/dom/media/webspeech/recognition/SpeechTrackListener.cpp
@@ -1,34 +1,33 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
-#include "SpeechStreamListener.h"
+#include "SpeechTrackListener.h"
 
 #include "SpeechRecognition.h"
 #include "nsProxyRelease.h"
 
 namespace mozilla {
 namespace dom {
 
-SpeechStreamListener::SpeechStreamListener(SpeechRecognition* aRecognition)
+SpeechTrackListener::SpeechTrackListener(SpeechRecognition* aRecognition)
     : mRecognition(aRecognition) {}
 
-SpeechStreamListener::~SpeechStreamListener() {
-  NS_ReleaseOnMainThreadSystemGroup("SpeechStreamListener::mRecognition",
+SpeechTrackListener::~SpeechTrackListener() {
+  NS_ReleaseOnMainThreadSystemGroup("SpeechTrackListener::mRecognition",
                                     mRecognition.forget());
 }
 
-void SpeechStreamListener::NotifyQueuedAudioData(
-    MediaStreamGraph* aGraph, TrackID aID, StreamTime aTrackOffset,
-    const AudioSegment& aQueuedMedia, MediaStream* aInputStream,
-    TrackID aInputTrackID) {
+void SpeechTrackListener::NotifyQueuedChanges(
+    MediaStreamGraph* aGraph, StreamTime aTrackOffset,
+    const MediaSegment& aQueuedMedia) {
   AudioSegment* audio = const_cast<AudioSegment*>(
       static_cast<const AudioSegment*>(&aQueuedMedia));
 
   AudioSegment::ChunkIterator iterator(*audio);
   while (!iterator.IsEnded()) {
     // Skip over-large chunks so we don't crash!
     if (iterator->GetDuration() > INT_MAX) {
       continue;
@@ -58,28 +57,27 @@ void SpeechStreamListener::NotifyQueuedA
       }
     }
 
     iterator.Next();
   }
 }
 
 template <typename SampleFormatType>
-void SpeechStreamListener::ConvertAndDispatchAudioChunk(int aDuration,
-                                                        float aVolume,
-                                                        SampleFormatType* aData,
-                                                        TrackRate aTrackRate) {
+void SpeechTrackListener::ConvertAndDispatchAudioChunk(int aDuration,
+                                                       float aVolume,
+                                                       SampleFormatType* aData,
+                                                       TrackRate aTrackRate) {
   RefPtr<SharedBuffer> samples(SharedBuffer::Create(aDuration * 1 *  // channel
                                                     sizeof(int16_t)));
 
   int16_t* to = static_cast<int16_t*>(samples->Data());
   ConvertAudioSamplesWithScale(aData, to, aDuration, aVolume);
 
   mRecognition->FeedAudioData(samples.forget(), aDuration, this, aTrackRate);
 }
 
-void SpeechStreamListener::NotifyEvent(MediaStreamGraph* aGraph,
-                                       MediaStreamGraphEvent event) {
+void SpeechTrackListener::NotifyEnded() {
   // TODO dispatch SpeechEnd event so services can be informed
 }
 
 }  // namespace dom
 }  // namespace mozilla
rename from dom/media/webspeech/recognition/SpeechStreamListener.h
rename to dom/media/webspeech/recognition/SpeechTrackListener.h
--- a/dom/media/webspeech/recognition/SpeechStreamListener.h
+++ b/dom/media/webspeech/recognition/SpeechTrackListener.h
@@ -14,29 +14,25 @@
 namespace mozilla {
 
 class AudioSegment;
 
 namespace dom {
 
 class SpeechRecognition;
 
-class SpeechStreamListener : public MediaStreamListener {
+class SpeechTrackListener : public MediaStreamTrackListener {
  public:
-  explicit SpeechStreamListener(SpeechRecognition* aRecognition);
-  ~SpeechStreamListener();
+  explicit SpeechTrackListener(SpeechRecognition* aRecognition);
+  ~SpeechTrackListener();
 
-  void NotifyQueuedAudioData(MediaStreamGraph* aGraph, TrackID aID,
-                             StreamTime aTrackOffset,
-                             const AudioSegment& aQueuedMedia,
-                             MediaStream* aInputStream,
-                             TrackID aInputTrackID) override;
+  void NotifyQueuedChanges(MediaStreamGraph* aGraph, StreamTime aTrackOffset,
+                           const MediaSegment& aQueuedMedia) override;
 
-  void NotifyEvent(MediaStreamGraph* aGraph,
-                   MediaStreamGraphEvent event) override;
+  void NotifyEnded() override;
 
  private:
   template <typename SampleFormatType>
   void ConvertAndDispatchAudioChunk(int aDuration, float aVolume,
                                     SampleFormatType* aData,
                                     TrackRate aTrackRate);
   RefPtr<SpeechRecognition> mRecognition;
 };
--- a/dom/media/webspeech/recognition/moz.build
+++ b/dom/media/webspeech/recognition/moz.build
@@ -13,17 +13,17 @@ XPIDL_SOURCES = [
 
 EXPORTS.mozilla.dom += [
     'SpeechGrammar.h',
     'SpeechGrammarList.h',
     'SpeechRecognition.h',
     'SpeechRecognitionAlternative.h',
     'SpeechRecognitionResult.h',
     'SpeechRecognitionResultList.h',
-    'SpeechStreamListener.h',
+    'SpeechTrackListener.h',
 ]
 
 if CONFIG['MOZ_WEBSPEECH_TEST_BACKEND']:
     EXPORTS.mozilla.dom += [
         'test/FakeSpeechRecognitionService.h',
     ]
 
 UNIFIED_SOURCES += [
@@ -31,17 +31,17 @@ UNIFIED_SOURCES += [
     'energy_endpointer.cc',
     'energy_endpointer_params.cc',
     'SpeechGrammar.cpp',
     'SpeechGrammarList.cpp',
     'SpeechRecognition.cpp',
     'SpeechRecognitionAlternative.cpp',
     'SpeechRecognitionResult.cpp',
     'SpeechRecognitionResultList.cpp',
-    'SpeechStreamListener.cpp',
+    'SpeechTrackListener.cpp',
 ]
 
 if CONFIG['MOZ_WEBSPEECH_TEST_BACKEND']:
     UNIFIED_SOURCES += [
         'test/FakeSpeechRecognitionService.cpp',
     ]
 
 LOCAL_INCLUDES += [