2010-09-13 01:45:50 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
2012-05-21 04:12:37 -07:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2012-11-14 11:46:40 -08:00
|
|
|
#if !defined(WebMBufferedParser_h_)
|
|
|
|
#define WebMBufferedParser_h_
|
2010-09-13 01:45:50 -07:00
|
|
|
|
2010-09-20 17:49:50 -07:00
|
|
|
#include "nsISupportsImpl.h"
|
2010-09-13 01:45:50 -07:00
|
|
|
#include "nsTArray.h"
|
2011-04-29 12:21:57 -07:00
|
|
|
#include "mozilla/ReentrantMonitor.h"
|
2010-09-13 01:45:50 -07:00
|
|
|
|
2012-11-14 11:45:33 -08:00
|
|
|
namespace mozilla {
|
2010-09-20 17:49:50 -07:00
|
|
|
|
2013-11-17 18:31:46 -08:00
|
|
|
namespace dom {
|
|
|
|
class TimeRanges;
|
|
|
|
}
|
|
|
|
|
2010-09-13 01:45:50 -07:00
|
|
|
// Stores a stream byte offset and the scaled timecode of the block at
|
2014-08-24 21:09:43 -07:00
|
|
|
// that offset.
|
2012-11-14 11:46:40 -08:00
|
|
|
struct WebMTimeDataOffset
|
2010-09-13 01:45:50 -07:00
|
|
|
{
|
2014-08-24 21:09:44 -07:00
|
|
|
WebMTimeDataOffset(int64_t aEndOffset, uint64_t aTimecode, int64_t aSyncOffset)
|
|
|
|
: mEndOffset(aEndOffset), mSyncOffset(aSyncOffset), mTimecode(aTimecode)
|
2010-09-13 01:45:50 -07:00
|
|
|
{}
|
|
|
|
|
2014-08-24 21:09:44 -07:00
|
|
|
bool operator==(int64_t aEndOffset) const {
|
|
|
|
return mEndOffset == aEndOffset;
|
2010-09-13 01:45:50 -07:00
|
|
|
}
|
|
|
|
|
2014-08-24 21:09:44 -07:00
|
|
|
bool operator!=(int64_t aEndOffset) const {
|
|
|
|
return mEndOffset != aEndOffset;
|
2010-09-13 01:45:50 -07:00
|
|
|
}
|
|
|
|
|
2014-08-24 21:09:44 -07:00
|
|
|
bool operator<(int64_t aEndOffset) const {
|
|
|
|
return mEndOffset < aEndOffset;
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t mEndOffset;
|
2014-08-10 19:05:09 -07:00
|
|
|
int64_t mSyncOffset;
|
2014-08-24 21:09:43 -07:00
|
|
|
uint64_t mTimecode;
|
2010-09-13 01:45:50 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
// A simple WebM parser that produces data offset to timecode pairs as it
|
|
|
|
// consumes blocks. A new parser is created for each distinct range of data
|
|
|
|
// received and begins parsing from the first WebM cluster within that
|
|
|
|
// range. Old parsers are destroyed when their range merges with a later
|
|
|
|
// parser or an already parsed range. The parser may start at any position
|
|
|
|
// within the stream.
|
2012-11-14 11:46:40 -08:00
|
|
|
struct WebMBufferedParser
|
2010-09-13 01:45:50 -07:00
|
|
|
{
|
2014-08-24 21:09:43 -07:00
|
|
|
explicit WebMBufferedParser(int64_t aOffset)
|
|
|
|
: mStartOffset(aOffset), mCurrentOffset(aOffset), mState(READ_ELEMENT_ID),
|
2014-09-25 19:37:07 -07:00
|
|
|
mVIntRaw(false), mClusterSyncPos(0), mTimecodeScale(1000000),
|
|
|
|
mGotTimecodeScale(false)
|
2014-09-24 01:13:00 -07:00
|
|
|
{
|
|
|
|
if (mStartOffset != 0) {
|
|
|
|
mState = FIND_CLUSTER_SYNC;
|
|
|
|
}
|
|
|
|
}
|
2010-09-13 01:45:50 -07:00
|
|
|
|
2014-08-24 21:09:43 -07:00
|
|
|
uint32_t GetTimecodeScale() {
|
|
|
|
MOZ_ASSERT(mGotTimecodeScale);
|
|
|
|
return mTimecodeScale;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this parser is not expected to parse a segment info, it must be told
|
|
|
|
// the appropriate timecode scale to use from elsewhere.
|
|
|
|
void SetTimecodeScale(uint32_t aTimecodeScale) {
|
|
|
|
mTimecodeScale = aTimecodeScale;
|
|
|
|
mGotTimecodeScale = true;
|
|
|
|
}
|
|
|
|
|
2010-09-13 01:45:50 -07:00
|
|
|
// Steps the parser through aLength bytes of data. Always consumes
|
2011-03-23 15:28:58 -07:00
|
|
|
// aLength bytes. Updates mCurrentOffset before returning. Acquires
|
2011-04-29 12:21:57 -07:00
|
|
|
// aReentrantMonitor before using aMapping.
|
2012-08-22 08:56:38 -07:00
|
|
|
void Append(const unsigned char* aBuffer, uint32_t aLength,
|
2012-11-14 11:46:40 -08:00
|
|
|
nsTArray<WebMTimeDataOffset>& aMapping,
|
2011-04-29 12:21:57 -07:00
|
|
|
ReentrantMonitor& aReentrantMonitor);
|
2010-09-13 01:45:50 -07:00
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
bool operator==(int64_t aOffset) const {
|
2010-09-13 01:45:50 -07:00
|
|
|
return mCurrentOffset == aOffset;
|
|
|
|
}
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
bool operator<(int64_t aOffset) const {
|
2010-09-13 01:45:50 -07:00
|
|
|
return mCurrentOffset < aOffset;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The offset at which this parser started parsing. Used to merge
|
|
|
|
// adjacent parsers, in which case the later parser adopts the earlier
|
|
|
|
// parser's mStartOffset.
|
2012-08-22 08:56:38 -07:00
|
|
|
int64_t mStartOffset;
|
2010-09-13 01:45:50 -07:00
|
|
|
|
|
|
|
// Current offset with the stream. Updated in chunks as Append() consumes
|
|
|
|
// data.
|
2012-08-22 08:56:38 -07:00
|
|
|
int64_t mCurrentOffset;
|
2010-09-13 01:45:50 -07:00
|
|
|
|
|
|
|
private:
|
|
|
|
enum State {
|
2014-08-24 21:09:43 -07:00
|
|
|
// Parser start state. Expects to begin at a valid EBML element. Move
|
|
|
|
// to READ_VINT with mVIntRaw true, then return to READ_ELEMENT_SIZE.
|
|
|
|
READ_ELEMENT_ID,
|
|
|
|
|
|
|
|
// Store element ID read into mVInt into mElement.mID. Move to
|
|
|
|
// READ_VINT with mVIntRaw false, then return to PARSE_ELEMENT.
|
|
|
|
READ_ELEMENT_SIZE,
|
|
|
|
|
2014-09-24 01:13:00 -07:00
|
|
|
// Parser start state for parsers started at an arbitrary offset. Scans
|
|
|
|
// forward for the first cluster, then move to READ_ELEMENT_ID.
|
|
|
|
FIND_CLUSTER_SYNC,
|
|
|
|
|
2014-08-24 21:09:43 -07:00
|
|
|
// Simplistic core of the parser. Does not pay attention to nesting of
|
|
|
|
// elements. Checks mElement for an element ID of interest, then moves
|
|
|
|
// to the next state as determined by the element ID.
|
|
|
|
PARSE_ELEMENT,
|
2010-09-13 01:45:50 -07:00
|
|
|
|
|
|
|
// Read the first byte of a variable length integer. The first byte
|
|
|
|
// encodes both the variable integer's length and part of the value.
|
2014-08-24 21:09:43 -07:00
|
|
|
// The value read so far is stored in mVInt.mValue and the length is
|
|
|
|
// stored in mVInt.mLength. The number of bytes left to read is stored
|
|
|
|
// in mVIntLeft.
|
2010-09-13 01:45:50 -07:00
|
|
|
READ_VINT,
|
|
|
|
|
2014-08-24 21:09:43 -07:00
|
|
|
// Reads the remaining mVIntLeft bytes into mVInt.mValue.
|
2010-09-13 01:45:50 -07:00
|
|
|
READ_VINT_REST,
|
|
|
|
|
2014-08-24 21:09:43 -07:00
|
|
|
// mVInt holds the parsed timecode scale, store it in mTimecodeScale,
|
|
|
|
// then return READ_ELEMENT_ID.
|
|
|
|
READ_TIMECODESCALE,
|
2010-09-13 01:45:50 -07:00
|
|
|
|
2014-08-24 21:09:43 -07:00
|
|
|
// mVInt holds the parsed cluster timecode, store it in
|
|
|
|
// mClusterTimecode, then return to READ_ELEMENT_ID.
|
2010-09-13 01:45:50 -07:00
|
|
|
READ_CLUSTER_TIMECODE,
|
|
|
|
|
2014-08-24 21:09:43 -07:00
|
|
|
// mBlockTimecodeLength holds the remaining length of the block timecode
|
|
|
|
// left to read. Read each byte of the timecode into mBlockTimecode.
|
|
|
|
// Once complete, calculate the scaled timecode from the cluster
|
|
|
|
// timecode, block timecode, and timecode scale, and insert a
|
|
|
|
// WebMTimeDataOffset entry into aMapping if one is not already present
|
|
|
|
// for this offset.
|
2010-09-13 01:45:50 -07:00
|
|
|
READ_BLOCK_TIMECODE,
|
|
|
|
|
|
|
|
// Skip mSkipBytes of data before resuming parse at mNextState.
|
|
|
|
SKIP_DATA,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Current state machine action.
|
|
|
|
State mState;
|
|
|
|
|
|
|
|
// Next state machine action. SKIP_DATA and READ_VINT_REST advance to
|
|
|
|
// mNextState when the current action completes.
|
|
|
|
State mNextState;
|
|
|
|
|
2014-08-24 21:09:43 -07:00
|
|
|
struct VInt {
|
|
|
|
VInt() : mValue(0), mLength(0) {}
|
|
|
|
uint64_t mValue;
|
|
|
|
uint64_t mLength;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct EBMLElement {
|
|
|
|
uint64_t Length() { return mID.mLength + mSize.mLength; }
|
|
|
|
VInt mID;
|
|
|
|
VInt mSize;
|
|
|
|
};
|
|
|
|
|
|
|
|
EBMLElement mElement;
|
2010-09-13 01:45:50 -07:00
|
|
|
|
2014-08-24 21:09:43 -07:00
|
|
|
VInt mVInt;
|
2010-09-13 01:45:50 -07:00
|
|
|
|
2014-08-24 21:09:43 -07:00
|
|
|
bool mVIntRaw;
|
2010-09-13 01:45:50 -07:00
|
|
|
|
2014-09-24 01:13:00 -07:00
|
|
|
// Current match position within CLUSTER_SYNC_ID. Used to find sync
|
|
|
|
// within arbitrary data.
|
|
|
|
uint32_t mClusterSyncPos;
|
|
|
|
|
2010-09-13 01:45:50 -07:00
|
|
|
// Number of bytes of mVInt left to read. mVInt is complete once this
|
|
|
|
// reaches 0.
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t mVIntLeft;
|
2010-09-13 01:45:50 -07:00
|
|
|
|
|
|
|
// Size of the block currently being parsed. Any unused data within the
|
|
|
|
// block is skipped once the block timecode has been parsed.
|
2012-08-22 08:56:38 -07:00
|
|
|
uint64_t mBlockSize;
|
2010-09-13 01:45:50 -07:00
|
|
|
|
|
|
|
// Cluster-level timecode.
|
2012-08-22 08:56:38 -07:00
|
|
|
uint64_t mClusterTimecode;
|
2010-09-13 01:45:50 -07:00
|
|
|
|
2014-08-10 19:05:09 -07:00
|
|
|
// Start offset of the cluster currently being parsed. Used as the sync
|
|
|
|
// point offset for the offset-to-time mapping as each block timecode is
|
|
|
|
// been parsed.
|
|
|
|
int64_t mClusterOffset;
|
|
|
|
|
2010-09-13 01:45:50 -07:00
|
|
|
// Start offset of the block currently being parsed. Used as the byte
|
|
|
|
// offset for the offset-to-time mapping once the block timecode has been
|
|
|
|
// parsed.
|
2012-08-22 08:56:38 -07:00
|
|
|
int64_t mBlockOffset;
|
2010-09-13 01:45:50 -07:00
|
|
|
|
|
|
|
// Block-level timecode. This is summed with mClusterTimecode to produce
|
|
|
|
// an absolute timecode for the offset-to-time mapping.
|
2012-08-22 08:56:38 -07:00
|
|
|
int16_t mBlockTimecode;
|
2010-09-13 01:45:50 -07:00
|
|
|
|
|
|
|
// Number of bytes of mBlockTimecode left to read.
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t mBlockTimecodeLength;
|
2010-09-13 01:45:50 -07:00
|
|
|
|
|
|
|
// Count of bytes left to skip before resuming parse at mNextState.
|
|
|
|
// Mostly used to skip block payload data after reading a block timecode.
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t mSkipBytes;
|
2014-08-24 21:09:43 -07:00
|
|
|
|
|
|
|
// Timecode scale read from the segment info and used to scale absolute
|
|
|
|
// timecodes.
|
|
|
|
uint32_t mTimecodeScale;
|
|
|
|
|
|
|
|
// True if we read the timecode scale from the segment info or have
|
|
|
|
// confirmed that the default value is to be used.
|
|
|
|
bool mGotTimecodeScale;
|
2010-09-13 01:45:50 -07:00
|
|
|
};
|
|
|
|
|
2014-04-02 09:21:11 -07:00
|
|
|
class WebMBufferedState MOZ_FINAL
|
2010-09-20 17:49:50 -07:00
|
|
|
{
|
2012-11-14 11:46:40 -08:00
|
|
|
NS_INLINE_DECL_REFCOUNTING(WebMBufferedState)
|
2010-09-20 17:49:50 -07:00
|
|
|
|
|
|
|
public:
|
2012-11-14 11:46:40 -08:00
|
|
|
WebMBufferedState() : mReentrantMonitor("WebMBufferedState") {
|
|
|
|
MOZ_COUNT_CTOR(WebMBufferedState);
|
2010-09-20 17:49:50 -07:00
|
|
|
}
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset);
|
|
|
|
bool CalculateBufferedForRange(int64_t aStartOffset, int64_t aEndOffset,
|
|
|
|
uint64_t* aStartTime, uint64_t* aEndTime);
|
2014-08-24 21:09:44 -07:00
|
|
|
|
|
|
|
// Returns true if aTime is is present in mTimeMapping and sets aOffset to
|
|
|
|
// the latest offset for which decoding can resume without data
|
|
|
|
// dependencies to arrive at aTime.
|
|
|
|
bool GetOffsetForTime(uint64_t aTime, int64_t* aOffset);
|
2010-09-20 17:49:50 -07:00
|
|
|
|
|
|
|
private:
|
2014-04-02 09:21:11 -07:00
|
|
|
// Private destructor, to discourage deletion outside of Release():
|
|
|
|
~WebMBufferedState() {
|
|
|
|
MOZ_COUNT_DTOR(WebMBufferedState);
|
|
|
|
}
|
|
|
|
|
2011-03-23 15:28:58 -07:00
|
|
|
// Synchronizes access to the mTimeMapping array.
|
2011-04-29 12:21:57 -07:00
|
|
|
ReentrantMonitor mReentrantMonitor;
|
2011-03-23 15:28:58 -07:00
|
|
|
|
2010-09-20 17:49:50 -07:00
|
|
|
// Sorted (by offset) map of data offsets to timecodes. Populated
|
2012-11-14 11:46:40 -08:00
|
|
|
// on the main thread as data is received and parsed by WebMBufferedParsers.
|
|
|
|
nsTArray<WebMTimeDataOffset> mTimeMapping;
|
2010-09-20 17:49:50 -07:00
|
|
|
|
|
|
|
// Sorted (by offset) live parser instances. Main thread only.
|
2012-11-14 11:46:40 -08:00
|
|
|
nsTArray<WebMBufferedParser> mRangeParsers;
|
2010-09-20 17:49:50 -07:00
|
|
|
};
|
|
|
|
|
2012-11-14 11:45:33 -08:00
|
|
|
} // namespace mozilla
|
|
|
|
|
2010-09-13 01:45:50 -07:00
|
|
|
#endif
|