LCOV - code coverage report
Current view: top level - dom/media/ogg - OggDemuxer.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 24 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 8 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             : /* vim:set ts=2 sw=2 sts=2 et cindent: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : #if !defined(OggDemuxer_h_)
       7             : #define OggDemuxer_h_
       8             : 
       9             : #include "nsTArray.h"
      10             : #include "MediaDataDemuxer.h"
      11             : #include "OggCodecState.h"
      12             : #include "OggCodecStore.h"
      13             : #include "MediaMetadataManager.h"
      14             : 
      15             : namespace mozilla {
      16             : 
      17             : class OggTrackDemuxer;
      18             : 
      19             : class OggDemuxer : public MediaDataDemuxer
      20             : {
      21             : public:
      22             :   explicit OggDemuxer(MediaResource* aResource);
      23             : 
      24             :   RefPtr<InitPromise> Init() override;
      25             : 
      26             :   bool HasTrackType(TrackInfo::TrackType aType) const override;
      27             : 
      28             :   uint32_t GetNumberTracks(TrackInfo::TrackType aType) const override;
      29             : 
      30             :   already_AddRefed<MediaTrackDemuxer> GetTrackDemuxer(TrackInfo::TrackType aType,
      31             :                                                       uint32_t aTrackNumber) override;
      32             : 
      33             :   bool IsSeekable() const override;
      34             : 
      35             :   UniquePtr<EncryptionInfo> GetCrypto() override;
      36             : 
      37             :   // Set the events to notify when chaining is encountered.
      38             :   void SetChainingEvents(TimedMetadataEventProducer* aMetadataEvent,
      39             :                          MediaEventProducer<void>* aOnSeekableEvent);
      40             : 
      41             : private:
      42             : 
      43             :   // helpers for friend OggTrackDemuxer
      44             :   UniquePtr<TrackInfo> GetTrackInfo(TrackInfo::TrackType aType, size_t aTrackNumber) const;
      45             : 
      46             :   struct nsAutoOggSyncState {
      47           0 :     nsAutoOggSyncState() {
      48           0 :       ogg_sync_init(&mState);
      49           0 :     }
      50           0 :     ~nsAutoOggSyncState() {
      51           0 :       ogg_sync_clear(&mState);
      52           0 :     }
      53             :     ogg_sync_state mState;
      54             :   };
      55             :   media::TimeIntervals GetBuffered(TrackInfo::TrackType aType);
      56             :   void FindStartTime(int64_t& aOutStartTime);
      57             :   void FindStartTime(TrackInfo::TrackType, int64_t& aOutStartTime);
      58             : 
      59             :   nsresult SeekInternal(TrackInfo::TrackType aType, const media::TimeUnit& aTarget);
      60             : 
      61             :   // Seeks to the keyframe preceding the target time using available
      62             :   // keyframe indexes.
      63             :   enum IndexedSeekResult
      64             :   {
      65             :     SEEK_OK,          // Success.
      66             :     SEEK_INDEX_FAIL,  // Failure due to no index, or invalid index.
      67             :     SEEK_FATAL_ERROR  // Error returned by a stream operation.
      68             :   };
      69             :   IndexedSeekResult SeekToKeyframeUsingIndex(TrackInfo::TrackType aType, int64_t aTarget);
      70             : 
      71             :   // Rolls back a seek-using-index attempt, returning a failure error code.
      72             :   IndexedSeekResult RollbackIndexedSeek(TrackInfo::TrackType aType, int64_t aOffset);
      73             : 
      74             :   // Represents a section of contiguous media, with a start and end offset,
      75             :   // and the timestamps of the start and end of that range, that is cached.
      76             :   // Used to denote the extremities of a range in which we can seek quickly
      77             :   // (because it's cached).
      78             :   class SeekRange
      79             :   {
      80             :   public:
      81           0 :     SeekRange()
      82           0 :       : mOffsetStart(0)
      83             :       , mOffsetEnd(0)
      84             :       , mTimeStart(0)
      85           0 :       , mTimeEnd(0)
      86           0 :     {}
      87             : 
      88           0 :     SeekRange(int64_t aOffsetStart,
      89             :               int64_t aOffsetEnd,
      90             :               int64_t aTimeStart,
      91             :               int64_t aTimeEnd)
      92           0 :       : mOffsetStart(aOffsetStart)
      93             :       , mOffsetEnd(aOffsetEnd)
      94             :       , mTimeStart(aTimeStart)
      95           0 :       , mTimeEnd(aTimeEnd)
      96           0 :     {}
      97             : 
      98           0 :     bool IsNull() const {
      99           0 :       return mOffsetStart == 0 &&
     100           0 :              mOffsetEnd == 0 &&
     101           0 :              mTimeStart == 0 &&
     102           0 :              mTimeEnd == 0;
     103             :     }
     104             : 
     105             :     int64_t mOffsetStart, mOffsetEnd; // in bytes.
     106             :     int64_t mTimeStart, mTimeEnd; // in usecs.
     107             :   };
     108             : 
     109             :   nsresult GetSeekRanges(TrackInfo::TrackType aType, nsTArray<SeekRange>& aRanges);
     110             :   SeekRange SelectSeekRange(TrackInfo::TrackType aType,
     111             :                             const nsTArray<SeekRange>& ranges,
     112             :                             int64_t aTarget,
     113             :                             int64_t aStartTime,
     114             :                             int64_t aEndTime,
     115             :                             bool aExact);
     116             : 
     117             :   // Seeks to aTarget usecs in the buffered range aRange using bisection search,
     118             :   // or to the keyframe prior to aTarget if we have video. aAdjustedTarget is
     119             :   // an adjusted version of the target used to account for Opus pre-roll, if
     120             :   // necessary. aStartTime must be the presentation time at the start of media,
     121             :   // and aEndTime the time at end of media. aRanges must be the time/byte ranges
     122             :   // buffered in the media cache as per GetSeekRanges().
     123             :   nsresult SeekInBufferedRange(TrackInfo::TrackType aType,
     124             :                                int64_t aTarget,
     125             :                                int64_t aAdjustedTarget,
     126             :                                int64_t aStartTime,
     127             :                                int64_t aEndTime,
     128             :                                const nsTArray<SeekRange>& aRanges,
     129             :                                const SeekRange& aRange);
     130             : 
     131             :   // Seeks to before aTarget usecs in media using bisection search. If the media
     132             :   // has video, this will seek to before the keyframe required to render the
     133             :   // media at aTarget. Will use aRanges in order to narrow the bisection
     134             :   // search space. aStartTime must be the presentation time at the start of
     135             :   // media, and aEndTime the time at end of media. aRanges must be the time/byte
     136             :   // ranges buffered in the media cache as per GetSeekRanges().
     137             :   nsresult SeekInUnbuffered(TrackInfo::TrackType aType,
     138             :                             int64_t aTarget,
     139             :                             int64_t aStartTime,
     140             :                             int64_t aEndTime,
     141             :                             const nsTArray<SeekRange>& aRanges);
     142             : 
     143             :   // Performs a seek bisection to move the media stream's read cursor to the
     144             :   // last ogg page boundary which has end time before aTarget usecs on both the
     145             :   // Theora and Vorbis bitstreams. Limits its search to data inside aRange;
     146             :   // i.e. it will only read inside of the aRange's start and end offsets.
     147             :   // aFuzz is the number of usecs of leniency we'll allow; we'll terminate the
     148             :   // seek when we land in the range (aTime - aFuzz, aTime) usecs.
     149             :   nsresult SeekBisection(TrackInfo::TrackType aType,
     150             :                          int64_t aTarget,
     151             :                          const SeekRange& aRange,
     152             :                          uint32_t aFuzz);
     153             : 
     154             :   // Chunk size to read when reading Ogg files. Average Ogg page length
     155             :   // is about 4300 bytes, so we read the file in chunks larger than that.
     156             :   static const int PAGE_STEP = 8192;
     157             : 
     158             :   enum PageSyncResult
     159             :   {
     160             :     PAGE_SYNC_ERROR = 1,
     161             :     PAGE_SYNC_END_OF_RANGE= 2,
     162             :     PAGE_SYNC_OK = 3
     163             :   };
     164             :   static PageSyncResult PageSync(MediaResourceIndex* aResource,
     165             :                                  ogg_sync_state* aState,
     166             :                                  bool aCachedDataOnly,
     167             :                                  int64_t aOffset,
     168             :                                  int64_t aEndOffset,
     169             :                                  ogg_page* aPage,
     170             :                                  int& aSkippedBytes);
     171             : 
     172             :   // Demux next Ogg packet
     173             :   ogg_packet* GetNextPacket(TrackInfo::TrackType aType);
     174             : 
     175             :   nsresult Reset(TrackInfo::TrackType aType);
     176             : 
     177             :   static const nsString GetKind(const nsCString& aRole);
     178             :   static void InitTrack(MessageField* aMsgInfo,
     179             :                       TrackInfo* aInfo,
     180             :                       bool aEnable);
     181             : 
     182             :   // Really private!
     183             :   ~OggDemuxer();
     184             : 
     185             :   // Read enough of the file to identify track information and header
     186             :   // packets necessary for decoding to begin.
     187             :   nsresult ReadMetadata();
     188             : 
     189             :   // Read a page of data from the Ogg file. Returns true if a page has been
     190             :   // read, false if the page read failed or end of file reached.
     191             :   bool ReadOggPage(TrackInfo::TrackType aType, ogg_page* aPage);
     192             : 
     193             :   // Send a page off to the individual streams it belongs to.
     194             :   // Reconstructed packets, if any are ready, will be available
     195             :   // on the individual OggCodecStates.
     196             :   nsresult DemuxOggPage(TrackInfo::TrackType aType, ogg_page* aPage);
     197             : 
     198             :   // Read data and demux until a packet is available on the given stream state
     199             :   void DemuxUntilPacketAvailable(TrackInfo::TrackType aType, OggCodecState* aState);
     200             : 
     201             :   // Reads and decodes header packets for aState, until either header decode
     202             :   // fails, or is complete. Initializes the codec state before returning.
     203             :   // Returns true if reading headers and initializtion of the stream
     204             :   // succeeds.
     205             :   bool ReadHeaders(TrackInfo::TrackType aType, OggCodecState* aState);
     206             : 
     207             :   // Reads the next link in the chain.
     208             :   bool ReadOggChain(const media::TimeUnit& aLastEndTime);
     209             : 
     210             :   // Set this media as being a chain and notifies the state machine that the
     211             :   // media is no longer seekable.
     212             :   void SetChained();
     213             : 
     214             :   // Fills aTracks with the serial numbers of each active stream, for use by
     215             :   // various SkeletonState functions.
     216             :   void BuildSerialList(nsTArray<uint32_t>& aTracks);
     217             : 
     218             :   // Setup target bitstreams for decoding.
     219             :   void SetupTarget(OggCodecState** aSavedState, OggCodecState* aNewState);
     220             :   void SetupTargetSkeleton();
     221             :   void SetupMediaTracksInfo(const nsTArray<uint32_t>& aSerials);
     222             :   void FillTags(TrackInfo* aInfo, MetadataTags* aTags);
     223             : 
     224             :   // Compute an ogg page's checksum
     225             :   ogg_uint32_t GetPageChecksum(ogg_page* aPage);
     226             : 
     227             :   // Get the end time of aEndOffset. This is the playback position we'd reach
     228             :   // after playback finished at aEndOffset.
     229             :   int64_t RangeEndTime(TrackInfo::TrackType aType, int64_t aEndOffset);
     230             : 
     231             :   // Get the end time of aEndOffset, without reading before aStartOffset.
     232             :   // This is the playback position we'd reach after playback finished at
     233             :   // aEndOffset. If bool aCachedDataOnly is true, then we'll only read
     234             :   // from data which is cached in the media cached, otherwise we'll do
     235             :   // regular blocking reads from the media stream. If bool aCachedDataOnly
     236             :   // is true, this can safely be called on the main thread, otherwise it
     237             :   // must be called on the state machine thread.
     238             :   int64_t RangeEndTime(TrackInfo::TrackType aType,
     239             :                        int64_t aStartOffset,
     240             :                        int64_t aEndOffset,
     241             :                        bool aCachedDataOnly);
     242             : 
     243             :   // Get the start time of the range beginning at aOffset. This is the start
     244             :   // time of the first aType sample we'd be able to play if we
     245             :   // started playback at aOffset.
     246             :   int64_t RangeStartTime(TrackInfo::TrackType aType, int64_t aOffset);
     247             : 
     248             :   MediaInfo mInfo;
     249             :   nsTArray<RefPtr<OggTrackDemuxer>> mDemuxers;
     250             : 
     251             :   // Map of codec-specific bitstream states.
     252             :   OggCodecStore mCodecStore;
     253             : 
     254             :   // Decode state of the Theora bitstream we're decoding, if we have video.
     255             :   OggCodecState* mTheoraState;
     256             : 
     257             :   // Decode state of the Vorbis bitstream we're decoding, if we have audio.
     258             :   OggCodecState* mVorbisState;
     259             : 
     260             :   // Decode state of the Opus bitstream we're decoding, if we have one.
     261             :   OggCodecState* mOpusState;
     262             : 
     263             :   // Get the bitstream decode state for the given track type
     264             :   // Decode state of the Flac bitstream we're decoding, if we have one.
     265             :   OggCodecState* mFlacState;
     266             : 
     267             :   OggCodecState* GetTrackCodecState(TrackInfo::TrackType aType) const;
     268             :   TrackInfo::TrackType GetCodecStateType(OggCodecState* aState) const;
     269             : 
     270             :   // Represents the user pref media.opus.enabled at the time our
     271             :   // contructor was called. We can't check it dynamically because
     272             :   // we're not on the main thread;
     273             :   bool mOpusEnabled;
     274             : 
     275             :   // Decode state of the Skeleton bitstream.
     276             :   SkeletonState* mSkeletonState;
     277             : 
     278             :   // Ogg decoding state.
     279           0 :   struct OggStateContext
     280             :   {
     281           0 :     explicit OggStateContext(MediaResource* aResource)
     282           0 :     : mResource(aResource), mNeedKeyframe(true) {}
     283             :     nsAutoOggSyncState mOggState;
     284             :     MediaResourceIndex mResource;
     285             :     Maybe<media::TimeUnit> mStartTime;
     286             :     bool mNeedKeyframe;
     287             :   };
     288             : 
     289             :   OggStateContext& OggState(TrackInfo::TrackType aType);
     290             :   ogg_sync_state* OggSyncState(TrackInfo::TrackType aType);
     291             :   MediaResourceIndex* Resource(TrackInfo::TrackType aType);
     292             :   MediaResourceIndex* CommonResource();
     293             :   OggStateContext mAudioOggState;
     294             :   OggStateContext mVideoOggState;
     295             : 
     296             :   Maybe<int64_t> mStartTime;
     297             : 
     298             :   // Booleans to indicate if we have audio and/or video data
     299             :   bool HasVideo() const;
     300             :   bool HasAudio() const;
     301           0 :   bool HasSkeleton() const
     302             :   {
     303           0 :     return mSkeletonState != 0 && mSkeletonState->mActive;
     304             :   }
     305             :   bool HaveStartTime () const;
     306             :   bool HaveStartTime (TrackInfo::TrackType aType);
     307             :   int64_t StartTime() const;
     308             :   int64_t StartTime(TrackInfo::TrackType aType);
     309             : 
     310             :   // The picture region inside Theora frame to be displayed, if we have
     311             :   // a Theora video track.
     312             :   nsIntRect mPicture;
     313             : 
     314             :   // True if we are decoding a chained ogg.
     315             :   bool mIsChained;
     316             : 
     317             :   // Total audio duration played so far.
     318             :   media::TimeUnit mDecodedAudioDuration;
     319             : 
     320             :   // Events manager
     321             :   TimedMetadataEventProducer* mTimedMetadataEvent;
     322             :   MediaEventProducer<void>* mOnSeekableEvent;
     323             : 
     324             :   // This will be populated only if a content change occurs, otherwise it
     325             :   // will be left as null so the original metadata is used.
     326             :   // It is updated once a chained ogg is encountered.
     327             :   // As Ogg chaining is only supported for audio, we only need an audio track
     328             :   // info.
     329             :   RefPtr<TrackInfoSharedPtr> mSharedAudioTrackInfo;
     330             : 
     331             :   friend class OggTrackDemuxer;
     332             : };
     333             : 
     334             : class OggTrackDemuxer : public MediaTrackDemuxer
     335             : {
     336             : public:
     337             :   OggTrackDemuxer(OggDemuxer* aParent,
     338             :                   TrackInfo::TrackType aType,
     339             :                   uint32_t aTrackNumber);
     340             : 
     341             :   UniquePtr<TrackInfo> GetInfo() const override;
     342             : 
     343             :   RefPtr<SeekPromise> Seek(const media::TimeUnit& aTime) override;
     344             : 
     345             :   RefPtr<SamplesPromise> GetSamples(int32_t aNumSamples = 1) override;
     346             : 
     347             :   void Reset() override;
     348             : 
     349             :   RefPtr<SkipAccessPointPromise> SkipToNextRandomAccessPoint(const media::TimeUnit& aTimeThreshold) override;
     350             : 
     351             :   media::TimeIntervals GetBuffered() override;
     352             : 
     353             :   void BreakCycles() override;
     354             : 
     355             : private:
     356             :   ~OggTrackDemuxer();
     357             :   void SetNextKeyFrameTime();
     358             :   RefPtr<MediaRawData> NextSample();
     359             :   RefPtr<OggDemuxer> mParent;
     360             :   TrackInfo::TrackType mType;
     361             :   UniquePtr<TrackInfo> mInfo;
     362             : 
     363             :   // Queued sample extracted by the demuxer, but not yet returned.
     364             :   RefPtr<MediaRawData> mQueuedSample;
     365             : };
     366             : } // namespace mozilla
     367             : 
     368             : #endif

Generated by: LCOV version 1.13