LCOV - code coverage report
Current view: top level - dom/media - StreamTracks.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 106 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 33 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
       4             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #ifndef MOZILLA_STREAMTRACKS_H_
       7             : #define MOZILLA_STREAMTRACKS_H_
       8             : 
       9             : #include "MediaSegment.h"
      10             : #include "nsAutoPtr.h"
      11             : 
      12             : namespace mozilla {
      13             : 
      14             : /**
      15             :  * Unique ID for track within a StreamTracks. Tracks from different
      16             :  * StreamTrackss may have the same ID; this matters when appending StreamTrackss,
      17             :  * since tracks with the same ID are matched. Only IDs greater than 0 are allowed.
      18             :  */
      19             : typedef int32_t TrackID;
      20             : const TrackID TRACK_NONE = 0;
      21             : const TrackID TRACK_INVALID = -1;
      22             : const TrackID TRACK_ANY = -2;
      23             : 
      24           0 : inline bool IsTrackIDExplicit(const TrackID& aId) {
      25           0 :   return aId > TRACK_NONE;
      26             : }
      27             : 
      28           0 : inline TrackTicks RateConvertTicksRoundDown(TrackRate aOutRate,
      29             :                                             TrackRate aInRate,
      30             :                                             TrackTicks aTicks)
      31             : {
      32           0 :   NS_ASSERTION(0 < aOutRate && aOutRate <= TRACK_RATE_MAX, "Bad out rate");
      33           0 :   NS_ASSERTION(0 < aInRate && aInRate <= TRACK_RATE_MAX, "Bad in rate");
      34           0 :   NS_ASSERTION(0 <= aTicks && aTicks <= TRACK_TICKS_MAX, "Bad ticks");
      35           0 :   return (aTicks * aOutRate) / aInRate;
      36             : }
      37           0 : inline TrackTicks RateConvertTicksRoundUp(TrackRate aOutRate,
      38             :                                           TrackRate aInRate, TrackTicks aTicks)
      39             : {
      40           0 :   NS_ASSERTION(0 < aOutRate && aOutRate <= TRACK_RATE_MAX, "Bad out rate");
      41           0 :   NS_ASSERTION(0 < aInRate && aInRate <= TRACK_RATE_MAX, "Bad in rate");
      42           0 :   NS_ASSERTION(0 <= aTicks && aTicks <= TRACK_TICKS_MAX, "Bad ticks");
      43           0 :   return (aTicks * aOutRate + aInRate - 1) / aInRate;
      44             : }
      45             : 
      46             : /**
      47             :  * This object contains the decoded data for a stream's tracks.
      48             :  * A StreamTracks can be appended to. Logically a StreamTracks only gets longer,
      49             :  * but we also have the ability to "forget" data before a certain time that
      50             :  * we know won't be used again. (We prune a whole number of seconds internally.)
      51             :  *
      52             :  * StreamTrackss should only be used from one thread at a time.
      53             :  *
      54             :  * A StreamTracks has a set of tracks that can be of arbitrary types ---
      55             :  * the data for each track is a MediaSegment. The set of tracks can vary
      56             :  * over the timeline of the StreamTracks.
      57             :  */
      58             : class StreamTracks
      59             : {
      60             : public:
      61             :   /**
      62             :    * Every track has a start time --- when it started in the StreamTracks.
      63             :    * It has an end flag; when false, no end point is known; when true,
      64             :    * the track ends when the data we have for the track runs out.
      65             :    * Tracks have a unique ID assigned at creation. This allows us to identify
      66             :    * the same track across StreamTrackss. A StreamTracks should never have
      67             :    * two tracks with the same ID (even if they don't overlap in time).
      68             :    * TODO Tracks can also be enabled and disabled over time.
      69             :    * Takes ownership of aSegment.
      70             :    */
      71             :   class Track final
      72             :   {
      73           0 :     Track(TrackID aID, StreamTime aStart, MediaSegment* aSegment)
      74           0 :       : mStart(aStart),
      75             :         mSegment(aSegment),
      76             :         mID(aID),
      77           0 :         mEnded(false)
      78             :     {
      79           0 :       MOZ_COUNT_CTOR(Track);
      80             : 
      81           0 :       NS_ASSERTION(aID > TRACK_NONE, "Bad track ID");
      82           0 :       NS_ASSERTION(0 <= aStart && aStart <= aSegment->GetDuration(), "Bad start position");
      83           0 :     }
      84             : 
      85             :   public:
      86           0 :     ~Track()
      87           0 :     {
      88           0 :       MOZ_COUNT_DTOR(Track);
      89           0 :     }
      90             : 
      91           0 :     template <class T> T* Get() const
      92             :     {
      93           0 :       if (mSegment->GetType() == T::StaticType()) {
      94           0 :         return static_cast<T*>(mSegment.get());
      95             :       }
      96           0 :       return nullptr;
      97             :     }
      98             : 
      99           0 :     MediaSegment* GetSegment() const { return mSegment; }
     100           0 :     TrackID GetID() const { return mID; }
     101           0 :     bool IsEnded() const { return mEnded; }
     102             :     StreamTime GetStart() const { return mStart; }
     103           0 :     StreamTime GetEnd() const { return mSegment->GetDuration(); }
     104           0 :     MediaSegment::Type GetType() const { return mSegment->GetType(); }
     105             : 
     106           0 :     void SetEnded() { mEnded = true; }
     107             :     void AppendFrom(Track* aTrack)
     108             :     {
     109             :       NS_ASSERTION(!mEnded, "Can't append to ended track");
     110             :       NS_ASSERTION(aTrack->mID == mID, "IDs must match");
     111             :       NS_ASSERTION(aTrack->mStart == 0, "Source track must start at zero");
     112             :       NS_ASSERTION(aTrack->mSegment->GetType() == GetType(), "Track types must match");
     113             : 
     114             :       mSegment->AppendFrom(aTrack->mSegment);
     115             :       mEnded = aTrack->mEnded;
     116             :     }
     117             :     MediaSegment* RemoveSegment()
     118             :     {
     119             :       return mSegment.forget();
     120             :     }
     121           0 :     void ForgetUpTo(StreamTime aTime)
     122             :     {
     123           0 :       mSegment->ForgetUpTo(aTime);
     124           0 :     }
     125             :     void FlushAfter(StreamTime aNewEnd)
     126             :     {
     127             :       // Forget everything after a given endpoint
     128             :       // a specified amount
     129             :       mSegment->FlushAfter(aNewEnd);
     130             :     }
     131             : 
     132           0 :     size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
     133             :     {
     134           0 :       size_t amount = aMallocSizeOf(this);
     135           0 :       if (mSegment) {
     136           0 :         amount += mSegment->SizeOfIncludingThis(aMallocSizeOf);
     137             :       }
     138           0 :       return amount;
     139             :     }
     140             : 
     141             :   private:
     142             :     friend class StreamTracks;
     143             : 
     144             :     // Start offset is in ticks at rate mRate
     145             :     StreamTime mStart;
     146             :     // The segment data starts at the start of the owning StreamTracks, i.e.,
     147             :     // there's mStart silence/no video at the beginning.
     148             :     nsAutoPtr<MediaSegment> mSegment;
     149             :     // Unique ID
     150             :     TrackID mID;
     151             :     // True when the track ends with the data in mSegment
     152             :     bool mEnded;
     153             :   };
     154             : 
     155             :   class MOZ_STACK_CLASS CompareTracksByID final
     156             :   {
     157             :   public:
     158           0 :     bool Equals(Track* aA, Track* aB) const {
     159           0 :       return aA->GetID() == aB->GetID();
     160             :     }
     161           0 :     bool LessThan(Track* aA, Track* aB) const {
     162           0 :       return aA->GetID() < aB->GetID();
     163             :     }
     164             :   };
     165             : 
     166           0 :   StreamTracks()
     167           0 :     : mGraphRate(0)
     168             :     , mTracksKnownTime(0)
     169             :     , mForgottenTime(0)
     170             :     , mTracksDirty(false)
     171             : #ifdef DEBUG
     172           0 :     , mGraphRateIsSet(false)
     173             : #endif
     174             :   {
     175           0 :     MOZ_COUNT_CTOR(StreamTracks);
     176           0 :   }
     177           0 :   ~StreamTracks()
     178           0 :   {
     179           0 :     MOZ_COUNT_DTOR(StreamTracks);
     180           0 :   }
     181             : 
     182           0 :   size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
     183             :   {
     184           0 :     size_t amount = 0;
     185           0 :     amount += mTracks.ShallowSizeOfExcludingThis(aMallocSizeOf);
     186           0 :     for (size_t i = 0; i < mTracks.Length(); i++) {
     187           0 :       amount += mTracks[i]->SizeOfIncludingThis(aMallocSizeOf);
     188             :     }
     189           0 :     return amount;
     190             :   }
     191             : 
     192             :   /**
     193             :    * Initialize the graph rate for use in calculating StreamTimes from track
     194             :    * ticks.  Called when a MediaStream's graph pointer is initialized.
     195             :    */
     196           0 :   void InitGraphRate(TrackRate aGraphRate)
     197             :   {
     198           0 :     mGraphRate = aGraphRate;
     199             : #if DEBUG
     200           0 :     MOZ_ASSERT(!mGraphRateIsSet);
     201           0 :     mGraphRateIsSet = true;
     202             : #endif
     203           0 :   }
     204             : 
     205           0 :   TrackRate GraphRate() const
     206             :   {
     207           0 :     MOZ_ASSERT(mGraphRateIsSet);
     208           0 :     return mGraphRate;
     209             :   }
     210             : 
     211             :   /**
     212             :    * Takes ownership of aSegment. Don't do this while iterating, or while
     213             :    * holding a Track reference.
     214             :    * aSegment must have aStart worth of null data.
     215             :    */
     216           0 :   Track& AddTrack(TrackID aID, StreamTime aStart, MediaSegment* aSegment)
     217             :   {
     218           0 :     NS_ASSERTION(!FindTrack(aID), "Track with this ID already exists");
     219             : 
     220           0 :     Track* track = new Track(aID, aStart, aSegment);
     221           0 :     mTracks.InsertElementSorted(track, CompareTracksByID());
     222           0 :     mTracksDirty = true;
     223             : 
     224           0 :     if (mTracksKnownTime == STREAM_TIME_MAX) {
     225             :       // There exists code like
     226             :       // http://mxr.mozilla.org/mozilla-central/source/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp?rev=96b197deb91e&mark=1292-1297#1292
     227           0 :       NS_WARNING("Adding track to StreamTracks that should have no more tracks");
     228             :     } else {
     229           0 :       NS_ASSERTION(mTracksKnownTime <= aStart, "Start time too early");
     230             :     }
     231           0 :     return *track;
     232             :   }
     233             : 
     234           0 :   void AdvanceKnownTracksTime(StreamTime aKnownTime)
     235             :   {
     236           0 :     NS_ASSERTION(aKnownTime >= mTracksKnownTime, "Can't move tracks-known time earlier");
     237           0 :     mTracksKnownTime = aKnownTime;
     238           0 :   }
     239             : 
     240             :   /**
     241             :    * The end time for the StreamTracks is the latest time for which we have
     242             :    * data for all tracks that haven't ended by that time.
     243             :    */
     244             :   StreamTime GetEnd() const;
     245             : 
     246             :   /**
     247             :    * Returns the earliest time >= 0 at which all tracks have ended
     248             :    * and all their data has been played out and no new tracks can be added,
     249             :    * or STREAM_TIME_MAX if there is no such time.
     250             :    */
     251             :   StreamTime GetAllTracksEnd() const;
     252             : 
     253             : #ifdef DEBUG
     254             :   void DumpTrackInfo() const;
     255             : #endif
     256             : 
     257             :   Track* FindTrack(TrackID aID);
     258             : 
     259             :   class MOZ_STACK_CLASS TrackIter final
     260             :   {
     261             :   public:
     262             :     /**
     263             :      * Iterate through the tracks of aBuffer in order of ID.
     264             :      */
     265           0 :     explicit TrackIter(const StreamTracks& aBuffer) :
     266           0 :       mBuffer(&aBuffer.mTracks), mIndex(0), mMatchType(false) {}
     267             :     /**
     268             :      * Iterate through the tracks of aBuffer with type aType, in order of ID.
     269             :      */
     270           0 :     TrackIter(const StreamTracks& aBuffer, MediaSegment::Type aType) :
     271           0 :       mBuffer(&aBuffer.mTracks), mIndex(0), mType(aType), mMatchType(true) { FindMatch(); }
     272           0 :     bool IsEnded() { return mIndex >= mBuffer->Length(); }
     273           0 :     void Next()
     274             :     {
     275           0 :       ++mIndex;
     276           0 :       FindMatch();
     277           0 :     }
     278           0 :     Track* get() { return mBuffer->ElementAt(mIndex); }
     279           0 :     Track& operator*() { return *mBuffer->ElementAt(mIndex); }
     280           0 :     Track* operator->() { return mBuffer->ElementAt(mIndex); }
     281             :   private:
     282           0 :     void FindMatch()
     283             :     {
     284           0 :       if (!mMatchType)
     285           0 :         return;
     286           0 :       while (mIndex < mBuffer->Length() &&
     287           0 :              mBuffer->ElementAt(mIndex)->GetType() != mType) {
     288           0 :         ++mIndex;
     289             :       }
     290             :     }
     291             : 
     292             :     const nsTArray<nsAutoPtr<Track> >* mBuffer;
     293             :     uint32_t mIndex;
     294             :     MediaSegment::Type mType;
     295             :     bool mMatchType;
     296             :   };
     297             :   friend class TrackIter;
     298             : 
     299             :   /**
     300             :    * Forget stream data before aTime; they will no longer be needed.
     301             :    * Also can forget entire tracks that have ended at or before aTime.
     302             :    * Can't be used to forget beyond GetEnd().
     303             :    */
     304             :   void ForgetUpTo(StreamTime aTime);
     305             :   /**
     306             :    * Clears out all Tracks and the data they are holding.
     307             :    * MediaStreamGraph calls this during forced shutdown.
     308             :    */
     309             :   void Clear();
     310             :   /**
     311             :    * Returns the latest time passed to ForgetUpTo.
     312             :    */
     313           0 :   StreamTime GetForgottenDuration()
     314             :   {
     315           0 :     return mForgottenTime;
     316             :   }
     317             : 
     318           0 :   bool GetAndResetTracksDirty()
     319             :   {
     320           0 :     if (!mTracksDirty) {
     321           0 :       return false;
     322             :     }
     323             : 
     324           0 :     mTracksDirty = false;
     325           0 :     return true;
     326             :   }
     327             : 
     328             : protected:
     329             :   TrackRate mGraphRate; // StreamTime per second
     330             :   // Any new tracks added will start at or after this time. In other words, the track
     331             :   // list is complete and correct for all times less than this time.
     332             :   StreamTime mTracksKnownTime;
     333             :   StreamTime mForgottenTime;
     334             : 
     335             : private:
     336             :   // All known tracks for this StreamTracks
     337             :   nsTArray<nsAutoPtr<Track>> mTracks;
     338             :   bool mTracksDirty;
     339             : 
     340             : #ifdef DEBUG
     341             :   bool mGraphRateIsSet;
     342             : #endif
     343             : };
     344             : 
     345             : } // namespace mozilla
     346             : 
     347             : #endif /* MOZILLA_STREAMTRACKS_H_ */
     348             : 

Generated by: LCOV version 1.13