Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8ba606c3 authored by Andreas Huber's avatar Andreas Huber
Browse files

DO NOT MERGE Upgrade to the latest version of libwebm to fix YouTube webm playback.

DO NOT MERGE
related-to-bug: 3141937

Change-Id: Iaf1b0c5d45a6b5bb7624a59747041c27b4dde83b
parent ce0febae
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -252,7 +252,7 @@ void BlockIterator::reset() {
}

void BlockIterator::seek(int64_t seekTimeUs) {
    mCluster = mSegment->GetCluster(seekTimeUs * 1000ll);
    mCluster = mSegment->FindCluster(seekTimeUs * 1000ll);
    mBlockEntry = mCluster != NULL ? mCluster->GetFirst() : NULL;

    while (!eos() && block()->GetTrackNumber() != mTrackNum) {
@@ -476,7 +476,7 @@ void MatroskaExtractor::addTracks() {

        size_t codecPrivateSize;
        const unsigned char *codecPrivate =
            track->GetCodecPrivate(&codecPrivateSize);
            track->GetCodecPrivate(codecPrivateSize);

        enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };

+4511 −3103

File changed.

Preview size limit exceeded, changes collapsed.

+554 −428
Original line number Diff line number Diff line
// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS.  All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.

#ifndef MKVPARSER_HPP
#define MKVPARSER_HPP

@@ -13,7 +21,7 @@ const int E_BUFFER_NOT_FULL = -3;
class IMkvReader
{
public:
    virtual int Read(long long position, long length, unsigned char* buffer) = 0;
    virtual int Read(long long pos, long len, unsigned char* buf) = 0;
    virtual int Length(long long* total, long long* available) = 0;
protected:
    virtual ~IMkvReader();
@@ -29,11 +37,11 @@ short Unserialize2SInt(IMkvReader*, long long);
signed char Unserialize1SInt(IMkvReader*, long long);
bool Match(IMkvReader*, long long&, unsigned long, long long&);
bool Match(IMkvReader*, long long&, unsigned long, char*&);
bool Match(IMkvReader*, long long&, unsigned long,unsigned char*&,
           size_t *optionalSize = NULL);
bool Match(IMkvReader*, long long&, unsigned long,unsigned char*&, size_t&);
bool Match(IMkvReader*, long long&, unsigned long, double&);
bool Match(IMkvReader*, long long&, unsigned long, short&);

void GetVersion(int& major, int& minor, int& build, int& revision);

struct EBMLHeader
{
@@ -66,13 +74,13 @@ public:

    Block(long long start, long long size, IMkvReader*);

    unsigned long GetTrackNumber() const;
    
    long long GetTrackNumber() const;
    long long GetTimeCode(Cluster*) const;  //absolute, but not scaled
    long long GetTime(Cluster*) const;      //absolute, and scaled (nanosecond units)
    long long GetTime(Cluster*) const;      //absolute, and scaled (ns units)
    bool IsKey() const;
    void SetKey(bool);

    long long GetOffset() const;
    long GetSize() const;
    long Read(IMkvReader*, unsigned char*) const;

@@ -179,12 +187,11 @@ public:
    virtual ~Track();

    long long GetType() const;
    unsigned long GetNumber() const;
    long long GetNumber() const;
    const char* GetNameAsUTF8() const;
    const char* GetCodecNameAsUTF8() const;
    const char* GetCodecId() const;
    const unsigned char* GetCodecPrivate(
            size_t *optionalSize = NULL) const;
    const unsigned char* GetCodecPrivate(size_t&) const;

    const BlockEntry* GetEOS() const;

@@ -327,6 +334,96 @@ private:
    char* m_pTitleAsUTF8;
};

class Cues;
class CuePoint
{
    friend class Cues;

    CuePoint(size_t, long long);
    ~CuePoint();

    CuePoint(const CuePoint&);
    CuePoint& operator=(const CuePoint&);

public:
    void Load(IMkvReader*);

    long long GetTimeCode() const;      //absolute but unscaled
    long long GetTime(Segment*) const;  //absolute and scaled (ns units)

    struct TrackPosition
    {
        long long m_track;
        long long m_pos;  //of cluster
        long long m_block;
        //codec_state  //defaults to 0
        //reference = clusters containing req'd referenced blocks
        //  reftime = timecode of the referenced block

        void Parse(IMkvReader*, long long, long long);
    };

    const TrackPosition* Find(const Track*) const;

private:
    const size_t m_index;
    long long m_timecode;
    TrackPosition* m_track_positions;
    size_t m_track_positions_count;

};


class Cues
{
    friend class Segment;

    Cues(Segment*, long long start, long long size);
    ~Cues();

    Cues(const Cues&);
    Cues& operator=(const Cues&);

public:
    Segment* const m_pSegment;
    const long long m_start;
    const long long m_size;

    bool Find(  //lower bound of time_ns
        long long time_ns,
        const Track*,
        const CuePoint*&,
        const CuePoint::TrackPosition*&) const;

#if 0
    bool FindNext(  //upper_bound of time_ns
        long long time_ns,
        const Track*,
        const CuePoint*&,
        const CuePoint::TrackPosition*&) const;
#endif

    const CuePoint* GetFirst() const;
    const CuePoint* GetLast() const;

    const CuePoint* GetNext(const CuePoint*) const;

    const BlockEntry* GetBlock(
                        const CuePoint*,
                        const CuePoint::TrackPosition*) const;

private:
    void Init() const;
    bool LoadCuePoint() const;
    void PreloadCuePoint(size_t&, long long) const;

    mutable CuePoint** m_cue_points;
    mutable size_t m_count;
    mutable size_t m_preload_count;
    mutable long long m_pos;

};


class Cluster
{
@@ -335,10 +432,9 @@ class Cluster

public:
    Segment* const m_pSegment;
    const size_t m_index;

public:
    static Cluster* Parse(Segment*, size_t, long long off);
    static Cluster* Parse(Segment*, long, long long off);

    Cluster();  //EndOfStream
    ~Cluster();
@@ -347,19 +443,30 @@ public:

    long long GetTimeCode();   //absolute, but not scaled
    long long GetTime();       //absolute, and scaled (nanosecond units)
    long long GetFirstTime();  //time (ns) of first (earliest) block
    long long GetLastTime();   //time (ns) of last (latest) block

    const BlockEntry* GetFirst();
    const BlockEntry* GetLast();
    const BlockEntry* GetNext(const BlockEntry*) const;
    const BlockEntry* GetEntry(const Track*);
    const BlockEntry* GetEntry(
        const CuePoint&,
        const CuePoint::TrackPosition&);
    const BlockEntry* GetMaxKey(const VideoTrack*);

protected:
    Cluster(Segment*, size_t, long long off);
    Cluster(Segment*, long, long long off);

private:
    long long m_start;
public:
    //TODO: these should all be private, with public selector functions
    long m_index;
    long long m_pos;
    long long m_size;

private:
    long long m_timecode;
    BlockEntry** m_pEntries;
    BlockEntry** m_entries;
    size_t m_entriesCount;

    void Load();
@@ -372,6 +479,8 @@ private:

class Segment
{
    friend class Cues;

    Segment(const Segment&);
    Segment& operator=(const Segment&);

@@ -387,39 +496,56 @@ public:
    static long long CreateInstance(IMkvReader*, long long, Segment*&);
    ~Segment();

    //for big-bang loading (source filter)
    long Load();
    long Load();  //loads headers and all clusters

    //for incremental loading (splitter)
    long long Unparsed() const;
    long long ParseHeaders();
    long long ParseHeaders();  //stops when first cluster is found
    long LoadCluster();        //loads one cluster

#if 0
    //This pair parses one cluster, but only changes the state of the
    //segment object when the cluster is actually added to the index.
    long ParseCluster(Cluster*&, long long& newpos) const;
    bool AddCluster(Cluster*, long long);
#endif

    Tracks* GetTracks() const;
    const SegmentInfo* const GetInfo() const;
    long long GetDuration() const;
    const SegmentInfo* GetInfo() const;
    const Cues* GetCues() const;

    //NOTE: this turned out to be too inefficient.
    //long long Load(long long time_nanoseconds);
    long long GetDuration() const;

    unsigned long GetCount() const;
    Cluster* GetFirst();
    Cluster* GetLast();
    unsigned long GetCount() const;
    
    Cluster* GetNext(const Cluster*);
    Cluster* GetCluster(long long time_nanoseconds);

    Cluster* FindCluster(long long time_nanoseconds);
    const BlockEntry* Seek(long long time_nanoseconds, const Track*);

private:

    long long m_pos;  //absolute file posn; what has been consumed so far
    SegmentInfo* m_pInfo;
    Tracks* m_pTracks;
    Cues* m_pCues;
    Cluster** m_clusters;
    size_t m_clusterCount;
    long m_clusterCount;         //number of entries for which m_index >= 0
    long m_clusterPreloadCount;  //number of entries for which m_index < 0
    long m_clusterSize;          //array size

    void AppendCluster(Cluster*);
    void PreloadCluster(Cluster*, ptrdiff_t);

    void ParseSeekHead(long long pos, long long size);
    void ParseSeekEntry(long long pos, long long size);
    void ParseCues(long long);

    const BlockEntry* GetBlock(
        const CuePoint&,
        const CuePoint::TrackPosition&);

    void ParseSeekHead(long long pos, long long size, size_t*);
    void ParseSeekEntry(long long pos, long long size, size_t*);
    void ParseSecondarySeekHead(long long off, size_t*);
};