1233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
2233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
3233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Use of this source code is governed by a BSD-style license
4233d2500723e5594f3e7c70896ffeeef32b9c950ywan// that can be found in the LICENSE file in the root of the source
5233d2500723e5594f3e7c70896ffeeef32b9c950ywan// tree. An additional intellectual property rights grant can be found
6233d2500723e5594f3e7c70896ffeeef32b9c950ywan// in the file PATENTS.  All contributing project authors may
7233d2500723e5594f3e7c70896ffeeef32b9c950ywan// be found in the AUTHORS file in the root of the source tree.
8233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "mkvparser.hpp"
10233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <cassert>
11233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <cstring>
12233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <new>
13233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <climits>
14233d2500723e5594f3e7c70896ffeeef32b9c950ywan
15233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef _MSC_VER
16233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Disable MSVC warnings that suggest making code non-portable.
17233d2500723e5594f3e7c70896ffeeef32b9c950ywan#pragma warning(disable:4996)
18233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
19233d2500723e5594f3e7c70896ffeeef32b9c950ywan
20233d2500723e5594f3e7c70896ffeeef32b9c950ywanmkvparser::IMkvReader::~IMkvReader()
21233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
22233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
23233d2500723e5594f3e7c70896ffeeef32b9c950ywan
24233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid mkvparser::GetVersion(int& major, int& minor, int& build, int& revision)
25233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
26233d2500723e5594f3e7c70896ffeeef32b9c950ywan    major = 1;
27233d2500723e5594f3e7c70896ffeeef32b9c950ywan    minor = 0;
28233d2500723e5594f3e7c70896ffeeef32b9c950ywan    build = 0;
29233d2500723e5594f3e7c70896ffeeef32b9c950ywan    revision = 27;
30233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
31233d2500723e5594f3e7c70896ffeeef32b9c950ywan
32233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len)
33233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
34233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pReader);
35233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos >= 0);
36233d2500723e5594f3e7c70896ffeeef32b9c950ywan
37233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int status;
38233d2500723e5594f3e7c70896ffeeef32b9c950ywan
39233d2500723e5594f3e7c70896ffeeef32b9c950ywan//#ifdef _DEBUG
40233d2500723e5594f3e7c70896ffeeef32b9c950ywan//    long long total, available;
41233d2500723e5594f3e7c70896ffeeef32b9c950ywan//    status = pReader->Length(&total, &available);
42233d2500723e5594f3e7c70896ffeeef32b9c950ywan//    assert(status >= 0);
43233d2500723e5594f3e7c70896ffeeef32b9c950ywan//    assert((total < 0) || (available <= total));
44233d2500723e5594f3e7c70896ffeeef32b9c950ywan//    assert(pos < available);
45233d2500723e5594f3e7c70896ffeeef32b9c950ywan//    assert((available - pos) >= 1);  //assume here max u-int len is 8
46233d2500723e5594f3e7c70896ffeeef32b9c950ywan//#endif
47233d2500723e5594f3e7c70896ffeeef32b9c950ywan
48233d2500723e5594f3e7c70896ffeeef32b9c950ywan    len = 1;
49233d2500723e5594f3e7c70896ffeeef32b9c950ywan
50233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned char b;
51233d2500723e5594f3e7c70896ffeeef32b9c950ywan
52233d2500723e5594f3e7c70896ffeeef32b9c950ywan    status = pReader->Read(pos, 1, &b);
53233d2500723e5594f3e7c70896ffeeef32b9c950ywan
54233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error or underflow
55233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
56233d2500723e5594f3e7c70896ffeeef32b9c950ywan
57233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status > 0)  //interpreted as "underflow"
58233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_BUFFER_NOT_FULL;
59233d2500723e5594f3e7c70896ffeeef32b9c950ywan
60233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (b == 0)  //we can't handle u-int values larger than 8 bytes
61233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
62233d2500723e5594f3e7c70896ffeeef32b9c950ywan
63233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned char m = 0x80;
64233d2500723e5594f3e7c70896ffeeef32b9c950ywan
65233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (!(b & m))
66233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
67233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m >>= 1;
68233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ++len;
69233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
70233d2500723e5594f3e7c70896ffeeef32b9c950ywan
71233d2500723e5594f3e7c70896ffeeef32b9c950ywan//#ifdef _DEBUG
72233d2500723e5594f3e7c70896ffeeef32b9c950ywan//    assert((available - pos) >= len);
73233d2500723e5594f3e7c70896ffeeef32b9c950ywan//#endif
74233d2500723e5594f3e7c70896ffeeef32b9c950ywan
75233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long result = b & (~m);
76233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ++pos;
77233d2500723e5594f3e7c70896ffeeef32b9c950ywan
78233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (int i = 1; i < len; ++i)
79233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
80233d2500723e5594f3e7c70896ffeeef32b9c950ywan        status = pReader->Read(pos, 1, &b);
81233d2500723e5594f3e7c70896ffeeef32b9c950ywan
82233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)
83233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
84233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
85233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
86233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
87233d2500723e5594f3e7c70896ffeeef32b9c950ywan
88233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status > 0)
89233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
90233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
91233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
92233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
93233d2500723e5594f3e7c70896ffeeef32b9c950ywan
94233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result <<= 8;
95233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result |= b;
96233d2500723e5594f3e7c70896ffeeef32b9c950ywan
97233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ++pos;
98233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
99233d2500723e5594f3e7c70896ffeeef32b9c950ywan
100233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return result;
101233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
102233d2500723e5594f3e7c70896ffeeef32b9c950ywan
103233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long mkvparser::GetUIntLength(
104233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* pReader,
105233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos,
106233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long& len)
107233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
108233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pReader);
109233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos >= 0);
110233d2500723e5594f3e7c70896ffeeef32b9c950ywan
111233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long total, available;
112233d2500723e5594f3e7c70896ffeeef32b9c950ywan
113233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int status = pReader->Length(&total, &available);
114233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(status >= 0);
115233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((total < 0) || (available <= total));
116233d2500723e5594f3e7c70896ffeeef32b9c950ywan
117233d2500723e5594f3e7c70896ffeeef32b9c950ywan    len = 1;
118233d2500723e5594f3e7c70896ffeeef32b9c950ywan
119233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pos >= available)
120233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return pos;  //too few bytes available
121233d2500723e5594f3e7c70896ffeeef32b9c950ywan
122233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned char b;
123233d2500723e5594f3e7c70896ffeeef32b9c950ywan
124233d2500723e5594f3e7c70896ffeeef32b9c950ywan    status = pReader->Read(pos, 1, &b);
125233d2500723e5594f3e7c70896ffeeef32b9c950ywan
126233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)
127233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
128233d2500723e5594f3e7c70896ffeeef32b9c950ywan
129233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(status == 0);
130233d2500723e5594f3e7c70896ffeeef32b9c950ywan
131233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (b == 0)  //we can't handle u-int values larger than 8 bytes
132233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
133233d2500723e5594f3e7c70896ffeeef32b9c950ywan
134233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned char m = 0x80;
135233d2500723e5594f3e7c70896ffeeef32b9c950ywan
136233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (!(b & m))
137233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
138233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m >>= 1;
139233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ++len;
140233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
141233d2500723e5594f3e7c70896ffeeef32b9c950ywan
142233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;  //success
143233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
144233d2500723e5594f3e7c70896ffeeef32b9c950ywan
145233d2500723e5594f3e7c70896ffeeef32b9c950ywan
146233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long mkvparser::UnserializeUInt(
147233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* pReader,
148233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos,
149233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size)
150233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
151233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pReader);
152233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos >= 0);
153233d2500723e5594f3e7c70896ffeeef32b9c950ywan
154233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((size <= 0) || (size > 8))
155233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
156233d2500723e5594f3e7c70896ffeeef32b9c950ywan
157233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long result = 0;
158233d2500723e5594f3e7c70896ffeeef32b9c950ywan
159233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (long long i = 0; i < size; ++i)
160233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
161233d2500723e5594f3e7c70896ffeeef32b9c950ywan        unsigned char b;
162233d2500723e5594f3e7c70896ffeeef32b9c950ywan
163233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long status = pReader->Read(pos, 1, &b);
164233d2500723e5594f3e7c70896ffeeef32b9c950ywan
165233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)
166233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
167233d2500723e5594f3e7c70896ffeeef32b9c950ywan
168233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result <<= 8;
169233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result |= b;
170233d2500723e5594f3e7c70896ffeeef32b9c950ywan
171233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ++pos;
172233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
173233d2500723e5594f3e7c70896ffeeef32b9c950ywan
174233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return result;
175233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
176233d2500723e5594f3e7c70896ffeeef32b9c950ywan
177233d2500723e5594f3e7c70896ffeeef32b9c950ywan
178233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong mkvparser::UnserializeFloat(
179233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* pReader,
180233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos,
181233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size_,
182233d2500723e5594f3e7c70896ffeeef32b9c950ywan    double& result)
183233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
184233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pReader);
185233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos >= 0);
186233d2500723e5594f3e7c70896ffeeef32b9c950ywan
187233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((size_ != 4) && (size_ != 8))
188233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
189233d2500723e5594f3e7c70896ffeeef32b9c950ywan
190233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long size = static_cast<long>(size_);
191233d2500723e5594f3e7c70896ffeeef32b9c950ywan
192233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned char buf[8];
193233d2500723e5594f3e7c70896ffeeef32b9c950ywan
194233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int status = pReader->Read(pos, size, buf);
195233d2500723e5594f3e7c70896ffeeef32b9c950ywan
196233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error
197233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
198233d2500723e5594f3e7c70896ffeeef32b9c950ywan
199233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (size == 4)
200233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
201233d2500723e5594f3e7c70896ffeeef32b9c950ywan        union
202233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
203233d2500723e5594f3e7c70896ffeeef32b9c950ywan            float f;
204233d2500723e5594f3e7c70896ffeeef32b9c950ywan            unsigned long ff;
205233d2500723e5594f3e7c70896ffeeef32b9c950ywan        };
206233d2500723e5594f3e7c70896ffeeef32b9c950ywan
207233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ff = 0;
208233d2500723e5594f3e7c70896ffeeef32b9c950ywan
209233d2500723e5594f3e7c70896ffeeef32b9c950ywan        for (int i = 0;;)
210233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
211233d2500723e5594f3e7c70896ffeeef32b9c950ywan            ff |= buf[i];
212233d2500723e5594f3e7c70896ffeeef32b9c950ywan
213233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (++i >= 4)
214233d2500723e5594f3e7c70896ffeeef32b9c950ywan                break;
215233d2500723e5594f3e7c70896ffeeef32b9c950ywan
216233d2500723e5594f3e7c70896ffeeef32b9c950ywan            ff <<= 8;
217233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
218233d2500723e5594f3e7c70896ffeeef32b9c950ywan
219233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result = f;
220233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
221233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else
222233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
223233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(size == 8);
224233d2500723e5594f3e7c70896ffeeef32b9c950ywan
225233d2500723e5594f3e7c70896ffeeef32b9c950ywan        union
226233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
227233d2500723e5594f3e7c70896ffeeef32b9c950ywan            double d;
228233d2500723e5594f3e7c70896ffeeef32b9c950ywan            unsigned long long dd;
229233d2500723e5594f3e7c70896ffeeef32b9c950ywan        };
230233d2500723e5594f3e7c70896ffeeef32b9c950ywan
231233d2500723e5594f3e7c70896ffeeef32b9c950ywan        dd = 0;
232233d2500723e5594f3e7c70896ffeeef32b9c950ywan
233233d2500723e5594f3e7c70896ffeeef32b9c950ywan        for (int i = 0;;)
234233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
235233d2500723e5594f3e7c70896ffeeef32b9c950ywan            dd |= buf[i];
236233d2500723e5594f3e7c70896ffeeef32b9c950ywan
237233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (++i >= 8)
238233d2500723e5594f3e7c70896ffeeef32b9c950ywan                break;
239233d2500723e5594f3e7c70896ffeeef32b9c950ywan
240233d2500723e5594f3e7c70896ffeeef32b9c950ywan            dd <<= 8;
241233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
242233d2500723e5594f3e7c70896ffeeef32b9c950ywan
243233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result = d;
244233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
245233d2500723e5594f3e7c70896ffeeef32b9c950ywan
246233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
247233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
248233d2500723e5594f3e7c70896ffeeef32b9c950ywan
249233d2500723e5594f3e7c70896ffeeef32b9c950ywan
250233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong mkvparser::UnserializeInt(
251233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* pReader,
252233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos,
253233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long size,
254233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long& result)
255233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
256233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pReader);
257233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos >= 0);
258233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(size > 0);
259233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(size <= 8);
260233d2500723e5594f3e7c70896ffeeef32b9c950ywan
261233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
262233d2500723e5594f3e7c70896ffeeef32b9c950ywan        signed char b;
263233d2500723e5594f3e7c70896ffeeef32b9c950ywan
264233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long status = pReader->Read(pos, 1, (unsigned char*)&b);
265233d2500723e5594f3e7c70896ffeeef32b9c950ywan
266233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)
267233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
268233d2500723e5594f3e7c70896ffeeef32b9c950ywan
269233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result = b;
270233d2500723e5594f3e7c70896ffeeef32b9c950ywan
271233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ++pos;
272233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
273233d2500723e5594f3e7c70896ffeeef32b9c950ywan
274233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (long i = 1; i < size; ++i)
275233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
276233d2500723e5594f3e7c70896ffeeef32b9c950ywan        unsigned char b;
277233d2500723e5594f3e7c70896ffeeef32b9c950ywan
278233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long status = pReader->Read(pos, 1, &b);
279233d2500723e5594f3e7c70896ffeeef32b9c950ywan
280233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)
281233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
282233d2500723e5594f3e7c70896ffeeef32b9c950ywan
283233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result <<= 8;
284233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result |= b;
285233d2500723e5594f3e7c70896ffeeef32b9c950ywan
286233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ++pos;
287233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
288233d2500723e5594f3e7c70896ffeeef32b9c950ywan
289233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;  //success
290233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
291233d2500723e5594f3e7c70896ffeeef32b9c950ywan
292233d2500723e5594f3e7c70896ffeeef32b9c950ywan
293233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong mkvparser::UnserializeString(
294233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* pReader,
295233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos,
296233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size_,
297233d2500723e5594f3e7c70896ffeeef32b9c950ywan    char*& str)
298233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
299233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] str;
300233d2500723e5594f3e7c70896ffeeef32b9c950ywan    str = NULL;
301233d2500723e5594f3e7c70896ffeeef32b9c950ywan
302233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (size_ >= LONG_MAX)  //we need (size+1) chars
303233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
304233d2500723e5594f3e7c70896ffeeef32b9c950ywan
305233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long size = static_cast<long>(size_);
306233d2500723e5594f3e7c70896ffeeef32b9c950ywan
307233d2500723e5594f3e7c70896ffeeef32b9c950ywan    str = new (std::nothrow) char[size+1];
308233d2500723e5594f3e7c70896ffeeef32b9c950ywan
309233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (str == NULL)
310233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
311233d2500723e5594f3e7c70896ffeeef32b9c950ywan
312233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned char* const buf = reinterpret_cast<unsigned char*>(str);
313233d2500723e5594f3e7c70896ffeeef32b9c950ywan
314233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long status = pReader->Read(pos, size, buf);
315233d2500723e5594f3e7c70896ffeeef32b9c950ywan
316233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status)
317233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
318233d2500723e5594f3e7c70896ffeeef32b9c950ywan        delete[] str;
319233d2500723e5594f3e7c70896ffeeef32b9c950ywan        str = NULL;
320233d2500723e5594f3e7c70896ffeeef32b9c950ywan
321233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
322233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
323233d2500723e5594f3e7c70896ffeeef32b9c950ywan
324233d2500723e5594f3e7c70896ffeeef32b9c950ywan    str[size] = '\0';
325233d2500723e5594f3e7c70896ffeeef32b9c950ywan
326233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;  //success
327233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
328233d2500723e5594f3e7c70896ffeeef32b9c950ywan
329233d2500723e5594f3e7c70896ffeeef32b9c950ywan
330233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong mkvparser::ParseElementHeader(
331233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* pReader,
332233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long& pos,
333233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long stop,
334233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long& id,
335233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long& size)
336233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
337233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((stop >= 0) && (pos >= stop))
338233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
339233d2500723e5594f3e7c70896ffeeef32b9c950ywan
340233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long len;
341233d2500723e5594f3e7c70896ffeeef32b9c950ywan
342233d2500723e5594f3e7c70896ffeeef32b9c950ywan    id = ReadUInt(pReader, pos, len);
343233d2500723e5594f3e7c70896ffeeef32b9c950ywan
344233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (id < 0)
345233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
346233d2500723e5594f3e7c70896ffeeef32b9c950ywan
347233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += len;  //consume id
348233d2500723e5594f3e7c70896ffeeef32b9c950ywan
349233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((stop >= 0) && (pos >= stop))
350233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
351233d2500723e5594f3e7c70896ffeeef32b9c950ywan
352233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size = ReadUInt(pReader, pos, len);
353233d2500723e5594f3e7c70896ffeeef32b9c950ywan
354233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (size < 0)
355233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
356233d2500723e5594f3e7c70896ffeeef32b9c950ywan
357233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += len;  //consume length of size
358233d2500723e5594f3e7c70896ffeeef32b9c950ywan
359233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //pos now designates payload
360233d2500723e5594f3e7c70896ffeeef32b9c950ywan
361233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((stop >= 0) && ((pos + size) > stop))
362233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
363233d2500723e5594f3e7c70896ffeeef32b9c950ywan
364233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;  //success
365233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
366233d2500723e5594f3e7c70896ffeeef32b9c950ywan
367233d2500723e5594f3e7c70896ffeeef32b9c950ywan
368233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool mkvparser::Match(
369233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* pReader,
370233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long& pos,
371233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned long id_,
372233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long& val)
373233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
374233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pReader);
375233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos >= 0);
376233d2500723e5594f3e7c70896ffeeef32b9c950ywan
377233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long total, available;
378233d2500723e5594f3e7c70896ffeeef32b9c950ywan
379233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long status = pReader->Length(&total, &available);
380233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(status >= 0);
381233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((total < 0) || (available <= total));
382233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)
383233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
384233d2500723e5594f3e7c70896ffeeef32b9c950ywan
385233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long len;
386233d2500723e5594f3e7c70896ffeeef32b9c950ywan
387233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long id = ReadUInt(pReader, pos, len);
388233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(id >= 0);
389233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(len > 0);
390233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(len <= 8);
391233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((pos + len) <= available);
392233d2500723e5594f3e7c70896ffeeef32b9c950ywan
393233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((unsigned long)id != id_)
394233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
395233d2500723e5594f3e7c70896ffeeef32b9c950ywan
396233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += len;  //consume id
397233d2500723e5594f3e7c70896ffeeef32b9c950ywan
398233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long size = ReadUInt(pReader, pos, len);
399233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(size >= 0);
400233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(size <= 8);
401233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(len > 0);
402233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(len <= 8);
403233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((pos + len) <= available);
404233d2500723e5594f3e7c70896ffeeef32b9c950ywan
405233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += len;  //consume length of size of payload
406233d2500723e5594f3e7c70896ffeeef32b9c950ywan
407233d2500723e5594f3e7c70896ffeeef32b9c950ywan    val = UnserializeUInt(pReader, pos, size);
408233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(val >= 0);
409233d2500723e5594f3e7c70896ffeeef32b9c950ywan
410233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += size;  //consume size of payload
411233d2500723e5594f3e7c70896ffeeef32b9c950ywan
412233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return true;
413233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
414233d2500723e5594f3e7c70896ffeeef32b9c950ywan
415233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool mkvparser::Match(
416233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* pReader,
417233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long& pos,
418233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned long id_,
419233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned char*& buf,
420233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size_t& buflen)
421233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
422233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pReader);
423233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos >= 0);
424233d2500723e5594f3e7c70896ffeeef32b9c950ywan
425233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long total, available;
426233d2500723e5594f3e7c70896ffeeef32b9c950ywan
427233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long status = pReader->Length(&total, &available);
428233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(status >= 0);
429233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((total < 0) || (available <= total));
430233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)
431233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
432233d2500723e5594f3e7c70896ffeeef32b9c950ywan
433233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long len;
434233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long id = ReadUInt(pReader, pos, len);
435233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(id >= 0);
436233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(len > 0);
437233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(len <= 8);
438233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((pos + len) <= available);
439233d2500723e5594f3e7c70896ffeeef32b9c950ywan
440233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((unsigned long)id != id_)
441233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
442233d2500723e5594f3e7c70896ffeeef32b9c950ywan
443233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += len;  //consume id
444233d2500723e5594f3e7c70896ffeeef32b9c950ywan
445233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long size_ = ReadUInt(pReader, pos, len);
446233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(size_ >= 0);
447233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(len > 0);
448233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(len <= 8);
449233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((pos + len) <= available);
450233d2500723e5594f3e7c70896ffeeef32b9c950ywan
451233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += len;  //consume length of size of payload
452233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((pos + size_) <= available);
453233d2500723e5594f3e7c70896ffeeef32b9c950ywan
454233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long buflen_ = static_cast<long>(size_);
455233d2500723e5594f3e7c70896ffeeef32b9c950ywan
456233d2500723e5594f3e7c70896ffeeef32b9c950ywan    buf = new (std::nothrow) unsigned char[buflen_];
457233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(buf);  //TODO
458233d2500723e5594f3e7c70896ffeeef32b9c950ywan
459233d2500723e5594f3e7c70896ffeeef32b9c950ywan    status = pReader->Read(pos, buflen_, buf);
460233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(status == 0);  //TODO
461233d2500723e5594f3e7c70896ffeeef32b9c950ywan
462233d2500723e5594f3e7c70896ffeeef32b9c950ywan    buflen = buflen_;
463233d2500723e5594f3e7c70896ffeeef32b9c950ywan
464233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += size_;  //consume size of payload
465233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return true;
466233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
467233d2500723e5594f3e7c70896ffeeef32b9c950ywan
468233d2500723e5594f3e7c70896ffeeef32b9c950ywan
469233d2500723e5594f3e7c70896ffeeef32b9c950ywannamespace mkvparser
470233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
471233d2500723e5594f3e7c70896ffeeef32b9c950ywan
472233d2500723e5594f3e7c70896ffeeef32b9c950ywanEBMLHeader::EBMLHeader() :
473233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_docType(NULL)
474233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
475233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Init();
476233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
477233d2500723e5594f3e7c70896ffeeef32b9c950ywan
478233d2500723e5594f3e7c70896ffeeef32b9c950ywanEBMLHeader::~EBMLHeader()
479233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
480233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] m_docType;
481233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
482233d2500723e5594f3e7c70896ffeeef32b9c950ywan
483233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid EBMLHeader::Init()
484233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
485233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_version = 1;
486233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_readVersion = 1;
487233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_maxIdLength = 4;
488233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_maxSizeLength = 8;
489233d2500723e5594f3e7c70896ffeeef32b9c950ywan
490233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_docType)
491233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
492233d2500723e5594f3e7c70896ffeeef32b9c950ywan        delete[] m_docType;
493233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m_docType = NULL;
494233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
495233d2500723e5594f3e7c70896ffeeef32b9c950ywan
496233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_docTypeVersion = 1;
497233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_docTypeReadVersion = 1;
498233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
499233d2500723e5594f3e7c70896ffeeef32b9c950ywan
500233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long EBMLHeader::Parse(
501233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* pReader,
502233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long& pos)
503233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
504233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pReader);
505233d2500723e5594f3e7c70896ffeeef32b9c950ywan
506233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long total, available;
507233d2500723e5594f3e7c70896ffeeef32b9c950ywan
508233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long status = pReader->Length(&total, &available);
509233d2500723e5594f3e7c70896ffeeef32b9c950ywan
510233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error
511233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
512233d2500723e5594f3e7c70896ffeeef32b9c950ywan
513233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos = 0;
514233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long end = (available >= 1024) ? 1024 : available;
515233d2500723e5594f3e7c70896ffeeef32b9c950ywan
516233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (;;)
517233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
518233d2500723e5594f3e7c70896ffeeef32b9c950ywan        unsigned char b = 0;
519233d2500723e5594f3e7c70896ffeeef32b9c950ywan
520233d2500723e5594f3e7c70896ffeeef32b9c950ywan        while (pos < end)
521233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
522233d2500723e5594f3e7c70896ffeeef32b9c950ywan            status = pReader->Read(pos, 1, &b);
523233d2500723e5594f3e7c70896ffeeef32b9c950ywan
524233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status < 0)  //error
525233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return status;
526233d2500723e5594f3e7c70896ffeeef32b9c950ywan
527233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (b == 0x1A)
528233d2500723e5594f3e7c70896ffeeef32b9c950ywan                break;
529233d2500723e5594f3e7c70896ffeeef32b9c950ywan
530233d2500723e5594f3e7c70896ffeeef32b9c950ywan            ++pos;
531233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
532233d2500723e5594f3e7c70896ffeeef32b9c950ywan
533233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (b != 0x1A)
534233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
535233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (pos >= 1024)
536233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;  //don't bother looking anymore
537233d2500723e5594f3e7c70896ffeeef32b9c950ywan
538233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((total >= 0) && ((total - available) < 5))
539233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
540233d2500723e5594f3e7c70896ffeeef32b9c950ywan
541233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return available + 5;  //5 = 4-byte ID + 1st byte of size
542233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
543233d2500723e5594f3e7c70896ffeeef32b9c950ywan
544233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((total >= 0) && ((total - pos) < 5))
545233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
546233d2500723e5594f3e7c70896ffeeef32b9c950ywan
547233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((available - pos) < 5)
548233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return pos + 5;  //try again later
549233d2500723e5594f3e7c70896ffeeef32b9c950ywan
550233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long len;
551233d2500723e5594f3e7c70896ffeeef32b9c950ywan
552233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long result = ReadUInt(pReader, pos, len);
553233d2500723e5594f3e7c70896ffeeef32b9c950ywan
554233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
555233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return result;
556233d2500723e5594f3e7c70896ffeeef32b9c950ywan
557233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result == 0x0A45DFA3)  //EBML Header ID
558233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
559233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pos += len;  //consume ID
560233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
561233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
562233d2500723e5594f3e7c70896ffeeef32b9c950ywan
563233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ++pos;  //throw away just the 0x1A byte, and try again
564233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
565233d2500723e5594f3e7c70896ffeeef32b9c950ywan
566233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //pos designates start of size field
567233d2500723e5594f3e7c70896ffeeef32b9c950ywan
568233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //get length of size field
569233d2500723e5594f3e7c70896ffeeef32b9c950ywan
570233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long len;
571233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long result = GetUIntLength(pReader, pos, len);
572233d2500723e5594f3e7c70896ffeeef32b9c950ywan
573233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (result < 0)  //error
574233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return result;
575233d2500723e5594f3e7c70896ffeeef32b9c950ywan
576233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (result > 0)  //need more data
577233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return result;
578233d2500723e5594f3e7c70896ffeeef32b9c950ywan
579233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(len > 0);
580233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(len <= 8);
581233d2500723e5594f3e7c70896ffeeef32b9c950ywan
582233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((total >= 0) && ((total -  pos) < len))
583233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
584233d2500723e5594f3e7c70896ffeeef32b9c950ywan
585233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((available - pos) < len)
586233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return pos + len;  //try again later
587233d2500723e5594f3e7c70896ffeeef32b9c950ywan
588233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //get the EBML header size
589233d2500723e5594f3e7c70896ffeeef32b9c950ywan
590233d2500723e5594f3e7c70896ffeeef32b9c950ywan    result = ReadUInt(pReader, pos, len);
591233d2500723e5594f3e7c70896ffeeef32b9c950ywan
592233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (result < 0)  //error
593233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return result;
594233d2500723e5594f3e7c70896ffeeef32b9c950ywan
595233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += len;  //consume size field
596233d2500723e5594f3e7c70896ffeeef32b9c950ywan
597233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //pos now designates start of payload
598233d2500723e5594f3e7c70896ffeeef32b9c950ywan
599233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((total >= 0) && ((total - pos) < result))
600233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
601233d2500723e5594f3e7c70896ffeeef32b9c950ywan
602233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((available - pos) < result)
603233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return pos + result;
604233d2500723e5594f3e7c70896ffeeef32b9c950ywan
605233d2500723e5594f3e7c70896ffeeef32b9c950ywan    end = pos + result;
606233d2500723e5594f3e7c70896ffeeef32b9c950ywan
607233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Init();
608233d2500723e5594f3e7c70896ffeeef32b9c950ywan
609233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (pos < end)
610233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
611233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long id, size;
612233d2500723e5594f3e7c70896ffeeef32b9c950ywan
613233d2500723e5594f3e7c70896ffeeef32b9c950ywan        status = ParseElementHeader(
614233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    pReader,
615233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    pos,
616233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    end,
617233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    id,
618233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    size);
619233d2500723e5594f3e7c70896ffeeef32b9c950ywan
620233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0) //error
621233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
622233d2500723e5594f3e7c70896ffeeef32b9c950ywan
623233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == 0)  //weird
624233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
625233d2500723e5594f3e7c70896ffeeef32b9c950ywan
626233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x0286)  //version
627233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
628233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_version = UnserializeUInt(pReader, pos, size);
629233d2500723e5594f3e7c70896ffeeef32b9c950ywan
630233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_version <= 0)
631233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
632233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
633233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x02F7)  //read version
634233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
635233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_readVersion = UnserializeUInt(pReader, pos, size);
636233d2500723e5594f3e7c70896ffeeef32b9c950ywan
637233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_readVersion <= 0)
638233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
639233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
640233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x02F2)  //max id length
641233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
642233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_maxIdLength = UnserializeUInt(pReader, pos, size);
643233d2500723e5594f3e7c70896ffeeef32b9c950ywan
644233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_maxIdLength <= 0)
645233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
646233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
647233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x02F3)  //max size length
648233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
649233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_maxSizeLength = UnserializeUInt(pReader, pos, size);
650233d2500723e5594f3e7c70896ffeeef32b9c950ywan
651233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_maxSizeLength <= 0)
652233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
653233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
654233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x0282)  //doctype
655233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
656233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_docType)
657233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
658233d2500723e5594f3e7c70896ffeeef32b9c950ywan
659233d2500723e5594f3e7c70896ffeeef32b9c950ywan            status = UnserializeString(pReader, pos, size, m_docType);
660233d2500723e5594f3e7c70896ffeeef32b9c950ywan
661233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status)  //error
662233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return status;
663233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
664233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x0287)  //doctype version
665233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
666233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_docTypeVersion = UnserializeUInt(pReader, pos, size);
667233d2500723e5594f3e7c70896ffeeef32b9c950ywan
668233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_docTypeVersion <= 0)
669233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
670233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
671233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x0285)  //doctype read version
672233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
673233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_docTypeReadVersion = UnserializeUInt(pReader, pos, size);
674233d2500723e5594f3e7c70896ffeeef32b9c950ywan
675233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_docTypeReadVersion <= 0)
676233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
677233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
678233d2500723e5594f3e7c70896ffeeef32b9c950ywan
679233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;
680233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
681233d2500723e5594f3e7c70896ffeeef32b9c950ywan
682233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos == end);
683233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
684233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
685233d2500723e5594f3e7c70896ffeeef32b9c950ywan
686233d2500723e5594f3e7c70896ffeeef32b9c950ywan
687233d2500723e5594f3e7c70896ffeeef32b9c950ywanSegment::Segment(
688233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* pReader,
689233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long elem_start,
690233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //long long elem_size,
691233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long start,
692233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size) :
693233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pReader(pReader),
694233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_element_start(elem_start),
695233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //m_element_size(elem_size),
696233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_start(start),
697233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_size(size),
698233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pos(start),
699233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pUnknownSize(0),
700233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pSeekHead(NULL),
701233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pInfo(NULL),
702233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pTracks(NULL),
703233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pCues(NULL),
704233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pChapters(NULL),
705233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_clusters(NULL),
706233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_clusterCount(0),
707233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_clusterPreloadCount(0),
708233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_clusterSize(0)
709233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
710233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
711233d2500723e5594f3e7c70896ffeeef32b9c950ywan
712233d2500723e5594f3e7c70896ffeeef32b9c950ywan
713233d2500723e5594f3e7c70896ffeeef32b9c950ywanSegment::~Segment()
714233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
715233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long count = m_clusterCount + m_clusterPreloadCount;
716233d2500723e5594f3e7c70896ffeeef32b9c950ywan
717233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** i = m_clusters;
718233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** j = m_clusters + count;
719233d2500723e5594f3e7c70896ffeeef32b9c950ywan
720233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (i != j)
721233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
722233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster* const p = *i++;
723233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(p);
724233d2500723e5594f3e7c70896ffeeef32b9c950ywan
725233d2500723e5594f3e7c70896ffeeef32b9c950ywan        delete p;
726233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
727233d2500723e5594f3e7c70896ffeeef32b9c950ywan
728233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] m_clusters;
729233d2500723e5594f3e7c70896ffeeef32b9c950ywan
730233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete m_pTracks;
731233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete m_pInfo;
732233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete m_pCues;
733233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete m_pChapters;
734233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete m_pSeekHead;
735233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
736233d2500723e5594f3e7c70896ffeeef32b9c950ywan
737233d2500723e5594f3e7c70896ffeeef32b9c950ywan
738233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long Segment::CreateInstance(
739233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* pReader,
740233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos,
741233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Segment*& pSegment)
742233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
743233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pReader);
744233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos >= 0);
745233d2500723e5594f3e7c70896ffeeef32b9c950ywan
746233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pSegment = NULL;
747233d2500723e5594f3e7c70896ffeeef32b9c950ywan
748233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long total, available;
749233d2500723e5594f3e7c70896ffeeef32b9c950ywan
750233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long status = pReader->Length(&total, &available);
751233d2500723e5594f3e7c70896ffeeef32b9c950ywan
752233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0) //error
753233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
754233d2500723e5594f3e7c70896ffeeef32b9c950ywan
755233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (available < 0)
756233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
757233d2500723e5594f3e7c70896ffeeef32b9c950ywan
758233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((total >= 0) && (available > total))
759233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
760233d2500723e5594f3e7c70896ffeeef32b9c950ywan
761233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //I would assume that in practice this loop would execute
762233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //exactly once, but we allow for other elements (e.g. Void)
763233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //to immediately follow the EBML header.  This is fine for
764233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //the source filter case (since the entire file is available),
765233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //but in the splitter case over a network we should probably
766233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //just give up early.  We could for example decide only to
767233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //execute this loop a maximum of, say, 10 times.
768233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //TODO:
769233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //There is an implied "give up early" by only parsing up
770233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //to the available limit.  We do do that, but only if the
771233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //total file size is unknown.  We could decide to always
772233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //use what's available as our limit (irrespective of whether
773233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //we happen to know the total file length).  This would have
774233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //as its sense "parse this much of the file before giving up",
775233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //which a slightly different sense from "try to parse up to
776233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //10 EMBL elements before giving up".
777233d2500723e5594f3e7c70896ffeeef32b9c950ywan
778233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (;;)
779233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
780233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((total >= 0) && (pos >= total))
781233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
782233d2500723e5594f3e7c70896ffeeef32b9c950ywan
783233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Read ID
784233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long len;
785233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long result = GetUIntLength(pReader, pos, len);
786233d2500723e5594f3e7c70896ffeeef32b9c950ywan
787233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result)  //error, or too few available bytes
788233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return result;
789233d2500723e5594f3e7c70896ffeeef32b9c950ywan
790233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((total >= 0) && ((pos + len) > total))
791233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
792233d2500723e5594f3e7c70896ffeeef32b9c950ywan
793233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > available)
794233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return pos + len;
795233d2500723e5594f3e7c70896ffeeef32b9c950ywan
796233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long idpos = pos;
797233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id = ReadUInt(pReader, pos, len);
798233d2500723e5594f3e7c70896ffeeef32b9c950ywan
799233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id < 0)  //error
800233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return id;
801233d2500723e5594f3e7c70896ffeeef32b9c950ywan
802233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume ID
803233d2500723e5594f3e7c70896ffeeef32b9c950ywan
804233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Read Size
805233d2500723e5594f3e7c70896ffeeef32b9c950ywan
806233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result = GetUIntLength(pReader, pos, len);
807233d2500723e5594f3e7c70896ffeeef32b9c950ywan
808233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result)  //error, or too few available bytes
809233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return result;
810233d2500723e5594f3e7c70896ffeeef32b9c950ywan
811233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((total >= 0) && ((pos + len) > total))
812233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
813233d2500723e5594f3e7c70896ffeeef32b9c950ywan
814233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > available)
815233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return pos + len;
816233d2500723e5594f3e7c70896ffeeef32b9c950ywan
817233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long size = ReadUInt(pReader, pos, len);
818233d2500723e5594f3e7c70896ffeeef32b9c950ywan
819233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size < 0)  //error
820233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return size;
821233d2500723e5594f3e7c70896ffeeef32b9c950ywan
822233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume length of size of element
823233d2500723e5594f3e7c70896ffeeef32b9c950ywan
824233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Pos now points to start of payload
825233d2500723e5594f3e7c70896ffeeef32b9c950ywan
826233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Handle "unknown size" for live streaming of webm files.
827233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long unknown_size = (1LL << (7 * len)) - 1;
828233d2500723e5594f3e7c70896ffeeef32b9c950ywan
829233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x08538067)  //Segment ID
830233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
831233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (size == unknown_size)
832233d2500723e5594f3e7c70896ffeeef32b9c950ywan                size = -1;
833233d2500723e5594f3e7c70896ffeeef32b9c950ywan
834233d2500723e5594f3e7c70896ffeeef32b9c950ywan            else if (total < 0)
835233d2500723e5594f3e7c70896ffeeef32b9c950ywan                size = -1;
836233d2500723e5594f3e7c70896ffeeef32b9c950ywan
837233d2500723e5594f3e7c70896ffeeef32b9c950ywan            else if ((pos + size) > total)
838233d2500723e5594f3e7c70896ffeeef32b9c950ywan                size = -1;
839233d2500723e5594f3e7c70896ffeeef32b9c950ywan
840233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pSegment = new (std::nothrow) Segment(
841233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                            pReader,
842233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                            idpos,
843233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                            //elem_size
844233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                            pos,
845233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                            size);
846233d2500723e5594f3e7c70896ffeeef32b9c950ywan
847233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (pSegment == 0)
848233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return -1;  //generic error
849233d2500723e5594f3e7c70896ffeeef32b9c950ywan
850233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 0;    //success
851233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
852233d2500723e5594f3e7c70896ffeeef32b9c950ywan
853233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == unknown_size)
854233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
855233d2500723e5594f3e7c70896ffeeef32b9c950ywan
856233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((total >= 0) && ((pos + size) > total))
857233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
858233d2500723e5594f3e7c70896ffeeef32b9c950ywan
859233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + size) > available)
860233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return pos + size;
861233d2500723e5594f3e7c70896ffeeef32b9c950ywan
862233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;  //consume payload
863233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
864233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
865233d2500723e5594f3e7c70896ffeeef32b9c950ywan
866233d2500723e5594f3e7c70896ffeeef32b9c950ywan
867233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long Segment::ParseHeaders()
868233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
869233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //Outermost (level 0) segment object has been constructed,
870233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //and pos designates start of payload.  We need to find the
871233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //inner (level 1) elements.
872233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long total, available;
873233d2500723e5594f3e7c70896ffeeef32b9c950ywan
874233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int status = m_pReader->Length(&total, &available);
875233d2500723e5594f3e7c70896ffeeef32b9c950ywan
876233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0) //error
877233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
878233d2500723e5594f3e7c70896ffeeef32b9c950ywan
879233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((total < 0) || (available <= total));
880233d2500723e5594f3e7c70896ffeeef32b9c950ywan
881233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
882233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((segment_stop < 0) || (total < 0) || (segment_stop <= total));
883233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((segment_stop < 0) || (m_pos <= segment_stop));
884233d2500723e5594f3e7c70896ffeeef32b9c950ywan
885233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (;;)
886233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
887233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((total >= 0) && (m_pos >= total))
888233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
889233d2500723e5594f3e7c70896ffeeef32b9c950ywan
890233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((segment_stop >= 0) && (m_pos >= segment_stop))
891233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
892233d2500723e5594f3e7c70896ffeeef32b9c950ywan
893233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long pos = m_pos;
894233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long element_start = pos;
895233d2500723e5594f3e7c70896ffeeef32b9c950ywan
896233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > available)
897233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return (pos + 1);
898233d2500723e5594f3e7c70896ffeeef32b9c950ywan
899233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long len;
900233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long result = GetUIntLength(m_pReader, pos, len);
901233d2500723e5594f3e7c70896ffeeef32b9c950ywan
902233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
903233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return result;
904233d2500723e5594f3e7c70896ffeeef32b9c950ywan
905233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //underflow (weird)
906233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return (pos + 1);
907233d2500723e5594f3e7c70896ffeeef32b9c950ywan
908233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((segment_stop >= 0) && ((pos + len) > segment_stop))
909233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
910233d2500723e5594f3e7c70896ffeeef32b9c950ywan
911233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > available)
912233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return pos + len;
913233d2500723e5594f3e7c70896ffeeef32b9c950ywan
914233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long idpos = pos;
915233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id = ReadUInt(m_pReader, idpos, len);
916233d2500723e5594f3e7c70896ffeeef32b9c950ywan
917233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id < 0)  //error
918233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return id;
919233d2500723e5594f3e7c70896ffeeef32b9c950ywan
920233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x0F43B675)  //Cluster ID
921233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
922233d2500723e5594f3e7c70896ffeeef32b9c950ywan
923233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume ID
924233d2500723e5594f3e7c70896ffeeef32b9c950ywan
925233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > available)
926233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return (pos + 1);
927233d2500723e5594f3e7c70896ffeeef32b9c950ywan
928233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Read Size
929233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result = GetUIntLength(m_pReader, pos, len);
930233d2500723e5594f3e7c70896ffeeef32b9c950ywan
931233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
932233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return result;
933233d2500723e5594f3e7c70896ffeeef32b9c950ywan
934233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //underflow (weird)
935233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return (pos + 1);
936233d2500723e5594f3e7c70896ffeeef32b9c950ywan
937233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((segment_stop >= 0) && ((pos + len) > segment_stop))
938233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
939233d2500723e5594f3e7c70896ffeeef32b9c950ywan
940233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > available)
941233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return pos + len;
942233d2500723e5594f3e7c70896ffeeef32b9c950ywan
943233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long size = ReadUInt(m_pReader, pos, len);
944233d2500723e5594f3e7c70896ffeeef32b9c950ywan
945233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size < 0)  //error
946233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return size;
947233d2500723e5594f3e7c70896ffeeef32b9c950ywan
948233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume length of size of element
949233d2500723e5594f3e7c70896ffeeef32b9c950ywan
950233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long element_size = size + pos - element_start;
951233d2500723e5594f3e7c70896ffeeef32b9c950ywan
952233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Pos now points to start of payload
953233d2500723e5594f3e7c70896ffeeef32b9c950ywan
954233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((segment_stop >= 0) && ((pos + size) > segment_stop))
955233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
956233d2500723e5594f3e7c70896ffeeef32b9c950ywan
957233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //We read EBML elements either in total or nothing at all.
958233d2500723e5594f3e7c70896ffeeef32b9c950ywan
959233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + size) > available)
960233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return pos + size;
961233d2500723e5594f3e7c70896ffeeef32b9c950ywan
962233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x0549A966)  //Segment Info ID
963233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
964233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_pInfo)
965233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
966233d2500723e5594f3e7c70896ffeeef32b9c950ywan
967233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_pInfo = new (std::nothrow) SegmentInfo(
968233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                          this,
969233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                          pos,
970233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                          size,
971233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                          element_start,
972233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                          element_size);
973233d2500723e5594f3e7c70896ffeeef32b9c950ywan
974233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_pInfo == NULL)
975233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return -1;
976233d2500723e5594f3e7c70896ffeeef32b9c950ywan
977233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long status = m_pInfo->Parse();
978233d2500723e5594f3e7c70896ffeeef32b9c950ywan
979233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status)
980233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return status;
981233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
982233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x0654AE6B)  //Tracks ID
983233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
984233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_pTracks)
985233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
986233d2500723e5594f3e7c70896ffeeef32b9c950ywan
987233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_pTracks = new (std::nothrow) Tracks(this,
988233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  pos,
989233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  size,
990233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  element_start,
991233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                  element_size);
992233d2500723e5594f3e7c70896ffeeef32b9c950ywan
993233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_pTracks == NULL)
994233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return -1;
995233d2500723e5594f3e7c70896ffeeef32b9c950ywan
996233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long status = m_pTracks->Parse();
997233d2500723e5594f3e7c70896ffeeef32b9c950ywan
998233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status)
999233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return status;
1000233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1001233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x0C53BB6B)  //Cues ID
1002233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
1003233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_pCues == NULL)
1004233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
1005233d2500723e5594f3e7c70896ffeeef32b9c950ywan                m_pCues = new (std::nothrow) Cues(
1006233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                this,
1007233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                pos,
1008233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                size,
1009233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                element_start,
1010233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                element_size);
1011233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1012233d2500723e5594f3e7c70896ffeeef32b9c950ywan                if (m_pCues == NULL)
1013233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    return -1;
1014233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
1015233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1016233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x014D9B74)  //SeekHead ID
1017233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
1018233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_pSeekHead == NULL)
1019233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
1020233d2500723e5594f3e7c70896ffeeef32b9c950ywan                m_pSeekHead = new (std::nothrow) SeekHead(
1021233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    this,
1022233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    pos,
1023233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    size,
1024233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    element_start,
1025233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    element_size);
1026233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1027233d2500723e5594f3e7c70896ffeeef32b9c950ywan                if (m_pSeekHead == NULL)
1028233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    return -1;
1029233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1030233d2500723e5594f3e7c70896ffeeef32b9c950ywan                const long status = m_pSeekHead->Parse();
1031233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1032233d2500723e5594f3e7c70896ffeeef32b9c950ywan                if (status)
1033233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    return status;
1034233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
1035233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1036233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x0043A770)  //Chapters ID
1037233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
1038233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_pChapters == NULL)
1039233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
1040233d2500723e5594f3e7c70896ffeeef32b9c950ywan                m_pChapters = new (std::nothrow) Chapters(
1041233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                this,
1042233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                pos,
1043233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                size,
1044233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                element_start,
1045233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                element_size);
1046233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1047233d2500723e5594f3e7c70896ffeeef32b9c950ywan                if (m_pChapters == NULL)
1048233d2500723e5594f3e7c70896ffeeef32b9c950ywan                  return -1;
1049233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1050233d2500723e5594f3e7c70896ffeeef32b9c950ywan                const long status = m_pChapters->Parse();
1051233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1052233d2500723e5594f3e7c70896ffeeef32b9c950ywan                if (status)
1053233d2500723e5594f3e7c70896ffeeef32b9c950ywan                  return status;
1054233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
1055233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1056233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1057233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m_pos = pos + size;  //consume payload
1058233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1059233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1060233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((segment_stop < 0) || (m_pos <= segment_stop));
1061233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1062233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_pInfo == NULL)  //TODO: liberalize this behavior
1063233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
1064233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1065233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_pTracks == NULL)
1066233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
1067233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1068233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;  //success
1069233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1070233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1071233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1072233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Segment::LoadCluster(
1073233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long& pos,
1074233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long& len)
1075233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1076233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (;;)
1077233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
1078233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long result = DoLoadCluster(pos, len);
1079233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1080233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result <= 1)
1081233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return result;
1082233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1083233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1084233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1085233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1086233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Segment::DoLoadCluster(
1087233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long& pos,
1088233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long& len)
1089233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1090233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_pos < 0)
1091233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return DoLoadClusterUnknownSize(pos, len);
1092233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1093233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long total, avail;
1094233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1095233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long status = m_pReader->Length(&total, &avail);
1096233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1097233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error
1098233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
1099233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1100233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((total < 0) || (avail <= total));
1101233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1102233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
1103233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1104233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long cluster_off = -1;   //offset relative to start of segment
1105233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long cluster_size = -1;  //size of cluster payload
1106233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1107233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (;;)
1108233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
1109233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((total >= 0) && (m_pos >= total))
1110233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 1;  //no more clusters
1111233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1112233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((segment_stop >= 0) && (m_pos >= segment_stop))
1113233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 1;  //no more clusters
1114233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1115233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos = m_pos;
1116233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1117233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Read ID
1118233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1119233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > avail)
1120233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
1121233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
1122233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
1123233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1124233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1125233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long result = GetUIntLength(m_pReader, pos, len);
1126233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1127233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
1128233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(result);
1129233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1130233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //weird
1131233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
1132233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1133233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((segment_stop >= 0) && ((pos + len) > segment_stop))
1134233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
1135233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1136233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > avail)
1137233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
1138233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1139233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long idpos = pos;
1140233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id = ReadUInt(m_pReader, idpos, len);
1141233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1142233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id < 0)  //error (or underflow)
1143233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(id);
1144233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1145233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume ID
1146233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1147233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Read Size
1148233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1149233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > avail)
1150233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
1151233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
1152233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
1153233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1154233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1155233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result = GetUIntLength(m_pReader, pos, len);
1156233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1157233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
1158233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(result);
1159233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1160233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //weird
1161233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
1162233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1163233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((segment_stop >= 0) && ((pos + len) > segment_stop))
1164233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
1165233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1166233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > avail)
1167233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
1168233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1169233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long size = ReadUInt(m_pReader, pos, len);
1170233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1171233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size < 0)  //error
1172233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(size);
1173233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1174233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume length of size of element
1175233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1176233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //pos now points to start of payload
1177233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1178233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == 0)  //weird
1179233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
1180233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_pos = pos;
1181233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
1182233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1183233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1184233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long unknown_size = (1LL << (7 * len)) - 1;
1185233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1186233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0  //we must handle this to support live webm
1187233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == unknown_size)
1188233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;  //TODO: allow this
1189233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
1190233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1191233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((segment_stop >= 0) &&
1192233d2500723e5594f3e7c70896ffeeef32b9c950ywan            (size != unknown_size) &&
1193233d2500723e5594f3e7c70896ffeeef32b9c950ywan            ((pos + size) > segment_stop))
1194233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
1195233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
1196233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1197233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1198233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0  //commented-out, to support incremental cluster parsing
1199233d2500723e5594f3e7c70896ffeeef32b9c950ywan        len = static_cast<long>(size);
1200233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1201233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + size) > avail)
1202233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
1203233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
1204233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1205233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x0C53BB6B)  //Cues ID
1206233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
1207233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (size == unknown_size)
1208233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;  //TODO: liberalize
1209233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1210233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_pCues == NULL)
1211233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
1212233d2500723e5594f3e7c70896ffeeef32b9c950ywan                const long long element_size = (pos - idpos) + size;
1213233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1214233d2500723e5594f3e7c70896ffeeef32b9c950ywan                m_pCues = new Cues(this,
1215233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                   pos,
1216233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                   size,
1217233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                   idpos,
1218233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                   element_size);
1219233d2500723e5594f3e7c70896ffeeef32b9c950ywan                assert(m_pCues);  //TODO
1220233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
1221233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1222233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_pos = pos + size;  //consume payload
1223233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
1224233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1225233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1226233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id != 0x0F43B675)  //Cluster ID
1227233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
1228233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (size == unknown_size)
1229233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;  //TODO: liberalize
1230233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1231233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_pos = pos + size;  //consume payload
1232233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
1233233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1234233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1235233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //We have a cluster.
1236233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1237233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cluster_off = idpos - m_start;  //relative pos
1238233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1239233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size != unknown_size)
1240233d2500723e5594f3e7c70896ffeeef32b9c950ywan            cluster_size = size;
1241233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1242233d2500723e5594f3e7c70896ffeeef32b9c950ywan        break;
1243233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1244233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1245233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(cluster_off >= 0);  //have cluster
1246233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1247233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos_;
1248233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long len_;
1249233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1250233d2500723e5594f3e7c70896ffeeef32b9c950ywan    status = Cluster::HasBlockEntries(this, cluster_off, pos_, len_);
1251233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1252233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0) //error, or underflow
1253233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
1254233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos = pos_;
1255233d2500723e5594f3e7c70896ffeeef32b9c950ywan        len = len_;
1256233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1257233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
1258233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1259233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1260233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //status == 0 means "no block entries found"
1261233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //status > 0 means "found at least one block entry"
1262233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1263233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //TODO:
1264233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //The issue here is that the segment increments its own
1265233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //pos ptr past the most recent cluster parsed, and then
1266233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //starts from there to parse the next cluster.  If we
1267233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //don't know the size of the current cluster, then we
1268233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //must either parse its payload (as we do below), looking
1269233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //for the cluster (or cues) ID to terminate the parse.
1270233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //This isn't really what we want: rather, we really need
1271233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //a way to create the curr cluster object immediately.
1272233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //The pity is that cluster::parse can determine its own
1273233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //boundary, and we largely duplicate that same logic here.
1274233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //
1275233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //Maybe we need to get rid of our look-ahead preloading
1276233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //in source::parse???
1277233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //
1278233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //As we're parsing the blocks in the curr cluster
1279233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //(in cluster::parse), we should have some way to signal
1280233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //to the segment that we have determined the boundary,
1281233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //so it can adjust its own segment::m_pos member.
1282233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //
1283233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //The problem is that we're asserting in asyncreadinit,
1284233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //because we adjust the pos down to the curr seek pos,
1285233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //and the resulting adjusted len is > 2GB.  I'm suspicious
1286233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //that this is even correct, but even if it is, we can't
1287233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //be loading that much data in the cache anyway.
1288233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1289233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long idx = m_clusterCount;
1290233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1291233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_clusterPreloadCount > 0)
1292233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
1293233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(idx < m_clusterSize);
1294233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1295233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster* const pCluster = m_clusters[idx];
1296233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster);
1297233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster->m_index < 0);
1298233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1299233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long off = pCluster->GetPosition();
1300233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(off >= 0);
1301233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1302233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (off == cluster_off)  //preloaded already
1303233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
1304233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status == 0)  //no entries found
1305233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
1306233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1307233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (cluster_size >= 0)
1308233d2500723e5594f3e7c70896ffeeef32b9c950ywan                pos += cluster_size;
1309233d2500723e5594f3e7c70896ffeeef32b9c950ywan            else
1310233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
1311233d2500723e5594f3e7c70896ffeeef32b9c950ywan                const long long element_size = pCluster->GetElementSize();
1312233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1313233d2500723e5594f3e7c70896ffeeef32b9c950ywan                if (element_size <= 0)
1314233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    return E_FILE_FORMAT_INVALID;  //TODO: handle this case
1315233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1316233d2500723e5594f3e7c70896ffeeef32b9c950ywan                pos = pCluster->m_element_start + element_size;
1317233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
1318233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1319233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pCluster->m_index = idx;  //move from preloaded to loaded
1320233d2500723e5594f3e7c70896ffeeef32b9c950ywan            ++m_clusterCount;
1321233d2500723e5594f3e7c70896ffeeef32b9c950ywan            --m_clusterPreloadCount;
1322233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1323233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_pos = pos;  //consume payload
1324233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert((segment_stop < 0) || (m_pos <= segment_stop));
1325233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1326233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 0;  //success
1327233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1328233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1329233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1330233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status == 0)  //no entries found
1331233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
1332233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (cluster_size < 0)
1333233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;  //TODO: handle this
1334233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1335233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += cluster_size;
1336233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1337233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((total >= 0) && (pos >= total))
1338233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
1339233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_pos = total;
1340233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 1;  //no more clusters
1341233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1342233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1343233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((segment_stop >= 0) && (pos >= segment_stop))
1344233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
1345233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_pos = segment_stop;
1346233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 1;  //no more clusters
1347233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1348233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1349233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m_pos = pos;
1350233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 2;  //try again
1351233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1352233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1353233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //status > 0 means we have an entry
1354233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1355233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster* const pCluster = Cluster::Create(this,
1356233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                              idx,
1357233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                              cluster_off);
1358233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                              //element_size);
1359233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster);
1360233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1361233d2500723e5594f3e7c70896ffeeef32b9c950ywan    AppendCluster(pCluster);
1362233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_clusters);
1363233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(idx < m_clusterSize);
1364233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_clusters[idx] == pCluster);
1365233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1366233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cluster_size >= 0)
1367233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
1368233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += cluster_size;
1369233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1370233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m_pos = pos;
1371233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((segment_stop < 0) || (m_pos <= segment_stop));
1372233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1373233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;
1374233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1375233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1376233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pUnknownSize = pCluster;
1377233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pos = -pos;
1378233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1379233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;  //partial success, since we have a new cluster
1380233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1381233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //status == 0 means "no block entries found"
1382233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1383233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //pos designates start of payload
1384233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //m_pos has NOT been adjusted yet (in case we need to come back here)
1385233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1386233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
1387233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1388233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cluster_size < 0)  //unknown size
1389233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
1390233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long payload_pos = pos;  //absolute pos of cluster payload
1391233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1392233d2500723e5594f3e7c70896ffeeef32b9c950ywan        for (;;)  //determine cluster size
1393233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
1394233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((total >= 0) && (pos >= total))
1395233d2500723e5594f3e7c70896ffeeef32b9c950ywan                break;
1396233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1397233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((segment_stop >= 0) && (pos >= segment_stop))
1398233d2500723e5594f3e7c70896ffeeef32b9c950ywan                break;  //no more clusters
1399233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1400233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //Read ID
1401233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1402233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((pos + 1) > avail)
1403233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
1404233d2500723e5594f3e7c70896ffeeef32b9c950ywan                len = 1;
1405233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_BUFFER_NOT_FULL;
1406233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
1407233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1408233d2500723e5594f3e7c70896ffeeef32b9c950ywan            long long result = GetUIntLength(m_pReader, pos, len);
1409233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1410233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (result < 0)  //error
1411233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return static_cast<long>(result);
1412233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1413233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (result > 0)  //weird
1414233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_BUFFER_NOT_FULL;
1415233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1416233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((segment_stop >= 0) && ((pos + len) > segment_stop))
1417233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
1418233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1419233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((pos + len) > avail)
1420233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_BUFFER_NOT_FULL;
1421233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1422233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long idpos = pos;
1423233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long id = ReadUInt(m_pReader, idpos, len);
1424233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1425233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (id < 0)  //error (or underflow)
1426233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return static_cast<long>(id);
1427233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1428233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //This is the distinguished set of ID's we use to determine
1429233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //that we have exhausted the sub-element's inside the cluster
1430233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //whose ID we parsed earlier.
1431233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1432233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (id == 0x0F43B675)  //Cluster ID
1433233d2500723e5594f3e7c70896ffeeef32b9c950ywan                break;
1434233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1435233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (id == 0x0C53BB6B)  //Cues ID
1436233d2500723e5594f3e7c70896ffeeef32b9c950ywan                break;
1437233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1438233d2500723e5594f3e7c70896ffeeef32b9c950ywan            switch (id)
1439233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
1440233d2500723e5594f3e7c70896ffeeef32b9c950ywan                case 0x20:  //BlockGroup
1441233d2500723e5594f3e7c70896ffeeef32b9c950ywan                case 0x23:  //Simple Block
1442233d2500723e5594f3e7c70896ffeeef32b9c950ywan                case 0x67:  //TimeCode
1443233d2500723e5594f3e7c70896ffeeef32b9c950ywan                case 0x2B:  //PrevSize
1444233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    break;
1445233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1446233d2500723e5594f3e7c70896ffeeef32b9c950ywan                default:
1447233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    assert(false);
1448233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    break;
1449233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
1450233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1451233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pos += len;  //consume ID (of sub-element)
1452233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1453233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //Read Size
1454233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1455233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((pos + 1) > avail)
1456233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
1457233d2500723e5594f3e7c70896ffeeef32b9c950ywan                len = 1;
1458233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_BUFFER_NOT_FULL;
1459233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
1460233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1461233d2500723e5594f3e7c70896ffeeef32b9c950ywan            result = GetUIntLength(m_pReader, pos, len);
1462233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1463233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (result < 0)  //error
1464233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return static_cast<long>(result);
1465233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1466233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (result > 0)  //weird
1467233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_BUFFER_NOT_FULL;
1468233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1469233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((segment_stop >= 0) && ((pos + len) > segment_stop))
1470233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
1471233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1472233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((pos + len) > avail)
1473233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_BUFFER_NOT_FULL;
1474233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1475233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long size = ReadUInt(m_pReader, pos, len);
1476233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1477233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (size < 0)  //error
1478233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return static_cast<long>(size);
1479233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1480233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pos += len;  //consume size field of element
1481233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1482233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //pos now points to start of sub-element's payload
1483233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1484233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (size == 0)  //weird
1485233d2500723e5594f3e7c70896ffeeef32b9c950ywan                continue;
1486233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1487233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long unknown_size = (1LL << (7 * len)) - 1;
1488233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1489233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (size == unknown_size)
1490233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;  //not allowed for sub-elements
1491233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1492233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((segment_stop >= 0) && ((pos + size) > segment_stop))  //weird
1493233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
1494233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1495233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pos += size;  //consume payload of sub-element
1496233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert((segment_stop < 0) || (pos <= segment_stop));
1497233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }  //determine cluster size
1498233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1499233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cluster_size = pos - payload_pos;
1500233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(cluster_size >= 0);
1501233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1502233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos = payload_pos;  //reset and re-parse original cluster
1503233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1504233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1505233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_clusterPreloadCount > 0)
1506233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
1507233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(idx < m_clusterSize);
1508233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1509233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster* const pCluster = m_clusters[idx];
1510233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster);
1511233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster->m_index < 0);
1512233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1513233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long off = pCluster->GetPosition();
1514233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(off >= 0);
1515233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1516233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (off == cluster_off)  //preloaded already
1517233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;  //subtle
1518233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1519233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1520233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pos = pos + cluster_size;  //consume payload
1521233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((segment_stop < 0) || (m_pos <= segment_stop));
1522233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1523233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 2;     //try to find another cluster
1524233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1525233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
1526233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1527233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1528233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1529233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1530233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Segment::DoLoadClusterUnknownSize(
1531233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long& pos,
1532233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long& len)
1533233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1534233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_pos < 0);
1535233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_pUnknownSize);
1536233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1537233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
1538233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_pUnknownSize->GetElementSize() < 0);  //TODO: verify this
1539233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1540233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long element_start = m_pUnknownSize->m_element_start;
1541233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1542233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos = -m_pos;
1543233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos > element_start);
1544233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1545233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //We have already consumed the (cluster) ID and size fields.
1546233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //We just need to consume the blocks and other sub-elements
1547233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //of this cluster, until we discover the boundary.
1548233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1549233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long total, avail;
1550233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1551233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long status = m_pReader->Length(&total, &avail);
1552233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1553233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error
1554233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
1555233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1556233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((total < 0) || (avail <= total));
1557233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1558233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
1559233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1560233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_size = -1;
1561233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1562233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (;;)  //determine cluster size
1563233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
1564233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((total >= 0) && (pos >= total))
1565233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
1566233d2500723e5594f3e7c70896ffeeef32b9c950ywan            element_size = total - element_start;
1567233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(element_size > 0);
1568233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1569233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
1570233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1571233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1572233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((segment_stop >= 0) && (pos >= segment_stop))
1573233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
1574233d2500723e5594f3e7c70896ffeeef32b9c950ywan            element_size = segment_stop - element_start;
1575233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(element_size > 0);
1576233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1577233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
1578233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1579233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1580233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Read ID
1581233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1582233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > avail)
1583233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
1584233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
1585233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
1586233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1587233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1588233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long result = GetUIntLength(m_pReader, pos, len);
1589233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1590233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
1591233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(result);
1592233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1593233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //weird
1594233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
1595233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1596233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((segment_stop >= 0) && ((pos + len) > segment_stop))
1597233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
1598233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1599233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > avail)
1600233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
1601233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1602233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long idpos = pos;
1603233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id = ReadUInt(m_pReader, idpos, len);
1604233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1605233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id < 0)  //error (or underflow)
1606233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(id);
1607233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1608233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //This is the distinguished set of ID's we use to determine
1609233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //that we have exhausted the sub-element's inside the cluster
1610233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //whose ID we parsed earlier.
1611233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1612233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((id == 0x0F43B675) || (id == 0x0C53BB6B)) //Cluster ID or Cues ID
1613233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
1614233d2500723e5594f3e7c70896ffeeef32b9c950ywan            element_size = pos - element_start;
1615233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(element_size > 0);
1616233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1617233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
1618233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1619233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1620233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef _DEBUG
1621233d2500723e5594f3e7c70896ffeeef32b9c950ywan        switch (id)
1622233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
1623233d2500723e5594f3e7c70896ffeeef32b9c950ywan            case 0x20:  //BlockGroup
1624233d2500723e5594f3e7c70896ffeeef32b9c950ywan            case 0x23:  //Simple Block
1625233d2500723e5594f3e7c70896ffeeef32b9c950ywan            case 0x67:  //TimeCode
1626233d2500723e5594f3e7c70896ffeeef32b9c950ywan            case 0x2B:  //PrevSize
1627233d2500723e5594f3e7c70896ffeeef32b9c950ywan                break;
1628233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1629233d2500723e5594f3e7c70896ffeeef32b9c950ywan            default:
1630233d2500723e5594f3e7c70896ffeeef32b9c950ywan                assert(false);
1631233d2500723e5594f3e7c70896ffeeef32b9c950ywan                break;
1632233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1633233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
1634233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1635233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume ID (of sub-element)
1636233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1637233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Read Size
1638233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1639233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > avail)
1640233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
1641233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
1642233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
1643233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1644233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1645233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result = GetUIntLength(m_pReader, pos, len);
1646233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1647233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
1648233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(result);
1649233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1650233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //weird
1651233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
1652233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1653233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((segment_stop >= 0) && ((pos + len) > segment_stop))
1654233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
1655233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1656233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > avail)
1657233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
1658233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1659233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long size = ReadUInt(m_pReader, pos, len);
1660233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1661233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size < 0)  //error
1662233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(size);
1663233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1664233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume size field of element
1665233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1666233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //pos now points to start of sub-element's payload
1667233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1668233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == 0)  //weird
1669233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
1670233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1671233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long unknown_size = (1LL << (7 * len)) - 1;
1672233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1673233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == unknown_size)
1674233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;  //not allowed for sub-elements
1675233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1676233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((segment_stop >= 0) && ((pos + size) > segment_stop))  //weird
1677233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
1678233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1679233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;  //consume payload of sub-element
1680233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((segment_stop < 0) || (pos <= segment_stop));
1681233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }  //determine cluster size
1682233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1683233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(element_size >= 0);
1684233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1685233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pos = element_start + element_size;
1686233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pUnknownSize = 0;
1687233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1688233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 2;  //continue parsing
1689233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
1690233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long status = m_pUnknownSize->Parse(pos, len);
1691233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1692233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error or underflow
1693233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
1694233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1695233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status == 0)  //parsed a block
1696233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 2;     //continue parsing
1697233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1698233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(status > 0);   //nothing left to parse of this cluster
1699233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1700233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long start = m_pUnknownSize->m_element_start;
1701233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1702233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long size = m_pUnknownSize->GetElementSize();
1703233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(size >= 0);
1704233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1705233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos = start + size;
1706233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pos = pos;
1707233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1708233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pUnknownSize = 0;
1709233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1710233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 2;  //continue parsing
1711233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
1712233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1713233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1714233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1715233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Segment::AppendCluster(Cluster* pCluster)
1716233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1717233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster);
1718233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster->m_index >= 0);
1719233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1720233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long count = m_clusterCount + m_clusterPreloadCount;
1721233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1722233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long& size = m_clusterSize;
1723233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(size >= count);
1724233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1725233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long idx = pCluster->m_index;
1726233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(idx == m_clusterCount);
1727233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1728233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (count >= size)
1729233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
1730233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long n = (size <= 0) ? 2048 : 2*size;
1731233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1732233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster** const qq = new Cluster*[n];
1733233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster** q = qq;
1734233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1735233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster** p = m_clusters;
1736233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster** const pp = p + count;
1737233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1738233d2500723e5594f3e7c70896ffeeef32b9c950ywan        while (p != pp)
1739233d2500723e5594f3e7c70896ffeeef32b9c950ywan            *q++ = *p++;
1740233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1741233d2500723e5594f3e7c70896ffeeef32b9c950ywan        delete[] m_clusters;
1742233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1743233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m_clusters = qq;
1744233d2500723e5594f3e7c70896ffeeef32b9c950ywan        size = n;
1745233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1746233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1747233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_clusterPreloadCount > 0)
1748233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
1749233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(m_clusters);
1750233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1751233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster** const p = m_clusters + m_clusterCount;
1752233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(*p);
1753233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((*p)->m_index < 0);
1754233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1755233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster** q = p + m_clusterPreloadCount;
1756233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(q < (m_clusters + size));
1757233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1758233d2500723e5594f3e7c70896ffeeef32b9c950ywan        for (;;)
1759233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
1760233d2500723e5594f3e7c70896ffeeef32b9c950ywan            Cluster** const qq = q - 1;
1761233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert((*qq)->m_index < 0);
1762233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1763233d2500723e5594f3e7c70896ffeeef32b9c950ywan            *q = *qq;
1764233d2500723e5594f3e7c70896ffeeef32b9c950ywan            q = qq;
1765233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1766233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (q == p)
1767233d2500723e5594f3e7c70896ffeeef32b9c950ywan                break;
1768233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1769233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1770233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1771233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_clusters[idx] = pCluster;
1772233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ++m_clusterCount;
1773233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1774233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1775233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1776233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Segment::PreloadCluster(Cluster* pCluster, ptrdiff_t idx)
1777233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1778233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster);
1779233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster->m_index < 0);
1780233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(idx >= m_clusterCount);
1781233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1782233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long count = m_clusterCount + m_clusterPreloadCount;
1783233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1784233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long& size = m_clusterSize;
1785233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(size >= count);
1786233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1787233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (count >= size)
1788233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
1789233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long n = (size <= 0) ? 2048 : 2*size;
1790233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1791233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster** const qq = new Cluster*[n];
1792233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster** q = qq;
1793233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1794233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster** p = m_clusters;
1795233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster** const pp = p + count;
1796233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1797233d2500723e5594f3e7c70896ffeeef32b9c950ywan        while (p != pp)
1798233d2500723e5594f3e7c70896ffeeef32b9c950ywan            *q++ = *p++;
1799233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1800233d2500723e5594f3e7c70896ffeeef32b9c950ywan        delete[] m_clusters;
1801233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1802233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m_clusters = qq;
1803233d2500723e5594f3e7c70896ffeeef32b9c950ywan        size = n;
1804233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1805233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1806233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_clusters);
1807233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1808233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** const p = m_clusters + idx;
1809233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1810233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** q = m_clusters + count;
1811233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(q >= p);
1812233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(q < (m_clusters + size));
1813233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1814233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (q > p)
1815233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
1816233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster** const qq = q - 1;
1817233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((*qq)->m_index < 0);
1818233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1819233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *q = *qq;
1820233d2500723e5594f3e7c70896ffeeef32b9c950ywan        q = qq;
1821233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1822233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1823233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_clusters[idx] = pCluster;
1824233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ++m_clusterPreloadCount;
1825233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1826233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1827233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1828233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Segment::Load()
1829233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1830233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_clusters == NULL);
1831233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_clusterSize == 0);
1832233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_clusterCount == 0);
1833233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //assert(m_size >= 0);
1834233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1835233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //Outermost (level 0) segment object has been constructed,
1836233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //and pos designates start of payload.  We need to find the
1837233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //inner (level 1) elements.
1838233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1839233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long header_status = ParseHeaders();
1840233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1841233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (header_status < 0)  //error
1842233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return static_cast<long>(header_status);
1843233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1844233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (header_status > 0)  //underflow
1845233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_BUFFER_NOT_FULL;
1846233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1847233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_pInfo);
1848233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_pTracks);
1849233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1850233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (;;)
1851233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
1852233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const int status = LoadCluster();
1853233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1854233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)  //error
1855233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
1856233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1857233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status >= 1)  //no more clusters
1858233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 0;
1859233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1860233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1861233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1862233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1863233d2500723e5594f3e7c70896ffeeef32b9c950ywanSeekHead::SeekHead(
1864233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Segment* pSegment,
1865233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long start,
1866233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size_,
1867233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_start,
1868233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_size) :
1869233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pSegment(pSegment),
1870233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_start(start),
1871233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_size(size_),
1872233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_element_start(element_start),
1873233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_element_size(element_size),
1874233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_entries(0),
1875233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_entry_count(0),
1876233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_void_elements(0),
1877233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_void_element_count(0)
1878233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1879233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1880233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1881233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1882233d2500723e5594f3e7c70896ffeeef32b9c950ywanSeekHead::~SeekHead()
1883233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1884233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] m_entries;
1885233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] m_void_elements;
1886233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1887233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1888233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1889233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong SeekHead::Parse()
1890233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1891233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* const pReader = m_pSegment->m_pReader;
1892233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1893233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos = m_start;
1894233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long stop = m_start + m_size;
1895233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1896233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //first count the seek head entries
1897233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1898233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int entry_count = 0;
1899233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int void_element_count = 0;
1900233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1901233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (pos < stop)
1902233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
1903233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long id, size;
1904233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1905233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long status = ParseElementHeader(
1906233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                pReader,
1907233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                pos,
1908233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                stop,
1909233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                id,
1910233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                size);
1911233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1912233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)  //error
1913233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
1914233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1915233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x0DBB)  //SeekEntry ID
1916233d2500723e5594f3e7c70896ffeeef32b9c950ywan            ++entry_count;
1917233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x6C)  //Void ID
1918233d2500723e5594f3e7c70896ffeeef32b9c950ywan            ++void_element_count;
1919233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1920233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;  //consume payload
1921233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos <= stop);
1922233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1923233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1924233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos == stop);
1925233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1926233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_entries = new (std::nothrow) Entry[entry_count];
1927233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1928233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_entries == NULL)
1929233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
1930233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1931233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_void_elements = new (std::nothrow) VoidElement[void_element_count];
1932233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1933233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_void_elements == NULL)
1934233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
1935233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1936233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //now parse the entries and void elements
1937233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1938233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Entry* pEntry = m_entries;
1939233d2500723e5594f3e7c70896ffeeef32b9c950ywan    VoidElement* pVoidElement = m_void_elements;
1940233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1941233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos = m_start;
1942233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1943233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (pos < stop)
1944233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
1945233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long idpos = pos;
1946233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1947233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long id, size;
1948233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1949233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long status = ParseElementHeader(
1950233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                pReader,
1951233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                pos,
1952233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                stop,
1953233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                id,
1954233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                size);
1955233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1956233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)  //error
1957233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
1958233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1959233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x0DBB)  //SeekEntry ID
1960233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
1961233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (ParseEntry(pReader, pos, size, pEntry))
1962233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
1963233d2500723e5594f3e7c70896ffeeef32b9c950ywan                Entry& e = *pEntry++;
1964233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1965233d2500723e5594f3e7c70896ffeeef32b9c950ywan                e.element_start = idpos;
1966233d2500723e5594f3e7c70896ffeeef32b9c950ywan                e.element_size = (pos + size) - idpos;
1967233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
1968233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1969233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x6C)  //Void ID
1970233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
1971233d2500723e5594f3e7c70896ffeeef32b9c950ywan            VoidElement& e = *pVoidElement++;
1972233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1973233d2500723e5594f3e7c70896ffeeef32b9c950ywan            e.element_start = idpos;
1974233d2500723e5594f3e7c70896ffeeef32b9c950ywan            e.element_size = (pos + size) - idpos;
1975233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1976233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1977233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;  //consume payload
1978233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos <= stop);
1979233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1980233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1981233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos == stop);
1982233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1983233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ptrdiff_t count_ = ptrdiff_t(pEntry - m_entries);
1984233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(count_ >= 0);
1985233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(count_ <= entry_count);
1986233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1987233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_entry_count = static_cast<int>(count_);
1988233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1989233d2500723e5594f3e7c70896ffeeef32b9c950ywan    count_ = ptrdiff_t(pVoidElement - m_void_elements);
1990233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(count_ >= 0);
1991233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(count_ <= void_element_count);
1992233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1993233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_void_element_count = static_cast<int>(count_);
1994233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1995233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
1996233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1997233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1998233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1999233d2500723e5594f3e7c70896ffeeef32b9c950ywanint SeekHead::GetCount() const
2000233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2001233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_entry_count;
2002233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2003233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2004233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst SeekHead::Entry* SeekHead::GetEntry(int idx) const
2005233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2006233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (idx < 0)
2007233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;
2008233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2009233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (idx >= m_entry_count)
2010233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;
2011233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2012233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_entries + idx;
2013233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2014233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2015233d2500723e5594f3e7c70896ffeeef32b9c950ywanint SeekHead::GetVoidElementCount() const
2016233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2017233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_void_element_count;
2018233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2019233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2020233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst SeekHead::VoidElement* SeekHead::GetVoidElement(int idx) const
2021233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2022233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (idx < 0)
2023233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;
2024233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2025233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (idx >= m_void_element_count)
2026233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;
2027233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2028233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_void_elements + idx;
2029233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2030233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2031233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2032233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
2033233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Segment::ParseCues(long long off)
2034233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2035233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_pCues)
2036233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return;
2037233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2038233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //odbgstream os;
2039233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //os << "Segment::ParseCues (begin)" << endl;
2040233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2041233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos = m_start + off;
2042233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long element_start = pos;
2043233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long stop = m_start + m_size;
2044233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2045233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long len;
2046233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2047233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long result = GetUIntLength(m_pReader, pos, len);
2048233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(result == 0);
2049233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((pos + len) <= stop);
2050233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2051233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long idpos = pos;
2052233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2053233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long id = ReadUInt(m_pReader, idpos, len);
2054233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(id == 0x0C53BB6B);  //Cues ID
2055233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2056233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += len;  //consume ID
2057233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos < stop);
2058233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2059233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //Read Size
2060233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2061233d2500723e5594f3e7c70896ffeeef32b9c950ywan    result = GetUIntLength(m_pReader, pos, len);
2062233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(result == 0);
2063233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((pos + len) <= stop);
2064233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2065233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long size = ReadUInt(m_pReader, pos, len);
2066233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(size >= 0);
2067233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2068233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += len;  //consume length of size of element
2069233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((pos + size) <= stop);
2070233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2071233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long element_size = size + pos - element_start;
2072233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2073233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //Pos now points to start of payload
2074233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2075233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pCues = new Cues(this, pos, size, element_start, element_size);
2076233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_pCues);  //TODO
2077233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2078233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //os << "Segment::ParseCues (end)" << endl;
2079233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2080233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
2081233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Segment::ParseCues(
2082233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long off,
2083233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long& pos,
2084233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long& len)
2085233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2086233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_pCues)
2087233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;  //success
2088233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2089233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (off < 0)
2090233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
2091233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2092233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long total, avail;
2093233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2094233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int status = m_pReader->Length(&total, &avail);
2095233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2096233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error
2097233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
2098233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2099233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((total < 0) || (avail <= total));
2100233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2101233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos = m_start + off;
2102233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2103233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((total < 0) || (pos >= total))
2104233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 1;  //don't bother parsing cues
2105233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2106233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long element_start = pos;
2107233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
2108233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2109233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((pos + 1) > avail)
2110233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
2111233d2500723e5594f3e7c70896ffeeef32b9c950ywan        len = 1;
2112233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_BUFFER_NOT_FULL;
2113233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2114233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2115233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long result = GetUIntLength(m_pReader, pos, len);
2116233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2117233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (result < 0)  //error
2118233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return static_cast<long>(result);
2119233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2120233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (result > 0) //underflow (weird)
2121233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
2122233d2500723e5594f3e7c70896ffeeef32b9c950ywan        len = 1;
2123233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_BUFFER_NOT_FULL;
2124233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2125233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2126233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((segment_stop >= 0) && ((pos + len) > segment_stop))
2127233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
2128233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2129233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((pos + len) > avail)
2130233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_BUFFER_NOT_FULL;
2131233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2132233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long idpos = pos;
2133233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2134233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long id = ReadUInt(m_pReader, idpos, len);
2135233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2136233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (id != 0x0C53BB6B)  //Cues ID
2137233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
2138233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2139233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += len;  //consume ID
2140233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((segment_stop < 0) || (pos <= segment_stop));
2141233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2142233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //Read Size
2143233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2144233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((pos + 1) > avail)
2145233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
2146233d2500723e5594f3e7c70896ffeeef32b9c950ywan        len = 1;
2147233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_BUFFER_NOT_FULL;
2148233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2149233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2150233d2500723e5594f3e7c70896ffeeef32b9c950ywan    result = GetUIntLength(m_pReader, pos, len);
2151233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2152233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (result < 0)  //error
2153233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return static_cast<long>(result);
2154233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2155233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (result > 0) //underflow (weird)
2156233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
2157233d2500723e5594f3e7c70896ffeeef32b9c950ywan        len = 1;
2158233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_BUFFER_NOT_FULL;
2159233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2160233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2161233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((segment_stop >= 0) && ((pos + len) > segment_stop))
2162233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
2163233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2164233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((pos + len) > avail)
2165233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_BUFFER_NOT_FULL;
2166233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2167233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long size = ReadUInt(m_pReader, pos, len);
2168233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2169233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (size < 0)  //error
2170233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return static_cast<long>(size);
2171233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2172233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (size == 0)  //weird, although technically not illegal
2173233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 1;   //done
2174233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2175233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += len;  //consume length of size of element
2176233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((segment_stop < 0) || (pos <= segment_stop));
2177233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2178233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //Pos now points to start of payload
2179233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2180233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long element_stop = pos + size;
2181233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2182233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((segment_stop >= 0) && (element_stop > segment_stop))
2183233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
2184233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2185233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((total >= 0) && (element_stop > total))
2186233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 1;  //don't bother parsing anymore
2187233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2188233d2500723e5594f3e7c70896ffeeef32b9c950ywan    len = static_cast<long>(size);
2189233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2190233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (element_stop > avail)
2191233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_BUFFER_NOT_FULL;
2192233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2193233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long element_size = element_stop - element_start;
2194233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2195233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pCues = new (std::nothrow) Cues(
2196233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    this,
2197233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pos,
2198233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    size,
2199233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    element_start,
2200233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    element_size);
2201233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_pCues);  //TODO
2202233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2203233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;  //success
2204233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2205233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
2206233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2207233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2208233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
2209233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Segment::ParseSeekEntry(
2210233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long start,
2211233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size_)
2212233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2213233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos = start;
2214233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2215233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long stop = start + size_;
2216233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2217233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long len;
2218233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2219233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long seekIdId = ReadUInt(m_pReader, pos, len);
2220233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //seekIdId;
2221233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(seekIdId == 0x13AB);  //SeekID ID
2222233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((pos + len) <= stop);
2223233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2224233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += len;  //consume id
2225233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2226233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long seekIdSize = ReadUInt(m_pReader, pos, len);
2227233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(seekIdSize >= 0);
2228233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((pos + len) <= stop);
2229233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2230233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += len;  //consume size
2231233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2232233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long seekId = ReadUInt(m_pReader, pos, len);  //payload
2233233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(seekId >= 0);
2234233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(len == seekIdSize);
2235233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((pos + len) <= stop);
2236233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2237233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += seekIdSize;  //consume payload
2238233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2239233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long seekPosId = ReadUInt(m_pReader, pos, len);
2240233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //seekPosId;
2241233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(seekPosId == 0x13AC);  //SeekPos ID
2242233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((pos + len) <= stop);
2243233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2244233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += len;  //consume id
2245233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2246233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long seekPosSize = ReadUInt(m_pReader, pos, len);
2247233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(seekPosSize >= 0);
2248233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((pos + len) <= stop);
2249233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2250233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += len;  //consume size
2251233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((pos + seekPosSize) <= stop);
2252233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2253233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long seekOff = UnserializeUInt(m_pReader, pos, seekPosSize);
2254233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(seekOff >= 0);
2255233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(seekOff < m_size);
2256233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2257233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += seekPosSize;  //consume payload
2258233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos == stop);
2259233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2260233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long seekPos = m_start + seekOff;
2261233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(seekPos < (m_start + m_size));
2262233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2263233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (seekId == 0x0C53BB6B)  //Cues ID
2264233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ParseCues(seekOff);
2265233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2266233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
2267233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool SeekHead::ParseEntry(
2268233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* pReader,
2269233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long start,
2270233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size_,
2271233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Entry* pEntry)
2272233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2273233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (size_ <= 0)
2274233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2275233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2276233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos = start;
2277233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long stop = start + size_;
2278233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2279233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long len;
2280233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2281233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //parse the container for the level-1 element ID
2282233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2283233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long seekIdId = ReadUInt(pReader, pos, len);
2284233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //seekIdId;
2285233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2286233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (seekIdId != 0x13AB)  //SeekID ID
2287233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2288233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2289233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((pos + len) > stop)
2290233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2291233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2292233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += len;  //consume SeekID id
2293233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2294233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long seekIdSize = ReadUInt(pReader, pos, len);
2295233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2296233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (seekIdSize <= 0)
2297233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2298233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2299233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((pos + len) > stop)
2300233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2301233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2302233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += len;  //consume size of field
2303233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2304233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((pos + seekIdSize) > stop)
2305233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2306233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2307233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //Note that the SeekId payload really is serialized
2308233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //as a "Matroska integer", not as a plain binary value.
2309233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //In fact, Matroska requires that ID values in the
2310233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //stream exactly match the binary representation as listed
2311233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //in the Matroska specification.
2312233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //
2313233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //This parser is more liberal, and permits IDs to have
2314233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //any width.  (This could make the representation in the stream
2315233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //different from what's in the spec, but it doesn't matter here,
2316233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //since we always normalize "Matroska integer" values.)
2317233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2318233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pEntry->id = ReadUInt(pReader, pos, len);  //payload
2319233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2320233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pEntry->id <= 0)
2321233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2322233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2323233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (len != seekIdSize)
2324233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2325233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2326233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += seekIdSize;  //consume SeekID payload
2327233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2328233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long seekPosId = ReadUInt(pReader, pos, len);
2329233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2330233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (seekPosId != 0x13AC)  //SeekPos ID
2331233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2332233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2333233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((pos + len) > stop)
2334233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2335233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2336233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += len;  //consume id
2337233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2338233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long seekPosSize = ReadUInt(pReader, pos, len);
2339233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2340233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (seekPosSize <= 0)
2341233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2342233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2343233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((pos + len) > stop)
2344233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2345233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2346233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += len;  //consume size
2347233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2348233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((pos + seekPosSize) > stop)
2349233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2350233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2351233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pEntry->pos = UnserializeUInt(pReader, pos, seekPosSize);
2352233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2353233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pEntry->pos < 0)
2354233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2355233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2356233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += seekPosSize;  //consume payload
2357233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2358233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pos != stop)
2359233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2360233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2361233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return true;
2362233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2363233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
2364233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2365233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2366233d2500723e5594f3e7c70896ffeeef32b9c950ywanCues::Cues(
2367233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Segment* pSegment,
2368233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long start_,
2369233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size_,
2370233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_start,
2371233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_size) :
2372233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pSegment(pSegment),
2373233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_start(start_),
2374233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_size(size_),
2375233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_element_start(element_start),
2376233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_element_size(element_size),
2377233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_cue_points(NULL),
2378233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_count(0),
2379233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_preload_count(0),
2380233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pos(start_)
2381233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2382233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2383233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2384233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2385233d2500723e5594f3e7c70896ffeeef32b9c950ywanCues::~Cues()
2386233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2387233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long n = m_count + m_preload_count;
2388233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2389233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CuePoint** p = m_cue_points;
2390233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CuePoint** const q = p + n;
2391233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2392233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (p != q)
2393233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
2394233d2500723e5594f3e7c70896ffeeef32b9c950ywan        CuePoint* const pCP = *p++;
2395233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCP);
2396233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2397233d2500723e5594f3e7c70896ffeeef32b9c950ywan        delete pCP;
2398233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2399233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2400233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] m_cue_points;
2401233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2402233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2403233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2404233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Cues::GetCount() const
2405233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2406233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_cue_points == NULL)
2407233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
2408233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2409233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_count;  //TODO: really ignore preload count?
2410233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2411233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2412233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2413233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Cues::DoneParsing() const
2414233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2415233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long stop = m_start + m_size;
2416233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return (m_pos >= stop);
2417233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2418233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2419233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2420233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Cues::Init() const
2421233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2422233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_cue_points)
2423233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return;
2424233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2425233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_count == 0);
2426233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_preload_count == 0);
2427233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2428233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* const pReader = m_pSegment->m_pReader;
2429233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2430233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long stop = m_start + m_size;
2431233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos = m_start;
2432233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2433233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long cue_points_size = 0;
2434233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2435233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (pos < stop)
2436233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
2437233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long idpos = pos;
2438233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2439233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long len;
2440233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2441233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id = ReadUInt(pReader, pos, len);
2442233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(id >= 0);  //TODO
2443233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pos + len) <= stop);
2444233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2445233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume ID
2446233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2447233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long size = ReadUInt(pReader, pos, len);
2448233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(size >= 0);
2449233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pos + len) <= stop);
2450233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2451233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume Size field
2452233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pos + size) <= stop);
2453233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2454233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x3B)  //CuePoint ID
2455233d2500723e5594f3e7c70896ffeeef32b9c950ywan            PreloadCuePoint(cue_points_size, idpos);
2456233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2457233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;  //consume payload
2458233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos <= stop);
2459233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2460233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2461233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2462233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2463233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Cues::PreloadCuePoint(
2464233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long& cue_points_size,
2465233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos) const
2466233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2467233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_count == 0);
2468233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2469233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_preload_count >= cue_points_size)
2470233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
2471233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long n = (cue_points_size <= 0) ? 2048 : 2*cue_points_size;
2472233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2473233d2500723e5594f3e7c70896ffeeef32b9c950ywan        CuePoint** const qq = new CuePoint*[n];
2474233d2500723e5594f3e7c70896ffeeef32b9c950ywan        CuePoint** q = qq;  //beginning of target
2475233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2476233d2500723e5594f3e7c70896ffeeef32b9c950ywan        CuePoint** p = m_cue_points;                //beginning of source
2477233d2500723e5594f3e7c70896ffeeef32b9c950ywan        CuePoint** const pp = p + m_preload_count;  //end of source
2478233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2479233d2500723e5594f3e7c70896ffeeef32b9c950ywan        while (p != pp)
2480233d2500723e5594f3e7c70896ffeeef32b9c950ywan            *q++ = *p++;
2481233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2482233d2500723e5594f3e7c70896ffeeef32b9c950ywan        delete[] m_cue_points;
2483233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2484233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m_cue_points = qq;
2485233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cue_points_size = n;
2486233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2487233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2488233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CuePoint* const pCP = new CuePoint(m_preload_count, pos);
2489233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_cue_points[m_preload_count++] = pCP;
2490233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2491233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2492233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2493233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Cues::LoadCuePoint() const
2494233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2495233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //odbgstream os;
2496233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //os << "Cues::LoadCuePoint" << endl;
2497233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2498233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long stop = m_start + m_size;
2499233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2500233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_pos >= stop)
2501233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;  //nothing else to do
2502233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2503233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Init();
2504233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2505233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* const pReader = m_pSegment->m_pReader;
2506233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2507233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (m_pos < stop)
2508233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
2509233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long idpos = m_pos;
2510233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2511233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long len;
2512233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2513233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id = ReadUInt(pReader, m_pos, len);
2514233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(id >= 0);  //TODO
2515233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((m_pos + len) <= stop);
2516233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2517233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m_pos += len;  //consume ID
2518233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2519233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long size = ReadUInt(pReader, m_pos, len);
2520233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(size >= 0);
2521233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((m_pos + len) <= stop);
2522233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2523233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m_pos += len;  //consume Size field
2524233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((m_pos + size) <= stop);
2525233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2526233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id != 0x3B)  //CuePoint ID
2527233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
2528233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_pos += size;  //consume payload
2529233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(m_pos <= stop);
2530233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2531233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
2532233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
2533233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2534233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(m_preload_count > 0);
2535233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2536233d2500723e5594f3e7c70896ffeeef32b9c950ywan        CuePoint* const pCP = m_cue_points[m_count];
2537233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCP);
2538233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pCP->GetTimeCode() >= 0) || (-pCP->GetTimeCode() == idpos));
2539233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pCP->GetTimeCode() < 0 && (-pCP->GetTimeCode() != idpos))
2540233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return false;
2541233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2542233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pCP->Load(pReader);
2543233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ++m_count;
2544233d2500723e5594f3e7c70896ffeeef32b9c950ywan        --m_preload_count;
2545233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2546233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m_pos += size;  //consume payload
2547233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(m_pos <= stop);
2548233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2549233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return true;  //yes, we loaded a cue point
2550233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2551233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2552233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //return (m_pos < stop);
2553233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;  //no, we did not load a cue point
2554233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2555233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2556233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2557233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Cues::Find(
2558233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long time_ns,
2559233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Track* pTrack,
2560233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const CuePoint*& pCP,
2561233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const CuePoint::TrackPosition*& pTP) const
2562233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2563233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(time_ns >= 0);
2564233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pTrack);
2565233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2566233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
2567233d2500723e5594f3e7c70896ffeeef32b9c950ywan    LoadCuePoint();  //establish invariant
2568233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2569233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_cue_points);
2570233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_count > 0);
2571233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2572233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CuePoint** const ii = m_cue_points;
2573233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CuePoint** i = ii;
2574233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2575233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CuePoint** const jj = ii + m_count + m_preload_count;
2576233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CuePoint** j = jj;
2577233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2578233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pCP = *i;
2579233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCP);
2580233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2581233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (time_ns <= pCP->GetTime(m_pSegment))
2582233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
2583233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pTP = pCP->Find(pTrack);
2584233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return (pTP != NULL);
2585233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2586233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2587233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* const pReader = m_pSegment->m_pReader;
2588233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2589233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (i < j)
2590233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
2591233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //INVARIANT:
2592233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[ii, i) <= time_ns
2593233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[i, j)  ?
2594233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[j, jj) > time_ns
2595233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2596233d2500723e5594f3e7c70896ffeeef32b9c950ywan        CuePoint** const k = i + (j - i) / 2;
2597233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(k < jj);
2598233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2599233d2500723e5594f3e7c70896ffeeef32b9c950ywan        CuePoint* const pCP = *k;
2600233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCP);
2601233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2602233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pCP->Load(pReader);
2603233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2604233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long t = pCP->GetTime(m_pSegment);
2605233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2606233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (t <= time_ns)
2607233d2500723e5594f3e7c70896ffeeef32b9c950ywan            i = k + 1;
2608233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else
2609233d2500723e5594f3e7c70896ffeeef32b9c950ywan            j = k;
2610233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2611233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(i <= j);
2612233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2613233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2614233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(i == j);
2615233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(i <= jj);
2616233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(i > ii);
2617233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2618233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pCP = *--i;
2619233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCP);
2620233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCP->GetTime(m_pSegment) <= time_ns);
2621233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
2622233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_cue_points == NULL)
2623233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2624233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2625233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_count == 0)
2626233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2627233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2628233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CuePoint** const ii = m_cue_points;
2629233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CuePoint** i = ii;
2630233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2631233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CuePoint** const jj = ii + m_count;
2632233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CuePoint** j = jj;
2633233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2634233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pCP = *i;
2635233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCP);
2636233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2637233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (time_ns <= pCP->GetTime(m_pSegment))
2638233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
2639233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pTP = pCP->Find(pTrack);
2640233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return (pTP != NULL);
2641233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2642233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2643233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (i < j)
2644233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
2645233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //INVARIANT:
2646233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[ii, i) <= time_ns
2647233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[i, j)  ?
2648233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[j, jj) > time_ns
2649233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2650233d2500723e5594f3e7c70896ffeeef32b9c950ywan        CuePoint** const k = i + (j - i) / 2;
2651233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(k < jj);
2652233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2653233d2500723e5594f3e7c70896ffeeef32b9c950ywan        CuePoint* const pCP = *k;
2654233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCP);
2655233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2656233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long t = pCP->GetTime(m_pSegment);
2657233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2658233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (t <= time_ns)
2659233d2500723e5594f3e7c70896ffeeef32b9c950ywan            i = k + 1;
2660233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else
2661233d2500723e5594f3e7c70896ffeeef32b9c950ywan            j = k;
2662233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2663233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(i <= j);
2664233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2665233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2666233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(i == j);
2667233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(i <= jj);
2668233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(i > ii);
2669233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2670233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pCP = *--i;
2671233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCP);
2672233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCP->GetTime(m_pSegment) <= time_ns);
2673233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
2674233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2675233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //TODO: here and elsewhere, it's probably not correct to search
2676233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //for the cue point with this time, and then search for a matching
2677233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //track.  In principle, the matching track could be on some earlier
2678233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //cue point, and with our current algorithm, we'd miss it.  To make
2679233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //this bullet-proof, we'd need to create a secondary structure,
2680233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //with a list of cue points that apply to a track, and then search
2681233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //that track-based structure for a matching cue point.
2682233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2683233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pTP = pCP->Find(pTrack);
2684233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return (pTP != NULL);
2685233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2686233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2687233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2688233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
2689233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Cues::FindNext(
2690233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long time_ns,
2691233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Track* pTrack,
2692233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const CuePoint*& pCP,
2693233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const CuePoint::TrackPosition*& pTP) const
2694233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2695233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pCP = 0;
2696233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pTP = 0;
2697233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2698233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_count == 0)
2699233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2700233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2701233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_cue_points);
2702233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2703233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const CuePoint* const* const ii = m_cue_points;
2704233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const CuePoint* const* i = ii;
2705233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2706233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const CuePoint* const* const jj = ii + m_count;
2707233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const CuePoint* const* j = jj;
2708233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2709233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (i < j)
2710233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
2711233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //INVARIANT:
2712233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[ii, i) <= time_ns
2713233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[i, j)  ?
2714233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[j, jj) > time_ns
2715233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2716233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const CuePoint* const* const k = i + (j - i) / 2;
2717233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(k < jj);
2718233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2719233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pCP = *k;
2720233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCP);
2721233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2722233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long t = pCP->GetTime(m_pSegment);
2723233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2724233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (t <= time_ns)
2725233d2500723e5594f3e7c70896ffeeef32b9c950ywan            i = k + 1;
2726233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else
2727233d2500723e5594f3e7c70896ffeeef32b9c950ywan            j = k;
2728233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2729233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(i <= j);
2730233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2731233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2732233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(i == j);
2733233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(i <= jj);
2734233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2735233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (i >= jj)  //time_ns is greater than max cue point
2736233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2737233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2738233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pCP = *i;
2739233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCP);
2740233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCP->GetTime(m_pSegment) > time_ns);
2741233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2742233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pTP = pCP->Find(pTrack);
2743233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return (pTP != NULL);
2744233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2745233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
2746233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2747233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2748233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst CuePoint* Cues::GetFirst() const
2749233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2750233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_cue_points == NULL)
2751233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return NULL;
2752233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2753233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_count == 0)
2754233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return NULL;
2755233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2756233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
2757233d2500723e5594f3e7c70896ffeeef32b9c950ywan    LoadCuePoint();  //init cues
2758233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2759233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const size_t count = m_count + m_preload_count;
2760233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2761233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (count == 0)  //weird
2762233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return NULL;
2763233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
2764233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2765233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CuePoint* const* const pp = m_cue_points;
2766233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pp);
2767233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2768233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CuePoint* const pCP = pp[0];
2769233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCP);
2770233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCP->GetTimeCode() >= 0);
2771233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2772233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return pCP;
2773233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2774233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2775233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2776233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst CuePoint* Cues::GetLast() const
2777233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2778233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_cue_points == NULL)
2779233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return NULL;
2780233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2781233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_count <= 0)
2782233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return NULL;
2783233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2784233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
2785233d2500723e5594f3e7c70896ffeeef32b9c950ywan    LoadCuePoint();  //init cues
2786233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2787233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const size_t count = m_count + m_preload_count;
2788233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2789233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (count == 0)  //weird
2790233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return NULL;
2791233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2792233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const size_t index = count - 1;
2793233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2794233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CuePoint* const* const pp = m_cue_points;
2795233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pp);
2796233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2797233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CuePoint* const pCP = pp[index];
2798233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCP);
2799233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2800233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pCP->Load(m_pSegment->m_pReader);
2801233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCP->GetTimeCode() >= 0);
2802233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
2803233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long index = m_count - 1;
2804233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2805233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CuePoint* const* const pp = m_cue_points;
2806233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pp);
2807233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2808233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CuePoint* const pCP = pp[index];
2809233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCP);
2810233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCP->GetTimeCode() >= 0);
2811233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
2812233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2813233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return pCP;
2814233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2815233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2816233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2817233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst CuePoint* Cues::GetNext(const CuePoint* pCurr) const
2818233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2819233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pCurr == NULL)
2820233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return NULL;
2821233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2822233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCurr->GetTimeCode() >= 0);
2823233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_cue_points);
2824233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_count >= 1);
2825233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2826233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
2827233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const size_t count = m_count + m_preload_count;
2828233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2829233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size_t index = pCurr->m_index;
2830233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(index < count);
2831233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2832233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CuePoint* const* const pp = m_cue_points;
2833233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pp);
2834233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pp[index] == pCurr);
2835233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2836233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ++index;
2837233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2838233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (index >= count)
2839233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return NULL;
2840233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2841233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CuePoint* const pNext = pp[index];
2842233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pNext);
2843233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2844233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pNext->Load(m_pSegment->m_pReader);
2845233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
2846233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long index = pCurr->m_index;
2847233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(index < m_count);
2848233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2849233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CuePoint* const* const pp = m_cue_points;
2850233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pp);
2851233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pp[index] == pCurr);
2852233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2853233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ++index;
2854233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2855233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (index >= m_count)
2856233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return NULL;
2857233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2858233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CuePoint* const pNext = pp[index];
2859233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pNext);
2860233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pNext->GetTimeCode() >= 0);
2861233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
2862233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2863233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return pNext;
2864233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2865233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2866233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2867233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst BlockEntry* Cues::GetBlock(
2868233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const CuePoint* pCP,
2869233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const CuePoint::TrackPosition* pTP) const
2870233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2871233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pCP == NULL)
2872233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return NULL;
2873233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2874233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pTP == NULL)
2875233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return NULL;
2876233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2877233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_pSegment->GetBlock(*pCP, *pTP);
2878233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2879233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2880233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2881233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst BlockEntry* Segment::GetBlock(
2882233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const CuePoint& cp,
2883233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const CuePoint::TrackPosition& tp)
2884233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2885233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** const ii = m_clusters;
2886233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** i = ii;
2887233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2888233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long count = m_clusterCount + m_clusterPreloadCount;
2889233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2890233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** const jj = ii + count;
2891233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** j = jj;
2892233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2893233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (i < j)
2894233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
2895233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //INVARIANT:
2896233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[ii, i) < pTP->m_pos
2897233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[i, j) ?
2898233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[j, jj)  > pTP->m_pos
2899233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2900233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster** const k = i + (j - i) / 2;
2901233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(k < jj);
2902233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2903233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster* const pCluster = *k;
2904233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster);
2905233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2906233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //const long long pos_ = pCluster->m_pos;
2907233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //assert(pos_);
2908233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //const long long pos = pos_ * ((pos_ < 0) ? -1 : 1);
2909233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2910233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long pos = pCluster->GetPosition();
2911233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos >= 0);
2912233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2913233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pos < tp.m_pos)
2914233d2500723e5594f3e7c70896ffeeef32b9c950ywan            i = k + 1;
2915233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (pos > tp.m_pos)
2916233d2500723e5594f3e7c70896ffeeef32b9c950ywan            j = k;
2917233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else
2918233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return pCluster->GetEntry(cp, tp);
2919233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2920233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2921233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(i == j);
2922233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //assert(Cluster::HasBlockEntries(this, tp.m_pos));
2923233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2924233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster* const pCluster = Cluster::Create(this, -1, tp.m_pos); //, -1);
2925233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster);
2926233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2927233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const ptrdiff_t idx = i - m_clusters;
2928233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2929233d2500723e5594f3e7c70896ffeeef32b9c950ywan    PreloadCluster(pCluster, idx);
2930233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_clusters);
2931233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_clusterPreloadCount > 0);
2932233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_clusters[idx] == pCluster);
2933233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2934233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return pCluster->GetEntry(cp, tp);
2935233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2936233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2937233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2938233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst Cluster* Segment::FindOrPreloadCluster(long long requested_pos)
2939233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2940233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (requested_pos < 0)
2941233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;
2942233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2943233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** const ii = m_clusters;
2944233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** i = ii;
2945233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2946233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long count = m_clusterCount + m_clusterPreloadCount;
2947233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2948233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** const jj = ii + count;
2949233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** j = jj;
2950233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2951233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (i < j)
2952233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
2953233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //INVARIANT:
2954233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[ii, i) < pTP->m_pos
2955233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[i, j) ?
2956233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[j, jj)  > pTP->m_pos
2957233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2958233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster** const k = i + (j - i) / 2;
2959233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(k < jj);
2960233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2961233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster* const pCluster = *k;
2962233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster);
2963233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2964233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //const long long pos_ = pCluster->m_pos;
2965233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //assert(pos_);
2966233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //const long long pos = pos_ * ((pos_ < 0) ? -1 : 1);
2967233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2968233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long pos = pCluster->GetPosition();
2969233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos >= 0);
2970233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2971233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pos < requested_pos)
2972233d2500723e5594f3e7c70896ffeeef32b9c950ywan            i = k + 1;
2973233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (pos > requested_pos)
2974233d2500723e5594f3e7c70896ffeeef32b9c950ywan            j = k;
2975233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else
2976233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return pCluster;
2977233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2978233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2979233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(i == j);
2980233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //assert(Cluster::HasBlockEntries(this, tp.m_pos));
2981233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2982233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster* const pCluster = Cluster::Create(
2983233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                this,
2984233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                -1,
2985233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                requested_pos);
2986233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                //-1);
2987233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster);
2988233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2989233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const ptrdiff_t idx = i - m_clusters;
2990233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2991233d2500723e5594f3e7c70896ffeeef32b9c950ywan    PreloadCluster(pCluster, idx);
2992233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_clusters);
2993233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_clusterPreloadCount > 0);
2994233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_clusters[idx] == pCluster);
2995233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2996233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return pCluster;
2997233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2998233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2999233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3000233d2500723e5594f3e7c70896ffeeef32b9c950ywanCuePoint::CuePoint(long idx, long long pos) :
3001233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_element_start(0),
3002233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_element_size(0),
3003233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_index(idx),
3004233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_timecode(-1 * pos),
3005233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_track_positions(NULL),
3006233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_track_positions_count(0)
3007233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
3008233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos > 0);
3009233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3010233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3011233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3012233d2500723e5594f3e7c70896ffeeef32b9c950ywanCuePoint::~CuePoint()
3013233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
3014233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] m_track_positions;
3015233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3016233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3017233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3018233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid CuePoint::Load(IMkvReader* pReader)
3019233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
3020233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //odbgstream os;
3021233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //os << "CuePoint::Load(begin): timecode=" << m_timecode << endl;
3022233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3023233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_timecode >= 0)  //already loaded
3024233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return;
3025233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3026233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_track_positions == NULL);
3027233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_track_positions_count == 0);
3028233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3029233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos_ = -m_timecode;
3030233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long element_start = pos_;
3031233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3032233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long stop;
3033233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3034233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
3035233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long len;
3036233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3037233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id = ReadUInt(pReader, pos_, len);
3038233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(id == 0x3B);  //CuePoint ID
3039233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id != 0x3B)
3040233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return;
3041233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3042233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos_ += len;  //consume ID
3043233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3044233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long size = ReadUInt(pReader, pos_, len);
3045233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(size >= 0);
3046233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3047233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos_ += len;  //consume Size field
3048233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //pos_ now points to start of payload
3049233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3050233d2500723e5594f3e7c70896ffeeef32b9c950ywan        stop = pos_ + size;
3051233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3052233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3053233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long element_size = stop - element_start;
3054233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3055233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos = pos_;
3056233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3057233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //First count number of track positions
3058233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3059233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (pos < stop)
3060233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
3061233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long len;
3062233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3063233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id = ReadUInt(pReader, pos, len);
3064233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(id >= 0);  //TODO
3065233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pos + len) <= stop);
3066233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3067233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume ID
3068233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3069233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long size = ReadUInt(pReader, pos, len);
3070233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(size >= 0);
3071233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pos + len) <= stop);
3072233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3073233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume Size field
3074233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pos + size) <= stop);
3075233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3076233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x33)  //CueTime ID
3077233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_timecode = UnserializeUInt(pReader, pos, size);
3078233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3079233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x37) //CueTrackPosition(s) ID
3080233d2500723e5594f3e7c70896ffeeef32b9c950ywan            ++m_track_positions_count;
3081233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3082233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;  //consume payload
3083233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos <= stop);
3084233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3085233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3086233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_timecode >= 0);
3087233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_track_positions_count > 0);
3088233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3089233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //os << "CuePoint::Load(cont'd): idpos=" << idpos
3090233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //   << " timecode=" << m_timecode
3091233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //   << endl;
3092233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3093233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_track_positions = new TrackPosition[m_track_positions_count];
3094233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3095233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //Now parse track positions
3096233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3097233d2500723e5594f3e7c70896ffeeef32b9c950ywan    TrackPosition* p = m_track_positions;
3098233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos = pos_;
3099233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3100233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (pos < stop)
3101233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
3102233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long len;
3103233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3104233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id = ReadUInt(pReader, pos, len);
3105233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(id >= 0);  //TODO
3106233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pos + len) <= stop);
3107233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3108233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume ID
3109233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3110233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long size = ReadUInt(pReader, pos, len);
3111233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(size >= 0);
3112233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pos + len) <= stop);
3113233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3114233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume Size field
3115233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pos + size) <= stop);
3116233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3117233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x37) //CueTrackPosition(s) ID
3118233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
3119233d2500723e5594f3e7c70896ffeeef32b9c950ywan            TrackPosition& tp = *p++;
3120233d2500723e5594f3e7c70896ffeeef32b9c950ywan            tp.Parse(pReader, pos, size);
3121233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
3122233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3123233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;  //consume payload
3124233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos <= stop);
3125233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3126233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3127233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(size_t(p - m_track_positions) == m_track_positions_count);
3128233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3129233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_element_start = element_start;
3130233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_element_size = element_size;
3131233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3132233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3133233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3134233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3135233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid CuePoint::TrackPosition::Parse(
3136233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* pReader,
3137233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long start_,
3138233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size_)
3139233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
3140233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long stop = start_ + size_;
3141233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos = start_;
3142233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3143233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_track = -1;
3144233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pos = -1;
3145233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_block = 1;  //default
3146233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3147233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (pos < stop)
3148233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
3149233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long len;
3150233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3151233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id = ReadUInt(pReader, pos, len);
3152233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(id >= 0);  //TODO
3153233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pos + len) <= stop);
3154233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3155233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume ID
3156233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3157233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long size = ReadUInt(pReader, pos, len);
3158233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(size >= 0);
3159233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pos + len) <= stop);
3160233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3161233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume Size field
3162233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pos + size) <= stop);
3163233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3164233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x77)  //CueTrack ID
3165233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_track = UnserializeUInt(pReader, pos, size);
3166233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3167233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x71)  //CueClusterPos ID
3168233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_pos = UnserializeUInt(pReader, pos, size);
3169233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3170233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x1378)  //CueBlockNumber
3171233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_block = UnserializeUInt(pReader, pos, size);
3172233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3173233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;  //consume payload
3174233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos <= stop);
3175233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3176233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3177233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_pos >= 0);
3178233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_track > 0);
3179233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //assert(m_block > 0);
3180233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3181233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3182233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3183233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst CuePoint::TrackPosition* CuePoint::Find(const Track* pTrack) const
3184233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
3185233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pTrack);
3186233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3187233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long n = pTrack->GetNumber();
3188233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3189233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const TrackPosition* i = m_track_positions;
3190233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const TrackPosition* const j = i + m_track_positions_count;
3191233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3192233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (i != j)
3193233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
3194233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const TrackPosition& p = *i++;
3195233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3196233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (p.m_track == n)
3197233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return &p;
3198233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3199233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3200233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NULL;  //no matching track number found
3201233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3202233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3203233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3204233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long CuePoint::GetTimeCode() const
3205233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
3206233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_timecode;
3207233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3208233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3209233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long CuePoint::GetTime(const Segment* pSegment) const
3210233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
3211233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pSegment);
3212233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_timecode >= 0);
3213233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3214233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const SegmentInfo* const pInfo = pSegment->GetInfo();
3215233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pInfo);
3216233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3217233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long scale = pInfo->GetTimeCodeScale();
3218233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(scale >= 1);
3219233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3220233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long time = scale * m_timecode;
3221233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3222233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return time;
3223233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3224233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3225233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3226233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
3227233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long Segment::Unparsed() const
3228233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
3229233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_size < 0)
3230233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return LLONG_MAX;
3231233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3232233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long stop = m_start + m_size;
3233233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3234233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long result = stop - m_pos;
3235233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(result >= 0);
3236233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3237233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return result;
3238233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3239233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
3240233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Segment::DoneParsing() const
3241233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
3242233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_size < 0)
3243233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
3244233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long total, avail;
3245233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3246233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const int status = m_pReader->Length(&total, &avail);
3247233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3248233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)  //error
3249233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return true;  //must assume done
3250233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3251233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (total < 0)
3252233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return false;  //assume live stream
3253233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3254233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return (m_pos >= total);
3255233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3256233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3257233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long stop = m_start + m_size;
3258233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3259233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return (m_pos >= stop);
3260233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3261233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
3262233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3263233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3264233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst Cluster* Segment::GetFirst() const
3265233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
3266233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((m_clusters == NULL) || (m_clusterCount <= 0))
3267233d2500723e5594f3e7c70896ffeeef32b9c950ywan       return &m_eos;
3268233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3269233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster* const pCluster = m_clusters[0];
3270233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster);
3271233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3272233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return pCluster;
3273233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3274233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3275233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3276233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst Cluster* Segment::GetLast() const
3277233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
3278233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((m_clusters == NULL) || (m_clusterCount <= 0))
3279233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return &m_eos;
3280233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3281233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long idx = m_clusterCount - 1;
3282233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3283233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster* const pCluster = m_clusters[idx];
3284233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster);
3285233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3286233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return pCluster;
3287233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3288233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3289233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3290233d2500723e5594f3e7c70896ffeeef32b9c950ywanunsigned long Segment::GetCount() const
3291233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
3292233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_clusterCount;
3293233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3294233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3295233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3296233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst Cluster* Segment::GetNext(const Cluster* pCurr)
3297233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
3298233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCurr);
3299233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCurr != &m_eos);
3300233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_clusters);
3301233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3302233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long idx =  pCurr->m_index;
3303233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3304233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (idx >= 0)
3305233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
3306233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(m_clusterCount > 0);
3307233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(idx < m_clusterCount);
3308233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCurr == m_clusters[idx]);
3309233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3310233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ++idx;
3311233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3312233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (idx >= m_clusterCount)
3313233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return &m_eos;  //caller will LoadCluster as desired
3314233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3315233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster* const pNext = m_clusters[idx];
3316233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pNext);
3317233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pNext->m_index >= 0);
3318233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pNext->m_index == idx);
3319233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3320233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return pNext;
3321233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3322233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3323233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_clusterPreloadCount > 0);
3324233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3325233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos = pCurr->m_element_start;
3326233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3327233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_size >= 0);  //TODO
3328233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long stop = m_start + m_size;  //end of segment
3329233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3330233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
3331233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long len;
3332233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3333233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long result = GetUIntLength(m_pReader, pos, len);
3334233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(result == 0);
3335233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pos + len) <= stop);  //TODO
3336233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result != 0)
3337233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return NULL;
3338233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3339233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id = ReadUInt(m_pReader, pos, len);
3340233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(id == 0x0F43B675);  //Cluster ID
3341233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id != 0x0F43B675)
3342233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return NULL;
3343233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3344233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume ID
3345233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3346233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Read Size
3347233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result = GetUIntLength(m_pReader, pos, len);
3348233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(result == 0);  //TODO
3349233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pos + len) <= stop);  //TODO
3350233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3351233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long size = ReadUInt(m_pReader, pos, len);
3352233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(size > 0);  //TODO
3353233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //assert((pCurr->m_size <= 0) || (pCurr->m_size == size));
3354233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3355233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume length of size of element
3356233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pos + size) <= stop);  //TODO
3357233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3358233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Pos now points to start of payload
3359233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3360233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;  //consume payload
3361233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3362233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3363233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long off_next = 0;
3364233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3365233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (pos < stop)
3366233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
3367233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long len;
3368233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3369233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long result = GetUIntLength(m_pReader, pos, len);
3370233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(result == 0);
3371233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pos + len) <= stop);  //TODO
3372233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result != 0)
3373233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return NULL;
3374233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3375233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long idpos = pos;  //pos of next (potential) cluster
3376233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3377233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id = ReadUInt(m_pReader, idpos, len);
3378233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(id > 0);  //TODO
3379233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3380233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume ID
3381233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3382233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Read Size
3383233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result = GetUIntLength(m_pReader, pos, len);
3384233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(result == 0);  //TODO
3385233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pos + len) <= stop);  //TODO
3386233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3387233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long size = ReadUInt(m_pReader, pos, len);
3388233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(size >= 0);  //TODO
3389233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3390233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume length of size of element
3391233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pos + size) <= stop);  //TODO
3392233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3393233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Pos now points to start of payload
3394233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3395233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == 0)  //weird
3396233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
3397233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3398233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x0F43B675)  //Cluster ID
3399233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
3400233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long off_next_ = idpos - m_start;
3401233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3402233d2500723e5594f3e7c70896ffeeef32b9c950ywan            long long pos_;
3403233d2500723e5594f3e7c70896ffeeef32b9c950ywan            long len_;
3404233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3405233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long status = Cluster::HasBlockEntries(
3406233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    this,
3407233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    off_next_,
3408233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pos_,
3409233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    len_);
3410233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3411233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(status >= 0);
3412233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3413233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status > 0)
3414233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
3415233d2500723e5594f3e7c70896ffeeef32b9c950ywan                off_next = off_next_;
3416233d2500723e5594f3e7c70896ffeeef32b9c950ywan                break;
3417233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
3418233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
3419233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3420233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;  //consume payload
3421233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3422233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3423233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (off_next <= 0)
3424233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;
3425233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3426233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** const ii = m_clusters + m_clusterCount;
3427233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** i = ii;
3428233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3429233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** const jj = ii + m_clusterPreloadCount;
3430233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** j = jj;
3431233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3432233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (i < j)
3433233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
3434233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //INVARIANT:
3435233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[0, i) < pos_next
3436233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[i, j) ?
3437233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[j, jj)  > pos_next
3438233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3439233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster** const k = i + (j - i) / 2;
3440233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(k < jj);
3441233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3442233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster* const pNext = *k;
3443233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pNext);
3444233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pNext->m_index < 0);
3445233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3446233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //const long long pos_ = pNext->m_pos;
3447233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //assert(pos_);
3448233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //pos = pos_ * ((pos_ < 0) ? -1 : 1);
3449233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3450233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos = pNext->GetPosition();
3451233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3452233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pos < off_next)
3453233d2500723e5594f3e7c70896ffeeef32b9c950ywan            i = k + 1;
3454233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (pos > off_next)
3455233d2500723e5594f3e7c70896ffeeef32b9c950ywan            j = k;
3456233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else
3457233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return pNext;
3458233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3459233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3460233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(i == j);
3461233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3462233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster* const pNext = Cluster::Create(this,
3463233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                          -1,
3464233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                          off_next);
3465233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pNext);
3466233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3467233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const ptrdiff_t idx_next = i - m_clusters;  //insertion position
3468233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3469233d2500723e5594f3e7c70896ffeeef32b9c950ywan    PreloadCluster(pNext, idx_next);
3470233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_clusters);
3471233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(idx_next < m_clusterSize);
3472233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_clusters[idx_next] == pNext);
3473233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3474233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return pNext;
3475233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3476233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3477233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3478233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Segment::ParseNext(
3479233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Cluster* pCurr,
3480233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Cluster*& pResult,
3481233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long& pos,
3482233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long& len)
3483233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
3484233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCurr);
3485233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(!pCurr->EOS());
3486233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_clusters);
3487233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3488233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pResult = 0;
3489233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3490233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pCurr->m_index >= 0)  //loaded (not merely preloaded)
3491233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
3492233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(m_clusters[pCurr->m_index] == pCurr);
3493233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3494233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long next_idx = pCurr->m_index + 1;
3495233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3496233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (next_idx < m_clusterCount)
3497233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
3498233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pResult = m_clusters[next_idx];
3499233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 0;  //success
3500233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
3501233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3502233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //curr cluster is last among loaded
3503233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3504233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long result = LoadCluster(pos, len);
3505233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3506233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error or underflow
3507233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return result;
3508233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3509233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //no more clusters
3510233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
3511233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //pResult = &m_eos;
3512233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 1;
3513233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
3514233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3515233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pResult = GetLast();
3516233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;  //success
3517233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3518233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3519233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_pos > 0);
3520233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3521233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long total, avail;
3522233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3523233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long status = m_pReader->Length(&total, &avail);
3524233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3525233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error
3526233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
3527233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3528233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((total < 0) || (avail <= total));
3529233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3530233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
3531233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3532233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //interrogate curr cluster
3533233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3534233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos = pCurr->m_element_start;
3535233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3536233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pCurr->m_element_size >= 0)
3537233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += pCurr->m_element_size;
3538233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else
3539233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
3540233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > avail)
3541233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
3542233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
3543233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
3544233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
3545233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3546233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long result = GetUIntLength(m_pReader, pos, len);
3547233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3548233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
3549233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(result);
3550233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3551233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //weird
3552233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
3553233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3554233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((segment_stop >= 0) && ((pos + len) > segment_stop))
3555233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
3556233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3557233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > avail)
3558233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
3559233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3560233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id = ReadUInt(m_pReader, pos, len);
3561233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3562233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id != 0x0F43B675)  //weird: not Cluster ID
3563233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return -1;
3564233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3565233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume ID
3566233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3567233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Read Size
3568233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3569233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > avail)
3570233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
3571233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
3572233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
3573233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
3574233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3575233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result = GetUIntLength(m_pReader, pos, len);
3576233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3577233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
3578233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(result);
3579233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3580233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //weird
3581233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
3582233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3583233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((segment_stop >= 0) && ((pos + len) > segment_stop))
3584233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
3585233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3586233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > avail)
3587233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
3588233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3589233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long size = ReadUInt(m_pReader, pos, len);
3590233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3591233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size < 0) //error
3592233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(size);
3593233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3594233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume size field
3595233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3596233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long unknown_size = (1LL << (7 * len)) - 1;
3597233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3598233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == unknown_size)          //TODO: should never happen
3599233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;  //TODO: resolve this
3600233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3601233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //assert((pCurr->m_size <= 0) || (pCurr->m_size == size));
3602233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3603233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((segment_stop >= 0) && ((pos + size) > segment_stop))
3604233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
3605233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3606233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Pos now points to start of payload
3607233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3608233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;  //consume payload (that is, the current cluster)
3609233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((segment_stop < 0) || (pos <= segment_stop));
3610233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3611233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //By consuming the payload, we are assuming that the curr
3612233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //cluster isn't interesting.  That is, we don't bother checking
3613233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //whether the payload of the curr cluster is less than what
3614233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //happens to be available (obtained via IMkvReader::Length).
3615233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Presumably the caller has already dispensed with the current
3616233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //cluster, and really does want the next cluster.
3617233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3618233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3619233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //pos now points to just beyond the last fully-loaded cluster
3620233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3621233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (;;)
3622233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
3623233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long status = DoParseNext(pResult, pos, len);
3624233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3625233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status <= 1)
3626233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
3627233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3628233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3629233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3630233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3631233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Segment::DoParseNext(
3632233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Cluster*& pResult,
3633233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long& pos,
3634233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long& len)
3635233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
3636233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long total, avail;
3637233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3638233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long status = m_pReader->Length(&total, &avail);
3639233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3640233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error
3641233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
3642233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3643233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((total < 0) || (avail <= total));
3644233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3645233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
3646233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3647233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //Parse next cluster.  This is strictly a parsing activity.
3648233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //Creation of a new cluster object happens later, after the
3649233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //parsing is done.
3650233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3651233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long off_next = 0;
3652233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long cluster_size = -1;
3653233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3654233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (;;)
3655233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
3656233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((total >= 0) && (pos >= total))
3657233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 1;  //EOF
3658233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3659233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((segment_stop >= 0) && (pos >= segment_stop))
3660233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 1;  //EOF
3661233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3662233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > avail)
3663233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
3664233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
3665233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
3666233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
3667233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3668233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long result = GetUIntLength(m_pReader, pos, len);
3669233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3670233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
3671233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(result);
3672233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3673233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //weird
3674233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
3675233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3676233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((segment_stop >= 0) && ((pos + len) > segment_stop))
3677233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
3678233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3679233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > avail)
3680233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
3681233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3682233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long idpos = pos;             //absolute
3683233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long idoff = pos - m_start;   //relative
3684233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3685233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id = ReadUInt(m_pReader, idpos, len);  //absolute
3686233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3687233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id < 0)  //error
3688233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(id);
3689233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3690233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0)  //weird
3691233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return -1;  //generic error
3692233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3693233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume ID
3694233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3695233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Read Size
3696233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3697233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > avail)
3698233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
3699233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
3700233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
3701233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
3702233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3703233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result = GetUIntLength(m_pReader, pos, len);
3704233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3705233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
3706233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(result);
3707233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3708233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //weird
3709233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
3710233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3711233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((segment_stop >= 0) && ((pos + len) > segment_stop))
3712233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
3713233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3714233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > avail)
3715233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
3716233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3717233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long size = ReadUInt(m_pReader, pos, len);
3718233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3719233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size < 0)  //error
3720233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(size);
3721233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3722233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume length of size of element
3723233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3724233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Pos now points to start of payload
3725233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3726233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == 0)  //weird
3727233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
3728233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3729233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long unknown_size = (1LL << (7 * len)) - 1;
3730233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3731233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((segment_stop >= 0) &&
3732233d2500723e5594f3e7c70896ffeeef32b9c950ywan            (size != unknown_size) &&
3733233d2500723e5594f3e7c70896ffeeef32b9c950ywan            ((pos + size) > segment_stop))
3734233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
3735233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
3736233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
3737233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3738233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x0C53BB6B)  //Cues ID
3739233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
3740233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (size == unknown_size)
3741233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
3742233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3743233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long element_stop = pos + size;
3744233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3745233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((segment_stop >= 0) && (element_stop > segment_stop))
3746233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
3747233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3748233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long element_start = idpos;
3749233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long element_size = element_stop - element_start;
3750233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3751233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_pCues == NULL)
3752233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
3753233d2500723e5594f3e7c70896ffeeef32b9c950ywan                m_pCues = new Cues(this,
3754233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pos,
3755233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    size,
3756233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    element_start,
3757233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    element_size);
3758233d2500723e5594f3e7c70896ffeeef32b9c950ywan                assert(m_pCues);  //TODO
3759233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
3760233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3761233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pos += size;  //consume payload
3762233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert((segment_stop < 0) || (pos <= segment_stop));
3763233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3764233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
3765233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
3766233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3767233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id != 0x0F43B675)  //not a Cluster ID
3768233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
3769233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (size == unknown_size)
3770233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
3771233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3772233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pos += size;  //consume payload
3773233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert((segment_stop < 0) || (pos <= segment_stop));
3774233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3775233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
3776233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
3777233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3778233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0 //this is commented-out to support incremental cluster parsing
3779233d2500723e5594f3e7c70896ffeeef32b9c950ywan        len = static_cast<long>(size);
3780233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3781233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (element_stop > avail)
3782233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
3783233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
3784233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3785233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //We have a cluster.
3786233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3787233d2500723e5594f3e7c70896ffeeef32b9c950ywan        off_next = idoff;
3788233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3789233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size != unknown_size)
3790233d2500723e5594f3e7c70896ffeeef32b9c950ywan            cluster_size = size;
3791233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3792233d2500723e5594f3e7c70896ffeeef32b9c950ywan        break;
3793233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3794233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3795233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(off_next > 0);  //have cluster
3796233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3797233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //We have parsed the next cluster.
3798233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //We have not created a cluster object yet.  What we need
3799233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //to do now is determine whether it has already be preloaded
3800233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //(in which case, an object for this cluster has already been
3801233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //created), and if not, create a new cluster object.
3802233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3803233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** const ii = m_clusters + m_clusterCount;
3804233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** i = ii;
3805233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3806233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** const jj = ii + m_clusterPreloadCount;
3807233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** j = jj;
3808233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3809233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (i < j)
3810233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
3811233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //INVARIANT:
3812233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[0, i) < pos_next
3813233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[i, j) ?
3814233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[j, jj)  > pos_next
3815233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3816233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster** const k = i + (j - i) / 2;
3817233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(k < jj);
3818233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3819233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const Cluster* const pNext = *k;
3820233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pNext);
3821233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pNext->m_index < 0);
3822233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3823233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos = pNext->GetPosition();
3824233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos >= 0);
3825233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3826233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pos < off_next)
3827233d2500723e5594f3e7c70896ffeeef32b9c950ywan            i = k + 1;
3828233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (pos > off_next)
3829233d2500723e5594f3e7c70896ffeeef32b9c950ywan            j = k;
3830233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else
3831233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
3832233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pResult = pNext;
3833233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 0;  //success
3834233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
3835233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3836233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3837233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(i == j);
3838233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3839233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos_;
3840233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long len_;
3841233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3842233d2500723e5594f3e7c70896ffeeef32b9c950ywan    status = Cluster::HasBlockEntries(this, off_next, pos_, len_);
3843233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3844233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error or underflow
3845233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
3846233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos = pos_;
3847233d2500723e5594f3e7c70896ffeeef32b9c950ywan        len = len_;
3848233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3849233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
3850233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3851233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3852233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status > 0)  //means "found at least one block entry"
3853233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
3854233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster* const pNext = Cluster::Create(this,
3855233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                -1,   //preloaded
3856233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                off_next);
3857233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                //element_size);
3858233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pNext);
3859233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3860233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const ptrdiff_t idx_next = i - m_clusters;  //insertion position
3861233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3862233d2500723e5594f3e7c70896ffeeef32b9c950ywan        PreloadCluster(pNext, idx_next);
3863233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(m_clusters);
3864233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(idx_next < m_clusterSize);
3865233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(m_clusters[idx_next] == pNext);
3866233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3867233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pResult = pNext;
3868233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;  //success
3869233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3870233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3871233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //status == 0 means "no block entries found"
3872233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3873233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cluster_size < 0)  //unknown size
3874233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
3875233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long payload_pos = pos;  //absolute pos of cluster payload
3876233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3877233d2500723e5594f3e7c70896ffeeef32b9c950ywan        for (;;)  //determine cluster size
3878233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
3879233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((total >= 0) && (pos >= total))
3880233d2500723e5594f3e7c70896ffeeef32b9c950ywan                break;
3881233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3882233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((segment_stop >= 0) && (pos >= segment_stop))
3883233d2500723e5594f3e7c70896ffeeef32b9c950ywan                break;  //no more clusters
3884233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3885233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //Read ID
3886233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3887233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((pos + 1) > avail)
3888233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
3889233d2500723e5594f3e7c70896ffeeef32b9c950ywan                len = 1;
3890233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_BUFFER_NOT_FULL;
3891233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
3892233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3893233d2500723e5594f3e7c70896ffeeef32b9c950ywan            long long result = GetUIntLength(m_pReader, pos, len);
3894233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3895233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (result < 0)  //error
3896233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return static_cast<long>(result);
3897233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3898233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (result > 0)  //weird
3899233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_BUFFER_NOT_FULL;
3900233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3901233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((segment_stop >= 0) && ((pos + len) > segment_stop))
3902233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
3903233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3904233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((pos + len) > avail)
3905233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_BUFFER_NOT_FULL;
3906233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3907233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long idpos = pos;
3908233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long id = ReadUInt(m_pReader, idpos, len);
3909233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3910233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (id < 0)  //error (or underflow)
3911233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return static_cast<long>(id);
3912233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3913233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //This is the distinguished set of ID's we use to determine
3914233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //that we have exhausted the sub-element's inside the cluster
3915233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //whose ID we parsed earlier.
3916233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3917233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (id == 0x0F43B675)  //Cluster ID
3918233d2500723e5594f3e7c70896ffeeef32b9c950ywan                break;
3919233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3920233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (id == 0x0C53BB6B)  //Cues ID
3921233d2500723e5594f3e7c70896ffeeef32b9c950ywan                break;
3922233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3923233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pos += len;  //consume ID (of sub-element)
3924233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3925233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //Read Size
3926233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3927233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((pos + 1) > avail)
3928233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
3929233d2500723e5594f3e7c70896ffeeef32b9c950ywan                len = 1;
3930233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_BUFFER_NOT_FULL;
3931233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
3932233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3933233d2500723e5594f3e7c70896ffeeef32b9c950ywan            result = GetUIntLength(m_pReader, pos, len);
3934233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3935233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (result < 0)  //error
3936233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return static_cast<long>(result);
3937233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3938233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (result > 0)  //weird
3939233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_BUFFER_NOT_FULL;
3940233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3941233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((segment_stop >= 0) && ((pos + len) > segment_stop))
3942233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
3943233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3944233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((pos + len) > avail)
3945233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_BUFFER_NOT_FULL;
3946233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3947233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long size = ReadUInt(m_pReader, pos, len);
3948233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3949233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (size < 0)  //error
3950233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return static_cast<long>(size);
3951233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3952233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pos += len;  //consume size field of element
3953233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3954233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //pos now points to start of sub-element's payload
3955233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3956233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (size == 0)  //weird
3957233d2500723e5594f3e7c70896ffeeef32b9c950ywan                continue;
3958233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3959233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long unknown_size = (1LL << (7 * len)) - 1;
3960233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3961233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (size == unknown_size)
3962233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;  //not allowed for sub-elements
3963233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3964233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((segment_stop >= 0) && ((pos + size) > segment_stop))  //weird
3965233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
3966233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3967233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pos += size;  //consume payload of sub-element
3968233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert((segment_stop < 0) || (pos <= segment_stop));
3969233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }  //determine cluster size
3970233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3971233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cluster_size = pos - payload_pos;
3972233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(cluster_size >= 0);  //TODO: handle cluster_size = 0
3973233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3974233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos = payload_pos;  //reset and re-parse original cluster
3975233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3976233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3977233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += cluster_size;  //consume payload
3978233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((segment_stop < 0) || (pos <= segment_stop));
3979233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3980233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 2;             //try to find a cluster that follows next
3981233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3982233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3983233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3984233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst Cluster* Segment::FindCluster(long long time_ns) const
3985233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
3986233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((m_clusters == NULL) || (m_clusterCount <= 0))
3987233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return &m_eos;
3988233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3989233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
3990233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster* const pCluster = m_clusters[0];
3991233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster);
3992233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster->m_index == 0);
3993233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3994233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (time_ns <= pCluster->GetTime())
3995233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return pCluster;
3996233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3997233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3998233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //Binary search of cluster array
3999233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4000233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long i = 0;
4001233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long j = m_clusterCount;
4002233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4003233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (i < j)
4004233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
4005233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //INVARIANT:
4006233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[0, i) <= time_ns
4007233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[i, j) ?
4008233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[j, m_clusterCount)  > time_ns
4009233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4010233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long k = i + (j - i) / 2;
4011233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(k < m_clusterCount);
4012233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4013233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster* const pCluster = m_clusters[k];
4014233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster);
4015233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster->m_index == k);
4016233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4017233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long t = pCluster->GetTime();
4018233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4019233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (t <= time_ns)
4020233d2500723e5594f3e7c70896ffeeef32b9c950ywan            i = k + 1;
4021233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else
4022233d2500723e5594f3e7c70896ffeeef32b9c950ywan            j = k;
4023233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4024233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(i <= j);
4025233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
4026233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4027233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(i == j);
4028233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(i > 0);
4029233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(i <= m_clusterCount);
4030233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4031233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long k = i - 1;
4032233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4033233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster* const pCluster = m_clusters[k];
4034233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster);
4035233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster->m_index == k);
4036233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster->GetTime() <= time_ns);
4037233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4038233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return pCluster;
4039233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4040233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4041233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4042233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
4043233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst BlockEntry* Segment::Seek(
4044233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long time_ns,
4045233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Track* pTrack) const
4046233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4047233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pTrack);
4048233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4049233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((m_clusters == NULL) || (m_clusterCount <= 0))
4050233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return pTrack->GetEOS();
4051233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4052233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** const i = m_clusters;
4053233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(i);
4054233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4055233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
4056233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster* const pCluster = *i;
4057233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster);
4058233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster->m_index == 0);  //m_clusterCount > 0
4059233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster->m_pSegment == this);
4060233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4061233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (time_ns <= pCluster->GetTime())
4062233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return pCluster->GetEntry(pTrack);
4063233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
4064233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4065233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** const j = i + m_clusterCount;
4066233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4067233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pTrack->GetType() == 2)  //audio
4068233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
4069233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //TODO: we could decide to use cues for this, as we do for video.
4070233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //But we only use it for video because looking around for a keyframe
4071233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //can get expensive.  Audio doesn't require anything special so a
4072233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //straight cluster search is good enough (we assume).
4073233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4074233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster** lo = i;
4075233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster** hi = j;
4076233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4077233d2500723e5594f3e7c70896ffeeef32b9c950ywan        while (lo < hi)
4078233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
4079233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //INVARIANT:
4080233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //[i, lo) <= time_ns
4081233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //[lo, hi) ?
4082233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //[hi, j)  > time_ns
4083233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4084233d2500723e5594f3e7c70896ffeeef32b9c950ywan            Cluster** const mid = lo + (hi - lo) / 2;
4085233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(mid < hi);
4086233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4087233d2500723e5594f3e7c70896ffeeef32b9c950ywan            Cluster* const pCluster = *mid;
4088233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(pCluster);
4089233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(pCluster->m_index == long(mid - m_clusters));
4090233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(pCluster->m_pSegment == this);
4091233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4092233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long t = pCluster->GetTime();
4093233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4094233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (t <= time_ns)
4095233d2500723e5594f3e7c70896ffeeef32b9c950ywan                lo = mid + 1;
4096233d2500723e5594f3e7c70896ffeeef32b9c950ywan            else
4097233d2500723e5594f3e7c70896ffeeef32b9c950ywan                hi = mid;
4098233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4099233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(lo <= hi);
4100233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
4101233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4102233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(lo == hi);
4103233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(lo > i);
4104233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(lo <= j);
4105233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4106233d2500723e5594f3e7c70896ffeeef32b9c950ywan        while (lo > i)
4107233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
4108233d2500723e5594f3e7c70896ffeeef32b9c950ywan            Cluster* const pCluster = *--lo;
4109233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(pCluster);
4110233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(pCluster->GetTime() <= time_ns);
4111233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4112233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const BlockEntry* const pBE = pCluster->GetEntry(pTrack);
4113233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4114233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((pBE != 0) && !pBE->EOS())
4115233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return pBE;
4116233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4117233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //landed on empty cluster (no entries)
4118233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
4119233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4120233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return pTrack->GetEOS();  //weird
4121233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
4122233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4123233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pTrack->GetType() == 1);  //video
4124233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4125233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** lo = i;
4126233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** hi = j;
4127233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4128233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (lo < hi)
4129233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
4130233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //INVARIANT:
4131233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[i, lo) <= time_ns
4132233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[lo, hi) ?
4133233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[hi, j)  > time_ns
4134233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4135233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster** const mid = lo + (hi - lo) / 2;
4136233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(mid < hi);
4137233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4138233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster* const pCluster = *mid;
4139233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster);
4140233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4141233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long t = pCluster->GetTime();
4142233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4143233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (t <= time_ns)
4144233d2500723e5594f3e7c70896ffeeef32b9c950ywan            lo = mid + 1;
4145233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else
4146233d2500723e5594f3e7c70896ffeeef32b9c950ywan            hi = mid;
4147233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4148233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(lo <= hi);
4149233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
4150233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4151233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(lo == hi);
4152233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(lo > i);
4153233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(lo <= j);
4154233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4155233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster* pCluster = *--lo;
4156233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster);
4157233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster->GetTime() <= time_ns);
4158233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4159233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
4160233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const BlockEntry* const pBE = pCluster->GetEntry(pTrack, time_ns);
4161233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4162233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pBE != 0) && !pBE->EOS())  //found a keyframe
4163233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return pBE;
4164233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
4165233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4166233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const VideoTrack* const pVideo = static_cast<const VideoTrack*>(pTrack);
4167233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4168233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (lo != i)
4169233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
4170233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pCluster = *--lo;
4171233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster);
4172233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster->GetTime() <= time_ns);
4173233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4174233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const BlockEntry* const pBlockEntry = pCluster->GetMaxKey(pVideo);
4175233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4176233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pBlockEntry != 0) && !pBlockEntry->EOS())
4177233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return pBlockEntry;
4178233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
4179233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4180233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //weird: we're on the first cluster, but no keyframe found
4181233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //should never happen but we must return something anyway
4182233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4183233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return pTrack->GetEOS();
4184233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4185233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
4186233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4187233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4188233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
4189233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Segment::SearchCues(
4190233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long time_ns,
4191233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Track* pTrack,
4192233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster*& pCluster,
4193233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const BlockEntry*& pBlockEntry,
4194233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const CuePoint*& pCP,
4195233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const CuePoint::TrackPosition*& pTP)
4196233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4197233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pTrack->GetType() != 1)  //not video
4198233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;  //TODO: for now, just handle video stream
4199233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4200233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_pCues == NULL)
4201233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
4202233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4203233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!m_pCues->Find(time_ns, pTrack, pCP, pTP))
4204233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;  //weird
4205233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4206233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCP);
4207233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pTP);
4208233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pTP->m_track == pTrack->GetNumber());
4209233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4210233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //We have the cue point and track position we want,
4211233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //so we now need to search for the cluster having
4212233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //the indicated position.
4213233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4214233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return GetCluster(pCP, pTP, pCluster, pBlockEntry);
4215233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4216233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
4217233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4218233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4219233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst Tracks* Segment::GetTracks() const
4220233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4221233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_pTracks;
4222233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4223233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4224233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4225233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst SegmentInfo* Segment::GetInfo() const
4226233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4227233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_pInfo;
4228233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4229233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4230233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4231233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst Cues* Segment::GetCues() const
4232233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4233233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_pCues;
4234233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4235233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4236233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4237233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst Chapters* Segment::GetChapters() const
4238233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4239233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return m_pChapters;
4240233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4241233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4242233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4243233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst SeekHead* Segment::GetSeekHead() const
4244233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4245233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_pSeekHead;
4246233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4247233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4248233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4249233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long Segment::GetDuration() const
4250233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4251233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_pInfo);
4252233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_pInfo->GetDuration();
4253233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4254233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4255233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4256233d2500723e5594f3e7c70896ffeeef32b9c950ywanChapters::Chapters(
4257233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Segment* pSegment,
4258233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long payload_start,
4259233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long payload_size,
4260233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_start,
4261233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_size) :
4262233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pSegment(pSegment),
4263233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_start(payload_start),
4264233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_size(payload_size),
4265233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_element_start(element_start),
4266233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_element_size(element_size),
4267233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_editions(NULL),
4268233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_editions_size(0),
4269233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_editions_count(0)
4270233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4271233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4272233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4273233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4274233d2500723e5594f3e7c70896ffeeef32b9c950ywanChapters::~Chapters()
4275233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4276233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (m_editions_count > 0)
4277233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
4278233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Edition& e = m_editions[--m_editions_count];
4279233d2500723e5594f3e7c70896ffeeef32b9c950ywan        e.Clear();
4280233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
4281233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4282233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4283233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4284233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Chapters::Parse()
4285233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4286233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* const pReader = m_pSegment->m_pReader;
4287233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4288233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos = m_start;  // payload start
4289233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long stop = pos + m_size;  // payload stop
4290233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4291233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (pos < stop)
4292233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
4293233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long id, size;
4294233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4295233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long status = ParseElementHeader(
4296233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        pReader,
4297233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        pos,
4298233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        stop,
4299233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        id,
4300233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        size);
4301233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4302233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)  // error
4303233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
4304233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4305233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == 0)  // weird
4306233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
4307233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4308233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x05B9)  // EditionEntry ID
4309233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
4310233d2500723e5594f3e7c70896ffeeef32b9c950ywan            status = ParseEdition(pos, size);
4311233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4312233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status < 0)  // error
4313233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return status;
4314233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
4315233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4316233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;
4317233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos <= stop);
4318233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
4319233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4320233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos == stop);
4321233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
4322233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4323233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4324233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4325233d2500723e5594f3e7c70896ffeeef32b9c950ywanint Chapters::GetEditionCount() const
4326233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4327233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_editions_count;
4328233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4329233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4330233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4331233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst Chapters::Edition* Chapters::GetEdition(int idx) const
4332233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4333233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (idx < 0)
4334233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return NULL;
4335233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4336233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (idx >= m_editions_count)
4337233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return NULL;
4338233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4339233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_editions + idx;
4340233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4341233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4342233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4343233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Chapters::ExpandEditionsArray()
4344233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4345233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_editions_size > m_editions_count)
4346233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return true;  // nothing else to do
4347233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4348233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int size = (m_editions_size == 0) ? 1 : 2 * m_editions_size;
4349233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4350233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Edition* const editions = new (std::nothrow) Edition[size];
4351233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4352233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (editions == NULL)
4353233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
4354233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4355233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (int idx = 0; idx < m_editions_count; ++idx)
4356233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
4357233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m_editions[idx].ShallowCopy(editions[idx]);
4358233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
4359233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4360233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] m_editions;
4361233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_editions = editions;
4362233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4363233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_editions_size = size;
4364233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return true;
4365233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4366233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4367233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4368233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Chapters::ParseEdition(
4369233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos,
4370233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size)
4371233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4372233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!ExpandEditionsArray())
4373233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
4374233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4375233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Edition& e = m_editions[m_editions_count++];
4376233d2500723e5594f3e7c70896ffeeef32b9c950ywan    e.Init();
4377233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4378233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return e.Parse(m_pSegment->m_pReader, pos, size);
4379233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4380233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4381233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4382233d2500723e5594f3e7c70896ffeeef32b9c950ywanChapters::Edition::Edition()
4383233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4384233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4385233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4386233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4387233d2500723e5594f3e7c70896ffeeef32b9c950ywanChapters::Edition::~Edition()
4388233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4389233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4390233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4391233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4392233d2500723e5594f3e7c70896ffeeef32b9c950ywanint Chapters::Edition::GetAtomCount() const
4393233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4394233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_atoms_count;
4395233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4396233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4397233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4398233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst Chapters::Atom* Chapters::Edition::GetAtom(int index) const
4399233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4400233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (index < 0)
4401233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return NULL;
4402233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4403233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (index >= m_atoms_count)
4404233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return NULL;
4405233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4406233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_atoms + index;
4407233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4408233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4409233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4410233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Chapters::Edition::Init()
4411233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4412233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_atoms = NULL;
4413233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_atoms_size = 0;
4414233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_atoms_count = 0;
4415233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4416233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4417233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4418233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Chapters::Edition::ShallowCopy(Edition& rhs) const
4419233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4420233d2500723e5594f3e7c70896ffeeef32b9c950ywan    rhs.m_atoms = m_atoms;
4421233d2500723e5594f3e7c70896ffeeef32b9c950ywan    rhs.m_atoms_size = m_atoms_size;
4422233d2500723e5594f3e7c70896ffeeef32b9c950ywan    rhs.m_atoms_count = m_atoms_count;
4423233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4424233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4425233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4426233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Chapters::Edition::Clear()
4427233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4428233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (m_atoms_count > 0)
4429233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
4430233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Atom& a = m_atoms[--m_atoms_count];
4431233d2500723e5594f3e7c70896ffeeef32b9c950ywan        a.Clear();
4432233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
4433233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4434233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] m_atoms;
4435233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_atoms = NULL;
4436233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4437233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_atoms_size = 0;
4438233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4439233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4440233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4441233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Chapters::Edition::Parse(
4442233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* pReader,
4443233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos,
4444233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size)
4445233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4446233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long stop = pos + size;
4447233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4448233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (pos < stop)
4449233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
4450233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long id, size;
4451233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4452233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long status = ParseElementHeader(
4453233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        pReader,
4454233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        pos,
4455233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        stop,
4456233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        id,
4457233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        size);
4458233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4459233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)  // error
4460233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
4461233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4462233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == 0)  // weird
4463233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
4464233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4465233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x36)  // Atom ID
4466233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
4467233d2500723e5594f3e7c70896ffeeef32b9c950ywan            status = ParseAtom(pReader, pos, size);
4468233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4469233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status < 0)  // error
4470233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return status;
4471233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
4472233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4473233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;
4474233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos <= stop);
4475233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
4476233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4477233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos == stop);
4478233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
4479233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4480233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4481233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4482233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Chapters::Edition::ParseAtom(
4483233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* pReader,
4484233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos,
4485233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size)
4486233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4487233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!ExpandAtomsArray())
4488233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
4489233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4490233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Atom& a = m_atoms[m_atoms_count++];
4491233d2500723e5594f3e7c70896ffeeef32b9c950ywan    a.Init();
4492233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4493233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return a.Parse(pReader, pos, size);
4494233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4495233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4496233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4497233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Chapters::Edition::ExpandAtomsArray()
4498233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4499233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_atoms_size > m_atoms_count)
4500233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return true;  // nothing else to do
4501233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4502233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int size = (m_atoms_size == 0) ? 1 : 2 * m_atoms_size;
4503233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4504233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Atom* const atoms = new (std::nothrow) Atom[size];
4505233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4506233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (atoms == NULL)
4507233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
4508233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4509233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (int idx = 0; idx < m_atoms_count; ++idx)
4510233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
4511233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m_atoms[idx].ShallowCopy(atoms[idx]);
4512233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
4513233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4514233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] m_atoms;
4515233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_atoms = atoms;
4516233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4517233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_atoms_size = size;
4518233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return true;
4519233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4520233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4521233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4522233d2500723e5594f3e7c70896ffeeef32b9c950ywanChapters::Atom::Atom()
4523233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4524233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4525233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4526233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4527233d2500723e5594f3e7c70896ffeeef32b9c950ywanChapters::Atom::~Atom()
4528233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4529233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4530233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4531233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4532233d2500723e5594f3e7c70896ffeeef32b9c950ywanunsigned long long Chapters::Atom::GetUID() const
4533233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4534233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_uid;
4535233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4536233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4537233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4538233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst char* Chapters::Atom::GetStringUID() const
4539233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4540233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_string_uid;
4541233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4542233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4543233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4544233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long Chapters::Atom::GetStartTimecode() const
4545233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4546233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_start_timecode;
4547233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4548233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4549233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4550233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long Chapters::Atom::GetStopTimecode() const
4551233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4552233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_stop_timecode;
4553233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4554233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4555233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4556233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long Chapters::Atom::GetStartTime(const Chapters* pChapters) const
4557233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4558233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return GetTime(pChapters, m_start_timecode);
4559233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4560233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4561233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4562233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long Chapters::Atom::GetStopTime(const Chapters* pChapters) const
4563233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4564233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return GetTime(pChapters, m_stop_timecode);
4565233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4566233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4567233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4568233d2500723e5594f3e7c70896ffeeef32b9c950ywanint Chapters::Atom::GetDisplayCount() const
4569233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4570233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_displays_count;
4571233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4572233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4573233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4574233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst Chapters::Display* Chapters::Atom::GetDisplay(int index) const
4575233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4576233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (index < 0)
4577233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return NULL;
4578233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4579233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (index >= m_displays_count)
4580233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return NULL;
4581233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4582233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_displays + index;
4583233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4584233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4585233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4586233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Chapters::Atom::Init()
4587233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4588233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_string_uid = NULL;
4589233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_uid = 0;
4590233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_start_timecode = -1;
4591233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_stop_timecode = -1;
4592233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4593233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_displays = NULL;
4594233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_displays_size = 0;
4595233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_displays_count = 0;
4596233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4597233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4598233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4599233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Chapters::Atom::ShallowCopy(Atom& rhs) const
4600233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4601233d2500723e5594f3e7c70896ffeeef32b9c950ywan    rhs.m_string_uid = m_string_uid;
4602233d2500723e5594f3e7c70896ffeeef32b9c950ywan    rhs.m_uid = m_uid;
4603233d2500723e5594f3e7c70896ffeeef32b9c950ywan    rhs.m_start_timecode = m_start_timecode;
4604233d2500723e5594f3e7c70896ffeeef32b9c950ywan    rhs.m_stop_timecode = m_stop_timecode;
4605233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4606233d2500723e5594f3e7c70896ffeeef32b9c950ywan    rhs.m_displays = m_displays;
4607233d2500723e5594f3e7c70896ffeeef32b9c950ywan    rhs.m_displays_size = m_displays_size;
4608233d2500723e5594f3e7c70896ffeeef32b9c950ywan    rhs.m_displays_count = m_displays_count;
4609233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4610233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4611233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4612233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Chapters::Atom::Clear()
4613233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4614233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] m_string_uid;
4615233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_string_uid = NULL;
4616233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4617233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (m_displays_count > 0)
4618233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
4619233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Display& d = m_displays[--m_displays_count];
4620233d2500723e5594f3e7c70896ffeeef32b9c950ywan        d.Clear();
4621233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
4622233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4623233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] m_displays;
4624233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_displays = NULL;
4625233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4626233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_displays_size = 0;
4627233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4628233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4629233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4630233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Chapters::Atom::Parse(
4631233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* pReader,
4632233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos,
4633233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size)
4634233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4635233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long stop = pos + size;
4636233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4637233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (pos < stop)
4638233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
4639233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long id, size;
4640233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4641233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long status = ParseElementHeader(
4642233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        pReader,
4643233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        pos,
4644233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        stop,
4645233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        id,
4646233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        size);
4647233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4648233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)  // error
4649233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
4650233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4651233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == 0)  // weird
4652233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
4653233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4654233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x00)  // Display ID
4655233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
4656233d2500723e5594f3e7c70896ffeeef32b9c950ywan            status = ParseDisplay(pReader, pos, size);
4657233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4658233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status < 0)  // error
4659233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return status;
4660233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
4661233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x1654)  // StringUID ID
4662233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
4663233d2500723e5594f3e7c70896ffeeef32b9c950ywan            status = UnserializeString(pReader, pos, size, m_string_uid);
4664233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4665233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status < 0)  // error
4666233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return status;
4667233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
4668233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x33C4)  // UID ID
4669233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
4670233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long val = UnserializeUInt(pReader, pos, size);
4671233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4672233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (val < 0)  // error
4673233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return static_cast<long>(val);
4674233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4675233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_uid = val;
4676233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
4677233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x11)  // TimeStart ID
4678233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
4679233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long val = UnserializeUInt(pReader, pos, size);
4680233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4681233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (val < 0)  // error
4682233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return static_cast<long>(val);
4683233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4684233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_start_timecode = val;
4685233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
4686233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x12)  // TimeEnd ID
4687233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
4688233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long val = UnserializeUInt(pReader, pos, size);
4689233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4690233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (val < 0)  // error
4691233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return static_cast<long>(val);
4692233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4693233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_stop_timecode = val;
4694233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
4695233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4696233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;
4697233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos <= stop);
4698233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
4699233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4700233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos == stop);
4701233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
4702233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4703233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4704233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4705233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long Chapters::Atom::GetTime(
4706233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Chapters* pChapters,
4707233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long timecode)
4708233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4709233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pChapters == NULL)
4710233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
4711233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4712233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Segment* const pSegment = pChapters->m_pSegment;
4713233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4714233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pSegment == NULL)  // weird
4715233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
4716233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4717233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const SegmentInfo* const pInfo = pSegment->GetInfo();
4718233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4719233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pInfo == NULL)
4720233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
4721233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4722233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long timecode_scale = pInfo->GetTimeCodeScale();
4723233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4724233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (timecode_scale < 1)  // weird
4725233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
4726233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4727233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (timecode < 0)
4728233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
4729233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4730233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long result = timecode_scale * timecode;
4731233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4732233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return result;
4733233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4734233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4735233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4736233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Chapters::Atom::ParseDisplay(
4737233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* pReader,
4738233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos,
4739233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size)
4740233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4741233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!ExpandDisplaysArray())
4742233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
4743233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4744233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Display& d = m_displays[m_displays_count++];
4745233d2500723e5594f3e7c70896ffeeef32b9c950ywan    d.Init();
4746233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4747233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return d.Parse(pReader, pos, size);
4748233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4749233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4750233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4751233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Chapters::Atom::ExpandDisplaysArray()
4752233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4753233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_displays_size > m_displays_count)
4754233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return true;  // nothing else to do
4755233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4756233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int size = (m_displays_size == 0) ? 1 : 2 * m_displays_size;
4757233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4758233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Display* const displays = new (std::nothrow) Display[size];
4759233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4760233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (displays == NULL)
4761233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
4762233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4763233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (int idx = 0; idx < m_displays_count; ++idx)
4764233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
4765233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m_displays[idx].ShallowCopy(displays[idx]);
4766233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
4767233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4768233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] m_displays;
4769233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_displays = displays;
4770233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4771233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_displays_size = size;
4772233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return true;
4773233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4774233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4775233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4776233d2500723e5594f3e7c70896ffeeef32b9c950ywanChapters::Display::Display()
4777233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4778233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4779233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4780233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4781233d2500723e5594f3e7c70896ffeeef32b9c950ywanChapters::Display::~Display()
4782233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4783233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4784233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4785233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4786233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst char* Chapters::Display::GetString() const
4787233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4788233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_string;
4789233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4790233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4791233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4792233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst char* Chapters::Display::GetLanguage() const
4793233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4794233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_language;
4795233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4796233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4797233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4798233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst char* Chapters::Display::GetCountry() const
4799233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4800233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_country;
4801233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4802233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4803233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4804233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Chapters::Display::Init()
4805233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4806233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_string = NULL;
4807233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_language = NULL;
4808233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_country = NULL;
4809233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4810233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4811233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4812233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Chapters::Display::ShallowCopy(Display& rhs) const
4813233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4814233d2500723e5594f3e7c70896ffeeef32b9c950ywan    rhs.m_string = m_string;
4815233d2500723e5594f3e7c70896ffeeef32b9c950ywan    rhs.m_language = m_language;
4816233d2500723e5594f3e7c70896ffeeef32b9c950ywan    rhs.m_country = m_country;
4817233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4818233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4819233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4820233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Chapters::Display::Clear()
4821233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4822233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] m_string;
4823233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_string = NULL;
4824233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4825233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] m_language;
4826233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_language = NULL;
4827233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4828233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] m_country;
4829233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_country = NULL;
4830233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4831233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4832233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4833233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Chapters::Display::Parse(
4834233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* pReader,
4835233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos,
4836233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size)
4837233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4838233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long stop = pos + size;
4839233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4840233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (pos < stop)
4841233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
4842233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long id, size;
4843233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4844233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long status = ParseElementHeader(
4845233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        pReader,
4846233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        pos,
4847233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        stop,
4848233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        id,
4849233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        size);
4850233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4851233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)  // error
4852233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
4853233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4854233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == 0)  // weird
4855233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
4856233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4857233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x05)  // ChapterString ID
4858233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
4859233d2500723e5594f3e7c70896ffeeef32b9c950ywan            status = UnserializeString(pReader, pos, size, m_string);
4860233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4861233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status)
4862233d2500723e5594f3e7c70896ffeeef32b9c950ywan              return status;
4863233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
4864233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x037C)  // ChapterLanguage ID
4865233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
4866233d2500723e5594f3e7c70896ffeeef32b9c950ywan            status = UnserializeString(pReader, pos, size, m_language);
4867233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4868233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status)
4869233d2500723e5594f3e7c70896ffeeef32b9c950ywan              return status;
4870233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
4871233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x037E)  // ChapterCountry ID
4872233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
4873233d2500723e5594f3e7c70896ffeeef32b9c950ywan            status = UnserializeString(pReader, pos, size, m_country);
4874233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4875233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status)
4876233d2500723e5594f3e7c70896ffeeef32b9c950ywan              return status;
4877233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
4878233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4879233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;
4880233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos <= stop);
4881233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
4882233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4883233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos == stop);
4884233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
4885233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4886233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4887233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4888233d2500723e5594f3e7c70896ffeeef32b9c950ywanSegmentInfo::SegmentInfo(
4889233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Segment* pSegment,
4890233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long start,
4891233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size_,
4892233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_start,
4893233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_size) :
4894233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pSegment(pSegment),
4895233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_start(start),
4896233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_size(size_),
4897233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_element_start(element_start),
4898233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_element_size(element_size),
4899233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pMuxingAppAsUTF8(NULL),
4900233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pWritingAppAsUTF8(NULL),
4901233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pTitleAsUTF8(NULL)
4902233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4903233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4904233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4905233d2500723e5594f3e7c70896ffeeef32b9c950ywanSegmentInfo::~SegmentInfo()
4906233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4907233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] m_pMuxingAppAsUTF8;
4908233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pMuxingAppAsUTF8 = NULL;
4909233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4910233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] m_pWritingAppAsUTF8;
4911233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pWritingAppAsUTF8 = NULL;
4912233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4913233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] m_pTitleAsUTF8;
4914233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pTitleAsUTF8 = NULL;
4915233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
4916233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4917233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4918233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong SegmentInfo::Parse()
4919233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
4920233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_pMuxingAppAsUTF8 == NULL);
4921233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_pWritingAppAsUTF8 == NULL);
4922233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_pTitleAsUTF8 == NULL);
4923233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4924233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* const pReader = m_pSegment->m_pReader;
4925233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4926233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos = m_start;
4927233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long stop = m_start + m_size;
4928233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4929233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_timecodeScale = 1000000;
4930233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_duration = -1;
4931233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4932233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (pos < stop)
4933233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
4934233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long id, size;
4935233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4936233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long status = ParseElementHeader(
4937233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                pReader,
4938233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                pos,
4939233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                stop,
4940233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                id,
4941233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                size);
4942233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4943233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)  //error
4944233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
4945233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4946233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x0AD7B1)  //Timecode Scale
4947233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
4948233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_timecodeScale = UnserializeUInt(pReader, pos, size);
4949233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4950233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_timecodeScale <= 0)
4951233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
4952233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
4953233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x0489)  //Segment duration
4954233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
4955233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long status = UnserializeFloat(
4956233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pReader,
4957233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pos,
4958233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    size,
4959233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    m_duration);
4960233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4961233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status < 0)
4962233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return status;
4963233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4964233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_duration < 0)
4965233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
4966233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
4967233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x0D80)  //MuxingApp
4968233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
4969233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long status = UnserializeString(
4970233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pReader,
4971233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pos,
4972233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    size,
4973233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    m_pMuxingAppAsUTF8);
4974233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4975233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status)
4976233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return status;
4977233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
4978233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x1741)  //WritingApp
4979233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
4980233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long status = UnserializeString(
4981233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pReader,
4982233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pos,
4983233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    size,
4984233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    m_pWritingAppAsUTF8);
4985233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4986233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status)
4987233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return status;
4988233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
4989233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x3BA9)  //Title
4990233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
4991233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long status = UnserializeString(
4992233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pReader,
4993233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pos,
4994233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    size,
4995233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    m_pTitleAsUTF8);
4996233d2500723e5594f3e7c70896ffeeef32b9c950ywan
4997233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status)
4998233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return status;
4999233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
5000233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5001233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;
5002233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos <= stop);
5003233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
5004233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5005233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos == stop);
5006233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5007233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
5008233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5009233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5010233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5011233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long SegmentInfo::GetTimeCodeScale() const
5012233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5013233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_timecodeScale;
5014233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5015233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5016233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5017233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long SegmentInfo::GetDuration() const
5018233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5019233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_duration < 0)
5020233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
5021233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5022233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_timecodeScale >= 1);
5023233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5024233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const double dd = double(m_duration) * double(m_timecodeScale);
5025233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long d = static_cast<long long>(dd);
5026233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5027233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return d;
5028233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5029233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5030233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst char* SegmentInfo::GetMuxingAppAsUTF8() const
5031233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5032233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_pMuxingAppAsUTF8;
5033233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5034233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5035233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5036233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst char* SegmentInfo::GetWritingAppAsUTF8() const
5037233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5038233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_pWritingAppAsUTF8;
5039233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5040233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5041233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst char* SegmentInfo::GetTitleAsUTF8() const
5042233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5043233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_pTitleAsUTF8;
5044233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5045233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5046233d2500723e5594f3e7c70896ffeeef32b9c950ywan///////////////////////////////////////////////////////////////
5047233d2500723e5594f3e7c70896ffeeef32b9c950ywan// ContentEncoding element
5048233d2500723e5594f3e7c70896ffeeef32b9c950ywanContentEncoding::ContentCompression::ContentCompression()
5049233d2500723e5594f3e7c70896ffeeef32b9c950ywan    : algo(0),
5050233d2500723e5594f3e7c70896ffeeef32b9c950ywan      settings(NULL),
5051233d2500723e5594f3e7c70896ffeeef32b9c950ywan      settings_len(0) {
5052233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5053233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5054233d2500723e5594f3e7c70896ffeeef32b9c950ywanContentEncoding::ContentCompression::~ContentCompression() {
5055233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] settings;
5056233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5057233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5058233d2500723e5594f3e7c70896ffeeef32b9c950ywanContentEncoding::ContentEncryption::ContentEncryption()
5059233d2500723e5594f3e7c70896ffeeef32b9c950ywan    : algo(0),
5060233d2500723e5594f3e7c70896ffeeef32b9c950ywan      key_id(NULL),
5061233d2500723e5594f3e7c70896ffeeef32b9c950ywan      key_id_len(0),
5062233d2500723e5594f3e7c70896ffeeef32b9c950ywan      signature(NULL),
5063233d2500723e5594f3e7c70896ffeeef32b9c950ywan      signature_len(0),
5064233d2500723e5594f3e7c70896ffeeef32b9c950ywan      sig_key_id(NULL),
5065233d2500723e5594f3e7c70896ffeeef32b9c950ywan      sig_key_id_len(0),
5066233d2500723e5594f3e7c70896ffeeef32b9c950ywan      sig_algo(0),
5067233d2500723e5594f3e7c70896ffeeef32b9c950ywan      sig_hash_algo(0) {
5068233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5069233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5070233d2500723e5594f3e7c70896ffeeef32b9c950ywanContentEncoding::ContentEncryption::~ContentEncryption() {
5071233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] key_id;
5072233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] signature;
5073233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] sig_key_id;
5074233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5075233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5076233d2500723e5594f3e7c70896ffeeef32b9c950ywanContentEncoding::ContentEncoding()
5077233d2500723e5594f3e7c70896ffeeef32b9c950ywan    : compression_entries_(NULL),
5078233d2500723e5594f3e7c70896ffeeef32b9c950ywan      compression_entries_end_(NULL),
5079233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encryption_entries_(NULL),
5080233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encryption_entries_end_(NULL),
5081233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encoding_order_(0),
5082233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encoding_scope_(1),
5083233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encoding_type_(0) {
5084233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5085233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5086233d2500723e5594f3e7c70896ffeeef32b9c950ywanContentEncoding::~ContentEncoding() {
5087233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ContentCompression** comp_i = compression_entries_;
5088233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ContentCompression** const comp_j = compression_entries_end_;
5089233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5090233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (comp_i != comp_j) {
5091233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ContentCompression* const comp = *comp_i++;
5092233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete comp;
5093233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
5094233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5095233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] compression_entries_;
5096233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5097233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ContentEncryption** enc_i = encryption_entries_;
5098233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ContentEncryption** const enc_j = encryption_entries_end_;
5099233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5100233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (enc_i != enc_j) {
5101233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ContentEncryption* const enc = *enc_i++;
5102233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete enc;
5103233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
5104233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5105233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] encryption_entries_;
5106233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5107233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5108233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5109233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst ContentEncoding::ContentCompression*
5110233d2500723e5594f3e7c70896ffeeef32b9c950ywanContentEncoding::GetCompressionByIndex(unsigned long idx) const {
5111233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const ptrdiff_t count = compression_entries_end_ - compression_entries_;
5112233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(count >= 0);
5113233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5114233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (idx >= static_cast<unsigned long>(count))
5115233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NULL;
5116233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5117233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return compression_entries_[idx];
5118233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5119233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5120233d2500723e5594f3e7c70896ffeeef32b9c950ywanunsigned long ContentEncoding::GetCompressionCount() const {
5121233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const ptrdiff_t count = compression_entries_end_ - compression_entries_;
5122233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(count >= 0);
5123233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5124233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return static_cast<unsigned long>(count);
5125233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5126233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5127233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst ContentEncoding::ContentEncryption*
5128233d2500723e5594f3e7c70896ffeeef32b9c950ywanContentEncoding::GetEncryptionByIndex(unsigned long idx) const {
5129233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const ptrdiff_t count = encryption_entries_end_ - encryption_entries_;
5130233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(count >= 0);
5131233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5132233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (idx >= static_cast<unsigned long>(count))
5133233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NULL;
5134233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5135233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return encryption_entries_[idx];
5136233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5137233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5138233d2500723e5594f3e7c70896ffeeef32b9c950ywanunsigned long ContentEncoding::GetEncryptionCount() const {
5139233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const ptrdiff_t count = encryption_entries_end_ - encryption_entries_;
5140233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(count >= 0);
5141233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5142233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return static_cast<unsigned long>(count);
5143233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5144233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5145233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong ContentEncoding::ParseContentEncAESSettingsEntry(
5146233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long start,
5147233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size,
5148233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* pReader,
5149233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ContentEncAESSettings* aes) {
5150233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(pReader);
5151233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(aes);
5152233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5153233d2500723e5594f3e7c70896ffeeef32b9c950ywan  long long pos = start;
5154233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const long long stop = start + size;
5155233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5156233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (pos < stop) {
5157233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long id, size;
5158233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long status = ParseElementHeader(pReader,
5159233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           pos,
5160233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           stop,
5161233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           id,
5162233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           size);
5163233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error
5164233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return status;
5165233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5166233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (id == 0x7E8) {
5167233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // AESSettingsCipherMode
5168233d2500723e5594f3e7c70896ffeeef32b9c950ywan      aes->cipher_mode = UnserializeUInt(pReader, pos, size);
5169233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (aes->cipher_mode != 1)
5170233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
5171233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
5172233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5173233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += size;  //consume payload
5174233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos <= stop);
5175233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
5176233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5177233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
5178233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5179233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5180233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong ContentEncoding::ParseContentEncodingEntry(long long start,
5181233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                long long size,
5182233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                IMkvReader* pReader) {
5183233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(pReader);
5184233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5185233d2500723e5594f3e7c70896ffeeef32b9c950ywan  long long pos = start;
5186233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const long long stop = start + size;
5187233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5188233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Count ContentCompression and ContentEncryption elements.
5189233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int compression_count = 0;
5190233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int encryption_count = 0;
5191233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5192233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (pos < stop) {
5193233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long id, size;
5194233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long status = ParseElementHeader(pReader,
5195233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           pos,
5196233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           stop,
5197233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           id,
5198233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           size);
5199233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error
5200233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return status;
5201233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5202233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (id == 0x1034)  // ContentCompression ID
5203233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ++compression_count;
5204233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5205233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (id == 0x1035)  // ContentEncryption ID
5206233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ++encryption_count;
5207233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5208233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += size;  //consume payload
5209233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos <= stop);
5210233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
5211233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5212233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (compression_count <= 0 && encryption_count <= 0)
5213233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
5214233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5215233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (compression_count > 0) {
5216233d2500723e5594f3e7c70896ffeeef32b9c950ywan    compression_entries_ =
5217233d2500723e5594f3e7c70896ffeeef32b9c950ywan        new (std::nothrow) ContentCompression*[compression_count];
5218233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!compression_entries_)
5219233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return -1;
5220233d2500723e5594f3e7c70896ffeeef32b9c950ywan    compression_entries_end_ = compression_entries_;
5221233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
5222233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5223233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (encryption_count > 0) {
5224233d2500723e5594f3e7c70896ffeeef32b9c950ywan    encryption_entries_ =
5225233d2500723e5594f3e7c70896ffeeef32b9c950ywan        new (std::nothrow) ContentEncryption*[encryption_count];
5226233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!encryption_entries_) {
5227233d2500723e5594f3e7c70896ffeeef32b9c950ywan      delete [] compression_entries_;
5228233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return -1;
5229233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
5230233d2500723e5594f3e7c70896ffeeef32b9c950ywan    encryption_entries_end_ = encryption_entries_;
5231233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
5232233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5233233d2500723e5594f3e7c70896ffeeef32b9c950ywan  pos = start;
5234233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (pos < stop) {
5235233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long id, size;
5236233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long status = ParseElementHeader(pReader,
5237233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     pos,
5238233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     stop,
5239233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     id,
5240233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     size);
5241233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error
5242233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return status;
5243233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5244233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (id == 0x1031) {
5245233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // ContentEncodingOrder
5246233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encoding_order_ = UnserializeUInt(pReader, pos, size);
5247233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (id == 0x1032) {
5248233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // ContentEncodingScope
5249233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encoding_scope_ = UnserializeUInt(pReader, pos, size);
5250233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (encoding_scope_ < 1)
5251233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
5252233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (id == 0x1033) {
5253233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // ContentEncodingType
5254233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encoding_type_ = UnserializeUInt(pReader, pos, size);
5255233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (id == 0x1034) {
5256233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // ContentCompression ID
5257233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ContentCompression* const compression =
5258233d2500723e5594f3e7c70896ffeeef32b9c950ywan        new (std::nothrow) ContentCompression();
5259233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!compression)
5260233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
5261233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5262233d2500723e5594f3e7c70896ffeeef32b9c950ywan      status = ParseCompressionEntry(pos, size, pReader, compression);
5263233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (status) {
5264233d2500723e5594f3e7c70896ffeeef32b9c950ywan        delete compression;
5265233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
5266233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
5267233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *compression_entries_end_++ = compression;
5268233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (id == 0x1035) {
5269233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // ContentEncryption ID
5270233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ContentEncryption* const encryption =
5271233d2500723e5594f3e7c70896ffeeef32b9c950ywan          new (std::nothrow) ContentEncryption();
5272233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!encryption)
5273233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
5274233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5275233d2500723e5594f3e7c70896ffeeef32b9c950ywan      status = ParseEncryptionEntry(pos, size, pReader, encryption);
5276233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (status) {
5277233d2500723e5594f3e7c70896ffeeef32b9c950ywan        delete encryption;
5278233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
5279233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
5280233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *encryption_entries_end_++ = encryption;
5281233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
5282233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5283233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += size;  //consume payload
5284233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos <= stop);
5285233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
5286233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5287233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(pos == stop);
5288233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
5289233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5290233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5291233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong ContentEncoding::ParseCompressionEntry(
5292233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long start,
5293233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size,
5294233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* pReader,
5295233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ContentCompression* compression) {
5296233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(pReader);
5297233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(compression);
5298233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5299233d2500723e5594f3e7c70896ffeeef32b9c950ywan  long long pos = start;
5300233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const long long stop = start + size;
5301233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5302233d2500723e5594f3e7c70896ffeeef32b9c950ywan  bool valid = false;
5303233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5304233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (pos < stop) {
5305233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long id, size;
5306233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long status = ParseElementHeader(pReader,
5307233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           pos,
5308233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           stop,
5309233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           id,
5310233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           size);
5311233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error
5312233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return status;
5313233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5314233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (id == 0x254) {
5315233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // ContentCompAlgo
5316233d2500723e5594f3e7c70896ffeeef32b9c950ywan      long long algo = UnserializeUInt(pReader, pos, size);
5317233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (algo < 0)
5318233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
5319233d2500723e5594f3e7c70896ffeeef32b9c950ywan      compression->algo = algo;
5320233d2500723e5594f3e7c70896ffeeef32b9c950ywan      valid = true;
5321233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (id == 0x255) {
5322233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // ContentCompSettings
5323233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (size <= 0)
5324233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
5325233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5326233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const size_t buflen = static_cast<size_t>(size);
5327233d2500723e5594f3e7c70896ffeeef32b9c950ywan      typedef unsigned char* buf_t;
5328233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const buf_t buf = new (std::nothrow) unsigned char[buflen];
5329233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (buf == NULL)
5330233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
5331233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5332233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int read_status = pReader->Read(pos, buflen, buf);
5333233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (read_status) {
5334233d2500723e5594f3e7c70896ffeeef32b9c950ywan        delete [] buf;
5335233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
5336233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
5337233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5338233d2500723e5594f3e7c70896ffeeef32b9c950ywan      compression->settings = buf;
5339233d2500723e5594f3e7c70896ffeeef32b9c950ywan      compression->settings_len = buflen;
5340233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
5341233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5342233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += size;  //consume payload
5343233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos <= stop);
5344233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
5345233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5346233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // ContentCompAlgo is mandatory
5347233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!valid)
5348233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return E_FILE_FORMAT_INVALID;
5349233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5350233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
5351233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5352233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5353233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong ContentEncoding::ParseEncryptionEntry(
5354233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long start,
5355233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size,
5356233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* pReader,
5357233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ContentEncryption* encryption) {
5358233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(pReader);
5359233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(encryption);
5360233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5361233d2500723e5594f3e7c70896ffeeef32b9c950ywan  long long pos = start;
5362233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const long long stop = start + size;
5363233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5364233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (pos < stop) {
5365233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long id, size;
5366233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long status = ParseElementHeader(pReader,
5367233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           pos,
5368233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           stop,
5369233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           id,
5370233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           size);
5371233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error
5372233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return status;
5373233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5374233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (id == 0x7E1) {
5375233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // ContentEncAlgo
5376233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encryption->algo = UnserializeUInt(pReader, pos, size);
5377233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (encryption->algo != 5)
5378233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
5379233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (id == 0x7E2) {
5380233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // ContentEncKeyID
5381233d2500723e5594f3e7c70896ffeeef32b9c950ywan      delete[] encryption->key_id;
5382233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encryption->key_id = NULL;
5383233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encryption->key_id_len = 0;
5384233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5385233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (size <= 0)
5386233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
5387233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5388233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const size_t buflen = static_cast<size_t>(size);
5389233d2500723e5594f3e7c70896ffeeef32b9c950ywan      typedef unsigned char* buf_t;
5390233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const buf_t buf = new (std::nothrow) unsigned char[buflen];
5391233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (buf == NULL)
5392233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
5393233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5394233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int read_status = pReader->Read(pos, buflen, buf);
5395233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (read_status) {
5396233d2500723e5594f3e7c70896ffeeef32b9c950ywan        delete [] buf;
5397233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
5398233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
5399233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5400233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encryption->key_id = buf;
5401233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encryption->key_id_len = buflen;
5402233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (id == 0x7E3) {
5403233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // ContentSignature
5404233d2500723e5594f3e7c70896ffeeef32b9c950ywan      delete[] encryption->signature;
5405233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encryption->signature = NULL;
5406233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encryption->signature_len = 0;
5407233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5408233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (size <= 0)
5409233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
5410233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5411233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const size_t buflen = static_cast<size_t>(size);
5412233d2500723e5594f3e7c70896ffeeef32b9c950ywan      typedef unsigned char* buf_t;
5413233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const buf_t buf = new (std::nothrow) unsigned char[buflen];
5414233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (buf == NULL)
5415233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
5416233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5417233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int read_status = pReader->Read(pos, buflen, buf);
5418233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (read_status) {
5419233d2500723e5594f3e7c70896ffeeef32b9c950ywan        delete [] buf;
5420233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
5421233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
5422233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5423233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encryption->signature = buf;
5424233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encryption->signature_len = buflen;
5425233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (id == 0x7E4) {
5426233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // ContentSigKeyID
5427233d2500723e5594f3e7c70896ffeeef32b9c950ywan      delete[] encryption->sig_key_id;
5428233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encryption->sig_key_id = NULL;
5429233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encryption->sig_key_id_len = 0;
5430233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5431233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (size <= 0)
5432233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
5433233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5434233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const size_t buflen = static_cast<size_t>(size);
5435233d2500723e5594f3e7c70896ffeeef32b9c950ywan      typedef unsigned char* buf_t;
5436233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const buf_t buf = new (std::nothrow) unsigned char[buflen];
5437233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (buf == NULL)
5438233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
5439233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5440233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int read_status = pReader->Read(pos, buflen, buf);
5441233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (read_status) {
5442233d2500723e5594f3e7c70896ffeeef32b9c950ywan        delete [] buf;
5443233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
5444233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
5445233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5446233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encryption->sig_key_id = buf;
5447233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encryption->sig_key_id_len = buflen;
5448233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (id == 0x7E5) {
5449233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // ContentSigAlgo
5450233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encryption->sig_algo = UnserializeUInt(pReader, pos, size);
5451233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (id == 0x7E6) {
5452233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // ContentSigHashAlgo
5453233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encryption->sig_hash_algo = UnserializeUInt(pReader, pos, size);
5454233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (id == 0x7E7) {
5455233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // ContentEncAESSettings
5456233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const long status = ParseContentEncAESSettingsEntry(
5457233d2500723e5594f3e7c70896ffeeef32b9c950ywan          pos,
5458233d2500723e5594f3e7c70896ffeeef32b9c950ywan          size,
5459233d2500723e5594f3e7c70896ffeeef32b9c950ywan          pReader,
5460233d2500723e5594f3e7c70896ffeeef32b9c950ywan          &encryption->aes_settings);
5461233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (status)
5462233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
5463233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
5464233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5465233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += size;  //consume payload
5466233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos <= stop);
5467233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
5468233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5469233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
5470233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5471233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5472233d2500723e5594f3e7c70896ffeeef32b9c950ywanTrack::Track(
5473233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Segment* pSegment,
5474233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_start,
5475233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_size) :
5476233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pSegment(pSegment),
5477233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_element_start(element_start),
5478233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_element_size(element_size),
5479233d2500723e5594f3e7c70896ffeeef32b9c950ywan    content_encoding_entries_(NULL),
5480233d2500723e5594f3e7c70896ffeeef32b9c950ywan    content_encoding_entries_end_(NULL)
5481233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5482233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5483233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5484233d2500723e5594f3e7c70896ffeeef32b9c950ywanTrack::~Track()
5485233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5486233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Info& info = const_cast<Info&>(m_info);
5487233d2500723e5594f3e7c70896ffeeef32b9c950ywan    info.Clear();
5488233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5489233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ContentEncoding** i = content_encoding_entries_;
5490233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ContentEncoding** const j = content_encoding_entries_end_;
5491233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5492233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (i != j) {
5493233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ContentEncoding* const encoding = *i++;
5494233d2500723e5594f3e7c70896ffeeef32b9c950ywan        delete encoding;
5495233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
5496233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5497233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete [] content_encoding_entries_;
5498233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5499233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5500233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Track::Create(
5501233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Segment* pSegment,
5502233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Info& info,
5503233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_start,
5504233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_size,
5505233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Track*& pResult)
5506233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5507233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pResult)
5508233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
5509233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5510233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Track* const pTrack = new (std::nothrow) Track(pSegment,
5511233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                   element_start,
5512233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                   element_size);
5513233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5514233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pTrack == NULL)
5515233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;  //generic error
5516233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5517233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int status = info.Copy(pTrack->m_info);
5518233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5519233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status)  // error
5520233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
5521233d2500723e5594f3e7c70896ffeeef32b9c950ywan        delete pTrack;
5522233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
5523233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
5524233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5525233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pResult = pTrack;
5526233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;  //success
5527233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5528233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5529233d2500723e5594f3e7c70896ffeeef32b9c950ywanTrack::Info::Info():
5530233d2500723e5594f3e7c70896ffeeef32b9c950ywan    uid(0),
5531233d2500723e5594f3e7c70896ffeeef32b9c950ywan    defaultDuration(0),
5532233d2500723e5594f3e7c70896ffeeef32b9c950ywan    codecDelay(0),
5533233d2500723e5594f3e7c70896ffeeef32b9c950ywan    seekPreRoll(0),
5534233d2500723e5594f3e7c70896ffeeef32b9c950ywan    nameAsUTF8(NULL),
5535233d2500723e5594f3e7c70896ffeeef32b9c950ywan    language(NULL),
5536233d2500723e5594f3e7c70896ffeeef32b9c950ywan    codecId(NULL),
5537233d2500723e5594f3e7c70896ffeeef32b9c950ywan    codecNameAsUTF8(NULL),
5538233d2500723e5594f3e7c70896ffeeef32b9c950ywan    codecPrivate(NULL),
5539233d2500723e5594f3e7c70896ffeeef32b9c950ywan    codecPrivateSize(0),
5540233d2500723e5594f3e7c70896ffeeef32b9c950ywan    lacing(false)
5541233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5542233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5543233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5544233d2500723e5594f3e7c70896ffeeef32b9c950ywanTrack::Info::~Info()
5545233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5546233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Clear();
5547233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5548233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5549233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Track::Info::Clear()
5550233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5551233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] nameAsUTF8;
5552233d2500723e5594f3e7c70896ffeeef32b9c950ywan    nameAsUTF8 = NULL;
5553233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5554233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] language;
5555233d2500723e5594f3e7c70896ffeeef32b9c950ywan    language = NULL;
5556233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5557233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] codecId;
5558233d2500723e5594f3e7c70896ffeeef32b9c950ywan    codecId = NULL;
5559233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5560233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] codecPrivate;
5561233d2500723e5594f3e7c70896ffeeef32b9c950ywan    codecPrivate = NULL;
5562233d2500723e5594f3e7c70896ffeeef32b9c950ywan    codecPrivateSize = 0;
5563233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5564233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] codecNameAsUTF8;
5565233d2500723e5594f3e7c70896ffeeef32b9c950ywan    codecNameAsUTF8 = NULL;
5566233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5567233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5568233d2500723e5594f3e7c70896ffeeef32b9c950ywanint Track::Info::CopyStr(char* Info::*str, Info& dst_) const
5569233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5570233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (str == static_cast<char* Info::*>(NULL))
5571233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
5572233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5573233d2500723e5594f3e7c70896ffeeef32b9c950ywan    char*& dst = dst_.*str;
5574233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5575233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (dst)  //should be NULL already
5576233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
5577233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5578233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const char* const src = this->*str;
5579233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5580233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (src == NULL)
5581233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;
5582233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5583233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const size_t len = strlen(src);
5584233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5585233d2500723e5594f3e7c70896ffeeef32b9c950ywan    dst = new (std::nothrow) char[len+1];
5586233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5587233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (dst == NULL)
5588233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
5589233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5590233d2500723e5594f3e7c70896ffeeef32b9c950ywan    strcpy(dst, src);
5591233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5592233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
5593233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5594233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5595233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5596233d2500723e5594f3e7c70896ffeeef32b9c950ywanint Track::Info::Copy(Info& dst) const
5597233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5598233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (&dst == this)
5599233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;
5600233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5601233d2500723e5594f3e7c70896ffeeef32b9c950ywan    dst.type = type;
5602233d2500723e5594f3e7c70896ffeeef32b9c950ywan    dst.number = number;
5603233d2500723e5594f3e7c70896ffeeef32b9c950ywan    dst.defaultDuration = defaultDuration;
5604233d2500723e5594f3e7c70896ffeeef32b9c950ywan    dst.codecDelay = codecDelay;
5605233d2500723e5594f3e7c70896ffeeef32b9c950ywan    dst.seekPreRoll = seekPreRoll;
5606233d2500723e5594f3e7c70896ffeeef32b9c950ywan    dst.uid = uid;
5607233d2500723e5594f3e7c70896ffeeef32b9c950ywan    dst.lacing = lacing;
5608233d2500723e5594f3e7c70896ffeeef32b9c950ywan    dst.settings = settings;
5609233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5610233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //We now copy the string member variables from src to dst.
5611233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //This involves memory allocation so in principle the operation
5612233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //can fail (indeed, that's why we have Info::Copy), so we must
5613233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //report this to the caller.  An error return from this function
5614233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //therefore implies that the copy was only partially successful.
5615233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5616233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (int status = CopyStr(&Info::nameAsUTF8, dst))
5617233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
5618233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5619233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (int status = CopyStr(&Info::language, dst))
5620233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
5621233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5622233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (int status = CopyStr(&Info::codecId, dst))
5623233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
5624233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5625233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (int status = CopyStr(&Info::codecNameAsUTF8, dst))
5626233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
5627233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5628233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (codecPrivateSize > 0)
5629233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
5630233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (codecPrivate == NULL)
5631233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return -1;
5632233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5633233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (dst.codecPrivate)
5634233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return -1;
5635233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5636233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (dst.codecPrivateSize != 0)
5637233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return -1;
5638233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5639233d2500723e5594f3e7c70896ffeeef32b9c950ywan        dst.codecPrivate = new (std::nothrow) unsigned char[codecPrivateSize];
5640233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5641233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (dst.codecPrivate == NULL)
5642233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return -1;
5643233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5644233d2500723e5594f3e7c70896ffeeef32b9c950ywan        memcpy(dst.codecPrivate, codecPrivate, codecPrivateSize);
5645233d2500723e5594f3e7c70896ffeeef32b9c950ywan        dst.codecPrivateSize = codecPrivateSize;
5646233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
5647233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5648233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
5649233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5650233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5651233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst BlockEntry* Track::GetEOS() const
5652233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5653233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return &m_eos;
5654233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5655233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5656233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Track::GetType() const
5657233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5658233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_info.type;
5659233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5660233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5661233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Track::GetNumber() const
5662233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5663233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_info.number;
5664233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5665233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5666233d2500723e5594f3e7c70896ffeeef32b9c950ywanunsigned long long Track::GetUid() const
5667233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5668233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_info.uid;
5669233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5670233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5671233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst char* Track::GetNameAsUTF8() const
5672233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5673233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_info.nameAsUTF8;
5674233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5675233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5676233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst char* Track::GetLanguage() const
5677233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5678233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_info.language;
5679233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5680233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5681233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst char* Track::GetCodecNameAsUTF8() const
5682233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5683233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_info.codecNameAsUTF8;
5684233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5685233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5686233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5687233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst char* Track::GetCodecId() const
5688233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5689233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_info.codecId;
5690233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5691233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5692233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst unsigned char* Track::GetCodecPrivate(size_t& size) const
5693233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5694233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size = m_info.codecPrivateSize;
5695233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_info.codecPrivate;
5696233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5697233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5698233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5699233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Track::GetLacing() const
5700233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5701233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_info.lacing;
5702233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5703233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5704233d2500723e5594f3e7c70896ffeeef32b9c950ywanunsigned long long Track::GetDefaultDuration() const
5705233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5706233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_info.defaultDuration;
5707233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5708233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5709233d2500723e5594f3e7c70896ffeeef32b9c950ywanunsigned long long Track::GetCodecDelay() const
5710233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5711233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_info.codecDelay;
5712233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5713233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5714233d2500723e5594f3e7c70896ffeeef32b9c950ywanunsigned long long Track::GetSeekPreRoll() const
5715233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5716233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_info.seekPreRoll;
5717233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5718233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5719233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Track::GetFirst(const BlockEntry*& pBlockEntry) const
5720233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5721233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Cluster* pCluster = m_pSegment->GetFirst();
5722233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5723233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (int i = 0; ; )
5724233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
5725233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pCluster == NULL)
5726233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
5727233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pBlockEntry = GetEOS();
5728233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 1;
5729233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
5730233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5731233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pCluster->EOS())
5732233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
5733233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
5734233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_pSegment->Unparsed() <= 0)  //all clusters have been loaded
5735233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
5736233d2500723e5594f3e7c70896ffeeef32b9c950ywan                pBlockEntry = GetEOS();
5737233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return 1;
5738233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
5739233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
5740233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_pSegment->DoneParsing())
5741233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
5742233d2500723e5594f3e7c70896ffeeef32b9c950ywan                pBlockEntry = GetEOS();
5743233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return 1;
5744233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
5745233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
5746233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5747233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pBlockEntry = 0;
5748233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
5749233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
5750233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5751233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long status = pCluster->GetFirst(pBlockEntry);
5752233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5753233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)  //error
5754233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
5755233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5756233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pBlockEntry == 0)  //empty cluster
5757233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
5758233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pCluster = m_pSegment->GetNext(pCluster);
5759233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
5760233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
5761233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5762233d2500723e5594f3e7c70896ffeeef32b9c950ywan        for (;;)
5763233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
5764233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const Block* const pBlock = pBlockEntry->GetBlock();
5765233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(pBlock);
5766233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5767233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long tn = pBlock->GetTrackNumber();
5768233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5769233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((tn == m_info.number) && VetEntry(pBlockEntry))
5770233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return 0;
5771233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5772233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const BlockEntry* pNextEntry;
5773233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5774233d2500723e5594f3e7c70896ffeeef32b9c950ywan            status = pCluster->GetNext(pBlockEntry, pNextEntry);
5775233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5776233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status < 0)  //error
5777233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return status;
5778233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5779233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (pNextEntry == 0)
5780233d2500723e5594f3e7c70896ffeeef32b9c950ywan                break;
5781233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5782233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pBlockEntry = pNextEntry;
5783233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
5784233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5785233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ++i;
5786233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5787233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (i >= 100)
5788233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
5789233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5790233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pCluster = m_pSegment->GetNext(pCluster);
5791233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
5792233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5793233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //NOTE: if we get here, it means that we didn't find a block with
5794233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //a matching track number.  We interpret that as an error (which
5795233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //might be too conservative).
5796233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5797233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pBlockEntry = GetEOS();  //so we can return a non-NULL value
5798233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 1;
5799233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5800233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5801233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5802233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Track::GetNext(
5803233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const BlockEntry* pCurrEntry,
5804233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const BlockEntry*& pNextEntry) const
5805233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5806233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCurrEntry);
5807233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(!pCurrEntry->EOS());  //?
5808233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5809233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Block* const pCurrBlock = pCurrEntry->GetBlock();
5810233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCurrBlock && pCurrBlock->GetTrackNumber() == m_info.number);
5811233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!pCurrBlock || pCurrBlock->GetTrackNumber() != m_info.number)
5812233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
5813233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5814233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Cluster* pCluster = pCurrEntry->GetCluster();
5815233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster);
5816233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(!pCluster->EOS());
5817233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5818233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long status = pCluster->GetNext(pCurrEntry, pNextEntry);
5819233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5820233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error
5821233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
5822233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5823233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (int i = 0; ; )
5824233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
5825233d2500723e5594f3e7c70896ffeeef32b9c950ywan        while (pNextEntry)
5826233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
5827233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const Block* const pNextBlock = pNextEntry->GetBlock();
5828233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(pNextBlock);
5829233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5830233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (pNextBlock->GetTrackNumber() == m_info.number)
5831233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return 0;
5832233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5833233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pCurrEntry = pNextEntry;
5834233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5835233d2500723e5594f3e7c70896ffeeef32b9c950ywan            status = pCluster->GetNext(pCurrEntry, pNextEntry);
5836233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5837233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status < 0) //error
5838233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return status;
5839233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
5840233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5841233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pCluster = m_pSegment->GetNext(pCluster);
5842233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5843233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pCluster == NULL)
5844233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
5845233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pNextEntry = GetEOS();
5846233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 1;
5847233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
5848233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5849233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pCluster->EOS())
5850233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
5851233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
5852233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_pSegment->Unparsed() <= 0)   //all clusters have been loaded
5853233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
5854233d2500723e5594f3e7c70896ffeeef32b9c950ywan                pNextEntry = GetEOS();
5855233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return 1;
5856233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
5857233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
5858233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_pSegment->DoneParsing())
5859233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
5860233d2500723e5594f3e7c70896ffeeef32b9c950ywan                pNextEntry = GetEOS();
5861233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return 1;
5862233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
5863233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
5864233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5865233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //TODO: there is a potential O(n^2) problem here: we tell the
5866233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //caller to (pre)load another cluster, which he does, but then he
5867233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //calls GetNext again, which repeats the same search.  This is
5868233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //a pathological case, since the only way it can happen is if
5869233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //there exists a long sequence of clusters none of which contain a
5870233d2500723e5594f3e7c70896ffeeef32b9c950ywan            // block from this track.  One way around this problem is for the
5871233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //caller to be smarter when he loads another cluster: don't call
5872233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //us back until you have a cluster that contains a block from this
5873233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //track. (Of course, that's not cheap either, since our caller
5874233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //would have to scan the each cluster as it's loaded, so that
5875233d2500723e5594f3e7c70896ffeeef32b9c950ywan            //would just push back the problem.)
5876233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5877233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pNextEntry = NULL;
5878233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
5879233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
5880233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5881233d2500723e5594f3e7c70896ffeeef32b9c950ywan        status = pCluster->GetFirst(pNextEntry);
5882233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5883233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)  //error
5884233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
5885233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5886233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pNextEntry == NULL)  //empty cluster
5887233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
5888233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5889233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ++i;
5890233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5891233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (i >= 100)
5892233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
5893233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
5894233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5895233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //NOTE: if we get here, it means that we didn't find a block with
5896233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //a matching track number after lots of searching, so we give
5897233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //up trying.
5898233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5899233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pNextEntry = GetEOS();  //so we can return a non-NULL value
5900233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 1;
5901233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5902233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5903233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Track::VetEntry(const BlockEntry* pBlockEntry) const
5904233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5905233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pBlockEntry);
5906233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Block* const pBlock = pBlockEntry->GetBlock();
5907233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pBlock);
5908233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pBlock->GetTrackNumber() == m_info.number);
5909233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!pBlock || pBlock->GetTrackNumber() != m_info.number)
5910233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
5911233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5912233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // This function is used during a seek to determine whether the
5913233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // frame is a valid seek target.  This default function simply
5914233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // returns true, which means all frames are valid seek targets.
5915233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // It gets overridden by the VideoTrack class, because only video
5916233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // keyframes can be used as seek target.
5917233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5918233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return true;
5919233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
5920233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5921233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Track::Seek(
5922233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long time_ns,
5923233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const BlockEntry*& pResult) const
5924233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
5925233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long status = GetFirst(pResult);
5926233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5927233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //buffer underflow, etc
5928233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
5929233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5930233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pResult);
5931233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5932233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pResult->EOS())
5933233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;
5934233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5935233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Cluster* pCluster = pResult->GetCluster();
5936233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster);
5937233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster->GetIndex() >= 0);
5938233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5939233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (time_ns <= pResult->GetBlock()->GetTime(pCluster))
5940233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;
5941233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5942233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** const clusters = m_pSegment->m_clusters;
5943233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(clusters);
5944233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5945233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long count = m_pSegment->GetCount();  //loaded only, not preloaded
5946233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(count > 0);
5947233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5948233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** const i = clusters + pCluster->GetIndex();
5949233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(i);
5950233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(*i == pCluster);
5951233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster->GetTime() <= time_ns);
5952233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5953233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** const j = clusters + count;
5954233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5955233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** lo = i;
5956233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** hi = j;
5957233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5958233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (lo < hi)
5959233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
5960233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //INVARIANT:
5961233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[i, lo) <= time_ns
5962233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[lo, hi) ?
5963233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[hi, j)  > time_ns
5964233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5965233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster** const mid = lo + (hi - lo) / 2;
5966233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(mid < hi);
5967233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5968233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pCluster = *mid;
5969233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster);
5970233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster->GetIndex() >= 0);
5971233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster->GetIndex() == long(mid - m_pSegment->m_clusters));
5972233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5973233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long t = pCluster->GetTime();
5974233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5975233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (t <= time_ns)
5976233d2500723e5594f3e7c70896ffeeef32b9c950ywan            lo = mid + 1;
5977233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else
5978233d2500723e5594f3e7c70896ffeeef32b9c950ywan            hi = mid;
5979233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5980233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(lo <= hi);
5981233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
5982233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5983233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(lo == hi);
5984233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(lo > i);
5985233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(lo <= j);
5986233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5987233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (lo > i)
5988233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
5989233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pCluster = *--lo;
5990233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster);
5991233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster->GetTime() <= time_ns);
5992233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5993233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pResult = pCluster->GetEntry(this);
5994233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5995233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pResult != 0) && !pResult->EOS())
5996233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 0;
5997233d2500723e5594f3e7c70896ffeeef32b9c950ywan
5998233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //landed on empty cluster (no entries)
5999233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
6000233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6001233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pResult = GetEOS();  //weird
6002233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
6003233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6004233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6005233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst ContentEncoding*
6006233d2500723e5594f3e7c70896ffeeef32b9c950ywanTrack::GetContentEncodingByIndex(unsigned long idx) const {
6007233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const ptrdiff_t count =
6008233d2500723e5594f3e7c70896ffeeef32b9c950ywan      content_encoding_entries_end_ - content_encoding_entries_;
6009233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(count >= 0);
6010233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6011233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (idx >= static_cast<unsigned long>(count))
6012233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NULL;
6013233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6014233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return content_encoding_entries_[idx];
6015233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6016233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6017233d2500723e5594f3e7c70896ffeeef32b9c950ywanunsigned long Track::GetContentEncodingCount() const {
6018233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const ptrdiff_t count =
6019233d2500723e5594f3e7c70896ffeeef32b9c950ywan      content_encoding_entries_end_ - content_encoding_entries_;
6020233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(count >= 0);
6021233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6022233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return static_cast<unsigned long>(count);
6023233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6024233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6025233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Track::ParseContentEncodingsEntry(long long start, long long size) {
6026233d2500723e5594f3e7c70896ffeeef32b9c950ywan  IMkvReader* const pReader = m_pSegment->m_pReader;
6027233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(pReader);
6028233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6029233d2500723e5594f3e7c70896ffeeef32b9c950ywan  long long pos = start;
6030233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const long long stop = start + size;
6031233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6032233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Count ContentEncoding elements.
6033233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int count = 0;
6034233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (pos < stop) {
6035233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long id, size;
6036233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long status = ParseElementHeader(pReader,
6037233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           pos,
6038233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           stop,
6039233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           id,
6040233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           size);
6041233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error
6042233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return status;
6043233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6044233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6045233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //pos now designates start of element
6046233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (id == 0x2240)  // ContentEncoding ID
6047233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ++count;
6048233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6049233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += size;  //consume payload
6050233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos <= stop);
6051233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
6052233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6053233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (count <= 0)
6054233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
6055233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6056233d2500723e5594f3e7c70896ffeeef32b9c950ywan  content_encoding_entries_ = new (std::nothrow) ContentEncoding*[count];
6057233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!content_encoding_entries_)
6058233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
6059233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6060233d2500723e5594f3e7c70896ffeeef32b9c950ywan  content_encoding_entries_end_ = content_encoding_entries_;
6061233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6062233d2500723e5594f3e7c70896ffeeef32b9c950ywan  pos = start;
6063233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (pos < stop) {
6064233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long id, size;
6065233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long status = ParseElementHeader(pReader,
6066233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     pos,
6067233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     stop,
6068233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     id,
6069233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     size);
6070233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error
6071233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return status;
6072233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6073233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //pos now designates start of element
6074233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (id == 0x2240) { // ContentEncoding ID
6075233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ContentEncoding* const content_encoding =
6076233d2500723e5594f3e7c70896ffeeef32b9c950ywan          new (std::nothrow) ContentEncoding();
6077233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!content_encoding)
6078233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
6079233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6080233d2500723e5594f3e7c70896ffeeef32b9c950ywan      status = content_encoding->ParseContentEncodingEntry(pos,
6081233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                           size,
6082233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                           pReader);
6083233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (status) {
6084233d2500723e5594f3e7c70896ffeeef32b9c950ywan        delete content_encoding;
6085233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
6086233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
6087233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6088233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *content_encoding_entries_end_++ = content_encoding;
6089233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
6090233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6091233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += size;  //consume payload
6092233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos <= stop);
6093233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
6094233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6095233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(pos == stop);
6096233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6097233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
6098233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6099233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6100233d2500723e5594f3e7c70896ffeeef32b9c950ywanTrack::EOSBlock::EOSBlock() :
6101233d2500723e5594f3e7c70896ffeeef32b9c950ywan    BlockEntry(NULL, LONG_MIN)
6102233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6103233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6104233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6105233d2500723e5594f3e7c70896ffeeef32b9c950ywanBlockEntry::Kind Track::EOSBlock::GetKind() const
6106233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6107233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return kBlockEOS;
6108233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6109233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6110233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6111233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst Block* Track::EOSBlock::GetBlock() const
6112233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6113233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NULL;
6114233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6115233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6116233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6117233d2500723e5594f3e7c70896ffeeef32b9c950ywanVideoTrack::VideoTrack(
6118233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Segment* pSegment,
6119233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_start,
6120233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_size) :
6121233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Track(pSegment, element_start, element_size)
6122233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6123233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6124233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6125233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6126233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong VideoTrack::Parse(
6127233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Segment* pSegment,
6128233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Info& info,
6129233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_start,
6130233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_size,
6131233d2500723e5594f3e7c70896ffeeef32b9c950ywan    VideoTrack*& pResult)
6132233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6133233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pResult)
6134233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
6135233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6136233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (info.type != Track::kVideo)
6137233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
6138233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6139233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long width = 0;
6140233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long height = 0;
6141233d2500723e5594f3e7c70896ffeeef32b9c950ywan    double rate = 0.0;
6142233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6143233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* const pReader = pSegment->m_pReader;
6144233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6145233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Settings& s = info.settings;
6146233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(s.start >= 0);
6147233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(s.size >= 0);
6148233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6149233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos = s.start;
6150233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos >= 0);
6151233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6152233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long stop = pos + s.size;
6153233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6154233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (pos < stop)
6155233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
6156233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long id, size;
6157233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6158233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long status = ParseElementHeader(
6159233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                pReader,
6160233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                pos,
6161233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                stop,
6162233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                id,
6163233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                size);
6164233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6165233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)  //error
6166233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
6167233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6168233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x30)  //pixel width
6169233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
6170233d2500723e5594f3e7c70896ffeeef32b9c950ywan            width = UnserializeUInt(pReader, pos, size);
6171233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6172233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (width <= 0)
6173233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
6174233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
6175233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x3A)  //pixel height
6176233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
6177233d2500723e5594f3e7c70896ffeeef32b9c950ywan            height = UnserializeUInt(pReader, pos, size);
6178233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6179233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (height <= 0)
6180233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
6181233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
6182233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x0383E3)  //frame rate
6183233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
6184233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long status = UnserializeFloat(
6185233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pReader,
6186233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pos,
6187233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    size,
6188233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    rate);
6189233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6190233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status < 0)
6191233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return status;
6192233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6193233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (rate <= 0)
6194233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
6195233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
6196233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6197233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;  //consume payload
6198233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos <= stop);
6199233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
6200233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6201233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos == stop);
6202233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6203233d2500723e5594f3e7c70896ffeeef32b9c950ywan    VideoTrack* const pTrack = new (std::nothrow) VideoTrack(pSegment,
6204233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                             element_start,
6205233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                             element_size);
6206233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6207233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pTrack == NULL)
6208233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;  //generic error
6209233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6210233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int status = info.Copy(pTrack->m_info);
6211233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6212233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status)  // error
6213233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
6214233d2500723e5594f3e7c70896ffeeef32b9c950ywan        delete pTrack;
6215233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
6216233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
6217233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6218233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pTrack->m_width = width;
6219233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pTrack->m_height = height;
6220233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pTrack->m_rate = rate;
6221233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6222233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pResult = pTrack;
6223233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;  //success
6224233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6225233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6226233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6227233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool VideoTrack::VetEntry(const BlockEntry* pBlockEntry) const
6228233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6229233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return Track::VetEntry(pBlockEntry) && pBlockEntry->GetBlock()->IsKey();
6230233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6231233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6232233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong VideoTrack::Seek(
6233233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long time_ns,
6234233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const BlockEntry*& pResult) const
6235233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6236233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long status = GetFirst(pResult);
6237233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6238233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //buffer underflow, etc
6239233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
6240233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6241233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pResult);
6242233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6243233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pResult->EOS())
6244233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;
6245233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6246233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Cluster* pCluster = pResult->GetCluster();
6247233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster);
6248233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster->GetIndex() >= 0);
6249233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6250233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (time_ns <= pResult->GetBlock()->GetTime(pCluster))
6251233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;
6252233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6253233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** const clusters = m_pSegment->m_clusters;
6254233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(clusters);
6255233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6256233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long count = m_pSegment->GetCount();  //loaded only, not pre-loaded
6257233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(count > 0);
6258233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6259233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** const i = clusters + pCluster->GetIndex();
6260233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(i);
6261233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(*i == pCluster);
6262233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster->GetTime() <= time_ns);
6263233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6264233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** const j = clusters + count;
6265233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6266233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** lo = i;
6267233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** hi = j;
6268233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6269233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (lo < hi)
6270233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
6271233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //INVARIANT:
6272233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[i, lo) <= time_ns
6273233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[lo, hi) ?
6274233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //[hi, j)  > time_ns
6275233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6276233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster** const mid = lo + (hi - lo) / 2;
6277233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(mid < hi);
6278233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6279233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pCluster = *mid;
6280233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster);
6281233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster->GetIndex() >= 0);
6282233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster->GetIndex() == long(mid - m_pSegment->m_clusters));
6283233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6284233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long t = pCluster->GetTime();
6285233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6286233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (t <= time_ns)
6287233d2500723e5594f3e7c70896ffeeef32b9c950ywan            lo = mid + 1;
6288233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else
6289233d2500723e5594f3e7c70896ffeeef32b9c950ywan            hi = mid;
6290233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6291233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(lo <= hi);
6292233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
6293233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6294233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(lo == hi);
6295233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(lo > i);
6296233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(lo <= j);
6297233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6298233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pCluster = *--lo;
6299233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster);
6300233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster->GetTime() <= time_ns);
6301233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6302233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pResult = pCluster->GetEntry(this, time_ns);
6303233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6304233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((pResult != 0) && !pResult->EOS())  //found a keyframe
6305233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;
6306233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6307233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (lo != i)
6308233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
6309233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pCluster = *--lo;
6310233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster);
6311233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pCluster->GetTime() <= time_ns);
6312233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6313233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
6314233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //TODO:
6315233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //We need to handle the case when a cluster
6316233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //contains multiple keyframes.  Simply returning
6317233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //the largest keyframe on the cluster isn't
6318233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //good enough.
6319233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pResult = pCluster->GetMaxKey(this);
6320233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
6321233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pResult = pCluster->GetEntry(this, time_ns);
6322233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
6323233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6324233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pResult != 0) && !pResult->EOS())
6325233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 0;
6326233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
6327233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6328233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //weird: we're on the first cluster, but no keyframe found
6329233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //should never happen but we must return something anyway
6330233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6331233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pResult = GetEOS();
6332233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
6333233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6334233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6335233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6336233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long VideoTrack::GetWidth() const
6337233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6338233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_width;
6339233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6340233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6341233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6342233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long VideoTrack::GetHeight() const
6343233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6344233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_height;
6345233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6346233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6347233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6348233d2500723e5594f3e7c70896ffeeef32b9c950ywandouble VideoTrack::GetFrameRate() const
6349233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6350233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_rate;
6351233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6352233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6353233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6354233d2500723e5594f3e7c70896ffeeef32b9c950ywanAudioTrack::AudioTrack(
6355233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Segment* pSegment,
6356233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_start,
6357233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_size) :
6358233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Track(pSegment, element_start, element_size)
6359233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6360233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6361233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6362233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6363233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong AudioTrack::Parse(
6364233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Segment* pSegment,
6365233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Info& info,
6366233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_start,
6367233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_size,
6368233d2500723e5594f3e7c70896ffeeef32b9c950ywan    AudioTrack*& pResult)
6369233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6370233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pResult)
6371233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
6372233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6373233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (info.type != Track::kAudio)
6374233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
6375233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6376233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* const pReader = pSegment->m_pReader;
6377233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6378233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Settings& s = info.settings;
6379233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(s.start >= 0);
6380233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(s.size >= 0);
6381233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6382233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos = s.start;
6383233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos >= 0);
6384233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6385233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long stop = pos + s.size;
6386233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6387233d2500723e5594f3e7c70896ffeeef32b9c950ywan    double rate = 8000.0;  // MKV default
6388233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long channels = 1;
6389233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long bit_depth = 0;
6390233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6391233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (pos < stop)
6392233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
6393233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long id, size;
6394233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6395233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long status = ParseElementHeader(
6396233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                pReader,
6397233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                pos,
6398233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                stop,
6399233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                id,
6400233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                size);
6401233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6402233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)  //error
6403233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
6404233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6405233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x35)  //Sample Rate
6406233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
6407233d2500723e5594f3e7c70896ffeeef32b9c950ywan            status = UnserializeFloat(pReader, pos, size, rate);
6408233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6409233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status < 0)
6410233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return status;
6411233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6412233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (rate <= 0)
6413233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
6414233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
6415233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x1F)  //Channel Count
6416233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
6417233d2500723e5594f3e7c70896ffeeef32b9c950ywan            channels = UnserializeUInt(pReader, pos, size);
6418233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6419233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (channels <= 0)
6420233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
6421233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
6422233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x2264)  //Bit Depth
6423233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
6424233d2500723e5594f3e7c70896ffeeef32b9c950ywan            bit_depth = UnserializeUInt(pReader, pos, size);
6425233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6426233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (bit_depth <= 0)
6427233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
6428233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
6429233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6430233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;  //consume payload
6431233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos <= stop);
6432233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
6433233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6434233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos == stop);
6435233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6436233d2500723e5594f3e7c70896ffeeef32b9c950ywan    AudioTrack* const pTrack = new (std::nothrow) AudioTrack(pSegment,
6437233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                             element_start,
6438233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                             element_size);
6439233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6440233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pTrack == NULL)
6441233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;  //generic error
6442233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6443233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int status = info.Copy(pTrack->m_info);
6444233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6445233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status)
6446233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
6447233d2500723e5594f3e7c70896ffeeef32b9c950ywan        delete pTrack;
6448233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
6449233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
6450233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6451233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pTrack->m_rate = rate;
6452233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pTrack->m_channels = channels;
6453233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pTrack->m_bitDepth = bit_depth;
6454233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6455233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pResult = pTrack;
6456233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;  //success
6457233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6458233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6459233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6460233d2500723e5594f3e7c70896ffeeef32b9c950ywandouble AudioTrack::GetSamplingRate() const
6461233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6462233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_rate;
6463233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6464233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6465233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6466233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long AudioTrack::GetChannels() const
6467233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6468233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_channels;
6469233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6470233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6471233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long AudioTrack::GetBitDepth() const
6472233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6473233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_bitDepth;
6474233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6475233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6476233d2500723e5594f3e7c70896ffeeef32b9c950ywanTracks::Tracks(
6477233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Segment* pSegment,
6478233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long start,
6479233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size_,
6480233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_start,
6481233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_size) :
6482233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pSegment(pSegment),
6483233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_start(start),
6484233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_size(size_),
6485233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_element_start(element_start),
6486233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_element_size(element_size),
6487233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_trackEntries(NULL),
6488233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_trackEntriesEnd(NULL)
6489233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6490233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6491233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6492233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6493233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Tracks::Parse()
6494233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6495233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_trackEntries == NULL);
6496233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_trackEntriesEnd == NULL);
6497233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6498233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long stop = m_start + m_size;
6499233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* const pReader = m_pSegment->m_pReader;
6500233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6501233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int count = 0;
6502233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos = m_start;
6503233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6504233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (pos < stop)
6505233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
6506233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long id, size;
6507233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6508233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long status = ParseElementHeader(
6509233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                pReader,
6510233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                pos,
6511233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                stop,
6512233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                id,
6513233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                size);
6514233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6515233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)  //error
6516233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
6517233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6518233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == 0)  //weird
6519233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
6520233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6521233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x2E)  //TrackEntry ID
6522233d2500723e5594f3e7c70896ffeeef32b9c950ywan            ++count;
6523233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6524233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;  //consume payload
6525233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos <= stop);
6526233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
6527233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6528233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos == stop);
6529233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6530233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (count <= 0)
6531233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;  //success
6532233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6533233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_trackEntries = new (std::nothrow) Track*[count];
6534233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6535233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_trackEntries == NULL)
6536233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
6537233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6538233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_trackEntriesEnd = m_trackEntries;
6539233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6540233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos = m_start;
6541233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6542233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (pos < stop)
6543233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
6544233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long element_start = pos;
6545233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6546233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long id, payload_size;
6547233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6548233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long status = ParseElementHeader(
6549233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                pReader,
6550233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                pos,
6551233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                stop,
6552233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                id,
6553233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                payload_size);
6554233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6555233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)  //error
6556233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
6557233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6558233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (payload_size == 0)  //weird
6559233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
6560233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6561233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long payload_stop = pos + payload_size;
6562233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(payload_stop <= stop);  //checked in ParseElement
6563233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6564233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long element_size = payload_stop - element_start;
6565233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6566233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x2E)  //TrackEntry ID
6567233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
6568233d2500723e5594f3e7c70896ffeeef32b9c950ywan            Track*& pTrack = *m_trackEntriesEnd;
6569233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pTrack = NULL;
6570233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6571233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long status = ParseTrackEntry(
6572233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pos,
6573233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    payload_size,
6574233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    element_start,
6575233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    element_size,
6576233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pTrack);
6577233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6578233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status)
6579233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return status;
6580233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6581233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (pTrack)
6582233d2500723e5594f3e7c70896ffeeef32b9c950ywan                ++m_trackEntriesEnd;
6583233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
6584233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6585233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos = payload_stop;
6586233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos <= stop);
6587233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
6588233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6589233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos == stop);
6590233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6591233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;  //success
6592233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6593233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6594233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6595233d2500723e5594f3e7c70896ffeeef32b9c950ywanunsigned long Tracks::GetTracksCount() const
6596233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6597233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const ptrdiff_t result = m_trackEntriesEnd - m_trackEntries;
6598233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(result >= 0);
6599233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6600233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return static_cast<unsigned long>(result);
6601233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6602233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6603233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Tracks::ParseTrackEntry(
6604233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long track_start,
6605233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long track_size,
6606233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_start,
6607233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_size,
6608233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Track*& pResult) const
6609233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6610233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pResult)
6611233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
6612233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6613233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* const pReader = m_pSegment->m_pReader;
6614233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6615233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos = track_start;
6616233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long track_stop = track_start + track_size;
6617233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6618233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Track::Info info;
6619233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6620233d2500723e5594f3e7c70896ffeeef32b9c950ywan    info.type = 0;
6621233d2500723e5594f3e7c70896ffeeef32b9c950ywan    info.number = 0;
6622233d2500723e5594f3e7c70896ffeeef32b9c950ywan    info.uid = 0;
6623233d2500723e5594f3e7c70896ffeeef32b9c950ywan    info.defaultDuration = 0;
6624233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6625233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Track::Settings v;
6626233d2500723e5594f3e7c70896ffeeef32b9c950ywan    v.start = -1;
6627233d2500723e5594f3e7c70896ffeeef32b9c950ywan    v.size = -1;
6628233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6629233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Track::Settings a;
6630233d2500723e5594f3e7c70896ffeeef32b9c950ywan    a.start = -1;
6631233d2500723e5594f3e7c70896ffeeef32b9c950ywan    a.size = -1;
6632233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6633233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Track::Settings e;  //content_encodings_settings;
6634233d2500723e5594f3e7c70896ffeeef32b9c950ywan    e.start = -1;
6635233d2500723e5594f3e7c70896ffeeef32b9c950ywan    e.size = -1;
6636233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6637233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long lacing = 1;  //default is true
6638233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6639233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (pos < track_stop)
6640233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
6641233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long id, size;
6642233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6643233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long status = ParseElementHeader(
6644233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                pReader,
6645233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                pos,
6646233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                track_stop,
6647233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                id,
6648233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                size);
6649233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6650233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)  //error
6651233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
6652233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6653233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size < 0)
6654233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
6655233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6656233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long start = pos;
6657233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6658233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x60)  // VideoSettings ID
6659233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
6660233d2500723e5594f3e7c70896ffeeef32b9c950ywan            v.start = start;
6661233d2500723e5594f3e7c70896ffeeef32b9c950ywan            v.size = size;
6662233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
6663233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x61)  // AudioSettings ID
6664233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
6665233d2500723e5594f3e7c70896ffeeef32b9c950ywan            a.start = start;
6666233d2500723e5594f3e7c70896ffeeef32b9c950ywan            a.size = size;
6667233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
6668233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x2D80) // ContentEncodings ID
6669233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
6670233d2500723e5594f3e7c70896ffeeef32b9c950ywan            e.start = start;
6671233d2500723e5594f3e7c70896ffeeef32b9c950ywan            e.size = size;
6672233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
6673233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x33C5)  //Track UID
6674233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
6675233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (size > 8)
6676233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
6677233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6678233d2500723e5594f3e7c70896ffeeef32b9c950ywan            info.uid = 0;
6679233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6680233d2500723e5594f3e7c70896ffeeef32b9c950ywan            long long pos_ = start;
6681233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long pos_end = start + size;
6682233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6683233d2500723e5594f3e7c70896ffeeef32b9c950ywan            while (pos_ != pos_end)
6684233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
6685233d2500723e5594f3e7c70896ffeeef32b9c950ywan                unsigned char b;
6686233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6687233d2500723e5594f3e7c70896ffeeef32b9c950ywan                const int status = pReader->Read(pos_, 1, &b);
6688233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6689233d2500723e5594f3e7c70896ffeeef32b9c950ywan                if (status)
6690233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    return status;
6691233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6692233d2500723e5594f3e7c70896ffeeef32b9c950ywan                info.uid <<= 8;
6693233d2500723e5594f3e7c70896ffeeef32b9c950ywan                info.uid |= b;
6694233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6695233d2500723e5594f3e7c70896ffeeef32b9c950ywan                ++pos_;
6696233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
6697233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
6698233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x57)  //Track Number
6699233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
6700233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long num = UnserializeUInt(pReader, pos, size);
6701233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6702233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((num <= 0) || (num > 127))
6703233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
6704233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6705233d2500723e5594f3e7c70896ffeeef32b9c950ywan            info.number = static_cast<long>(num);
6706233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
6707233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x03)  //Track Type
6708233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
6709233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long type = UnserializeUInt(pReader, pos, size);
6710233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6711233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((type <= 0) || (type > 254))
6712233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
6713233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6714233d2500723e5594f3e7c70896ffeeef32b9c950ywan            info.type = static_cast<long>(type);
6715233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
6716233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x136E)  //Track Name
6717233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
6718233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long status = UnserializeString(
6719233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pReader,
6720233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pos,
6721233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    size,
6722233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    info.nameAsUTF8);
6723233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6724233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status)
6725233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return status;
6726233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
6727233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x02B59C)  //Track Language
6728233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
6729233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long status = UnserializeString(
6730233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pReader,
6731233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pos,
6732233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    size,
6733233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    info.language);
6734233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6735233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status)
6736233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return status;
6737233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
6738233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x03E383)  //Default Duration
6739233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
6740233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long duration = UnserializeUInt(pReader, pos, size);
6741233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6742233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (duration < 0)
6743233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
6744233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6745233d2500723e5594f3e7c70896ffeeef32b9c950ywan            info.defaultDuration = static_cast<unsigned long long>(duration);
6746233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
6747233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x06)  //CodecID
6748233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
6749233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long status = UnserializeString(
6750233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pReader,
6751233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pos,
6752233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    size,
6753233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    info.codecId);
6754233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6755233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status)
6756233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return status;
6757233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
6758233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x1C)  //lacing
6759233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
6760233d2500723e5594f3e7c70896ffeeef32b9c950ywan            lacing = UnserializeUInt(pReader, pos, size);
6761233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6762233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((lacing < 0) || (lacing > 1))
6763233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
6764233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
6765233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x23A2)  //Codec Private
6766233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
6767233d2500723e5594f3e7c70896ffeeef32b9c950ywan            delete[] info.codecPrivate;
6768233d2500723e5594f3e7c70896ffeeef32b9c950ywan            info.codecPrivate = NULL;
6769233d2500723e5594f3e7c70896ffeeef32b9c950ywan            info.codecPrivateSize = 0;
6770233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6771233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const size_t buflen = static_cast<size_t>(size);
6772233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6773233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (buflen)
6774233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
6775233d2500723e5594f3e7c70896ffeeef32b9c950ywan                typedef unsigned char* buf_t;
6776233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6777233d2500723e5594f3e7c70896ffeeef32b9c950ywan                const buf_t buf = new (std::nothrow) unsigned char[buflen];
6778233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6779233d2500723e5594f3e7c70896ffeeef32b9c950ywan                if (buf == NULL)
6780233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    return -1;
6781233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6782233d2500723e5594f3e7c70896ffeeef32b9c950ywan                const int status = pReader->Read(pos, buflen, buf);
6783233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6784233d2500723e5594f3e7c70896ffeeef32b9c950ywan                if (status)
6785233d2500723e5594f3e7c70896ffeeef32b9c950ywan                {
6786233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    delete[] buf;
6787233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    return status;
6788233d2500723e5594f3e7c70896ffeeef32b9c950ywan                }
6789233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6790233d2500723e5594f3e7c70896ffeeef32b9c950ywan                info.codecPrivate = buf;
6791233d2500723e5594f3e7c70896ffeeef32b9c950ywan                info.codecPrivateSize = buflen;
6792233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
6793233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
6794233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x058688)  //Codec Name
6795233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
6796233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long status = UnserializeString(
6797233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pReader,
6798233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    pos,
6799233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    size,
6800233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    info.codecNameAsUTF8);
6801233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6802233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status)
6803233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return status;
6804233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
6805233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x16AA)  //Codec Delay
6806233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
6807233d2500723e5594f3e7c70896ffeeef32b9c950ywan            info.codecDelay = UnserializeUInt(pReader, pos, size);
6808233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6809233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
6810233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x16BB) //Seek Pre Roll
6811233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
6812233d2500723e5594f3e7c70896ffeeef32b9c950ywan            info.seekPreRoll = UnserializeUInt(pReader, pos, size);
6813233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
6814233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6815233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;  //consume payload
6816233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos <= track_stop);
6817233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
6818233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6819233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos == track_stop);
6820233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6821233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (info.number <= 0)  //not specified
6822233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
6823233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6824233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (GetTrackByNumber(info.number))
6825233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
6826233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6827233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (info.type <= 0)  //not specified
6828233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
6829233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6830233d2500723e5594f3e7c70896ffeeef32b9c950ywan    info.lacing = (lacing > 0) ? true : false;
6831233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6832233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (info.type == Track::kVideo)
6833233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
6834233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (v.start < 0)
6835233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
6836233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6837233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (a.start >= 0)
6838233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
6839233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6840233d2500723e5594f3e7c70896ffeeef32b9c950ywan        info.settings = v;
6841233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6842233d2500723e5594f3e7c70896ffeeef32b9c950ywan        VideoTrack* pTrack = NULL;
6843233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6844233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long status = VideoTrack::Parse(m_pSegment,
6845233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                              info,
6846233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                              element_start,
6847233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                              element_size,
6848233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                              pTrack);
6849233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6850233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status)
6851233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
6852233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6853233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pResult = pTrack;
6854233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pResult);
6855233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6856233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (e.start >= 0)
6857233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pResult->ParseContentEncodingsEntry(e.start, e.size);
6858233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
6859233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (info.type == Track::kAudio)
6860233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
6861233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (a.start < 0)
6862233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
6863233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6864233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (v.start >= 0)
6865233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
6866233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6867233d2500723e5594f3e7c70896ffeeef32b9c950ywan        info.settings = a;
6868233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6869233d2500723e5594f3e7c70896ffeeef32b9c950ywan        AudioTrack* pTrack = NULL;
6870233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6871233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long status = AudioTrack::Parse(m_pSegment,
6872233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                              info,
6873233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                              element_start,
6874233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                              element_size,
6875233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                              pTrack);
6876233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6877233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status)
6878233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
6879233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6880233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pResult = pTrack;
6881233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pResult);
6882233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6883233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (e.start >= 0)
6884233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pResult->ParseContentEncodingsEntry(e.start, e.size);
6885233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
6886233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else
6887233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
6888233d2500723e5594f3e7c70896ffeeef32b9c950ywan        // neither video nor audio - probably metadata or subtitles
6889233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6890233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (a.start >= 0)
6891233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
6892233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6893233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (v.start >= 0)
6894233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
6895233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6896233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (e.start >= 0)
6897233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
6898233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6899233d2500723e5594f3e7c70896ffeeef32b9c950ywan        info.settings.start = -1;
6900233d2500723e5594f3e7c70896ffeeef32b9c950ywan        info.settings.size = 0;
6901233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6902233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Track* pTrack = NULL;
6903233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6904233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long status = Track::Create(m_pSegment,
6905233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                          info,
6906233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                          element_start,
6907233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                          element_size,
6908233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                          pTrack);
6909233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6910233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status)
6911233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
6912233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6913233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pResult = pTrack;
6914233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pResult);
6915233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
6916233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6917233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;  //success
6918233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6919233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6920233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6921233d2500723e5594f3e7c70896ffeeef32b9c950ywanTracks::~Tracks()
6922233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6923233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Track** i = m_trackEntries;
6924233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Track** const j = m_trackEntriesEnd;
6925233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6926233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (i != j)
6927233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
6928233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Track* const pTrack = *i++;
6929233d2500723e5594f3e7c70896ffeeef32b9c950ywan        delete pTrack;
6930233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
6931233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6932233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] m_trackEntries;
6933233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6934233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6935233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst Track* Tracks::GetTrackByNumber(long tn) const
6936233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6937233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (tn < 0)
6938233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return NULL;
6939233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6940233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Track** i = m_trackEntries;
6941233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Track** const j = m_trackEntriesEnd;
6942233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6943233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (i != j)
6944233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
6945233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Track* const pTrack = *i++;
6946233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6947233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pTrack == NULL)
6948233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
6949233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6950233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (tn == pTrack->GetNumber())
6951233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return pTrack;
6952233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
6953233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6954233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NULL;  //not found
6955233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6956233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6957233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6958233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst Track* Tracks::GetTrackByIndex(unsigned long idx) const
6959233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6960233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const ptrdiff_t count = m_trackEntriesEnd - m_trackEntries;
6961233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6962233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (idx >= static_cast<unsigned long>(count))
6963233d2500723e5594f3e7c70896ffeeef32b9c950ywan         return NULL;
6964233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6965233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_trackEntries[idx];
6966233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6967233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6968233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
6969233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long Cluster::Unparsed() const
6970233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6971233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_timecode < 0)  //not even partially loaded
6972233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return LLONG_MAX;
6973233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6974233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_pos >= m_element_start);
6975233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //assert(m_element_size > m_size);
6976233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6977233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long element_stop = m_element_start + m_element_size;
6978233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_pos <= element_stop);
6979233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6980233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long result = element_stop - m_pos;
6981233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(result >= 0);
6982233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6983233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return result;
6984233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
6985233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
6986233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6987233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6988233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Cluster::Load(long long& pos, long& len) const
6989233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
6990233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_pSegment);
6991233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_pos >= m_element_start);
6992233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6993233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_timecode >= 0)  //at least partially loaded
6994233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;
6995233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6996233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_pos == m_element_start);
6997233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_element_size < 0);
6998233d2500723e5594f3e7c70896ffeeef32b9c950ywan
6999233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* const pReader = m_pSegment->m_pReader;
7000233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7001233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long total, avail;
7002233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7003233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int status = pReader->Length(&total, &avail);
7004233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7005233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error
7006233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
7007233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7008233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((total < 0) || (avail <= total));
7009233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((total < 0) || (m_pos <= total));  //TODO: verify this
7010233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7011233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos = m_pos;
7012233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7013233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long cluster_size = -1;
7014233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7015233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
7016233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > avail)
7017233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7018233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
7019233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7020233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7021233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7022233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long result = GetUIntLength(pReader, pos, len);
7023233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7024233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error or underflow
7025233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(result);
7026233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7027233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //underflow (weird)
7028233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7029233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7030233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //if ((pos + len) > segment_stop)
7031233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //    return E_FILE_FORMAT_INVALID;
7032233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7033233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > avail)
7034233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7035233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7036233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id_ = ReadUInt(pReader, pos, len);
7037233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7038233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id_ < 0)  //error
7039233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(id_);
7040233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7041233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id_ != 0x0F43B675)  //Cluster ID
7042233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7043233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7044233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume id
7045233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7046233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //read cluster size
7047233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7048233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > avail)
7049233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7050233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
7051233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7052233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7053233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7054233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result = GetUIntLength(pReader, pos, len);
7055233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7056233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
7057233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(result);
7058233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7059233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //weird
7060233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7061233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7062233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //if ((pos + len) > segment_stop)
7063233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //    return E_FILE_FORMAT_INVALID;
7064233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7065233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > avail)
7066233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7067233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7068233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long size = ReadUInt(pReader, pos, len);
7069233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7070233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size < 0)  //error
7071233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(cluster_size);
7072233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7073233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == 0)
7074233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;  //TODO: verify this
7075233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7076233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume length of size of element
7077233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7078233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long unknown_size = (1LL << (7 * len)) - 1;
7079233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7080233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size != unknown_size)
7081233d2500723e5594f3e7c70896ffeeef32b9c950ywan            cluster_size = size;
7082233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
7083233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7084233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //pos points to start of payload
7085233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7086233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
7087233d2500723e5594f3e7c70896ffeeef32b9c950ywan    len = static_cast<long>(size_);
7088233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7089233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cluster_stop > avail)
7090233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_BUFFER_NOT_FULL;
7091233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
7092233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7093233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long timecode = -1;
7094233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long new_pos = -1;
7095233d2500723e5594f3e7c70896ffeeef32b9c950ywan    bool bBlock = false;
7096233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7097233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long cluster_stop = (cluster_size < 0) ? -1 : pos + cluster_size;
7098233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7099233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (;;)
7100233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
7101233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((cluster_stop >= 0) && (pos >= cluster_stop))
7102233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
7103233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7104233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Parse ID
7105233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7106233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > avail)
7107233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7108233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
7109233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7110233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7111233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7112233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long result = GetUIntLength(pReader, pos, len);
7113233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7114233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
7115233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(result);
7116233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7117233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //weird
7118233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7119233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7120233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
7121233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7122233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7123233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > avail)
7124233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7125233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7126233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id = ReadUInt(pReader, pos, len);
7127233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7128233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id < 0) //error
7129233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(id);
7130233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7131233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0)
7132233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7133233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7134233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //This is the distinguished set of ID's we use to determine
7135233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //that we have exhausted the sub-element's inside the cluster
7136233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //whose ID we parsed earlier.
7137233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7138233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x0F43B675)  //Cluster ID
7139233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
7140233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7141233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x0C53BB6B)  //Cues ID
7142233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
7143233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7144233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume ID field
7145233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7146233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Parse Size
7147233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7148233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > avail)
7149233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7150233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
7151233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7152233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7153233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7154233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result = GetUIntLength(pReader, pos, len);
7155233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7156233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
7157233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(result);
7158233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7159233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //weird
7160233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7161233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7162233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
7163233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7164233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7165233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > avail)
7166233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7167233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7168233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long size = ReadUInt(pReader, pos, len);
7169233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7170233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size < 0)  //error
7171233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(size);
7172233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7173233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long unknown_size = (1LL << (7 * len)) - 1;
7174233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7175233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == unknown_size)
7176233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7177233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7178233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume size field
7179233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7180233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((cluster_stop >= 0) && (pos > cluster_stop))
7181233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7182233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7183233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //pos now points to start of payload
7184233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7185233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == 0)  //weird
7186233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
7187233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7188233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((cluster_stop >= 0) && ((pos + size) > cluster_stop))
7189233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7190233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7191233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x67)  //TimeCode ID
7192233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7193233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = static_cast<long>(size);
7194233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7195233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((pos + size) > avail)
7196233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_BUFFER_NOT_FULL;
7197233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7198233d2500723e5594f3e7c70896ffeeef32b9c950ywan            timecode = UnserializeUInt(pReader, pos, size);
7199233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7200233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (timecode < 0)  //error (or underflow)
7201233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return static_cast<long>(timecode);
7202233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7203233d2500723e5594f3e7c70896ffeeef32b9c950ywan            new_pos = pos + size;
7204233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7205233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (bBlock)
7206233d2500723e5594f3e7c70896ffeeef32b9c950ywan                break;
7207233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7208233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x20)  //BlockGroup ID
7209233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7210233d2500723e5594f3e7c70896ffeeef32b9c950ywan            bBlock = true;
7211233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
7212233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7213233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x23)  //SimpleBlock ID
7214233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7215233d2500723e5594f3e7c70896ffeeef32b9c950ywan            bBlock = true;
7216233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
7217233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7218233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7219233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;  //consume payload
7220233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((cluster_stop < 0) || (pos <= cluster_stop));
7221233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
7222233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7223233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((cluster_stop < 0) || (pos <= cluster_stop));
7224233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7225233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (timecode < 0)  //no timecode found
7226233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
7227233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7228233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!bBlock)
7229233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
7230233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7231233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pos = new_pos;  //designates position just beyond timecode payload
7232233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_timecode = timecode;  // m_timecode >= 0 means we're partially loaded
7233233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7234233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cluster_size >= 0)
7235233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m_element_size = cluster_stop - m_element_start;
7236233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7237233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
7238233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
7239233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7240233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7241233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Cluster::Parse(long long& pos, long& len) const
7242233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
7243233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long status = Load(pos, len);
7244233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7245233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)
7246233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
7247233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7248233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_pos >= m_element_start);
7249233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_timecode >= 0);
7250233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //assert(m_size > 0);
7251233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //assert(m_element_size > m_size);
7252233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7253233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long cluster_stop =
7254233d2500723e5594f3e7c70896ffeeef32b9c950ywan        (m_element_size < 0) ? -1 : m_element_start + m_element_size;
7255233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7256233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((cluster_stop >= 0) && (m_pos >= cluster_stop))
7257233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 1;  //nothing else to do
7258233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7259233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* const pReader = m_pSegment->m_pReader;
7260233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7261233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long total, avail;
7262233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7263233d2500723e5594f3e7c70896ffeeef32b9c950ywan    status = pReader->Length(&total, &avail);
7264233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7265233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error
7266233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
7267233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7268233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((total < 0) || (avail <= total));
7269233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7270233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos = m_pos;
7271233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7272233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (;;)
7273233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
7274233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((cluster_stop >= 0) && (pos >= cluster_stop))
7275233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
7276233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7277233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((total >= 0) && (pos >= total))
7278233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7279233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_element_size < 0)
7280233d2500723e5594f3e7c70896ffeeef32b9c950ywan                m_element_size = pos - m_element_start;
7281233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7282233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
7283233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7284233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7285233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Parse ID
7286233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7287233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > avail)
7288233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7289233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
7290233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7291233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7292233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7293233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long result = GetUIntLength(pReader, pos, len);
7294233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7295233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
7296233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(result);
7297233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7298233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //weird
7299233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7300233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7301233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
7302233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7303233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7304233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > avail)
7305233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7306233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7307233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id = ReadUInt(pReader, pos, len);
7308233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7309233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id < 0) //error
7310233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(id);
7311233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7312233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0)  //weird
7313233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7314233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7315233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //This is the distinguished set of ID's we use to determine
7316233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //that we have exhausted the sub-element's inside the cluster
7317233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //whose ID we parsed earlier.
7318233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7319233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((id == 0x0F43B675) || (id == 0x0C53BB6B)) //Cluster or Cues ID
7320233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7321233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (m_element_size < 0)
7322233d2500723e5594f3e7c70896ffeeef32b9c950ywan                m_element_size = pos - m_element_start;
7323233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7324233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
7325233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7326233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7327233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume ID field
7328233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7329233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Parse Size
7330233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7331233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > avail)
7332233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7333233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
7334233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7335233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7336233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7337233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result = GetUIntLength(pReader, pos, len);
7338233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7339233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
7340233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(result);
7341233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7342233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //weird
7343233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7344233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7345233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
7346233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7347233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7348233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > avail)
7349233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7350233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7351233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long size = ReadUInt(pReader, pos, len);
7352233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7353233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size < 0)  //error
7354233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(size);
7355233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7356233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long unknown_size = (1LL << (7 * len)) - 1;
7357233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7358233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == unknown_size)
7359233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7360233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7361233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume size field
7362233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7363233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((cluster_stop >= 0) && (pos > cluster_stop))
7364233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7365233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7366233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //pos now points to start of payload
7367233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7368233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == 0)  //weird
7369233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
7370233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7371233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //const long long block_start = pos;
7372233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long block_stop = pos + size;
7373233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7374233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (cluster_stop >= 0)
7375233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7376233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (block_stop > cluster_stop)
7377233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
7378233d2500723e5594f3e7c70896ffeeef32b9c950ywan                if ((id == 0x20) || (id == 0x23))
7379233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    return E_FILE_FORMAT_INVALID;
7380233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7381233d2500723e5594f3e7c70896ffeeef32b9c950ywan                pos = cluster_stop;
7382233d2500723e5594f3e7c70896ffeeef32b9c950ywan                break;
7383233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
7384233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7385233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if ((total >= 0) && (block_stop > total))
7386233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7387233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_element_size = total - m_element_start;
7388233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pos = total;
7389233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
7390233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7391233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (block_stop > avail)
7392233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7393233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = static_cast<long>(size);
7394233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7395233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7396233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7397233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Cluster* const this_ = const_cast<Cluster*>(this);
7398233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7399233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x20)  //BlockGroup
7400233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return this_->ParseBlockGroup(size, pos, len);
7401233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7402233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x23)  //SimpleBlock
7403233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return this_->ParseSimpleBlock(size, pos, len);
7404233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7405233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;  //consume payload
7406233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((cluster_stop < 0) || (pos <= cluster_stop));
7407233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
7408233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7409233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_element_size > 0);
7410233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7411233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pos = pos;
7412233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((cluster_stop < 0) || (m_pos <= cluster_stop));
7413233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7414233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_entries_count > 0)
7415233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
7416233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long idx = m_entries_count - 1;
7417233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7418233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const BlockEntry* const pLast = m_entries[idx];
7419233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pLast);
7420233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7421233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const Block* const pBlock = pLast->GetBlock();
7422233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pBlock);
7423233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7424233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long start = pBlock->m_start;
7425233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7426233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((total >= 0) && (start > total))
7427233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return -1;  //defend against trucated stream
7428233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7429233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long size = pBlock->m_size;
7430233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7431233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long stop = start + size;
7432233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((cluster_stop < 0) || (stop <= cluster_stop));
7433233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7434233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((total >= 0) && (stop > total))
7435233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return -1;  //defend against trucated stream
7436233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
7437233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7438233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 1;  //no more entries
7439233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
7440233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7441233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7442233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Cluster::ParseSimpleBlock(
7443233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long block_size,
7444233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long& pos,
7445233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long& len)
7446233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
7447233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long block_start = pos;
7448233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long block_stop = pos + block_size;
7449233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7450233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* const pReader = m_pSegment->m_pReader;
7451233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7452233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long total, avail;
7453233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7454233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long status = pReader->Length(&total, &avail);
7455233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7456233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error
7457233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
7458233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7459233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((total < 0) || (avail <= total));
7460233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7461233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //parse track number
7462233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7463233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((pos + 1) > avail)
7464233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
7465233d2500723e5594f3e7c70896ffeeef32b9c950ywan        len = 1;
7466233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_BUFFER_NOT_FULL;
7467233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
7468233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7469233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long result = GetUIntLength(pReader, pos, len);
7470233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7471233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (result < 0)  //error
7472233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return static_cast<long>(result);
7473233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7474233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (result > 0)  //weird
7475233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_BUFFER_NOT_FULL;
7476233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7477233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((pos + len) > block_stop)
7478233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
7479233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7480233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((pos + len) > avail)
7481233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_BUFFER_NOT_FULL;
7482233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7483233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long track = ReadUInt(pReader, pos, len);
7484233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7485233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (track < 0) //error
7486233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return static_cast<long>(track);
7487233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7488233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (track == 0)
7489233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
7490233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7491233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
7492233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //TODO(matthewjheaney)
7493233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //This turned out to be too conservative.  The problem is that
7494233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //if we see a track header in the tracks element with an unsupported
7495233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //track type, we throw that track header away, so it is not present
7496233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //in the track map.  But even though we don't understand the track
7497233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //header, there are still blocks in the cluster with that track
7498233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //number.  It was our decision to ignore that track header, so it's
7499233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //up to us to deal with blocks associated with that track -- we
7500233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //cannot simply report an error since technically there's nothing
7501233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //wrong with the file.
7502233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //
7503233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //For now we go ahead and finish the parse, creating a block entry
7504233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //for this block.  This is somewhat wasteful, because without a
7505233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //track header there's nothing you can do with the block. What
7506233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //we really need here is a special return value that indicates to
7507233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //the caller that he should ignore this particular block, and
7508233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //continue parsing.
7509233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7510233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Tracks* const pTracks = m_pSegment->GetTracks();
7511233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pTracks);
7512233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7513233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long tn = static_cast<long>(track);
7514233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7515233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Track* const pTrack = pTracks->GetTrackByNumber(tn);
7516233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7517233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pTrack == NULL)
7518233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
7519233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
7520233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7521233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += len;  //consume track number
7522233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7523233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((pos + 2) > block_stop)
7524233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
7525233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7526233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((pos + 2) > avail)
7527233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
7528233d2500723e5594f3e7c70896ffeeef32b9c950ywan        len = 2;
7529233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_BUFFER_NOT_FULL;
7530233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
7531233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7532233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += 2;  //consume timecode
7533233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7534233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((pos + 1) > block_stop)
7535233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
7536233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7537233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((pos + 1) > avail)
7538233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
7539233d2500723e5594f3e7c70896ffeeef32b9c950ywan        len = 1;
7540233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_BUFFER_NOT_FULL;
7541233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
7542233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7543233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned char flags;
7544233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7545233d2500723e5594f3e7c70896ffeeef32b9c950ywan    status = pReader->Read(pos, 1, &flags);
7546233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7547233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error or underflow
7548233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
7549233d2500723e5594f3e7c70896ffeeef32b9c950ywan        len = 1;
7550233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
7551233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
7552233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7553233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ++pos;  //consume flags byte
7554233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos <= avail);
7555233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7556233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pos >= block_stop)
7557233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
7558233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7559233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int lacing = int(flags & 0x06) >> 1;
7560233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7561233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((lacing != 0) && (block_stop > avail))
7562233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
7563233d2500723e5594f3e7c70896ffeeef32b9c950ywan        len = static_cast<long>(block_stop - pos);
7564233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_BUFFER_NOT_FULL;
7565233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
7566233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7567233d2500723e5594f3e7c70896ffeeef32b9c950ywan    status = CreateBlock(0x23,  //simple block id
7568233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         block_start, block_size,
7569233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         0);  //DiscardPadding
7570233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7571233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status != 0)
7572233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
7573233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7574233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pos = block_stop;
7575233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7576233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;  //success
7577233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
7578233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7579233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7580233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Cluster::ParseBlockGroup(
7581233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long payload_size,
7582233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long& pos,
7583233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long& len)
7584233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
7585233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long payload_start = pos;
7586233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long payload_stop = pos + payload_size;
7587233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7588233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* const pReader = m_pSegment->m_pReader;
7589233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7590233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long total, avail;
7591233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7592233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long status = pReader->Length(&total, &avail);
7593233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7594233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error
7595233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
7596233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7597233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((total < 0) || (avail <= total));
7598233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7599233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((total >= 0) && (payload_stop > total))
7600233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
7601233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7602233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (payload_stop > avail)
7603233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
7604233d2500723e5594f3e7c70896ffeeef32b9c950ywan         len = static_cast<long>(payload_size);
7605233d2500723e5594f3e7c70896ffeeef32b9c950ywan         return E_BUFFER_NOT_FULL;
7606233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
7607233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7608233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long discard_padding = 0;
7609233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7610233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (pos < payload_stop)
7611233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
7612233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //parse sub-block element ID
7613233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7614233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > avail)
7615233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7616233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
7617233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7618233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7619233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7620233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long result = GetUIntLength(pReader, pos, len);
7621233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7622233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
7623233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(result);
7624233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7625233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //weird
7626233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7627233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7628233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > payload_stop)
7629233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7630233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7631233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > avail)
7632233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7633233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7634233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id = ReadUInt(pReader, pos, len);
7635233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7636233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id < 0) //error
7637233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(id);
7638233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7639233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0)  //not a value ID
7640233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7641233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7642233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume ID field
7643233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7644233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //Parse Size
7645233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7646233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > avail)
7647233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7648233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
7649233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7650233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7651233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7652233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result = GetUIntLength(pReader, pos, len);
7653233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7654233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
7655233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(result);
7656233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7657233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //weird
7658233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7659233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7660233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > payload_stop)
7661233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7662233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7663233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > avail)
7664233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7665233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7666233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long size = ReadUInt(pReader, pos, len);
7667233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7668233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size < 0)  //error
7669233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(size);
7670233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7671233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume size field
7672233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7673233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //pos now points to start of sub-block group payload
7674233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7675233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pos > payload_stop)
7676233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7677233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7678233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == 0)  //weird
7679233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
7680233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7681233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long unknown_size = (1LL << (7 * len)) - 1;
7682233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7683233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == unknown_size)
7684233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7685233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7686233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x35A2)  //DiscardPadding
7687233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7688233d2500723e5594f3e7c70896ffeeef32b9c950ywan            result = GetUIntLength(pReader, pos, len);
7689233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7690233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (result < 0)  //error
7691233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return static_cast<long>(result);
7692233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7693233d2500723e5594f3e7c70896ffeeef32b9c950ywan            status = UnserializeInt(pReader, pos, len, discard_padding);
7694233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7695233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status < 0)  //error
7696233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return status;
7697233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7698233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7699233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id != 0x21)  //sub-part of BlockGroup is not a Block
7700233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7701233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pos += size;  //consume sub-part of block group
7702233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7703233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (pos > payload_stop)
7704233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
7705233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7706233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
7707233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7708233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7709233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long block_stop = pos + size;
7710233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7711233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (block_stop > payload_stop)
7712233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7713233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7714233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //parse track number
7715233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7716233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > avail)
7717233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7718233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
7719233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7720233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7721233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7722233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result = GetUIntLength(pReader, pos, len);
7723233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7724233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
7725233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(result);
7726233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7727233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //weird
7728233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7729233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7730233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > block_stop)
7731233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7732233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7733233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > avail)
7734233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7735233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7736233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long track = ReadUInt(pReader, pos, len);
7737233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7738233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (track < 0) //error
7739233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(track);
7740233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7741233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (track == 0)
7742233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7743233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7744233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
7745233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //TODO(matthewjheaney)
7746233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //This turned out to be too conservative.  The problem is that
7747233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //if we see a track header in the tracks element with an unsupported
7748233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //track type, we throw that track header away, so it is not present
7749233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //in the track map.  But even though we don't understand the track
7750233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //header, there are still blocks in the cluster with that track
7751233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //number.  It was our decision to ignore that track header, so it's
7752233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //up to us to deal with blocks associated with that track -- we
7753233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //cannot simply report an error since technically there's nothing
7754233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //wrong with the file.
7755233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //
7756233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //For now we go ahead and finish the parse, creating a block entry
7757233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //for this block.  This is somewhat wasteful, because without a
7758233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //track header there's nothing you can do with the block. What
7759233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //we really need here is a special return value that indicates to
7760233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //the caller that he should ignore this particular block, and
7761233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //continue parsing.
7762233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7763233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const Tracks* const pTracks = m_pSegment->GetTracks();
7764233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pTracks);
7765233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7766233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long tn = static_cast<long>(track);
7767233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7768233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const Track* const pTrack = pTracks->GetTrackByNumber(tn);
7769233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7770233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pTrack == NULL)
7771233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7772233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
7773233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7774233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume track number
7775233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7776233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 2) > block_stop)
7777233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7778233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7779233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 2) > avail)
7780233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7781233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 2;
7782233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7783233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7784233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7785233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += 2;  //consume timecode
7786233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7787233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > block_stop)
7788233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7789233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7790233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > avail)
7791233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7792233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
7793233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7794233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7795233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7796233d2500723e5594f3e7c70896ffeeef32b9c950ywan        unsigned char flags;
7797233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7798233d2500723e5594f3e7c70896ffeeef32b9c950ywan        status = pReader->Read(pos, 1, &flags);
7799233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7800233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)  //error or underflow
7801233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7802233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
7803233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
7804233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7805233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7806233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ++pos;  //consume flags byte
7807233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos <= avail);
7808233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7809233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pos >= block_stop)
7810233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
7811233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7812233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const int lacing = int(flags & 0x06) >> 1;
7813233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7814233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((lacing != 0) && (block_stop > avail))
7815233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
7816233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = static_cast<long>(block_stop - pos);
7817233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
7818233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
7819233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7820233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos = block_stop;  //consume block-part of block group
7821233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos <= payload_stop);
7822233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
7823233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7824233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos == payload_stop);
7825233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7826233d2500723e5594f3e7c70896ffeeef32b9c950ywan    status = CreateBlock(0x20,  //BlockGroup ID
7827233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         payload_start, payload_size,
7828233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         discard_padding);
7829233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status != 0)
7830233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
7831233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7832233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pos = payload_stop;
7833233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7834233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;  //success
7835233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
7836233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7837233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7838233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Cluster::GetEntry(long index, const mkvparser::BlockEntry*& pEntry) const
7839233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
7840233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_pos >= m_element_start);
7841233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7842233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pEntry = NULL;
7843233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7844233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (index < 0)
7845233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;  //generic error
7846233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7847233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_entries_count < 0)
7848233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_BUFFER_NOT_FULL;
7849233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7850233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_entries);
7851233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_entries_size > 0);
7852233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_entries_count <= m_entries_size);
7853233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7854233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (index < m_entries_count)
7855233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
7856233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pEntry = m_entries[index];
7857233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pEntry);
7858233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7859233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 1;  //found entry
7860233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
7861233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7862233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_element_size < 0)        //we don't know cluster end yet
7863233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_BUFFER_NOT_FULL;  //underflow
7864233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7865233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long element_stop = m_element_start + m_element_size;
7866233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7867233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_pos >= element_stop)
7868233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;  //nothing left to parse
7869233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7870233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return E_BUFFER_NOT_FULL;  //underflow, since more remains to be parsed
7871233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
7872233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7873233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7874233d2500723e5594f3e7c70896ffeeef32b9c950ywanCluster* Cluster::Create(
7875233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Segment* pSegment,
7876233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long idx,
7877233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long off)
7878233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //long long element_size)
7879233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
7880233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pSegment);
7881233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(off >= 0);
7882233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7883233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long element_start = pSegment->m_start + off;
7884233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7885233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster* const pCluster = new Cluster(pSegment,
7886233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                          idx,
7887233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                          element_start);
7888233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                          //element_size);
7889233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster);
7890233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7891233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return pCluster;
7892233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
7893233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7894233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7895233d2500723e5594f3e7c70896ffeeef32b9c950ywanCluster::Cluster() :
7896233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pSegment(NULL),
7897233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_element_start(0),
7898233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_index(0),
7899233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pos(0),
7900233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_element_size(0),
7901233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_timecode(0),
7902233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_entries(NULL),
7903233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_entries_size(0),
7904233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_entries_count(0)  //means "no entries"
7905233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
7906233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
7907233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7908233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7909233d2500723e5594f3e7c70896ffeeef32b9c950ywanCluster::Cluster(
7910233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Segment* pSegment,
7911233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long idx,
7912233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long element_start
7913233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* long long element_size */ ) :
7914233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pSegment(pSegment),
7915233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_element_start(element_start),
7916233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_index(idx),
7917233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pos(element_start),
7918233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_element_size(-1 /* element_size */ ),
7919233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_timecode(-1),
7920233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_entries(NULL),
7921233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_entries_size(0),
7922233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_entries_count(-1)  //means "has not been parsed yet"
7923233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
7924233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
7925233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7926233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7927233d2500723e5594f3e7c70896ffeeef32b9c950ywanCluster::~Cluster()
7928233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
7929233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_entries_count <= 0)
7930233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return;
7931233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7932233d2500723e5594f3e7c70896ffeeef32b9c950ywan    BlockEntry** i = m_entries;
7933233d2500723e5594f3e7c70896ffeeef32b9c950ywan    BlockEntry** const j = m_entries + m_entries_count;
7934233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7935233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (i != j)
7936233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
7937233d2500723e5594f3e7c70896ffeeef32b9c950ywan         BlockEntry* p = *i++;
7938233d2500723e5594f3e7c70896ffeeef32b9c950ywan         assert(p);
7939233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7940233d2500723e5594f3e7c70896ffeeef32b9c950ywan         delete p;
7941233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
7942233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7943233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] m_entries;
7944233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
7945233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7946233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7947233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Cluster::EOS() const
7948233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
7949233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return (m_pSegment == NULL);
7950233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
7951233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7952233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7953233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Cluster::GetIndex() const
7954233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
7955233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_index;
7956233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
7957233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7958233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7959233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long Cluster::GetPosition() const
7960233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
7961233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long pos = m_element_start - m_pSegment->m_start;
7962233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos >= 0);
7963233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7964233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return pos;
7965233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
7966233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7967233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7968233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long Cluster::GetElementSize() const
7969233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
7970233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_element_size;
7971233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
7972233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7973233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7974233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
7975233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Cluster::HasBlockEntries(
7976233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Segment* pSegment,
7977233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long off)  //relative to start of segment payload
7978233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
7979233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pSegment);
7980233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(off >= 0);  //relative to segment
7981233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7982233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* const pReader = pSegment->m_pReader;
7983233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7984233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos = pSegment->m_start + off;  //absolute
7985233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size;
7986233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7987233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
7988233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long len;
7989233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7990233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id = ReadUInt(pReader, pos, len);
7991233d2500723e5594f3e7c70896ffeeef32b9c950ywan        (void)id;
7992233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(id >= 0);
7993233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(id == 0x0F43B675);  //Cluster ID
7994233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7995233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume id
7996233d2500723e5594f3e7c70896ffeeef32b9c950ywan
7997233d2500723e5594f3e7c70896ffeeef32b9c950ywan        size = ReadUInt(pReader, pos, len);
7998233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(size > 0);
7999233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8000233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume size
8001233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8002233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //pos now points to start of payload
8003233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
8004233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8005233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long stop = pos + size;
8006233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8007233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (pos < stop)
8008233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
8009233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long len;
8010233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8011233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id = ReadUInt(pReader, pos, len);
8012233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(id >= 0);  //TODO
8013233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pos + len) <= stop);
8014233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8015233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume id
8016233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8017233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long size = ReadUInt(pReader, pos, len);
8018233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(size >= 0);  //TODO
8019233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pos + len) <= stop);
8020233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8021233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume size
8022233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8023233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x20)  //BlockGroup ID
8024233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return true;
8025233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8026233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x23)  //SimpleBlock ID
8027233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return true;
8028233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8029233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;  //consume payload
8030233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos <= stop);
8031233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
8032233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8033233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
8034233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
8035233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
8036233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8037233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8038233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Cluster::HasBlockEntries(
8039233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Segment* pSegment,
8040233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long off,  //relative to start of segment payload
8041233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long& pos,
8042233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long& len)
8043233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
8044233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pSegment);
8045233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(off >= 0);  //relative to segment
8046233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8047233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* const pReader = pSegment->m_pReader;
8048233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8049233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long total, avail;
8050233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8051233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long status = pReader->Length(&total, &avail);
8052233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8053233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error
8054233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
8055233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8056233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((total < 0) || (avail <= total));
8057233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8058233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos = pSegment->m_start + off;  //absolute
8059233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8060233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((total >= 0) && (pos >= total))
8061233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;  //we don't even have a complete cluster
8062233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8063233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long segment_stop =
8064233d2500723e5594f3e7c70896ffeeef32b9c950ywan        (pSegment->m_size < 0) ? -1 : pSegment->m_start + pSegment->m_size;
8065233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8066233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long cluster_stop = -1;  //interpreted later to mean "unknown size"
8067233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8068233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
8069233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > avail)
8070233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8071233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
8072233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
8073233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8074233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8075233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long result = GetUIntLength(pReader, pos, len);
8076233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8077233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
8078233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(result);
8079233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8080233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //need more data
8081233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
8082233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8083233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((segment_stop >= 0) && ((pos + len) > segment_stop))
8084233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
8085233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8086233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((total >= 0) && ((pos + len) > total))
8087233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 0;
8088233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8089233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > avail)
8090233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
8091233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8092233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id = ReadUInt(pReader, pos, len);
8093233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8094233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id < 0)  //error
8095233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(id);
8096233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8097233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id != 0x0F43B675)  //weird: not cluster ID
8098233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return -1;         //generic error
8099233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8100233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume Cluster ID field
8101233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8102233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //read size field
8103233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8104233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > avail)
8105233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8106233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
8107233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
8108233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8109233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8110233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result = GetUIntLength(pReader, pos, len);
8111233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8112233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
8113233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(result);
8114233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8115233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //weird
8116233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
8117233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8118233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((segment_stop >= 0) && ((pos + len) > segment_stop))
8119233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
8120233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8121233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((total >= 0) && ((pos + len) > total))
8122233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 0;
8123233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8124233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > avail)
8125233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
8126233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8127233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long size = ReadUInt(pReader, pos, len);
8128233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8129233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size < 0)  //error
8130233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(size);
8131233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8132233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == 0)
8133233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 0;  //cluster does not have entries
8134233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8135233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume size field
8136233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8137233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //pos now points to start of payload
8138233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8139233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long unknown_size = (1LL << (7 * len)) - 1;
8140233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8141233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size != unknown_size)
8142233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8143233d2500723e5594f3e7c70896ffeeef32b9c950ywan            cluster_stop = pos + size;
8144233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(cluster_stop >= 0);
8145233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8146233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((segment_stop >= 0) && (cluster_stop > segment_stop))
8147233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
8148233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8149233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((total >= 0) && (cluster_stop > total))
8150233d2500723e5594f3e7c70896ffeeef32b9c950ywan                //return E_FILE_FORMAT_INVALID;  //too conservative
8151233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return 0;  //cluster does not have any entries
8152233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8153233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
8154233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8155233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (;;)
8156233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
8157233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((cluster_stop >= 0) && (pos >= cluster_stop))
8158233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 0;  //no entries detected
8159233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8160233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > avail)
8161233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8162233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
8163233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
8164233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8165233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8166233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long result = GetUIntLength(pReader, pos, len);
8167233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8168233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
8169233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(result);
8170233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8171233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //need more data
8172233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
8173233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8174233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
8175233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
8176233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8177233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > avail)
8178233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
8179233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8180233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id = ReadUInt(pReader, pos, len);
8181233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8182233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id < 0)  //error
8183233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(id);
8184233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8185233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //This is the distinguished set of ID's we use to determine
8186233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //that we have exhausted the sub-element's inside the cluster
8187233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //whose ID we parsed earlier.
8188233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8189233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x0F43B675)  //Cluster ID
8190233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 0;  //no entries found
8191233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8192233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x0C53BB6B)  //Cues ID
8193233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 0;  //no entries found
8194233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8195233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume id field
8196233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8197233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((cluster_stop >= 0) && (pos >= cluster_stop))
8198233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
8199233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8200233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //read size field
8201233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8202233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + 1) > avail)
8203233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8204233d2500723e5594f3e7c70896ffeeef32b9c950ywan            len = 1;
8205233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
8206233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8207233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8208233d2500723e5594f3e7c70896ffeeef32b9c950ywan        result = GetUIntLength(pReader, pos, len);
8209233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8210233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result < 0)  //error
8211233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(result);
8212233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8213233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (result > 0)  //underflow
8214233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
8215233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8216233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
8217233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
8218233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8219233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > avail)
8220233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_BUFFER_NOT_FULL;
8221233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8222233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long size = ReadUInt(pReader, pos, len);
8223233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8224233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size < 0)  //error
8225233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return static_cast<long>(size);
8226233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8227233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume size field
8228233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8229233d2500723e5594f3e7c70896ffeeef32b9c950ywan        //pos now points to start of payload
8230233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8231233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((cluster_stop >= 0) && (pos > cluster_stop))
8232233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
8233233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8234233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == 0)  //weird
8235233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
8236233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8237233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long unknown_size = (1LL << (7 * len)) - 1;
8238233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8239233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (size == unknown_size)
8240233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;  //not supported inside cluster
8241233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8242233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((cluster_stop >= 0) && ((pos + size) > cluster_stop))
8243233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
8244233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8245233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x20)  //BlockGroup ID
8246233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 1;    //have at least one entry
8247233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8248233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x23)  //SimpleBlock ID
8249233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 1;    //have at least one entry
8250233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8251233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;  //consume payload
8252233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((cluster_stop < 0) || (pos <= cluster_stop));
8253233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
8254233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
8255233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8256233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8257233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long Cluster::GetTimeCode() const
8258233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
8259233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos;
8260233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long len;
8261233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8262233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long status = Load(pos, len);
8263233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8264233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0) //error
8265233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
8266233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8267233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_timecode;
8268233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
8269233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8270233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8271233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long Cluster::GetTime() const
8272233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
8273233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long tc = GetTimeCode();
8274233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8275233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (tc < 0)
8276233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return tc;
8277233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8278233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const SegmentInfo* const pInfo = m_pSegment->GetInfo();
8279233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pInfo);
8280233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8281233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long scale = pInfo->GetTimeCodeScale();
8282233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(scale >= 1);
8283233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8284233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long t = m_timecode * scale;
8285233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8286233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return t;
8287233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
8288233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8289233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8290233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long Cluster::GetFirstTime() const
8291233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
8292233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const BlockEntry* pEntry;
8293233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8294233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long status = GetFirst(pEntry);
8295233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8296233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error
8297233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
8298233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8299233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pEntry == NULL)  //empty cluster
8300233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return GetTime();
8301233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8302233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Block* const pBlock = pEntry->GetBlock();
8303233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pBlock);
8304233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8305233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return pBlock->GetTime(this);
8306233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
8307233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8308233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8309233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long Cluster::GetLastTime() const
8310233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
8311233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const BlockEntry* pEntry;
8312233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8313233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long status = GetLast(pEntry);
8314233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8315233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status < 0)  //error
8316233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
8317233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8318233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pEntry == NULL)  //empty cluster
8319233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return GetTime();
8320233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8321233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Block* const pBlock = pEntry->GetBlock();
8322233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pBlock);
8323233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8324233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return pBlock->GetTime(this);
8325233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
8326233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8327233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8328233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Cluster::CreateBlock(
8329233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long id,
8330233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos,   //absolute pos of payload
8331233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size,
8332233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long discard_padding)
8333233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
8334233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert((id == 0x20) || (id == 0x23));  //BlockGroup or SimpleBlock
8335233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8336233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_entries_count < 0)  //haven't parsed anything yet
8337233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
8338233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(m_entries == NULL);
8339233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(m_entries_size == 0);
8340233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8341233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m_entries_size = 1024;
8342233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m_entries = new BlockEntry*[m_entries_size];
8343233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8344233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m_entries_count = 0;
8345233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
8346233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else
8347233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
8348233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(m_entries);
8349233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(m_entries_size > 0);
8350233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(m_entries_count <= m_entries_size);
8351233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8352233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (m_entries_count >= m_entries_size)
8353233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8354233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long entries_size = 2 * m_entries_size;
8355233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8356233d2500723e5594f3e7c70896ffeeef32b9c950ywan            BlockEntry** const entries = new BlockEntry*[entries_size];
8357233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(entries);
8358233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8359233d2500723e5594f3e7c70896ffeeef32b9c950ywan            BlockEntry** src = m_entries;
8360233d2500723e5594f3e7c70896ffeeef32b9c950ywan            BlockEntry** const src_end = src + m_entries_count;
8361233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8362233d2500723e5594f3e7c70896ffeeef32b9c950ywan            BlockEntry** dst = entries;
8363233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8364233d2500723e5594f3e7c70896ffeeef32b9c950ywan            while (src != src_end)
8365233d2500723e5594f3e7c70896ffeeef32b9c950ywan                *dst++ = *src++;
8366233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8367233d2500723e5594f3e7c70896ffeeef32b9c950ywan            delete[] m_entries;
8368233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8369233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_entries = entries;
8370233d2500723e5594f3e7c70896ffeeef32b9c950ywan            m_entries_size = entries_size;
8371233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8372233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
8373233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8374233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (id == 0x20)  //BlockGroup ID
8375233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return CreateBlockGroup(pos, size, discard_padding);
8376233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else  //SimpleBlock ID
8377233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return CreateSimpleBlock(pos, size);
8378233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
8379233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8380233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8381233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Cluster::CreateBlockGroup(
8382233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long start_offset,
8383233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size,
8384233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long discard_padding)
8385233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
8386233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_entries);
8387233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_entries_size > 0);
8388233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_entries_count >= 0);
8389233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_entries_count < m_entries_size);
8390233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8391233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* const pReader = m_pSegment->m_pReader;
8392233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8393233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos = start_offset;
8394233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long stop = start_offset + size;
8395233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8396233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //For WebM files, there is a bias towards previous reference times
8397233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //(in order to support alt-ref frames, which refer back to the previous
8398233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //keyframe).  Normally a 0 value is not possible, but here we tenatively
8399233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //allow 0 as the value of a reference frame, with the interpretation
8400233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //that this is a "previous" reference time.
8401233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8402233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long prev = 1;  //nonce
8403233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long next = 0;  //nonce
8404233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long duration = -1;  //really, this is unsigned
8405233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8406233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long bpos = -1;
8407233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long bsize = -1;
8408233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8409233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (pos < stop)
8410233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
8411233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long len;
8412233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long id = ReadUInt(pReader, pos, len);
8413233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(id >= 0);  //TODO
8414233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pos + len) <= stop);
8415233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8416233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume ID
8417233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8418233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long size = ReadUInt(pReader, pos, len);
8419233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(size >= 0);  //TODO
8420233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert((pos + len) <= stop);
8421233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8422233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len;  //consume size
8423233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8424233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (id == 0x21) //Block ID
8425233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8426233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (bpos < 0) //Block ID
8427233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
8428233d2500723e5594f3e7c70896ffeeef32b9c950ywan                bpos = pos;
8429233d2500723e5594f3e7c70896ffeeef32b9c950ywan                bsize = size;
8430233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
8431233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8432233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x1B)  //Duration ID
8433233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8434233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(size <= 8);
8435233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8436233d2500723e5594f3e7c70896ffeeef32b9c950ywan            duration = UnserializeUInt(pReader, pos, size);
8437233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(duration >= 0);  //TODO
8438233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8439233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (id == 0x7B)  //ReferenceBlock
8440233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8441233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(size <= 8);
8442233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long size_ = static_cast<long>(size);
8443233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8444233d2500723e5594f3e7c70896ffeeef32b9c950ywan            long long time;
8445233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8446233d2500723e5594f3e7c70896ffeeef32b9c950ywan            long status = UnserializeInt(pReader, pos, size_, time);
8447233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(status == 0);
8448233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status != 0)
8449233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return -1;
8450233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8451233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (time <= 0)  //see note above
8452233d2500723e5594f3e7c70896ffeeef32b9c950ywan                prev = time;
8453233d2500723e5594f3e7c70896ffeeef32b9c950ywan            else  //weird
8454233d2500723e5594f3e7c70896ffeeef32b9c950ywan                next = time;
8455233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8456233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8457233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += size;  //consume payload
8458233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos <= stop);
8459233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
8460233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8461233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos == stop);
8462233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(bpos >= 0);
8463233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(bsize >= 0);
8464233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8465233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long idx = m_entries_count;
8466233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8467233d2500723e5594f3e7c70896ffeeef32b9c950ywan    BlockEntry** const ppEntry = m_entries + idx;
8468233d2500723e5594f3e7c70896ffeeef32b9c950ywan    BlockEntry*& pEntry = *ppEntry;
8469233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8470233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pEntry = new (std::nothrow) BlockGroup(
8471233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  this,
8472233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  idx,
8473233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  bpos,
8474233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  bsize,
8475233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  prev,
8476233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  next,
8477233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  duration,
8478233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  discard_padding);
8479233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8480233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pEntry == NULL)
8481233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;  //generic error
8482233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8483233d2500723e5594f3e7c70896ffeeef32b9c950ywan    BlockGroup* const p = static_cast<BlockGroup*>(pEntry);
8484233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8485233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long status = p->Parse();
8486233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8487233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status == 0)  //success
8488233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
8489233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ++m_entries_count;
8490233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;
8491233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
8492233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8493233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete pEntry;
8494233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pEntry = 0;
8495233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8496233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return status;
8497233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
8498233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8499233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8500233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8501233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Cluster::CreateSimpleBlock(
8502233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long st,
8503233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long sz)
8504233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
8505233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_entries);
8506233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_entries_size > 0);
8507233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_entries_count >= 0);
8508233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_entries_count < m_entries_size);
8509233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8510233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long idx = m_entries_count;
8511233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8512233d2500723e5594f3e7c70896ffeeef32b9c950ywan    BlockEntry** const ppEntry = m_entries + idx;
8513233d2500723e5594f3e7c70896ffeeef32b9c950ywan    BlockEntry*& pEntry = *ppEntry;
8514233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8515233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pEntry = new (std::nothrow) SimpleBlock(this, idx, st, sz);
8516233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8517233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pEntry == NULL)
8518233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;  //generic error
8519233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8520233d2500723e5594f3e7c70896ffeeef32b9c950ywan    SimpleBlock* const p = static_cast<SimpleBlock*>(pEntry);
8521233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8522233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long status = p->Parse();
8523233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8524233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status == 0)
8525233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
8526233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ++m_entries_count;
8527233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;
8528233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
8529233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8530233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete pEntry;
8531233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pEntry = 0;
8532233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8533233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return status;
8534233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
8535233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8536233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8537233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Cluster::GetFirst(const BlockEntry*& pFirst) const
8538233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
8539233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_entries_count <= 0)
8540233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
8541233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long pos;
8542233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long len;
8543233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8544233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long status = Parse(pos, len);
8545233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8546233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)  //error
8547233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8548233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pFirst = NULL;
8549233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
8550233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8551233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8552233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (m_entries_count <= 0)  //empty cluster
8553233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8554233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pFirst = NULL;
8555233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 0;
8556233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8557233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
8558233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8559233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_entries);
8560233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8561233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pFirst = m_entries[0];
8562233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pFirst);
8563233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8564233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;  //success
8565233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
8566233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8567233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Cluster::GetLast(const BlockEntry*& pLast) const
8568233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
8569233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (;;)
8570233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
8571233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long pos;
8572233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long len;
8573233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8574233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long status = Parse(pos, len);
8575233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8576233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)  //error
8577233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8578233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pLast = NULL;
8579233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
8580233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8581233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8582233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status > 0)  //no new block
8583233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
8584233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
8585233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8586233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_entries_count <= 0)
8587233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
8588233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pLast = NULL;
8589233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;
8590233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
8591233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8592233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_entries);
8593233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8594233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long idx = m_entries_count - 1;
8595233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8596233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pLast = m_entries[idx];
8597233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pLast);
8598233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8599233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
8600233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
8601233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8602233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8603233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Cluster::GetNext(
8604233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const BlockEntry* pCurr,
8605233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const BlockEntry*& pNext) const
8606233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
8607233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCurr);
8608233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_entries);
8609233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_entries_count > 0);
8610233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8611233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size_t idx = pCurr->GetIndex();
8612233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(idx < size_t(m_entries_count));
8613233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_entries[idx] == pCurr);
8614233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8615233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ++idx;
8616233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8617233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (idx >= size_t(m_entries_count))
8618233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
8619233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long pos;
8620233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long len;
8621233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8622233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long status = Parse(pos, len);
8623233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8624233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status < 0)  //error
8625233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8626233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pNext = NULL;
8627233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return status;
8628233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8629233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8630233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (status > 0)
8631233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8632233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pNext = NULL;
8633233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return 0;
8634233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8635233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8636233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(m_entries);
8637233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(m_entries_count > 0);
8638233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(idx < size_t(m_entries_count));
8639233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
8640233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8641233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pNext = m_entries[idx];
8642233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pNext);
8643233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8644233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
8645233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
8646233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8647233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8648233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Cluster::GetEntryCount() const
8649233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
8650233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_entries_count;
8651233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
8652233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8653233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8654233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst BlockEntry* Cluster::GetEntry(
8655233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Track* pTrack,
8656233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long time_ns) const
8657233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
8658233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pTrack);
8659233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8660233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_pSegment == NULL)  //this is the special EOS cluster
8661233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return pTrack->GetEOS();
8662233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8663233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
8664233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8665233d2500723e5594f3e7c70896ffeeef32b9c950ywan    LoadBlockEntries();
8666233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8667233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((m_entries == NULL) || (m_entries_count <= 0))
8668233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return NULL;  //return EOS here?
8669233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8670233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const BlockEntry* pResult = pTrack->GetEOS();
8671233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8672233d2500723e5594f3e7c70896ffeeef32b9c950ywan    BlockEntry** i = m_entries;
8673233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(i);
8674233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8675233d2500723e5594f3e7c70896ffeeef32b9c950ywan    BlockEntry** const j = i + m_entries_count;
8676233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8677233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (i != j)
8678233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
8679233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const BlockEntry* const pEntry = *i++;
8680233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pEntry);
8681233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(!pEntry->EOS());
8682233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8683233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const Block* const pBlock = pEntry->GetBlock();
8684233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pBlock);
8685233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8686233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pBlock->GetTrackNumber() != pTrack->GetNumber())
8687233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
8688233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8689233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pTrack->VetEntry(pEntry))
8690233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8691233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (time_ns < 0)  //just want first candidate block
8692233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return pEntry;
8693233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8694233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long ns = pBlock->GetTime(this);
8695233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8696233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (ns > time_ns)
8697233d2500723e5594f3e7c70896ffeeef32b9c950ywan                break;
8698233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8699233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pResult = pEntry;
8700233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8701233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (time_ns >= 0)
8702233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8703233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long ns = pBlock->GetTime(this);
8704233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8705233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (ns > time_ns)
8706233d2500723e5594f3e7c70896ffeeef32b9c950ywan                break;
8707233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8708233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
8709233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8710233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return pResult;
8711233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8712233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
8713233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8714233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const BlockEntry* pResult = pTrack->GetEOS();
8715233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8716233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long index = 0;
8717233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8718233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (;;)
8719233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
8720233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (index >= m_entries_count)
8721233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8722233d2500723e5594f3e7c70896ffeeef32b9c950ywan            long long pos;
8723233d2500723e5594f3e7c70896ffeeef32b9c950ywan            long len;
8724233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8725233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long status = Parse(pos, len);
8726233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(status >= 0);
8727233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8728233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status > 0)  //completely parsed, and no more entries
8729233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return pResult;
8730233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8731233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status < 0)  //should never happen
8732233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return 0;
8733233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8734233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(m_entries);
8735233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(index < m_entries_count);
8736233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8737233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8738233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const BlockEntry* const pEntry = m_entries[index];
8739233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pEntry);
8740233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(!pEntry->EOS());
8741233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8742233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const Block* const pBlock = pEntry->GetBlock();
8743233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pBlock);
8744233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8745233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pBlock->GetTrackNumber() != pTrack->GetNumber())
8746233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8747233d2500723e5594f3e7c70896ffeeef32b9c950ywan            ++index;
8748233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
8749233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8750233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8751233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pTrack->VetEntry(pEntry))
8752233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8753233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (time_ns < 0)  //just want first candidate block
8754233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return pEntry;
8755233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8756233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long ns = pBlock->GetTime(this);
8757233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8758233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (ns > time_ns)
8759233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return pResult;
8760233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8761233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pResult = pEntry;  //have a candidate
8762233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8763233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else if (time_ns >= 0)
8764233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8765233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long ns = pBlock->GetTime(this);
8766233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8767233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (ns > time_ns)
8768233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return pResult;
8769233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8770233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8771233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ++index;
8772233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
8773233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8774233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
8775233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
8776233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8777233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8778233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst BlockEntry*
8779233d2500723e5594f3e7c70896ffeeef32b9c950ywanCluster::GetEntry(
8780233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const CuePoint& cp,
8781233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const CuePoint::TrackPosition& tp) const
8782233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
8783233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_pSegment);
8784233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8785233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
8786233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8787233d2500723e5594f3e7c70896ffeeef32b9c950ywan    LoadBlockEntries();
8788233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8789233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_entries == NULL)
8790233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return NULL;
8791233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8792233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long count = m_entries_count;
8793233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8794233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (count <= 0)
8795233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return NULL;
8796233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8797233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long tc = cp.GetTimeCode();
8798233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8799233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((tp.m_block > 0) && (tp.m_block <= count))
8800233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
8801233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const size_t block = static_cast<size_t>(tp.m_block);
8802233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const size_t index = block - 1;
8803233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8804233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const BlockEntry* const pEntry = m_entries[index];
8805233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pEntry);
8806233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(!pEntry->EOS());
8807233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8808233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const Block* const pBlock = pEntry->GetBlock();
8809233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pBlock);
8810233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8811233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pBlock->GetTrackNumber() == tp.m_track) &&
8812233d2500723e5594f3e7c70896ffeeef32b9c950ywan            (pBlock->GetTimeCode(this) == tc))
8813233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8814233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return pEntry;
8815233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8816233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
8817233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8818233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const BlockEntry* const* i = m_entries;
8819233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const BlockEntry* const* const j = i + count;
8820233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8821233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (i != j)
8822233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
8823233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef _DEBUG
8824233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const ptrdiff_t idx = i - m_entries;
8825233d2500723e5594f3e7c70896ffeeef32b9c950ywan        idx;
8826233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
8827233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8828233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const BlockEntry* const pEntry = *i++;
8829233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pEntry);
8830233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(!pEntry->EOS());
8831233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8832233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const Block* const pBlock = pEntry->GetBlock();
8833233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pBlock);
8834233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8835233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pBlock->GetTrackNumber() != tp.m_track)
8836233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
8837233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8838233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long tc_ = pBlock->GetTimeCode(this);
8839233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(tc_ >= 0);
8840233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8841233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (tc_ < tc)
8842233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
8843233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8844233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (tc_ > tc)
8845233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return NULL;
8846233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8847233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const Tracks* const pTracks = m_pSegment->GetTracks();
8848233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pTracks);
8849233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8850233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long tn = static_cast<long>(tp.m_track);
8851233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const Track* const pTrack = pTracks->GetTrackByNumber(tn);
8852233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8853233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pTrack == NULL)
8854233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return NULL;
8855233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8856233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long type = pTrack->GetType();
8857233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8858233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (type == 2)  //audio
8859233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return pEntry;
8860233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8861233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (type != 1)  //not video
8862233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return NULL;
8863233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8864233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (!pBlock->IsKey())
8865233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return NULL;
8866233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8867233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return pEntry;
8868233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
8869233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8870233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NULL;
8871233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8872233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
8873233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8874233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long tc = cp.GetTimeCode();
8875233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8876233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (tp.m_block > 0)
8877233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
8878233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long block = static_cast<long>(tp.m_block);
8879233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long index = block - 1;
8880233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8881233d2500723e5594f3e7c70896ffeeef32b9c950ywan        while (index >= m_entries_count)
8882233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8883233d2500723e5594f3e7c70896ffeeef32b9c950ywan            long long pos;
8884233d2500723e5594f3e7c70896ffeeef32b9c950ywan            long len;
8885233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8886233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long status = Parse(pos, len);
8887233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8888233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status < 0)  //TODO: can this happen?
8889233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return NULL;
8890233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8891233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status > 0)  //nothing remains to be parsed
8892233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return NULL;
8893233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8894233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8895233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const BlockEntry* const pEntry = m_entries[index];
8896233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pEntry);
8897233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(!pEntry->EOS());
8898233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8899233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const Block* const pBlock = pEntry->GetBlock();
8900233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pBlock);
8901233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8902233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pBlock->GetTrackNumber() == tp.m_track) &&
8903233d2500723e5594f3e7c70896ffeeef32b9c950ywan            (pBlock->GetTimeCode(this) == tc))
8904233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8905233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return pEntry;
8906233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8907233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
8908233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8909233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long index = 0;
8910233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8911233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (;;)
8912233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
8913233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (index >= m_entries_count)
8914233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8915233d2500723e5594f3e7c70896ffeeef32b9c950ywan            long long pos;
8916233d2500723e5594f3e7c70896ffeeef32b9c950ywan            long len;
8917233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8918233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long status = Parse(pos, len);
8919233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8920233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status < 0)  //TODO: can this happen?
8921233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return NULL;
8922233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8923233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (status > 0)  //nothing remains to be parsed
8924233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return NULL;
8925233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8926233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(m_entries);
8927233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(index < m_entries_count);
8928233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8929233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8930233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const BlockEntry* const pEntry = m_entries[index];
8931233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pEntry);
8932233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(!pEntry->EOS());
8933233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8934233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const Block* const pBlock = pEntry->GetBlock();
8935233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pBlock);
8936233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8937233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pBlock->GetTrackNumber() != tp.m_track)
8938233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8939233d2500723e5594f3e7c70896ffeeef32b9c950ywan            ++index;
8940233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
8941233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8942233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8943233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long tc_ = pBlock->GetTimeCode(this);
8944233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8945233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (tc_ < tc)
8946233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
8947233d2500723e5594f3e7c70896ffeeef32b9c950ywan            ++index;
8948233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
8949233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
8950233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8951233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (tc_ > tc)
8952233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return NULL;
8953233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8954233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const Tracks* const pTracks = m_pSegment->GetTracks();
8955233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pTracks);
8956233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8957233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long tn = static_cast<long>(tp.m_track);
8958233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const Track* const pTrack = pTracks->GetTrackByNumber(tn);
8959233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8960233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pTrack == NULL)
8961233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return NULL;
8962233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8963233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long type = pTrack->GetType();
8964233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8965233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (type == 2)  //audio
8966233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return pEntry;
8967233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8968233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (type != 1)  //not video
8969233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return NULL;
8970233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8971233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (!pBlock->IsKey())
8972233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return NULL;
8973233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8974233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return pEntry;
8975233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
8976233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8977233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
8978233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8979233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
8980233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8981233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8982233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
8983233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst BlockEntry* Cluster::GetMaxKey(const VideoTrack* pTrack) const
8984233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
8985233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pTrack);
8986233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8987233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_pSegment == NULL)  //EOS
8988233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return pTrack->GetEOS();
8989233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8990233d2500723e5594f3e7c70896ffeeef32b9c950ywan    LoadBlockEntries();
8991233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8992233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((m_entries == NULL) || (m_entries_count <= 0))
8993233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return pTrack->GetEOS();
8994233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8995233d2500723e5594f3e7c70896ffeeef32b9c950ywan    BlockEntry** i = m_entries + m_entries_count;
8996233d2500723e5594f3e7c70896ffeeef32b9c950ywan    BlockEntry** const j = m_entries;
8997233d2500723e5594f3e7c70896ffeeef32b9c950ywan
8998233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (i != j)
8999233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
9000233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const BlockEntry* const pEntry = *--i;
9001233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pEntry);
9002233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(!pEntry->EOS());
9003233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9004233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const Block* const pBlock = pEntry->GetBlock();
9005233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pBlock);
9006233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9007233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pBlock->GetTrackNumber() != pTrack->GetNumber())
9008233d2500723e5594f3e7c70896ffeeef32b9c950ywan            continue;
9009233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9010233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pBlock->IsKey())
9011233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return pEntry;
9012233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
9013233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9014233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return pTrack->GetEOS();  //no satisfactory block found
9015233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9016233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
9017233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9018233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9019233d2500723e5594f3e7c70896ffeeef32b9c950ywanBlockEntry::BlockEntry(Cluster* p, long idx) :
9020233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pCluster(p),
9021233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_index(idx)
9022233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9023233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9024233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9025233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9026233d2500723e5594f3e7c70896ffeeef32b9c950ywanBlockEntry::~BlockEntry()
9027233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9028233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9029233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9030233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9031233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool BlockEntry::EOS() const
9032233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9033233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return (GetKind() == kBlockEOS);
9034233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9035233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9036233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9037233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst Cluster* BlockEntry::GetCluster() const
9038233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9039233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_pCluster;
9040233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9041233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9042233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9043233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong BlockEntry::GetIndex() const
9044233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9045233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_index;
9046233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9047233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9048233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9049233d2500723e5594f3e7c70896ffeeef32b9c950ywanSimpleBlock::SimpleBlock(
9050233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster* pCluster,
9051233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long idx,
9052233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long start,
9053233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long size) :
9054233d2500723e5594f3e7c70896ffeeef32b9c950ywan    BlockEntry(pCluster, idx),
9055233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_block(start, size, 0)
9056233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9057233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9058233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9059233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9060233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong SimpleBlock::Parse()
9061233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9062233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_block.Parse(m_pCluster);
9063233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9064233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9065233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9066233d2500723e5594f3e7c70896ffeeef32b9c950ywanBlockEntry::Kind SimpleBlock::GetKind() const
9067233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9068233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return kBlockSimple;
9069233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9070233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9071233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9072233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst Block* SimpleBlock::GetBlock() const
9073233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9074233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return &m_block;
9075233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9076233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9077233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9078233d2500723e5594f3e7c70896ffeeef32b9c950ywanBlockGroup::BlockGroup(
9079233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster* pCluster,
9080233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long idx,
9081233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long block_start,
9082233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long block_size,
9083233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long prev,
9084233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long next,
9085233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long duration,
9086233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long discard_padding) :
9087233d2500723e5594f3e7c70896ffeeef32b9c950ywan    BlockEntry(pCluster, idx),
9088233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_block(block_start, block_size, discard_padding),
9089233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_prev(prev),
9090233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_next(next),
9091233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_duration(duration)
9092233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9093233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9094233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9095233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9096233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong BlockGroup::Parse()
9097233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9098233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long status = m_block.Parse(m_pCluster);
9099233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9100233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status)
9101233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return status;
9102233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9103233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_block.SetKey((m_prev > 0) && (m_next <= 0));
9104233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9105233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
9106233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9107233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9108233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9109233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if 0
9110233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid BlockGroup::ParseBlock(long long start, long long size)
9111233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9112233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* const pReader = m_pCluster->m_pSegment->m_pReader;
9113233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9114233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Block* const pBlock = new Block(start, size, pReader);
9115233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pBlock);  //TODO
9116233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9117233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //TODO: the Matroska spec says you have multiple blocks within the
9118233d2500723e5594f3e7c70896ffeeef32b9c950ywan    //same block group, with blocks ranked by priority (the flag bits).
9119233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9120233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_pBlock == NULL);
9121233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_pBlock = pBlock;
9122233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9123233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
9124233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9125233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9126233d2500723e5594f3e7c70896ffeeef32b9c950ywanBlockEntry::Kind BlockGroup::GetKind() const
9127233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9128233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return kBlockGroup;
9129233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9130233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9131233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9132233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst Block* BlockGroup::GetBlock() const
9133233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9134233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return &m_block;
9135233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9136233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9137233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9138233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long BlockGroup::GetPrevTimeCode() const
9139233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9140233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_prev;
9141233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9142233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9143233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9144233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long BlockGroup::GetNextTimeCode() const
9145233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9146233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_next;
9147233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9148233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9149233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long BlockGroup::GetDurationTimeCode() const
9150233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9151233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_duration;
9152233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9153233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9154233d2500723e5594f3e7c70896ffeeef32b9c950ywanBlock::Block(long long start, long long size_, long long discard_padding) :
9155233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_start(start),
9156233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_size(size_),
9157233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_track(0),
9158233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_timecode(-1),
9159233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_flags(0),
9160233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_frames(NULL),
9161233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_frame_count(-1),
9162233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_discard_padding(discard_padding)
9163233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9164233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9165233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9166233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9167233d2500723e5594f3e7c70896ffeeef32b9c950ywanBlock::~Block()
9168233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9169233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete[] m_frames;
9170233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9171233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9172233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9173233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Block::Parse(const Cluster* pCluster)
9174233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9175233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pCluster == NULL)
9176233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
9177233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9178233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pCluster->m_pSegment == NULL)
9179233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
9180233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9181233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_start >= 0);
9182233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_size >= 0);
9183233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_track <= 0);
9184233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_frames == NULL);
9185233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_frame_count <= 0);
9186233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9187233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long pos = m_start;
9188233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long stop = m_start + m_size;
9189233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9190233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long len;
9191233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9192233d2500723e5594f3e7c70896ffeeef32b9c950ywan    IMkvReader* const pReader = pCluster->m_pSegment->m_pReader;
9193233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9194233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_track = ReadUInt(pReader, pos, len);
9195233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9196233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (m_track <= 0)
9197233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
9198233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9199233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((pos + len) > stop)
9200233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
9201233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9202233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += len;  //consume track number
9203233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9204233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((stop - pos) < 2)
9205233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
9206233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9207233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long status;
9208233d2500723e5594f3e7c70896ffeeef32b9c950ywan    long long value;
9209233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9210233d2500723e5594f3e7c70896ffeeef32b9c950ywan    status = UnserializeInt(pReader, pos, 2, value);
9211233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9212233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status)
9213233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
9214233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9215233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (value < SHRT_MIN)
9216233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
9217233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9218233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (value > SHRT_MAX)
9219233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
9220233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9221233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_timecode = static_cast<short>(value);
9222233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9223233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos += 2;
9224233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9225233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((stop - pos) <= 0)
9226233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
9227233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9228233d2500723e5594f3e7c70896ffeeef32b9c950ywan    status = pReader->Read(pos, 1, &m_flags);
9229233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9230233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status)
9231233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
9232233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9233233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int lacing = int(m_flags & 0x06) >> 1;
9234233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9235233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ++pos;  //consume flags byte
9236233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9237233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (lacing == 0)  //no lacing
9238233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
9239233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pos > stop)
9240233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
9241233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9242233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m_frame_count = 1;
9243233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m_frames = new Frame[m_frame_count];
9244233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9245233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Frame& f = m_frames[0];
9246233d2500723e5594f3e7c70896ffeeef32b9c950ywan        f.pos = pos;
9247233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9248233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long frame_size = stop - pos;
9249233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9250233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (frame_size > LONG_MAX)
9251233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
9252233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9253233d2500723e5594f3e7c70896ffeeef32b9c950ywan        f.len = static_cast<long>(frame_size);
9254233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9255233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 0;  //success
9256233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
9257233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9258233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pos >= stop)
9259233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
9260233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9261233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned char biased_count;
9262233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9263233d2500723e5594f3e7c70896ffeeef32b9c950ywan    status = pReader->Read(pos, 1, &biased_count);
9264233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9265233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (status)
9266233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return E_FILE_FORMAT_INVALID;
9267233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9268233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ++pos;  //consume frame count
9269233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pos <= stop);
9270233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9271233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_frame_count = int(biased_count) + 1;
9272233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9273233d2500723e5594f3e7c70896ffeeef32b9c950ywan    m_frames = new Frame[m_frame_count];
9274233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(m_frames);
9275233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9276233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (lacing == 1)  //Xiph
9277233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
9278233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Frame* pf = m_frames;
9279233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Frame* const pf_end = pf + m_frame_count;
9280233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9281233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long size = 0;
9282233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int frame_count = m_frame_count;
9283233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9284233d2500723e5594f3e7c70896ffeeef32b9c950ywan        while (frame_count > 1)
9285233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
9286233d2500723e5594f3e7c70896ffeeef32b9c950ywan            long frame_size = 0;
9287233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9288233d2500723e5594f3e7c70896ffeeef32b9c950ywan            for (;;)
9289233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
9290233d2500723e5594f3e7c70896ffeeef32b9c950ywan                unsigned char val;
9291233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9292233d2500723e5594f3e7c70896ffeeef32b9c950ywan                if (pos >= stop)
9293233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    return E_FILE_FORMAT_INVALID;
9294233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9295233d2500723e5594f3e7c70896ffeeef32b9c950ywan                status = pReader->Read(pos, 1, &val);
9296233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9297233d2500723e5594f3e7c70896ffeeef32b9c950ywan                if (status)
9298233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    return E_FILE_FORMAT_INVALID;
9299233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9300233d2500723e5594f3e7c70896ffeeef32b9c950ywan                ++pos;  //consume xiph size byte
9301233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9302233d2500723e5594f3e7c70896ffeeef32b9c950ywan                frame_size += val;
9303233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9304233d2500723e5594f3e7c70896ffeeef32b9c950ywan                if (val < 255)
9305233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    break;
9306233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
9307233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9308233d2500723e5594f3e7c70896ffeeef32b9c950ywan            Frame& f = *pf++;
9309233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(pf < pf_end);
9310233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9311233d2500723e5594f3e7c70896ffeeef32b9c950ywan            f.pos = 0;  //patch later
9312233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9313233d2500723e5594f3e7c70896ffeeef32b9c950ywan            f.len = frame_size;
9314233d2500723e5594f3e7c70896ffeeef32b9c950ywan            size += frame_size;  //contribution of this frame
9315233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9316233d2500723e5594f3e7c70896ffeeef32b9c950ywan            --frame_count;
9317233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
9318233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9319233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pf < pf_end);
9320233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos <= stop);
9321233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9322233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
9323233d2500723e5594f3e7c70896ffeeef32b9c950ywan            Frame& f = *pf++;
9324233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9325233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (pf != pf_end)
9326233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
9327233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9328233d2500723e5594f3e7c70896ffeeef32b9c950ywan            f.pos = 0;  //patch later
9329233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9330233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long total_size = stop - pos;
9331233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9332233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (total_size < size)
9333233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
9334233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9335233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long frame_size = total_size - size;
9336233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9337233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (frame_size > LONG_MAX)
9338233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
9339233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9340233d2500723e5594f3e7c70896ffeeef32b9c950ywan            f.len = static_cast<long>(frame_size);
9341233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
9342233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9343233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pf = m_frames;
9344233d2500723e5594f3e7c70896ffeeef32b9c950ywan        while (pf != pf_end)
9345233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
9346233d2500723e5594f3e7c70896ffeeef32b9c950ywan            Frame& f = *pf++;
9347233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert((pos + f.len) <= stop);
9348233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9349233d2500723e5594f3e7c70896ffeeef32b9c950ywan            f.pos = pos;
9350233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pos += f.len;
9351233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
9352233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9353233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos == stop);
9354233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
9355233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (lacing == 2)  //fixed-size lacing
9356233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
9357233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long total_size = stop - pos;
9358233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9359233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((total_size % m_frame_count) != 0)
9360233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
9361233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9362233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const long long frame_size = total_size / m_frame_count;
9363233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9364233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (frame_size > LONG_MAX)
9365233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
9366233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9367233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Frame* pf = m_frames;
9368233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Frame* const pf_end = pf + m_frame_count;
9369233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9370233d2500723e5594f3e7c70896ffeeef32b9c950ywan        while (pf != pf_end)
9371233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
9372233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert((pos + frame_size) <= stop);
9373233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9374233d2500723e5594f3e7c70896ffeeef32b9c950ywan            Frame& f = *pf++;
9375233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9376233d2500723e5594f3e7c70896ffeeef32b9c950ywan            f.pos = pos;
9377233d2500723e5594f3e7c70896ffeeef32b9c950ywan            f.len = static_cast<long>(frame_size);
9378233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9379233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pos += frame_size;
9380233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
9381233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9382233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos == stop);
9383233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
9384233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else
9385233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
9386233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(lacing == 3);  //EBML lacing
9387233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9388233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (pos >= stop)
9389233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
9390233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9391233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long size = 0;
9392233d2500723e5594f3e7c70896ffeeef32b9c950ywan        int frame_count = m_frame_count;
9393233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9394233d2500723e5594f3e7c70896ffeeef32b9c950ywan        long long frame_size = ReadUInt(pReader, pos, len);
9395233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9396233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (frame_size < 0)
9397233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
9398233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9399233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (frame_size > LONG_MAX)
9400233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
9401233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9402233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + len) > stop)
9403233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
9404233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9405233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pos += len; //consume length of size of first frame
9406233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9407233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if ((pos + frame_size) > stop)
9408233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return E_FILE_FORMAT_INVALID;
9409233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9410233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Frame* pf = m_frames;
9411233d2500723e5594f3e7c70896ffeeef32b9c950ywan        Frame* const pf_end = pf + m_frame_count;
9412233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9413233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
9414233d2500723e5594f3e7c70896ffeeef32b9c950ywan            Frame& curr = *pf;
9415233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9416233d2500723e5594f3e7c70896ffeeef32b9c950ywan            curr.pos = 0;  //patch later
9417233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9418233d2500723e5594f3e7c70896ffeeef32b9c950ywan            curr.len = static_cast<long>(frame_size);
9419233d2500723e5594f3e7c70896ffeeef32b9c950ywan            size += curr.len;  //contribution of this frame
9420233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
9421233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9422233d2500723e5594f3e7c70896ffeeef32b9c950ywan        --frame_count;
9423233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9424233d2500723e5594f3e7c70896ffeeef32b9c950ywan        while (frame_count > 1)
9425233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
9426233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (pos >= stop)
9427233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
9428233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9429233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(pf < pf_end);
9430233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9431233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const Frame& prev = *pf++;
9432233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(prev.len == frame_size);
9433233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (prev.len != frame_size)
9434233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
9435233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9436233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(pf < pf_end);
9437233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9438233d2500723e5594f3e7c70896ffeeef32b9c950ywan            Frame& curr = *pf;
9439233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9440233d2500723e5594f3e7c70896ffeeef32b9c950ywan            curr.pos = 0;  //patch later
9441233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9442233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long delta_size_ = ReadUInt(pReader, pos, len);
9443233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9444233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (delta_size_ < 0)
9445233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
9446233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9447233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if ((pos + len) > stop)
9448233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
9449233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9450233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pos += len;  //consume length of (delta) size
9451233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(pos <= stop);
9452233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9453233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const int exp = 7*len - 1;
9454233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long bias = (1LL << exp) - 1LL;
9455233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long delta_size = delta_size_ - bias;
9456233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9457233d2500723e5594f3e7c70896ffeeef32b9c950ywan            frame_size += delta_size;
9458233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9459233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (frame_size < 0)
9460233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
9461233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9462233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (frame_size > LONG_MAX)
9463233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
9464233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9465233d2500723e5594f3e7c70896ffeeef32b9c950ywan            curr.len = static_cast<long>(frame_size);
9466233d2500723e5594f3e7c70896ffeeef32b9c950ywan            size += curr.len;  //contribution of this frame
9467233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9468233d2500723e5594f3e7c70896ffeeef32b9c950ywan            --frame_count;
9469233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
9470233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9471233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
9472233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(pos <= stop);
9473233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(pf < pf_end);
9474233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9475233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const Frame& prev = *pf++;
9476233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(prev.len == frame_size);
9477233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (prev.len != frame_size)
9478233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
9479233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9480233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(pf < pf_end);
9481233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9482233d2500723e5594f3e7c70896ffeeef32b9c950ywan            Frame& curr = *pf++;
9483233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert(pf == pf_end);
9484233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9485233d2500723e5594f3e7c70896ffeeef32b9c950ywan            curr.pos = 0;  //patch later
9486233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9487233d2500723e5594f3e7c70896ffeeef32b9c950ywan            const long long total_size = stop - pos;
9488233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9489233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (total_size < size)
9490233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
9491233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9492233d2500723e5594f3e7c70896ffeeef32b9c950ywan            frame_size = total_size - size;
9493233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9494233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (frame_size > LONG_MAX)
9495233d2500723e5594f3e7c70896ffeeef32b9c950ywan                return E_FILE_FORMAT_INVALID;
9496233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9497233d2500723e5594f3e7c70896ffeeef32b9c950ywan            curr.len = static_cast<long>(frame_size);
9498233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
9499233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9500233d2500723e5594f3e7c70896ffeeef32b9c950ywan        pf = m_frames;
9501233d2500723e5594f3e7c70896ffeeef32b9c950ywan        while (pf != pf_end)
9502233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
9503233d2500723e5594f3e7c70896ffeeef32b9c950ywan            Frame& f = *pf++;
9504233d2500723e5594f3e7c70896ffeeef32b9c950ywan            assert((pos + f.len) <= stop);
9505233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9506233d2500723e5594f3e7c70896ffeeef32b9c950ywan            f.pos = pos;
9507233d2500723e5594f3e7c70896ffeeef32b9c950ywan            pos += f.len;
9508233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
9509233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9510233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(pos == stop);
9511233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
9512233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9513233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;  //success
9514233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9515233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9516233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9517233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long Block::GetTimeCode(const Cluster* pCluster) const
9518233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9519233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (pCluster == 0)
9520233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return m_timecode;
9521233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9522233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long tc0 = pCluster->GetTimeCode();
9523233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(tc0 >= 0);
9524233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9525233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long tc = tc0 + m_timecode;
9526233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9527233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return tc;  //unscaled timecode units
9528233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9529233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9530233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9531233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long Block::GetTime(const Cluster* pCluster) const
9532233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9533233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pCluster);
9534233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9535233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long tc = GetTimeCode(pCluster);
9536233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9537233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Segment* const pSegment = pCluster->m_pSegment;
9538233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const SegmentInfo* const pInfo = pSegment->GetInfo();
9539233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pInfo);
9540233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9541233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long scale = pInfo->GetTimeCodeScale();
9542233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(scale >= 1);
9543233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9544233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long long ns = tc * scale;
9545233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9546233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return ns;
9547233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9548233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9549233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9550233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long Block::GetTrackNumber() const
9551233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9552233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_track;
9553233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9554233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9555233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9556233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Block::IsKey() const
9557233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9558233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return ((m_flags & static_cast<unsigned char>(1 << 7)) != 0);
9559233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9560233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9561233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9562233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Block::SetKey(bool bKey)
9563233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9564233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (bKey)
9565233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m_flags |= static_cast<unsigned char>(1 << 7);
9566233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else
9567233d2500723e5594f3e7c70896ffeeef32b9c950ywan        m_flags &= 0x7F;
9568233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9569233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9570233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9571233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Block::IsInvisible() const
9572233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9573233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return bool(int(m_flags & 0x08) != 0);
9574233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9575233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9576233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9577233d2500723e5594f3e7c70896ffeeef32b9c950ywanBlock::Lacing Block::GetLacing() const
9578233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9579233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int value = int(m_flags & 0x06) >> 1;
9580233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return static_cast<Lacing>(value);
9581233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9582233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9583233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9584233d2500723e5594f3e7c70896ffeeef32b9c950ywanint Block::GetFrameCount() const
9585233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9586233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_frame_count;
9587233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9588233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9589233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9590233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst Block::Frame& Block::GetFrame(int idx) const
9591233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9592233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(idx >= 0);
9593233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(idx < m_frame_count);
9594233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9595233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Frame& f = m_frames[idx];
9596233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(f.pos > 0);
9597233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(f.len > 0);
9598233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9599233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return f;
9600233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9601233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9602233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9603233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong Block::Frame::Read(IMkvReader* pReader, unsigned char* buf) const
9604233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9605233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(pReader);
9606233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(buf);
9607233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9608233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const long status = pReader->Read(pos, len, buf);
9609233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return status;
9610233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9611233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9612233d2500723e5594f3e7c70896ffeeef32b9c950ywanlong long Block::GetDiscardPadding() const
9613233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
9614233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return m_discard_padding;
9615233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
9616233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9617233d2500723e5594f3e7c70896ffeeef32b9c950ywan}  //end namespace mkvparser
9618