Bug 1173656 - Disallow TrackID reuse in TrackUnionStream. r=roc
authorAndreas Pehrson <pehrsons@gmail.com>
Fri, 12 Jun 2015 18:56:27 +0800
changeset 279895 a726ca79e03d5c82f88f10c5c19cbc1db84118f3
parent 279894 e44f689c37565d889ebf96e70cfd891d9c992821
child 279896 e815b262f9ac0f747a09f36ddeca39540bb89b45
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-beta@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs1173656
milestone41.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 1173656 - Disallow TrackID reuse in TrackUnionStream. r=roc
dom/media/TrackUnionStream.cpp
dom/media/TrackUnionStream.h
--- a/dom/media/TrackUnionStream.cpp
+++ b/dom/media/TrackUnionStream.cpp
@@ -41,17 +41,17 @@ namespace mozilla {
 #ifdef STREAM_LOG
 #undef STREAM_LOG
 #endif
 
 PRLogModuleInfo* gTrackUnionStreamLog;
 #define STREAM_LOG(type, msg) MOZ_LOG(gTrackUnionStreamLog, type, msg)
 
 TrackUnionStream::TrackUnionStream(DOMMediaStream* aWrapper) :
-  ProcessedMediaStream(aWrapper)
+  ProcessedMediaStream(aWrapper), mNextAvailableTrackID(1)
 {
   if (!gTrackUnionStreamLog) {
     gTrackUnionStreamLog = PR_NewLogModule("TrackUnionStream");
   }
 }
 
   void TrackUnionStream::RemoveInput(MediaInputPort* aPort)
   {
@@ -156,33 +156,33 @@ TrackUnionStream::TrackUnionStream(DOMMe
           SetTrackEnabled(mTrackMap[i].mInputTrackID, aEnabled);
       }
     }
   }
 
   uint32_t TrackUnionStream::AddTrack(MediaInputPort* aPort, StreamBuffer::Track* aTrack,
                     GraphTime aFrom)
   {
-    // Use the ID of the source track if it's not already assigned to a track,
-    // otherwise allocate a new unique ID.
     TrackID id = aTrack->GetID();
-    TrackID maxTrackID = 0;
-    for (uint32_t i = 0; i < mTrackMap.Length(); ++i) {
-      TrackID outID = mTrackMap[i].mOutputTrackID;
-      maxTrackID = std::max(maxTrackID, outID);
-    }
-    // Note: we might have removed it here, but it might still be in the
-    // StreamBuffer if the TrackUnionStream sees its input stream flip from
-    // A to B, where both A and B have a track with the same ID
-    while (1) {
-      // search until we find one not in use here, and not in mBuffer
-      if (!mBuffer.FindTrack(id)) {
-        break;
+    if (id > mNextAvailableTrackID &&
+       mUsedTracks.BinaryIndexOf(id) == mUsedTracks.NoIndex) {
+      // Input id available. Mark it used in mUsedTracks.
+      mUsedTracks.InsertElementSorted(id);
+    } else {
+      // Input id taken, allocate a new one.
+      id = mNextAvailableTrackID;
+
+      // Update mNextAvailableTrackID and prune any mUsedTracks members it now
+      // covers.
+      while (1) {
+        if (!mUsedTracks.RemoveElementSorted(++mNextAvailableTrackID)) {
+          // Not in use. We're done.
+          break;
+        }
       }
-      id = ++maxTrackID;
     }
 
     // Round up the track start time so the track, if anything, starts a
     // little later than the true time. This means we'll have enough
     // samples in our input stream to go just beyond the destination time.
     StreamTime outputStart = GraphTimeToStreamTime(aFrom);
 
     nsAutoPtr<MediaSegment> segment;
--- a/dom/media/TrackUnionStream.h
+++ b/dom/media/TrackUnionStream.h
@@ -45,21 +45,30 @@ protected:
     // when a finished track is forgotten.) When we need a Track*,
     // we call StreamBuffer::FindTrack, which will return null if
     // the track has been deleted.
     TrackID mInputTrackID;
     TrackID mOutputTrackID;
     nsAutoPtr<MediaSegment> mSegment;
   };
 
+  // Add the track to this stream, retaining its TrackID if it has never
+  // been previously used in this stream, allocating a new TrackID otherwise.
   uint32_t AddTrack(MediaInputPort* aPort, StreamBuffer::Track* aTrack,
                     GraphTime aFrom);
   void EndTrack(uint32_t aIndex);
   void CopyTrackData(StreamBuffer::Track* aInputTrack,
                      uint32_t aMapIndex, GraphTime aFrom, GraphTime aTo,
                      bool* aOutputTrackFinished);
 
   nsTArray<TrackMapEntry> mTrackMap;
+
+  // The next available TrackID, starting at 1 and progressing upwards.
+  // All TrackIDs in [1, mNextAvailableTrackID) have implicitly been used.
+  TrackID mNextAvailableTrackID;
+
+  // Sorted array of used TrackIDs that require manual tracking.
+  nsTArray<TrackID> mUsedTracks;
 };
 
 }
 
 #endif /* MOZILLA_MEDIASTREAMGRAPH_H_ */