LCOV - code coverage report
Current view: top level - dom/media/ogg - OggCodecState.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 95 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 56 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(OggCodecState_h_)
       7             : #define OggCodecState_h_
       8             : 
       9             : #include <ogg/ogg.h>
      10             : // For MOZ_SAMPLE_TYPE_*
      11             : #include "FlacFrameParser.h"
      12             : #include "VideoUtils.h"
      13             : #include <nsDeque.h>
      14             : #include <nsTArray.h>
      15             : #include <nsClassHashtable.h>
      16             : 
      17             : #include <theora/theoradec.h>
      18             : #ifdef MOZ_TREMOR
      19             : #include <tremor/ivorbiscodec.h>
      20             : #else
      21             : #include <vorbis/codec.h>
      22             : #endif
      23             : 
      24             : // Uncomment the following to validate that we're predicting the number
      25             : // of Vorbis samples in each packet correctly.
      26             : #define VALIDATE_VORBIS_SAMPLE_CALCULATION
      27             : #ifdef  VALIDATE_VORBIS_SAMPLE_CALCULATION
      28             : #include <map>
      29             : #endif
      30             : 
      31             : struct OpusMSDecoder;
      32             : 
      33             : namespace mozilla {
      34             : 
      35             : class OpusParser;
      36             : 
      37             : struct OggPacketDeletePolicy
      38             : {
      39           0 :   void operator()(ogg_packet* aPacket) const
      40             :   {
      41           0 :     delete [] aPacket->packet;
      42             :     delete aPacket;
      43           0 :   }
      44             : };
      45             : 
      46             : using OggPacketPtr = UniquePtr<ogg_packet, OggPacketDeletePolicy>;
      47             : 
      48             : // Deallocates a packet, used in OggPacketQueue below.
      49           0 : class OggPacketDeallocator : public nsDequeFunctor
      50             : {
      51           0 :   virtual void* operator()(void* aPacket)
      52             :   {
      53           0 :     OggPacketDeletePolicy()(static_cast<ogg_packet*>(aPacket));
      54           0 :     return nullptr;
      55             :   }
      56             : };
      57             : 
      58             : // A queue of ogg_packets. When we read a page, we extract the page's packets
      59             : // and buffer them in the owning stream's OggCodecState. This is because
      60             : // if we're skipping up to the next keyframe in very large frame sized videos,
      61             : // there may be several megabytes of data between keyframes, and the
      62             : // ogg_stream_state would end up resizing its buffer every time we added a
      63             : // new 4KB page to the bitstream, which kills performance on Windows. This
      64             : // also gives us the option to timestamp packets rather than decoded
      65             : // frames/samples, reducing the amount of frames/samples we must decode to
      66             : // determine start-time at a particular offset, and gives us finer control
      67             : // over memory usage.
      68             : class OggPacketQueue : private nsDeque
      69             : {
      70             : public:
      71           0 :   OggPacketQueue() : nsDeque(new OggPacketDeallocator()) { }
      72           0 :   ~OggPacketQueue() { Erase(); }
      73           0 :   bool IsEmpty() { return nsDeque::GetSize() == 0; }
      74             :   void Append(OggPacketPtr aPacket);
      75           0 :   OggPacketPtr PopFront()
      76             :   {
      77           0 :     return OggPacketPtr(static_cast<ogg_packet*>(nsDeque::PopFront()));
      78             :   }
      79           0 :   ogg_packet* PeekFront()
      80             :   {
      81           0 :     return static_cast<ogg_packet*>(nsDeque::PeekFront());
      82             :   }
      83           0 :   OggPacketPtr Pop()
      84             :   {
      85           0 :     return OggPacketPtr(static_cast<ogg_packet*>(nsDeque::Pop()));
      86             :   }
      87           0 :   ogg_packet* operator[](size_t aIndex) const
      88             :   {
      89           0 :     return static_cast<ogg_packet*>(nsDeque::ObjectAt(aIndex));
      90             :   }
      91           0 :   size_t Length() const { return nsDeque::GetSize(); }
      92           0 :   void PushFront(OggPacketPtr aPacket)
      93             :   {
      94           0 :     nsDeque::PushFront(aPacket.release());
      95           0 :   }
      96           0 :   void Erase() { nsDeque::Erase(); }
      97             : };
      98             : 
      99             : // Encapsulates the data required for decoding an ogg bitstream and for
     100             : // converting granulepos to timestamps.
     101             : class OggCodecState
     102             : {
     103             : public:
     104             :   typedef mozilla::MetadataTags MetadataTags;
     105             :   // Ogg types we know about
     106             :   enum CodecType
     107             :   {
     108             :     TYPE_VORBIS=0,
     109             :     TYPE_THEORA,
     110             :     TYPE_OPUS,
     111             :     TYPE_SKELETON,
     112             :     TYPE_FLAC,
     113             :     TYPE_UNKNOWN
     114             :   };
     115             : 
     116             :   virtual ~OggCodecState();
     117             : 
     118             :   // Factory for creating nsCodecStates. Use instead of constructor.
     119             :   // aPage should be a beginning-of-stream page.
     120             :   static OggCodecState* Create(ogg_page* aPage);
     121             : 
     122           0 :   virtual CodecType GetType() { return TYPE_UNKNOWN; }
     123             : 
     124             :   // Reads a header packet. Returns false if an error was encountered
     125             :   // while reading header packets. Callers should check DoneReadingHeaders()
     126             :   // to determine if the last header has been read.
     127             :   // This function takes ownership of the packet and is responsible for
     128             :   // releasing it or queuing it for later processing.
     129           0 :   virtual bool DecodeHeader(OggPacketPtr aPacket)
     130             :   {
     131           0 :     return (mDoneReadingHeaders = true);
     132             :   }
     133             : 
     134             :   // Build a hash table with tag metadata parsed from the stream.
     135           0 :   virtual MetadataTags* GetTags()
     136             :   {
     137           0 :     return nullptr;
     138             :   }
     139             : 
     140             :   // Returns the end time that a granulepos represents.
     141           0 :   virtual int64_t Time(int64_t granulepos) { return -1; }
     142             : 
     143             :   // Returns the start time that a granulepos represents.
     144           0 :   virtual int64_t StartTime(int64_t granulepos) { return -1; }
     145             : 
     146             :   // Returns the duration of the given packet, if it can be determined.
     147           0 :   virtual int64_t PacketDuration(ogg_packet* aPacket) { return -1; }
     148             : 
     149             :   // Returns the start time of the given packet, if it can be determined.
     150           0 :   virtual int64_t PacketStartTime(ogg_packet* aPacket)
     151             :   {
     152           0 :     if (aPacket->granulepos < 0) {
     153           0 :       return -1;
     154             :     }
     155           0 :     int64_t endTime = Time(aPacket->granulepos);
     156           0 :     int64_t duration = PacketDuration(aPacket);
     157           0 :     if (duration > endTime) {
     158             :       // Audio preskip may eat a whole packet or more.
     159           0 :       return 0;
     160             :     } else {
     161           0 :       return endTime - duration;
     162             :     }
     163             :   }
     164             : 
     165             :   // Initializes the codec state.
     166           0 :   virtual bool Init() { return true; }
     167             : 
     168             :   // Returns true when this bitstream has finished reading all its
     169             :   // header packets.
     170           0 :   bool DoneReadingHeaders() { return mDoneReadingHeaders; }
     171             : 
     172             :   // Deactivates the bitstream. Only the primary video and audio bitstreams
     173             :   // should be active.
     174           0 :   void Deactivate()
     175             :   {
     176           0 :     mActive = false;
     177           0 :     mDoneReadingHeaders = true;
     178           0 :     Reset();
     179           0 :   }
     180             : 
     181             :   // Resets decoding state.
     182             :   virtual nsresult Reset();
     183             : 
     184             :   // Returns true if the OggCodecState thinks this packet is a header
     185             :   // packet. Note this does not verify the validity of the header packet,
     186             :   // it just guarantees that the packet is marked as a header packet (i.e.
     187             :   // it is definintely not a data packet). Do not use this to identify
     188             :   // streams, use it to filter header packets from data packets while
     189             :   // decoding.
     190           0 :   virtual bool IsHeader(ogg_packet* aPacket) { return false; }
     191             : 
     192             :   // Returns true if the OggCodecState thinks this packet represents a
     193             :   // keyframe, from which decoding can restart safely.
     194           0 :   virtual bool IsKeyframe(ogg_packet* aPacket) { return true; }
     195             : 
     196             :   // Returns true if there is a packet available for dequeueing in the stream.
     197             :   bool IsPacketReady();
     198             : 
     199             :   // Returns the next raw packet in the stream, or nullptr if there are no more
     200             :   // packets buffered in the packet queue. More packets can be buffered by
     201             :   // inserting one or more pages into the stream by calling PageIn().
     202             :   // The packet will have a valid granulepos.
     203             :   OggPacketPtr PacketOut();
     204             : 
     205             :   // Returns the next raw packet in the stream, or nullptr if there are no more
     206             :   // packets buffered in the packet queue, without consuming it.
     207             :   // The packet will have a valid granulepos.
     208             :   ogg_packet* PacketPeek();
     209             : 
     210             :   // Moves all raw packets from aOther to the front of the current packet queue.
     211             :   void PushFront(OggPacketQueue&& aOther);
     212             : 
     213             :   // Returns the next packet in the stream as a MediaRawData, or nullptr
     214             :   // if there are no more packets buffered in the packet queue. More packets
     215             :   // can be buffered by inserting one or more pages into the stream by calling
     216             :   // PageIn(). The packet will have a valid granulepos.
     217             :   virtual already_AddRefed<MediaRawData> PacketOutAsMediaRawData();
     218             : 
     219             :   // Extracts all packets from the page, and inserts them into the packet
     220             :   // queue. They can be extracted by calling PacketOut(). Packets from an
     221             :   // inactive stream are not buffered, i.e. this call has no effect for
     222             :   // inactive streams. Multiple pages may need to be inserted before
     223             :   // PacketOut() starts to return packets, as granulepos may need to be
     224             :   // captured.
     225             :   virtual nsresult PageIn(ogg_page* aPage);
     226             : 
     227             :   // Returns the maximum number of microseconds which a keyframe can be offset
     228             :   // from any given interframe.b
     229           0 :   virtual int64_t MaxKeyframeOffset() { return 0; }
     230             :   // Public access for mTheoraInfo.keyframe_granule_shift
     231           0 :   virtual int32_t KeyFrameGranuleJobs() { return 0; }
     232             : 
     233             :   // Number of packets read.
     234             :   uint64_t mPacketCount;
     235             : 
     236             :   // Serial number of the bitstream.
     237             :   uint32_t mSerial;
     238             : 
     239             :   // Ogg specific state.
     240             :   ogg_stream_state mState;
     241             : 
     242             :   // Queue of as yet undecoded packets. Packets are guaranteed to have
     243             :   // a valid granulepos.
     244             :   OggPacketQueue mPackets;
     245             : 
     246             :   // Is the bitstream active; whether we're decoding and playing this bitstream.
     247             :   bool mActive;
     248             : 
     249             :   // True when all headers packets have been read.
     250             :   bool mDoneReadingHeaders;
     251             : 
     252           0 :   virtual const TrackInfo* GetInfo() const
     253             :   {
     254           0 :     MOZ_RELEASE_ASSERT(false, "Can't be called directly");
     255             :     return nullptr;
     256             :   }
     257             : 
     258             :   // Validation utility for vorbis-style tag names.
     259             :   static bool IsValidVorbisTagName(nsCString& aName);
     260             : 
     261             :   // Utility method to parse and add a vorbis-style comment
     262             :   // to a metadata hash table. Most Ogg-encapsulated codecs
     263             :   // use the vorbis comment format for metadata.
     264             :   static bool AddVorbisComment(MetadataTags* aTags,
     265             :                         const char* aComment,
     266             :                         uint32_t aLength);
     267             : 
     268             : protected:
     269             :   // Constructs a new OggCodecState. aActive denotes whether the stream is
     270             :   // active. For streams of unsupported or unknown types, aActive should be
     271             :   // false.
     272             :   OggCodecState(ogg_page* aBosPage, bool aActive);
     273             : 
     274             :   // Deallocates all packets stored in mUnstamped, and clears the array.
     275             :   void ClearUnstamped();
     276             : 
     277             :   // Extracts packets out of mState until a data packet with a non -1
     278             :   // granulepos is encountered, or no more packets are readable. Header
     279             :   // packets are pushed into the packet queue immediately, and data packets
     280             :   // are buffered in mUnstamped. Once a non -1 granulepos packet is read
     281             :   // the granulepos of the packets in mUnstamped can be inferred, and they
     282             :   // can be pushed over to mPackets. Used by PageIn() implementations in
     283             :   // subclasses.
     284             :   nsresult PacketOutUntilGranulepos(bool& aFoundGranulepos);
     285             : 
     286             :   // Temporary buffer in which to store packets while we're reading packets
     287             :   // in order to capture granulepos.
     288             :   nsTArray<OggPacketPtr> mUnstamped;
     289             : 
     290             :   bool SetCodecSpecificConfig(MediaByteBuffer* aBuffer,
     291             :                               OggPacketQueue& aHeaders);
     292             : 
     293             : private:
     294             :   bool InternalInit();
     295             : };
     296             : 
     297             : class VorbisState : public OggCodecState
     298             : {
     299             : public:
     300             :   explicit VorbisState(ogg_page* aBosPage);
     301             :   virtual ~VorbisState();
     302             : 
     303           0 :   CodecType GetType() override { return TYPE_VORBIS; }
     304             :   bool DecodeHeader(OggPacketPtr aPacket) override;
     305             :   int64_t Time(int64_t granulepos) override;
     306             :   int64_t PacketDuration(ogg_packet* aPacket) override;
     307             :   bool Init() override;
     308             :   nsresult Reset() override;
     309             :   bool IsHeader(ogg_packet* aPacket) override;
     310             :   nsresult PageIn(ogg_page* aPage) override;
     311           0 :   const TrackInfo* GetInfo() const override { return &mInfo; }
     312             : 
     313             :   // Return a hash table with tag metadata.
     314             :   MetadataTags* GetTags() override;
     315             : 
     316             : private:
     317             :   AudioInfo mInfo;
     318             :   vorbis_info mVorbisInfo;
     319             :   vorbis_comment mComment;
     320             :   vorbis_dsp_state mDsp;
     321             :   vorbis_block mBlock;
     322             :   OggPacketQueue mHeaders;
     323             : 
     324             :   // Returns the end time that a granulepos represents.
     325             :   static int64_t Time(vorbis_info* aInfo, int64_t aGranulePos);
     326             : 
     327             :   // Reconstructs the granulepos of Vorbis packets stored in the mUnstamped
     328             :   // array.
     329             :   nsresult ReconstructVorbisGranulepos();
     330             : 
     331             :   // The "block size" of the previously decoded Vorbis packet, or 0 if we've
     332             :   // not yet decoded anything. This is used to calculate the number of samples
     333             :   // in a Vorbis packet, since each Vorbis packet depends on the previous
     334             :   // packet while being decoded.
     335             :   long mPrevVorbisBlockSize;
     336             : 
     337             :   // Granulepos (end sample) of the last decoded Vorbis packet. This is used
     338             :   // to calculate the Vorbis granulepos when we don't find a granulepos to
     339             :   // back-propagate from.
     340             :   int64_t mGranulepos;
     341             : 
     342             : #ifdef VALIDATE_VORBIS_SAMPLE_CALCULATION
     343             :   // When validating that we've correctly predicted Vorbis packets' number
     344             :   // of samples, we store each packet's predicted number of samples in this
     345             :   // map, and verify we decode the predicted number of samples.
     346             :   std::map<ogg_packet*, long> mVorbisPacketSamples;
     347             : #endif
     348             : 
     349             :   // Records that aPacket is predicted to have aSamples samples.
     350             :   // This function has no effect if VALIDATE_VORBIS_SAMPLE_CALCULATION
     351             :   // is not defined.
     352             :   void RecordVorbisPacketSamples(ogg_packet* aPacket, long aSamples);
     353             : 
     354             :   // Verifies that aPacket has had its number of samples predicted.
     355             :   // This function has no effect if VALIDATE_VORBIS_SAMPLE_CALCULATION
     356             :   // is not defined.
     357             :   void AssertHasRecordedPacketSamples(ogg_packet* aPacket);
     358             : 
     359             : public:
     360             :   // Asserts that the number of samples predicted for aPacket is aSamples.
     361             :   // This function has no effect if VALIDATE_VORBIS_SAMPLE_CALCULATION
     362             :   // is not defined.
     363             :   void ValidateVorbisPacketSamples(ogg_packet* aPacket, long aSamples);
     364             : 
     365             : };
     366             : 
     367             : // Returns 1 if the Theora info struct is decoding a media of Theora
     368             : // version (maj,min,sub) or later, otherwise returns 0.
     369             : int TheoraVersion(th_info* info,
     370             :                   unsigned char maj,
     371             :                   unsigned char min,
     372             :                   unsigned char sub);
     373             : 
     374             : class TheoraState : public OggCodecState
     375             : {
     376             : public:
     377             :   explicit TheoraState(ogg_page* aBosPage);
     378             :   virtual ~TheoraState();
     379             : 
     380           0 :   CodecType GetType() override { return TYPE_THEORA; }
     381             :   bool DecodeHeader(OggPacketPtr aPacket) override;
     382             :   int64_t Time(int64_t granulepos) override;
     383             :   int64_t StartTime(int64_t granulepos) override;
     384             :   int64_t PacketDuration(ogg_packet* aPacket) override;
     385             :   bool Init() override;
     386             :   nsresult Reset() override;
     387             :   bool IsHeader(ogg_packet* aPacket) override;
     388             :   bool IsKeyframe(ogg_packet* aPacket) override;
     389             :   nsresult PageIn(ogg_page* aPage) override;
     390           0 :   const TrackInfo* GetInfo() const override { return &mInfo; }
     391             :   int64_t MaxKeyframeOffset() override;
     392           0 :   int32_t KeyFrameGranuleJobs() override
     393             :   {
     394           0 :     return mTheoraInfo.keyframe_granule_shift;
     395             :   }
     396             : 
     397             : private:
     398             :   // Returns the end time that a granulepos represents.
     399             :   static int64_t Time(th_info* aInfo, int64_t aGranulePos);
     400             : 
     401             :   th_info mTheoraInfo;
     402             :   th_comment mComment;
     403             :   th_setup_info* mSetup;
     404             :   th_dec_ctx* mCtx;
     405             : 
     406             :   VideoInfo mInfo;
     407             :   OggPacketQueue mHeaders;
     408             : 
     409             :   // Reconstructs the granulepos of Theora packets stored in the
     410             :   // mUnstamped array. mUnstamped must be filled with consecutive packets from
     411             :   // the stream, with the last packet having a known granulepos. Using this
     412             :   // known granulepos, and the known frame numbers, we recover the granulepos
     413             :   // of all frames in the array. This enables us to determine their timestamps.
     414             :   void ReconstructTheoraGranulepos();
     415             : };
     416             : 
     417             : class OpusState : public OggCodecState
     418             : {
     419             : public:
     420             :   explicit OpusState(ogg_page* aBosPage);
     421             :   virtual ~OpusState();
     422             : 
     423           0 :   CodecType GetType() override { return TYPE_OPUS; }
     424             :   bool DecodeHeader(OggPacketPtr aPacket) override;
     425             :   int64_t Time(int64_t aGranulepos) override;
     426             :   int64_t PacketDuration(ogg_packet* aPacket) override;
     427             :   bool Init() override;
     428             :   nsresult Reset() override;
     429             :   nsresult Reset(bool aStart);
     430             :   bool IsHeader(ogg_packet* aPacket) override;
     431             :   nsresult PageIn(ogg_page* aPage) override;
     432             :   already_AddRefed<MediaRawData> PacketOutAsMediaRawData() override;
     433           0 :   const TrackInfo* GetInfo() const override { return &mInfo; }
     434             : 
     435             :   // Returns the end time that a granulepos represents.
     436             :   static int64_t Time(int aPreSkip, int64_t aGranulepos);
     437             : 
     438             :   // Construct and return a table of tags from the metadata header.
     439             :   MetadataTags* GetTags() override;
     440             : 
     441             : private:
     442             :   nsAutoPtr<OpusParser> mParser;
     443             :   OpusMSDecoder* mDecoder;
     444             : 
     445             :   // Granule position (end sample) of the last decoded Opus packet. This is
     446             :   // used to calculate the amount we should trim from the last packet.
     447             :   int64_t mPrevPacketGranulepos;
     448             : 
     449             :   // Reconstructs the granulepos of Opus packets stored in the
     450             :   // mUnstamped array. mUnstamped must be filled with consecutive packets from
     451             :   // the stream, with the last packet having a known granulepos. Using this
     452             :   // known granulepos, and the known frame numbers, we recover the granulepos
     453             :   // of all frames in the array. This enables us to determine their timestamps.
     454             :   bool ReconstructOpusGranulepos();
     455             : 
     456             :   // Granule position (end sample) of the last decoded Opus page. This is
     457             :   // used to calculate the Opus per-packet granule positions on the last page,
     458             :   // where we may need to trim some samples from the end.
     459             :   int64_t mPrevPageGranulepos;
     460             :   AudioInfo mInfo;
     461             :   OggPacketQueue mHeaders;
     462             : };
     463             : 
     464             : // Constructs a 32bit version number out of two 16 bit major,minor
     465             : // version numbers.
     466             : #define SKELETON_VERSION(major, minor) (((major)<<16)|(minor))
     467             : 
     468             : enum EMsgHeaderType
     469             : {
     470             :   eContentType,
     471             :   eRole,
     472             :   eName,
     473             :   eLanguage,
     474             :   eTitle,
     475             :   eDisplayHint,
     476             :   eAltitude,
     477             :   eTrackOrder,
     478             :   eTrackDependencies
     479             : };
     480             : 
     481             : typedef struct
     482             : {
     483             :   const char* mPatternToRecognize;
     484             :   EMsgHeaderType mMsgHeaderType;
     485             : } FieldPatternType;
     486             : 
     487             : // Stores the message information for different logical bitstream.
     488             : typedef struct
     489             : {
     490             :   nsClassHashtable<nsUint32HashKey, nsCString> mValuesStore;
     491           0 : } MessageField;
     492             : 
     493             : class SkeletonState : public OggCodecState
     494             : {
     495             : public:
     496             :   explicit SkeletonState(ogg_page* aBosPage);
     497             :   ~SkeletonState();
     498             : 
     499             :   nsClassHashtable<nsUint32HashKey, MessageField> mMsgFieldStore;
     500             : 
     501           0 :   CodecType GetType() override { return TYPE_SKELETON; }
     502             :   bool DecodeHeader(OggPacketPtr aPacket) override;
     503           0 :   int64_t Time(int64_t granulepos) override { return -1; }
     504           0 :   bool IsHeader(ogg_packet* aPacket) override { return true; }
     505             : 
     506             :   // Return true if the given time (in milliseconds) is within
     507             :   // the presentation time defined in the skeleton track.
     508             :   bool IsPresentable(int64_t aTime) { return aTime >= mPresentationTime; }
     509             : 
     510             :   // Stores the offset of the page on which a keyframe starts,
     511             :   // and its presentation time.
     512             :   class nsKeyPoint
     513             :   {
     514             :   public:
     515           0 :     nsKeyPoint()
     516           0 :       : mOffset(INT64_MAX)
     517           0 :       , mTime(INT64_MAX) {}
     518             : 
     519           0 :     nsKeyPoint(int64_t aOffset, int64_t aTime)
     520           0 :       : mOffset(aOffset)
     521           0 :       ,mTime(aTime) {}
     522             : 
     523             :     // Offset from start of segment/link-in-the-chain in bytes.
     524             :     int64_t mOffset;
     525             : 
     526             :     // Presentation time in usecs.
     527             :     int64_t mTime;
     528             : 
     529           0 :     bool IsNull()
     530             :     {
     531           0 :       return mOffset == INT64_MAX && mTime == INT64_MAX;
     532             :     }
     533             :   };
     534             : 
     535             :   // Stores a keyframe's byte-offset, presentation time and the serialno
     536             :   // of the stream it belongs to.
     537             :   class nsSeekTarget
     538             :   {
     539             :   public:
     540           0 :     nsSeekTarget() : mSerial(0) { }
     541             :     nsKeyPoint mKeyPoint;
     542             :     uint32_t mSerial;
     543           0 :     bool IsNull()
     544             :     {
     545           0 :       return mKeyPoint.IsNull() && mSerial == 0;
     546             :     }
     547             :   };
     548             : 
     549             :   // Determines from the seek index the keyframe which you must seek back to
     550             :   // in order to get all keyframes required to render all streams with
     551             :   // serialnos in aTracks, at time aTarget.
     552             :   nsresult IndexedSeekTarget(int64_t aTarget,
     553             :                              nsTArray<uint32_t>& aTracks,
     554             :                              nsSeekTarget& aResult);
     555             : 
     556           0 :   bool HasIndex() const
     557             :   {
     558           0 :     return mIndex.Count() > 0;
     559             :   }
     560             : 
     561             :   // Returns the duration of the active tracks in the media, if we have
     562             :   // an index. aTracks must be filled with the serialnos of the active tracks.
     563             :   // The duration is calculated as the greatest end time of all active tracks,
     564             :   // minus the smalled start time of all the active tracks.
     565             :   nsresult GetDuration(const nsTArray<uint32_t>& aTracks, int64_t& aDuration);
     566             : 
     567             : private:
     568             : 
     569             :   // Decodes an index packet. Returns false on failure.
     570             :   bool DecodeIndex(ogg_packet* aPacket);
     571             :   // Decodes an fisbone packet. Returns false on failure.
     572             :   bool DecodeFisbone(ogg_packet* aPacket);
     573             : 
     574             :   // Gets the keypoint you must seek to in order to get the keyframe required
     575             :   // to render the stream at time aTarget on stream with serial aSerialno.
     576             :   nsresult IndexedSeekTargetForTrack(uint32_t aSerialno,
     577             :                                      int64_t aTarget,
     578             :                                      nsKeyPoint& aResult);
     579             : 
     580             :   // Version of the decoded skeleton track, as per the SKELETON_VERSION macro.
     581             :   uint32_t mVersion;
     582             : 
     583             :   // Presentation time of the resource in milliseconds
     584             :   int64_t mPresentationTime;
     585             : 
     586             :   // Length of the resource in bytes.
     587             :   int64_t mLength;
     588             : 
     589             :   // Stores the keyframe index and duration information for a particular
     590             :   // stream.
     591             :   class nsKeyFrameIndex
     592             :   {
     593             :   public:
     594             : 
     595           0 :     nsKeyFrameIndex(int64_t aStartTime, int64_t aEndTime)
     596           0 :       : mStartTime(aStartTime)
     597           0 :       , mEndTime(aEndTime)
     598             :     {
     599           0 :       MOZ_COUNT_CTOR(nsKeyFrameIndex);
     600           0 :     }
     601             : 
     602           0 :     ~nsKeyFrameIndex()
     603           0 :     {
     604           0 :       MOZ_COUNT_DTOR(nsKeyFrameIndex);
     605           0 :     }
     606             : 
     607           0 :     void Add(int64_t aOffset, int64_t aTimeMs)
     608             :     {
     609           0 :       mKeyPoints.AppendElement(nsKeyPoint(aOffset, aTimeMs));
     610           0 :     }
     611             : 
     612           0 :     const nsKeyPoint& Get(uint32_t aIndex) const
     613             :     {
     614           0 :       return mKeyPoints[aIndex];
     615             :     }
     616             : 
     617           0 :     uint32_t Length() const
     618             :     {
     619           0 :       return mKeyPoints.Length();
     620             :     }
     621             : 
     622             :     // Presentation time of the first sample in this stream in usecs.
     623             :     const int64_t mStartTime;
     624             : 
     625             :     // End time of the last sample in this stream in usecs.
     626             :     const int64_t mEndTime;
     627             : 
     628             :   private:
     629             :     nsTArray<nsKeyPoint> mKeyPoints;
     630             :   };
     631             : 
     632             :   // Maps Ogg serialnos to the index-keypoint list.
     633             :   nsClassHashtable<nsUint32HashKey, nsKeyFrameIndex> mIndex;
     634             : };
     635             : 
     636           0 : class FlacState : public OggCodecState
     637             : {
     638             : public:
     639             :   explicit FlacState(ogg_page* aBosPage);
     640             : 
     641           0 :   CodecType GetType() override { return TYPE_FLAC; }
     642             :   bool DecodeHeader(OggPacketPtr aPacket) override;
     643             :   int64_t Time(int64_t granulepos) override;
     644             :   int64_t PacketDuration(ogg_packet* aPacket) override;
     645             :   bool IsHeader(ogg_packet* aPacket) override;
     646             :   nsresult PageIn(ogg_page* aPage) override;
     647             : 
     648             :   // Return a hash table with tag metadata.
     649             :   MetadataTags* GetTags() override;
     650             : 
     651             :   const TrackInfo* GetInfo() const override;
     652             : 
     653             : private:
     654             :   bool ReconstructFlacGranulepos(void);
     655             : 
     656             :   FlacFrameParser mParser;
     657             : };
     658             : 
     659             : } // namespace mozilla
     660             : 
     661             : #endif

Generated by: LCOV version 1.13