Bug 1208371 - Make AudioCaptureStream startable. r?padenot draft
authorAndreas Pehrson <pehrsons@gmail.com>
Thu, 05 Nov 2015 15:42:21 +0800
changeset 306633 4691c9db6bbcac38f9ab0025ec986321441f656d
parent 306632 dba5c61f208d1406bc0fd0ce775b9fd0edea6f2e
child 306634 2f5ba3e6b9b4b8d9bf475b341314cb13e344d982
push id7183
push userpehrsons@gmail.com
push dateThu, 05 Nov 2015 07:42:40 +0000
reviewerspadenot
bugs1208371
milestone45.0a1
Bug 1208371 - Make AudioCaptureStream startable. r?padenot This allows us to add the JS-side MediaStreamTrack before the MSG-side track.
dom/media/AudioCaptureStream.cpp
dom/media/AudioCaptureStream.h
dom/media/DOMMediaStream.cpp
--- a/dom/media/AudioCaptureStream.cpp
+++ b/dom/media/AudioCaptureStream.cpp
@@ -25,52 +25,79 @@ using namespace mozilla::gfx;
 
 namespace mozilla
 {
 
 // We are mixing to mono until PeerConnection can accept stereo
 static const uint32_t MONO = 1;
 
 AudioCaptureStream::AudioCaptureStream(DOMMediaStream* aWrapper, TrackID aTrackId)
-  : ProcessedMediaStream(aWrapper), mTrackId(aTrackId), mTrackCreated(false)
+  : ProcessedMediaStream(aWrapper), mTrackId(aTrackId), mStarted(false), mTrackCreated(false)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_COUNT_CTOR(AudioCaptureStream);
   mMixer.AddCallback(this);
 }
 
 AudioCaptureStream::~AudioCaptureStream()
 {
   MOZ_COUNT_DTOR(AudioCaptureStream);
   mMixer.RemoveCallback(this);
 }
 
 void
+AudioCaptureStream::Start()
+{
+  class Message : public ControlMessage {
+  public:
+    explicit Message(AudioCaptureStream* aStream)
+      : ControlMessage(aStream), mStream(aStream) {}
+
+    virtual void Run()
+    {
+      mStream->mStarted = true;
+    }
+
+  protected:
+    AudioCaptureStream* mStream;
+  };
+  GraphImpl()->AppendMessage(new Message(this));
+}
+
+void
 AudioCaptureStream::ProcessInput(GraphTime aFrom, GraphTime aTo,
                                  uint32_t aFlags)
 {
+  if (!mStarted) {
+    return;
+  }
+
   uint32_t inputCount = mInputs.Length();
   StreamBuffer::Track* track = EnsureTrack(mTrackId);
   // Notify the DOM everything is in order.
   if (!mTrackCreated) {
     for (uint32_t i = 0; i < mListeners.Length(); i++) {
       MediaStreamListener* l = mListeners[i];
       AudioSegment tmp;
       l->NotifyQueuedTrackChanges(
         Graph(), mTrackId, 0, MediaStreamListener::TRACK_EVENT_CREATED, tmp);
       l->NotifyFinishedTrackCreation(Graph());
     }
     mTrackCreated = true;
   }
 
+  if (IsFinishedOnGraphThread()) {
+    return;
+  }
+
   // If the captured stream is connected back to a object on the page (be it an
   // HTMLMediaElement with a stream as source, or an AudioContext), a cycle
   // situation occur. This can work if it's an AudioContext with at least one
   // DelayNode, but the MSG will mute the whole cycle otherwise.
-  if (mFinished || InMutedCycle() || inputCount == 0) {
+  if (InMutedCycle() || inputCount == 0) {
     track->Get<AudioSegment>()->AppendNullData(aTo - aFrom);
   } else {
     // We mix down all the tracks of all inputs, to a stereo track. Everything
     // is {up,down}-mixed to stereo.
     mMixer.StartMixing();
     AudioSegment output;
     for (uint32_t i = 0; i < inputCount; i++) {
       MediaStream* s = mInputs[i]->GetSource();
--- a/dom/media/AudioCaptureStream.h
+++ b/dom/media/AudioCaptureStream.h
@@ -21,21 +21,24 @@ class DOMMediaStream;
  */
 class AudioCaptureStream : public ProcessedMediaStream,
                            public MixerCallbackReceiver
 {
 public:
   explicit AudioCaptureStream(DOMMediaStream* aWrapper, TrackID aTrackId);
   virtual ~AudioCaptureStream();
 
+  void Start();
+
   void ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) override;
 
 protected:
   void MixerCallback(AudioDataValue* aMixedBuffer, AudioSampleFormat aFormat,
                      uint32_t aChannels, uint32_t aFrames,
                      uint32_t aSampleRate) override;
   AudioMixer mMixer;
   TrackID mTrackId;
+  bool mStarted;
   bool mTrackCreated;
 };
 }
 
 #endif /* MOZILLA_AUDIOCAPTURESTREAM_H_ */
--- a/dom/media/DOMMediaStream.cpp
+++ b/dom/media/DOMMediaStream.cpp
@@ -607,20 +607,23 @@ DOMMediaStream::InitTrackUnionStream(Med
   InitPlaybackStreamCommon(aGraph);
 }
 
 void
 DOMMediaStream::InitAudioCaptureStream(MediaStreamGraph* aGraph)
 {
   const TrackID AUDIO_TRACK = 1;
 
-  InitInputStreamCommon(aGraph->CreateAudioCaptureStream(this, AUDIO_TRACK), aGraph);
+  AudioCaptureStream* audioCaptureStream =
+    static_cast<AudioCaptureStream*>(aGraph->CreateAudioCaptureStream(this, AUDIO_TRACK));
+  InitInputStreamCommon(audioCaptureStream, aGraph);
   InitOwnedStreamCommon(aGraph);
   InitPlaybackStreamCommon(aGraph);
   CreateOwnDOMTrack(AUDIO_TRACK, MediaSegment::AUDIO);
+  audioCaptureStream->Start();
 }
 
 void
 DOMMediaStream::InitInputStreamCommon(MediaStream* aStream,
                                       MediaStreamGraph* aGraph)
 {
   MOZ_ASSERT(!mOwnedStream, "Input stream must be initialized before owned stream");