content/media/webm/WebMBufferedParser.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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(WebMBufferedParser_h_)
     7 #define WebMBufferedParser_h_
     9 #include "nsISupportsImpl.h"
    10 #include "nsTArray.h"
    11 #include "mozilla/ReentrantMonitor.h"
    13 namespace mozilla {
    15 namespace dom {
    16 class TimeRanges;
    17 }
    19 // Stores a stream byte offset and the scaled timecode of the block at
    20 // that offset.  The timecode must be scaled by the stream's timecode
    21 // scale before use.
    22 struct WebMTimeDataOffset
    23 {
    24   WebMTimeDataOffset(int64_t aOffset, uint64_t aTimecode)
    25     : mOffset(aOffset), mTimecode(aTimecode)
    26   {}
    28   bool operator==(int64_t aOffset) const {
    29     return mOffset == aOffset;
    30   }
    32   bool operator<(int64_t aOffset) const {
    33     return mOffset < aOffset;
    34   }
    36   int64_t mOffset;
    37   uint64_t mTimecode;
    38 };
    40 // A simple WebM parser that produces data offset to timecode pairs as it
    41 // consumes blocks.  A new parser is created for each distinct range of data
    42 // received and begins parsing from the first WebM cluster within that
    43 // range.  Old parsers are destroyed when their range merges with a later
    44 // parser or an already parsed range.  The parser may start at any position
    45 // within the stream.
    46 struct WebMBufferedParser
    47 {
    48   WebMBufferedParser(int64_t aOffset)
    49     : mStartOffset(aOffset), mCurrentOffset(aOffset), mState(CLUSTER_SYNC), mClusterIDPos(0)
    50   {}
    52   // Steps the parser through aLength bytes of data.  Always consumes
    53   // aLength bytes.  Updates mCurrentOffset before returning.  Acquires
    54   // aReentrantMonitor before using aMapping.
    55   void Append(const unsigned char* aBuffer, uint32_t aLength,
    56               nsTArray<WebMTimeDataOffset>& aMapping,
    57               ReentrantMonitor& aReentrantMonitor);
    59   bool operator==(int64_t aOffset) const {
    60     return mCurrentOffset == aOffset;
    61   }
    63   bool operator<(int64_t aOffset) const {
    64     return mCurrentOffset < aOffset;
    65   }
    67   // The offset at which this parser started parsing.  Used to merge
    68   // adjacent parsers, in which case the later parser adopts the earlier
    69   // parser's mStartOffset.
    70   int64_t mStartOffset;
    72   // Current offset with the stream.  Updated in chunks as Append() consumes
    73   // data.
    74   int64_t mCurrentOffset;
    76 private:
    77   enum State {
    78     // Parser start state.  Scans forward searching for stream sync by
    79     // matching CLUSTER_ID with the curernt byte.  The match state is stored
    80     // in mClusterIDPos.  Once this reaches sizeof(CLUSTER_ID), stream may
    81     // have sync.  The parser then advances to read the cluster size and
    82     // timecode.
    83     CLUSTER_SYNC,
    85     /*
    86       The the parser states below assume that CLUSTER_SYNC has found a valid
    87       sync point within the data.  If parsing fails in these states, the
    88       parser returns to CLUSTER_SYNC to find a new sync point.
    89     */
    91     // Read the first byte of a variable length integer.  The first byte
    92     // encodes both the variable integer's length and part of the value.
    93     // The value read so far is stored in mVInt and the length is stored in
    94     // mVIntLength.  The number of bytes left to read is stored in
    95     // mVIntLeft.
    96     READ_VINT,
    98     // Reads the remaining mVIntLeft bytes into mVInt.
    99     READ_VINT_REST,
   101     // Check that the next element is TIMECODE_ID.  The cluster timecode is
   102     // required to be the first element in a cluster.  Advances to READ_VINT
   103     // to read the timecode's length into mVInt.
   104     TIMECODE_SYNC,
   106     // mVInt holds the length of the variable length unsigned integer
   107     // containing the cluster timecode.  Read mVInt bytes into
   108     // mClusterTimecode.
   109     READ_CLUSTER_TIMECODE,
   111     // Skips elements with a cluster until BLOCKGROUP_ID or SIMPLEBLOCK_ID
   112     // is found.  If BLOCKGROUP_ID is found, the parser returns to
   113     // ANY_BLOCK_ID searching for a BLOCK_ID.  Once a block or simpleblock
   114     // is found, the current data offset is stored in mBlockOffset.  If the
   115     // current byte is the beginning of a four byte variant integer, it
   116     // indicates the parser has reached a top-level element ID and the
   117     // parser returns to CLUSTER_SYNC.
   118     ANY_BLOCK_SYNC,
   120     // Start reading a block.  Blocks and simpleblocks are parsed the same
   121     // way as the initial layouts are identical.  mBlockSize is initialized
   122     // from mVInt (holding the element size), and mBlockTimecode(Length) is
   123     // initialized for parsing.
   124     READ_BLOCK,
   126     // Reads mBlockTimecodeLength bytes of data into mBlockTimecode.  When
   127     // mBlockTimecodeLength reaches 0, the timecode has been read.  The sum
   128     // of mClusterTimecode and mBlockTimecode is stored as a pair with
   129     // mBlockOffset into the offset-to-time map.
   130     READ_BLOCK_TIMECODE,
   132     // Skip mSkipBytes of data before resuming parse at mNextState.
   133     SKIP_DATA,
   135     // Skip the content of an element.  mVInt holds the element length.
   136     SKIP_ELEMENT
   137   };
   139   // Current state machine action.
   140   State mState;
   142   // Next state machine action.  SKIP_DATA and READ_VINT_REST advance to
   143   // mNextState when the current action completes.
   144   State mNextState;
   146   // Match position within CLUSTER_ID.  Used to find sync within arbitrary
   147   // data.
   148   uint32_t mClusterIDPos;
   150   // Variable length integer read from data.
   151   uint64_t mVInt;
   153   // Encoding length of mVInt.  This is the total number of bytes used to
   154   // encoding mVInt's value.
   155   uint32_t mVIntLength;
   157   // Number of bytes of mVInt left to read.  mVInt is complete once this
   158   // reaches 0.
   159   uint32_t mVIntLeft;
   161   // Size of the block currently being parsed.  Any unused data within the
   162   // block is skipped once the block timecode has been parsed.
   163   uint64_t mBlockSize;
   165   // Cluster-level timecode.
   166   uint64_t mClusterTimecode;
   168   // Start offset of the block currently being parsed.  Used as the byte
   169   // offset for the offset-to-time mapping once the block timecode has been
   170   // parsed.
   171   int64_t mBlockOffset;
   173   // Block-level timecode.  This is summed with mClusterTimecode to produce
   174   // an absolute timecode for the offset-to-time mapping.
   175   int16_t mBlockTimecode;
   177   // Number of bytes of mBlockTimecode left to read.
   178   uint32_t mBlockTimecodeLength;
   180   // Count of bytes left to skip before resuming parse at mNextState.
   181   // Mostly used to skip block payload data after reading a block timecode.
   182   uint32_t mSkipBytes;
   183 };
   185 class WebMBufferedState MOZ_FINAL
   186 {
   187   NS_INLINE_DECL_REFCOUNTING(WebMBufferedState)
   189 public:
   190   WebMBufferedState() : mReentrantMonitor("WebMBufferedState") {
   191     MOZ_COUNT_CTOR(WebMBufferedState);
   192   }
   194   void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset);
   195   bool CalculateBufferedForRange(int64_t aStartOffset, int64_t aEndOffset,
   196                                  uint64_t* aStartTime, uint64_t* aEndTime);
   197   bool GetOffsetForTime(uint64_t aTime, int64_t* aOffset);
   199 private:
   200   // Private destructor, to discourage deletion outside of Release():
   201   ~WebMBufferedState() {
   202     MOZ_COUNT_DTOR(WebMBufferedState);
   203   }
   205   // Synchronizes access to the mTimeMapping array.
   206   ReentrantMonitor mReentrantMonitor;
   208   // Sorted (by offset) map of data offsets to timecodes.  Populated
   209   // on the main thread as data is received and parsed by WebMBufferedParsers.
   210   nsTArray<WebMTimeDataOffset> mTimeMapping;
   212   // Sorted (by offset) live parser instances.  Main thread only.
   213   nsTArray<WebMBufferedParser> mRangeParsers;
   214 };
   216 } // namespace mozilla
   218 #endif

mercurial