Bug 1423241 - Always add tracks at the stream's current time. r=padenot
authorAndreas Pehrson <apehrson@mozilla.com>
Fri, 23 Nov 2018 15:01:42 +0000
changeset 504271 d39a3f7454a17e70db5a2a34ac32f442f00bce29
parent 504270 926b591bb0cf53300f8ed17d6849644aa7626079
child 504272 12f91d8a1f694cb3186dd32624faee8242812c87
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [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 - Always add tracks at the stream's current time. r=padenot Differential Revision: https://phabricator.services.mozilla.com/D12271
dom/media/CanvasCaptureMediaStream.cpp
dom/media/MediaStreamGraph.cpp
dom/media/MediaStreamGraph.h
dom/media/mediasink/DecodedStream.cpp
dom/media/webrtc/MediaEngineDefault.cpp
dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
dom/media/webrtc/MediaEngineTabVideoSource.cpp
dom/media/webrtc/MediaEngineWebRTCAudio.cpp
media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
--- a/dom/media/CanvasCaptureMediaStream.cpp
+++ b/dom/media/CanvasCaptureMediaStream.cpp
@@ -108,17 +108,17 @@ OutputStreamDriver::OutputStreamDriver(S
                                        const TrackID& aTrackId,
                                        const PrincipalHandle& aPrincipalHandle)
     : FrameCaptureListener(),
       mSourceStream(aSourceStream),
       mTrackListener(
           new TrackListener(aTrackId, aPrincipalHandle, aSourceStream)) {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mSourceStream);
-  mSourceStream->AddTrack(aTrackId, 0, new VideoSegment());
+  mSourceStream->AddTrack(aTrackId, new VideoSegment());
   mSourceStream->AddTrackListener(mTrackListener, aTrackId);
   mSourceStream->AdvanceKnownTracksTime(STREAM_TIME_MAX);
   mSourceStream->SetPullEnabled(true);
 
   // All CanvasCaptureMediaStreams shall at least get one frame.
   mFrameCaptureRequested = true;
 }
 
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -1220,17 +1220,17 @@ void MediaStreamGraphImpl::UpdateGraph(G
 
   UpdateStreamOrder();
 
   bool ensureNextIteration = false;
 
   for (MediaStream* stream : mStreams) {
     if (SourceMediaStream* is = stream->AsSourceStream()) {
       ensureNextIteration |= is->PullNewData(aEndBlockingDecisions);
-      is->ExtractPendingInput();
+      is->ExtractPendingInput(mStateComputedTime);
     }
     if (stream->mFinished) {
       // The stream's not suspended, and since it's finished, underruns won't
       // stop it playing out. So there's no blocking other than what we impose
       // here.
       GraphTime endTime = stream->GetStreamTracks().GetAllTracksEnd() +
                           stream->mTracksStartTime;
       if (endTime <= mStateComputedTime) {
@@ -2630,17 +2630,17 @@ void SourceMediaStream::SetPullEnabled(b
       mStream->mPullEnabled = mEnabled;
     }
     SourceMediaStream* mStream;
     bool mEnabled;
   };
   GraphImpl()->AppendMessage(MakeUnique<Message>(this, aEnabled));
 }
 
-bool SourceMediaStream::PullNewData(StreamTime aDesiredUpToTime) {
+bool SourceMediaStream::PullNewData(GraphTime aDesiredUpToTime) {
   TRACE_AUDIO_CALLBACK_COMMENT("SourceMediaStream %p", this);
   MutexAutoLock lock(mMutex);
   if (!mPullEnabled || mFinished) {
     return false;
   }
   // Compute how much stream time we'll need assuming we don't block
   // the stream at all.
   StreamTime t = GraphTimeToStreamTime(aDesiredUpToTime);
@@ -2672,32 +2672,33 @@ bool SourceMediaStream::PullNewData(Stre
       if (l.mTrackID == track.mID) {
         l.mListener->NotifyPull(Graph(), current, t);
       }
     }
   }
   return true;
 }
 
-void SourceMediaStream::ExtractPendingInput() {
+void SourceMediaStream::ExtractPendingInput(GraphTime aCurrentTime) {
   MutexAutoLock lock(mMutex);
 
   bool finished = mFinishPending;
   bool shouldNotifyTrackCreated = false;
+  StreamTime streamCurrentTime = GraphTimeToStreamTime(aCurrentTime);
 
   for (int32_t i = mUpdateTracks.Length() - 1; i >= 0; --i) {
     SourceMediaStream::TrackData* data = &mUpdateTracks[i];
     ApplyTrackDisabling(data->mID, data->mData);
     // Dealing with NotifyQueuedTrackChanges and NotifyQueuedAudioData part.
 
     // The logic is different from the manipulating of aStream->mTracks part.
     // So it is not combined with the manipulating of aStream->mTracks part.
     StreamTime offset =
         (data->mCommands & SourceMediaStream::TRACK_CREATE)
-            ? data->mStart
+            ? streamCurrentTime
             : mTracks.FindTrack(data->mID)->GetSegment()->GetDuration();
 
     // Audio case.
     if (data->mData->GetType() == MediaSegment::AUDIO) {
       if (data->mCommands) {
         MOZ_ASSERT(!(data->mCommands & SourceMediaStream::TRACK_UNUSED));
         for (MediaStreamListener* l : mListeners) {
           if (data->mCommands & SourceMediaStream::TRACK_END) {
@@ -2741,21 +2742,22 @@ void SourceMediaStream::ExtractPendingIn
       }
       b.mListener->NotifyQueuedChanges(GraphImpl(), offset, *data->mData);
     }
     if (data->mCommands & SourceMediaStream::TRACK_CREATE) {
       MediaSegment* segment = data->mData.forget();
       LOG(LogLevel::Debug,
           ("%p: SourceMediaStream %p creating track %d, start %" PRId64
            ", initial end %" PRId64,
-           GraphImpl(), this, data->mID, int64_t(data->mStart),
+           GraphImpl(), this, data->mID, int64_t(streamCurrentTime),
            int64_t(segment->GetDuration())));
 
       data->mEndOfFlushedData += segment->GetDuration();
-      mTracks.AddTrack(data->mID, data->mStart, segment);
+      segment->InsertNullDataAtStart(streamCurrentTime);
+      mTracks.AddTrack(data->mID, streamCurrentTime, segment);
       // The track has taken ownership of data->mData, so let's replace
       // data->mData with an empty clone.
       data->mData = segment->CreateEmptyClone();
       data->mCommands &= ~SourceMediaStream::TRACK_CREATE;
       shouldNotifyTrackCreated = true;
     } else if (data->mData->GetDuration() > 0) {
       MediaSegment* dest = mTracks.FindTrack(data->mID)->GetSegment();
       LOG(LogLevel::Verbose,
@@ -2785,43 +2787,40 @@ void SourceMediaStream::ExtractPendingIn
   }
 
   if (finished) {
     FinishOnGraphThread();
   }
 }
 
 void SourceMediaStream::AddTrackInternal(TrackID aID, TrackRate aRate,
-                                         StreamTime aStart,
                                          MediaSegment* aSegment,
                                          uint32_t aFlags) {
   MutexAutoLock lock(mMutex);
   nsTArray<TrackData>* track_data =
       (aFlags & ADDTRACK_QUEUED) ? &mPendingTracks : &mUpdateTracks;
   TrackData* data = track_data->AppendElement();
   LOG(LogLevel::Debug,
       ("%p: AddTrackInternal: %lu/%lu", GraphImpl(),
        (long)mPendingTracks.Length(), (long)mUpdateTracks.Length()));
   data->mID = aID;
   data->mInputRate = aRate;
   data->mResamplerChannelCount = 0;
-  data->mStart = aStart;
-  data->mEndOfFlushedData = aStart;
+  data->mEndOfFlushedData = 0;
   data->mCommands = TRACK_CREATE;
   data->mData = aSegment;
   ResampleAudioToGraphSampleRate(data, aSegment);
   if (!(aFlags & ADDTRACK_QUEUED) && GraphImpl()) {
     GraphImpl()->EnsureNextIteration();
   }
 }
 
 void SourceMediaStream::AddAudioTrack(TrackID aID, TrackRate aRate,
-                                      StreamTime aStart, AudioSegment* aSegment,
-                                      uint32_t aFlags) {
-  AddTrackInternal(aID, aRate, aStart, aSegment, aFlags);
+                                      AudioSegment* aSegment, uint32_t aFlags) {
+  AddTrackInternal(aID, aRate, aSegment, aFlags);
 }
 
 void SourceMediaStream::FinishAddTracks() {
   MutexAutoLock lock(mMutex);
   mUpdateTracks.AppendElements(std::move(mPendingTracks));
   LOG(LogLevel::Debug,
       ("%p: FinishAddTracks: %lu/%lu", GraphImpl(),
        (long)mPendingTracks.Length(), (long)mUpdateTracks.Length()));
--- a/dom/media/MediaStreamGraph.h
+++ b/dom/media/MediaStreamGraph.h
@@ -697,50 +697,48 @@ class SourceMediaStream : public MediaSt
   // Call these on any thread.
   /**
    * Call all MediaStreamListeners to request new data via the NotifyPull API
    * (if enabled).
    * aDesiredUpToTime (in): end time of new data requested.
    *
    * Returns true if new data is about to be added.
    */
-  bool PullNewData(StreamTime aDesiredUpToTime);
+  bool PullNewData(GraphTime aDesiredUpToTime);
 
   /**
    * Extract any state updates pending in the stream, and apply them.
    */
-  void ExtractPendingInput();
+  void ExtractPendingInput(GraphTime aCurrentTime);
 
   /**
    * These add/remove DirectListeners, which allow bypassing the graph and any
    * synchronization delays for e.g. PeerConnection, which wants the data ASAP
    * and lets the far-end handle sync and playout timing.
    */
   void NotifyListenersEventImpl(MediaStreamGraphEvent aEvent);
   void NotifyListenersEvent(MediaStreamGraphEvent aEvent);
 
   enum {
     ADDTRACK_QUEUED = 0x01  // Queue track add until FinishAddTracks()
   };
   /**
-   * Add a new track to the stream starting at the given base time (which
-   * must be greater than or equal to the last time passed to
-   * AdvanceKnownTracksTime). Takes ownership of aSegment. aSegment should
-   * contain data starting after aStart.
+   * Add a new track to the stream starting at the stream's current time
+   * (which must be greater than or equal to the last time passed to
+   * AdvanceKnownTracksTime). Takes ownership of aSegment.
    */
-  void AddTrack(TrackID aID, StreamTime aStart, MediaSegment* aSegment,
-                uint32_t aFlags = 0) {
-    AddTrackInternal(aID, GraphRate(), aStart, aSegment, aFlags);
+  void AddTrack(TrackID aID, MediaSegment* aSegment, uint32_t aFlags = 0) {
+    AddTrackInternal(aID, GraphRate(), aSegment, aFlags);
   }
 
   /**
    * Like AddTrack, but resamples audio from aRate to the graph rate.
    */
-  void AddAudioTrack(TrackID aID, TrackRate aRate, StreamTime aStart,
-                     AudioSegment* aSegment, uint32_t aFlags = 0);
+  void AddAudioTrack(TrackID aID, TrackRate aRate, AudioSegment* aSegment,
+                     uint32_t aFlags = 0);
 
   /**
    * Call after a series of AddTrack or AddAudioTrack calls to implement
    * any pending track adds.
    */
   void FinishAddTracks();
 
   /**
@@ -827,17 +825,16 @@ class SourceMediaStream : public MediaSt
   struct TrackData {
     TrackID mID;
     // Sample rate of the input data.
     TrackRate mInputRate;
     // Resampler if the rate of the input track does not match the
     // MediaStreamGraph's.
     nsAutoRef<SpeexResamplerState> mResampler;
     int mResamplerChannelCount;
-    StreamTime mStart;
     // End-time of data already flushed to the track (excluding mData)
     StreamTime mEndOfFlushedData;
     // Each time the track updates are flushed to the media graph thread,
     // the segment buffer is emptied.
     nsAutoPtr<MediaSegment> mData;
     // Each time the track updates are flushed to the media graph thread,
     // this is cleared.
     uint32_t mCommands;
@@ -849,18 +846,18 @@ class SourceMediaStream : public MediaSt
                                       MediaSegment* aSegment);
 
   void AddDirectTrackListenerImpl(
       already_AddRefed<DirectMediaStreamTrackListener> aListener,
       TrackID aTrackID) override;
   void RemoveDirectTrackListenerImpl(DirectMediaStreamTrackListener* aListener,
                                      TrackID aTrackID) override;
 
-  void AddTrackInternal(TrackID aID, TrackRate aRate, StreamTime aStart,
-                        MediaSegment* aSegment, uint32_t aFlags);
+  void AddTrackInternal(TrackID aID, TrackRate aRate, MediaSegment* aSegment,
+                        uint32_t aFlags);
 
   TrackData* FindDataForTrack(TrackID aID) {
     mMutex.AssertCurrentThreadOwns();
     for (uint32_t i = 0; i < mUpdateTracks.Length(); ++i) {
       if (mUpdateTracks[i].mID == aID) {
         return &mUpdateTracks[i];
       }
     }
--- a/dom/media/mediasink/DecodedStream.cpp
+++ b/dom/media/mediasink/DecodedStream.cpp
@@ -187,22 +187,22 @@ DecodedStreamData::DecodedStreamData(
       mAbstractMainThread(aMainThread) {
   mStream->AddListener(mListener);
   TrackID audioTrack = TRACK_NONE;
   TrackID videoTrack = TRACK_NONE;
 
   // Initialize tracks.
   if (aInit.mInfo.HasAudio()) {
     audioTrack = aInit.mInfo.mAudio.mTrackId;
-    mStream->AddAudioTrack(audioTrack, aInit.mInfo.mAudio.mRate, 0,
+    mStream->AddAudioTrack(audioTrack, aInit.mInfo.mAudio.mRate,
                            new AudioSegment());
   }
   if (aInit.mInfo.HasVideo()) {
     videoTrack = aInit.mInfo.mVideo.mTrackId;
-    mStream->AddTrack(videoTrack, 0, new VideoSegment());
+    mStream->AddTrack(videoTrack, new VideoSegment());
   }
 
   mOutputStreamManager->Connect(mStream, audioTrack, videoTrack);
 }
 
 DecodedStreamData::~DecodedStreamData() {
   mOutputStreamManager->Disconnect();
   mStream->Destroy();
--- a/dom/media/webrtc/MediaEngineDefault.cpp
+++ b/dom/media/webrtc/MediaEngineDefault.cpp
@@ -170,17 +170,17 @@ nsresult MediaEngineDefaultVideoSource::
   MOZ_ASSERT(!mStream);
   MOZ_ASSERT(mTrackID == TRACK_NONE);
 
   {
     MutexAutoLock lock(mMutex);
     mStream = aStream;
     mTrackID = aTrackID;
   }
-  aStream->AddTrack(aTrackID, 0, new VideoSegment(),
+  aStream->AddTrack(aTrackID, new VideoSegment(),
                     SourceMediaStream::ADDTRACK_QUEUED);
   return NS_OK;
 }
 
 nsresult MediaEngineDefaultVideoSource::Start(
     const RefPtr<const AllocationHandle>& aHandle) {
   AssertIsOnOwningThread();
 
@@ -432,17 +432,17 @@ nsresult MediaEngineDefaultAudioSource::
 
   MOZ_ASSERT(mState == kAllocated);
   MOZ_ASSERT(!mStream);
   MOZ_ASSERT(mTrackID == TRACK_NONE);
 
   // AddAudioTrack will take ownership of segment
   mStream = aStream;
   mTrackID = aTrackID;
-  aStream->AddAudioTrack(aTrackID, aStream->GraphRate(), 0, new AudioSegment(),
+  aStream->AddAudioTrack(aTrackID, aStream->GraphRate(), new AudioSegment(),
                          SourceMediaStream::ADDTRACK_QUEUED);
   return NS_OK;
 }
 
 nsresult MediaEngineDefaultAudioSource::Start(
     const RefPtr<const AllocationHandle>& aHandle) {
   AssertIsOnOwningThread();
 
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
@@ -259,17 +259,17 @@ nsresult MediaEngineRemoteVideoSource::S
   }
 
   {
     MutexAutoLock lock(mMutex);
     mStream = aStream;
     mTrackID = aTrackID;
     mPrincipal = aPrincipal;
   }
-  aStream->AddTrack(aTrackID, 0, new VideoSegment(),
+  aStream->AddTrack(aTrackID, new VideoSegment(),
                     SourceMediaStream::ADDTRACK_QUEUED);
   return NS_OK;
 }
 
 nsresult MediaEngineRemoteVideoSource::Start(
     const RefPtr<const AllocationHandle>& aHandle) {
   LOG((__PRETTY_FUNCTION__));
   AssertIsOnOwningThread();
--- a/dom/media/webrtc/MediaEngineTabVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineTabVideoSource.cpp
@@ -201,17 +201,17 @@ nsresult MediaEngineTabVideoSource::SetT
   MOZ_ASSERT(mState == kAllocated);
 
   MOZ_ASSERT(!mStream);
   MOZ_ASSERT(mTrackID == TRACK_NONE);
   MOZ_ASSERT(aStream);
   MOZ_ASSERT(IsTrackIDExplicit(aTrackID));
   mStream = aStream;
   mTrackID = aTrackID;
-  mStream->AddTrack(mTrackID, 0, new VideoSegment());
+  mStream->AddTrack(mTrackID, new VideoSegment());
   return NS_OK;
 }
 
 nsresult MediaEngineTabVideoSource::Start(
     const RefPtr<const AllocationHandle>& aHandle) {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mState == kAllocated);
 
--- a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
+++ b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
@@ -522,17 +522,17 @@ nsresult MediaEngineWebRTCMicrophoneSour
   MOZ_ASSERT(mTrackID == TRACK_NONE);
   MOZ_ASSERT(mPrincipal == PRINCIPAL_HANDLE_NONE);
   mStream = aStream;
   mTrackID = aTrackID;
   mPrincipal = aPrincipal;
 
   AudioSegment* segment = new AudioSegment();
 
-  aStream->AddAudioTrack(aTrackID, aStream->GraphRate(), 0, segment,
+  aStream->AddAudioTrack(aTrackID, aStream->GraphRate(), segment,
                          SourceMediaStream::ADDTRACK_QUEUED);
 
   LOG(("Stream %p registered for microphone capture", aStream.get()));
   return NS_OK;
 }
 
 class StartStopMessage : public ControlMessage {
  public:
--- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
+++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
@@ -1665,20 +1665,19 @@ public:
   }
 
   void AddTrackToSource(uint32_t aRate = 0)
   {
     MOZ_ASSERT((aRate != 0 && mTrack->AsAudioStreamTrack()) ||
                mTrack->AsVideoStreamTrack());
 
     if (mTrack->AsAudioStreamTrack()) {
-      mSource->AddAudioTrack(
-          mTrackId, aRate, 0, new AudioSegment());
+      mSource->AddAudioTrack(mTrackId, aRate, new AudioSegment());
     } else if (mTrack->AsVideoStreamTrack()) {
-      mSource->AddTrack(mTrackId, 0, new VideoSegment());
+      mSource->AddTrack(mTrackId, new VideoSegment());
     }
     MOZ_LOG(gMediaPipelineLog, LogLevel::Debug,
             ("GenericReceiveListener added %s track %d (%p) to stream %p",
              mTrack->AsAudioStreamTrack() ? "audio" : "video",
              mTrackId,
              mTrack.get(),
              mSource.get()));