Bug 1256079 - Allow direct track listeners for tracks that don't exist yet. r?jesup draft bug_1256079
authorAndreas Pehrson <pehrsons@gmail.com>
Tue, 27 Sep 2016 19:13:20 +0200
changeset 418073 0b1427e3a467551cd4a1ade6b0c58116250a3c57
parent 417649 c55bcb7c777ea09431b4d16903ed079ae5632648
child 532250 8b9189722acdd290bbcee18f368e7b222cef2764
push id30579
push userbmo:pehrson@telenordigital.com
push dateTue, 27 Sep 2016 17:15:25 +0000
reviewersjesup
bugs1256079
milestone52.0a1
Bug 1256079 - Allow direct track listeners for tracks that don't exist yet. r?jesup This will cover potential bugs where the direct track listener was added before the track. Worth noting also that we could end up in a limbo state if we add the listener to a track that doesn't exist anymore (it ended!). MozReview-Commit-ID: FpSwU2ReCpm
dom/media/MediaStreamGraph.cpp
dom/media/MediaStreamGraph.h
dom/media/MediaStreamListener.h
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -261,16 +261,28 @@ MediaStreamGraphImpl::ExtractPendingInpu
 
         data->mEndOfFlushedData += segment->GetDuration();
         aStream->mTracks.AddTrack(data->mID, data->mStart, 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;
+
+        for (int32_t i = aStream->mPendingDirectTrackListeners.Length() - 1;
+               i >= 0; i--) {
+          if (aStream->mPendingDirectTrackListeners[i].mTrackID != data->mID) {
+            continue;
+          }
+
+          RefPtr<DirectMediaStreamTrackListener> l =
+            aStream->mPendingDirectTrackListeners[i].mListener;
+          aStream->mPendingDirectTrackListeners.RemoveElementAt(i);
+          aStream->AddDirectTrackListenerImpl(l.forget(), data->mID);
+        }
       } else if (data->mData->GetDuration() > 0) {
         MediaSegment* dest = aStream->mTracks.FindTrack(data->mID)->GetSegment();
         STREAM_LOG(LogLevel::Verbose, ("SourceMediaStream %p track %d, advancing end from %lld to %lld",
                                     aStream, data->mID,
                                     int64_t(dest->GetDuration()),
                                     int64_t(dest->GetDuration() + data->mData->GetDuration())));
         data->mEndOfFlushedData += data->mData->GetDuration();
         dest->AppendFrom(data->mData);
@@ -2923,20 +2935,23 @@ SourceMediaStream::AddDirectTrackListene
 
       TrackBound<DirectMediaStreamTrackListener>* sourceListener =
         mDirectTrackListeners.AppendElement();
       sourceListener->mListener = listener;
       sourceListener->mTrackID = aTrackID;
     }
   }
   if (!found) {
-    STREAM_LOG(LogLevel::Warning, ("Couldn't find source track for direct track listener %p",
-                                   listener.get()));
-    listener->NotifyDirectListenerInstalled(
-      DirectMediaStreamTrackListener::InstallationResult::TRACK_NOT_FOUND_AT_SOURCE);
+    STREAM_LOG(LogLevel::Info, ("Couldn't find source track for direct track "
+                                "listener %p. Waiting for the track to appear.",
+                                listener.get()));
+    TrackBound<DirectMediaStreamTrackListener>* pendingListener =
+      mPendingDirectTrackListeners.AppendElement();
+    pendingListener->mListener = listener;
+    pendingListener->mTrackID = aTrackID;
     return;
   }
   if (!isAudio && !isVideo) {
     STREAM_LOG(LogLevel::Warning, ("Source track for direct track listener %p is unknown",
                                    listener.get()));
     // It is not a video or audio track.
     MOZ_ASSERT(true);
     return;
--- a/dom/media/MediaStreamGraph.h
+++ b/dom/media/MediaStreamGraph.h
@@ -921,16 +921,19 @@ protected:
   // This time stamp will be updated in adding and blocked SourceMediaStream,
   // |AddStreamGraphThread| and |AdvanceTimeVaryingValuesToCurrentTime| in
   // particularly.
   TimeStamp mStreamTracksStartTimeStamp;
   nsTArray<TrackData> mUpdateTracks;
   nsTArray<TrackData> mPendingTracks;
   nsTArray<RefPtr<DirectMediaStreamListener>> mDirectListeners;
   nsTArray<TrackBound<DirectMediaStreamTrackListener>> mDirectTrackListeners;
+  // Direct track listeners that we don't have a track for yet. We'll move them
+  // to mDirectTrackListeners when their corresponding track becomes available.
+  nsTArray<TrackBound<DirectMediaStreamTrackListener>> mPendingDirectTrackListeners;
   bool mPullEnabled;
   bool mUpdateFinished;
   bool mNeedsMixing;
 };
 
 /**
  * The blocking mode decides how a track should be blocked in a MediaInputPort.
  */
--- a/dom/media/MediaStreamListener.h
+++ b/dom/media/MediaStreamListener.h
@@ -234,32 +234,27 @@ public:
   virtual void NotifyRealtimeTrackData(MediaStreamGraph* aGraph,
                                        StreamTime aTrackOffset,
                                        const MediaSegment& aMedia) {}
 
   /**
    * When a direct listener is processed for installation by the
    * MediaStreamGraph it will be notified with whether the installation was
    * successful or not. The results of this installation are the following:
-   * TRACK_NOT_FOUND_AT_SOURCE
-   *    We found the source stream of media data for this track, but the track
-   *    didn't exist. This should only happen if you try to install the listener
-   *    directly to a SourceMediaStream that doesn't contain the given TrackID.
    * STREAM_NOT_SUPPORTED
    *    While looking for the data source of this track, we found a MediaStream
    *    that is not a SourceMediaStream or a TrackUnionStream.
    * ALREADY_EXIST
    *    This DirectMediaStreamTrackListener already exists in the
    *    SourceMediaStream.
    * SUCCESS
    *    Installation was successful and this listener will start receiving
    *    NotifyRealtimeData on the next AppendToTrack().
    */
   enum class InstallationResult {
-    TRACK_NOT_FOUND_AT_SOURCE,
     TRACK_TYPE_NOT_SUPPORTED,
     STREAM_NOT_SUPPORTED,
     ALREADY_EXISTS,
     SUCCESS
   };
   virtual void NotifyDirectListenerInstalled(InstallationResult aResult) {}
   virtual void NotifyDirectListenerUninstalled() {}