193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org//
393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// Use of this source code is governed by a BSD-style license
493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// that can be found in the LICENSE file in the root of the source
593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// tree. An additional intellectual property rights grant can be found
693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// in the file PATENTS.  All contributing project authors may
793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// be found in the AUTHORS file in the root of the source tree.
893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "mkvparser.hpp"
1093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include <cassert>
1193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include <cstring>
1293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include <new>
1393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include <climits>
1493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#ifdef _MSC_VER
1693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// Disable MSVC warnings that suggest making code non-portable.
17810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org#pragma warning(disable : 4996)
1893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
1993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
20810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgmkvparser::IMkvReader::~IMkvReader() {}
2193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
22810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgvoid mkvparser::GetVersion(int& major, int& minor, int& build, int& revision) {
23810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  major = 1;
24810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  minor = 0;
25810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  build = 0;
26810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  revision = 28;
2793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
2893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
29810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len) {
30810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pReader);
31810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos >= 0);
3293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
33810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  int status;
3493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
35810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  //#ifdef _DEBUG
36810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  //    long long total, available;
37810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  //    status = pReader->Length(&total, &available);
38810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  //    assert(status >= 0);
39810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  //    assert((total < 0) || (available <= total));
40810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  //    assert(pos < available);
41810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  //    assert((available - pos) >= 1);  //assume here max u-int len is 8
42810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  //#endif
4393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
44810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  len = 1;
4593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
46810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  unsigned char b;
4793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
48810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  status = pReader->Read(pos, 1, &b);
4993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
50810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)  // error or underflow
51810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
5293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
53810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status > 0)  // interpreted as "underflow"
54810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_BUFFER_NOT_FULL;
5593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
56810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (b == 0)  // we can't handle u-int values larger than 8 bytes
57810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
5893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
59810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  unsigned char m = 0x80;
6093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
61810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (!(b & m)) {
62810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m >>= 1;
63810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    ++len;
64810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
6593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
66810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  //#ifdef _DEBUG
67810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  //    assert((available - pos) >= len);
68810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  //#endif
6993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
70810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long result = b & (~m);
71810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  ++pos;
7293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
73810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  for (int i = 1; i < len; ++i) {
74810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    status = pReader->Read(pos, 1, &b);
7593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
76810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0) {
77810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
78810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
79810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
8093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
81810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status > 0) {
82810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
83810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
84810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
8593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
86810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result <<= 8;
87810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result |= b;
8893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
89810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    ++pos;
90810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
9193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
92810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return result;
9393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
9493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
95810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long mkvparser::GetUIntLength(IMkvReader* pReader, long long pos,
96810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                   long& len) {
97810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pReader);
98810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos >= 0);
9993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
100810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long total, available;
10193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
102810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  int status = pReader->Length(&total, &available);
103810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(status >= 0);
104810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((total < 0) || (available <= total));
10593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
106810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  len = 1;
10793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
108810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pos >= available)
109810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return pos;  // too few bytes available
11093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
111810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  unsigned char b;
11293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
113810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  status = pReader->Read(pos, 1, &b);
11493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
115810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)
116810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
11793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
118810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(status == 0);
11993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
120810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (b == 0)  // we can't handle u-int values larger than 8 bytes
121810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
12293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
123810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  unsigned char m = 0x80;
12493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
125810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (!(b & m)) {
126810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m >>= 1;
127810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    ++len;
128810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
12993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
130810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;  // success
13193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
13293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
133810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long mkvparser::UnserializeUInt(IMkvReader* pReader, long long pos,
134810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                     long long size) {
135810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pReader);
136810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos >= 0);
13793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
138810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((size <= 0) || (size > 8))
139810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
14093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
141810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long result = 0;
14293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
143810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  for (long long i = 0; i < size; ++i) {
144810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    unsigned char b;
14593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
146810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long status = pReader->Read(pos, 1, &b);
14793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
148810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)
149810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
15093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
151810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result <<= 8;
152810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result |= b;
15393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
154810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    ++pos;
155810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
15693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
157810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return result;
15893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
15993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
160810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong mkvparser::UnserializeFloat(IMkvReader* pReader, long long pos,
161810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                 long long size_, double& result) {
162810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pReader);
163810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos >= 0);
16493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
165810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((size_ != 4) && (size_ != 8))
166810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
16793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
168810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long size = static_cast<long>(size_);
16993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
170810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  unsigned char buf[8];
17193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
172810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const int status = pReader->Read(pos, size, buf);
17393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
174810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)  // error
175810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
17693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
177810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (size == 4) {
178810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    union {
179810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      float f;
180810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      unsigned long ff;
181810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    };
18293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
183810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    ff = 0;
18493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
185810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    for (int i = 0;;) {
186810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      ff |= buf[i];
18793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
188810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (++i >= 4)
189810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        break;
19093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
191810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      ff <<= 8;
19293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
19393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
194810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result = f;
195810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  } else {
196810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(size == 8);
19793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
198810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    union {
199810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      double d;
200810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      unsigned long long dd;
201810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    };
20293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
203810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    dd = 0;
20493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
205810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    for (int i = 0;;) {
206810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      dd |= buf[i];
20793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
208810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (++i >= 8)
209810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        break;
21093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
211810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      dd <<= 8;
21293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
21393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
214810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result = d;
215810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
21693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
217810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;
218810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org}
21993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
220810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong mkvparser::UnserializeInt(IMkvReader* pReader, long long pos, long size,
221810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                               long long& result) {
222810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pReader);
223810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos >= 0);
224810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(size > 0);
225810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(size <= 8);
22693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
227810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  {
228810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    signed char b;
22993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
230810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long status = pReader->Read(pos, 1, (unsigned char*)&b);
23193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
232810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)
233810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
23493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
235810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result = b;
23693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
237810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    ++pos;
238810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
23993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
240810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  for (long i = 1; i < size; ++i) {
241810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    unsigned char b;
24293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
243810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long status = pReader->Read(pos, 1, &b);
24493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
245810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)
246810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
24793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
248810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result <<= 8;
249810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result |= b;
25093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
251810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    ++pos;
252810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
25393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
254810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;  // success
25593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
25693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
257810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong mkvparser::UnserializeString(IMkvReader* pReader, long long pos,
258810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                  long long size_, char*& str) {
259810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] str;
260810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  str = NULL;
26193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
262810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (size_ >= LONG_MAX)  // we need (size+1) chars
263810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
26493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
265810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long size = static_cast<long>(size_);
26693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
267810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  str = new (std::nothrow) char[size + 1];
26893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
269810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (str == NULL)
270810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
27193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
272810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  unsigned char* const buf = reinterpret_cast<unsigned char*>(str);
27393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
274810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long status = pReader->Read(pos, size, buf);
27593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
276810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status) {
277810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    delete[] str;
278810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    str = NULL;
27993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
280810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
281810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
28293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
283810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  str[size] = '\0';
28493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
285810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;  // success
28693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
28793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
288810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong mkvparser::ParseElementHeader(IMkvReader* pReader, long long& pos,
289810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                   long long stop, long long& id,
290810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                   long long& size) {
291810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((stop >= 0) && (pos >= stop))
292810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
29393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
294810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long len;
29593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
296810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  id = ReadUInt(pReader, pos, len);
29793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
298810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (id < 0)
299810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
30093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
301810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos += len;  // consume id
30293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
303810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((stop >= 0) && (pos >= stop))
304810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
30593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
306810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  size = ReadUInt(pReader, pos, len);
30793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
308810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (size < 0)
309810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
31093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
311810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos += len;  // consume length of size
31293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
313810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // pos now designates payload
31493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
315810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((stop >= 0) && ((pos + size) > stop))
316810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
31793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
318810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;  // success
31993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
32093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
321810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgbool mkvparser::Match(IMkvReader* pReader, long long& pos, unsigned long id_,
322810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                      long long& val) {
323810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pReader);
324810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos >= 0);
32593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
326810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long total, available;
32793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
328810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long status = pReader->Length(&total, &available);
329810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(status >= 0);
330810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((total < 0) || (available <= total));
331810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)
332810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
33393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
334810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long len;
33593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
336810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long id = ReadUInt(pReader, pos, len);
337810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(id >= 0);
338810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(len > 0);
339810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(len <= 8);
340810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((pos + len) <= available);
34193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
342810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((unsigned long)id != id_)
343810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
34493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
345810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos += len;  // consume id
34693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
347810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long size = ReadUInt(pReader, pos, len);
348810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(size >= 0);
349810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(size <= 8);
350810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(len > 0);
351810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(len <= 8);
352810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((pos + len) <= available);
35393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
354810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos += len;  // consume length of size of payload
35593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
356810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  val = UnserializeUInt(pReader, pos, size);
357810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(val >= 0);
35893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
359810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos += size;  // consume size of payload
36093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
361810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return true;
36293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
36393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
364810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgbool mkvparser::Match(IMkvReader* pReader, long long& pos, unsigned long id_,
365810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                      unsigned char*& buf, size_t& buflen) {
366810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pReader);
367810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos >= 0);
36893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
369810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long total, available;
37093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
371810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long status = pReader->Length(&total, &available);
372810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(status >= 0);
373810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((total < 0) || (available <= total));
374810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)
375810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
37693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
377810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long len;
378810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long id = ReadUInt(pReader, pos, len);
379810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(id >= 0);
380810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(len > 0);
381810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(len <= 8);
382810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((pos + len) <= available);
38393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
384810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((unsigned long)id != id_)
385810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
38693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
387810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos += len;  // consume id
38893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
389810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long size_ = ReadUInt(pReader, pos, len);
390810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(size_ >= 0);
391810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(len > 0);
392810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(len <= 8);
393810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((pos + len) <= available);
39493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
395810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos += len;  // consume length of size of payload
396810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((pos + size_) <= available);
39793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
398810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long buflen_ = static_cast<long>(size_);
39993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
400810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  buf = new (std::nothrow) unsigned char[buflen_];
401810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(buf);  // TODO
40293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
403810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  status = pReader->Read(pos, buflen_, buf);
404810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(status == 0);  // TODO
40593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
406810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  buflen = buflen_;
40793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
408810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos += size_;  // consume size of payload
409810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return true;
41093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
41193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
412810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgnamespace mkvparser {
41393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
414810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgEBMLHeader::EBMLHeader() : m_docType(NULL) { Init(); }
41593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
416810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgEBMLHeader::~EBMLHeader() { delete[] m_docType; }
41793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
418810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgvoid EBMLHeader::Init() {
419810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_version = 1;
420810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_readVersion = 1;
421810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_maxIdLength = 4;
422810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_maxSizeLength = 8;
42393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
424810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_docType) {
425810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    delete[] m_docType;
426810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m_docType = NULL;
427810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
42893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
429810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_docTypeVersion = 1;
430810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_docTypeReadVersion = 1;
43193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
43293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
433810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long EBMLHeader::Parse(IMkvReader* pReader, long long& pos) {
434810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pReader);
43593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
436810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long total, available;
43793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
438810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long status = pReader->Length(&total, &available);
43993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
440810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)  // error
441810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
44293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
443810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos = 0;
444810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long end = (available >= 1024) ? 1024 : available;
44593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
446810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  for (;;) {
447810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    unsigned char b = 0;
44893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
449810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    while (pos < end) {
450810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      status = pReader->Read(pos, 1, &b);
45193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
452810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status < 0)  // error
453810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
45493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
455810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (b == 0x1A)
456810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        break;
45793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
458810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      ++pos;
459810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
46093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
461810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (b != 0x1A) {
462810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (pos >= 1024)
463810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;  // don't bother looking anymore
46493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
465810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if ((total >= 0) && ((total - available) < 5))
466810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
46793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
468810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return available + 5;  // 5 = 4-byte ID + 1st byte of size
469810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
47093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
471810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((total >= 0) && ((total - pos) < 5))
472810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
47393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
474810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((available - pos) < 5)
475810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return pos + 5;  // try again later
47693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
477810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long len;
47893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
479810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long result = ReadUInt(pReader, pos, len);
48093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
481810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error
482810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return result;
48393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
484810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result == 0x0A45DFA3) {  // EBML Header ID
485810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pos += len;  // consume ID
486810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      break;
48793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
48893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
489810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    ++pos;  // throw away just the 0x1A byte, and try again
490810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
49193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
492810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // pos designates start of size field
49393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
494810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // get length of size field
49593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
496810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long len;
497810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long result = GetUIntLength(pReader, pos, len);
49893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
499810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (result < 0)  // error
500810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return result;
50193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
502810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (result > 0)  // need more data
503810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return result;
50493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
505810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(len > 0);
506810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(len <= 8);
50793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
508810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((total >= 0) && ((total - pos) < len))
509810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
51093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
511810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((available - pos) < len)
512810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return pos + len;  // try again later
51393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
514810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // get the EBML header size
51593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
516810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  result = ReadUInt(pReader, pos, len);
51793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
518810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (result < 0)  // error
519810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return result;
52093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
521810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos += len;  // consume size field
52293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
523810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // pos now designates start of payload
52493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
525810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((total >= 0) && ((total - pos) < result))
526810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
52793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
528810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((available - pos) < result)
529810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return pos + result;
53093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
531810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  end = pos + result;
53293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
533810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Init();
53493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
535810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (pos < end) {
536810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long id, size;
53793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
538810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    status = ParseElementHeader(pReader, pos, end, id, size);
53993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
540810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
541810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
54293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
543810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size == 0)  // weird
544810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
54593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
546810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x0286) {  // version
547810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_version = UnserializeUInt(pReader, pos, size);
54893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
549810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (m_version <= 0)
550810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
551810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x02F7) {  // read version
552810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_readVersion = UnserializeUInt(pReader, pos, size);
55393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
554810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (m_readVersion <= 0)
555810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
556810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x02F2) {  // max id length
557810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_maxIdLength = UnserializeUInt(pReader, pos, size);
55893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
559810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (m_maxIdLength <= 0)
560810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
561810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x02F3) {  // max size length
562810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_maxSizeLength = UnserializeUInt(pReader, pos, size);
56393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
564810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (m_maxSizeLength <= 0)
565810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
566810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x0282) {  // doctype
567810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (m_docType)
568810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
56993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
570810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      status = UnserializeString(pReader, pos, size, m_docType);
57193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
572810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status)  // error
573810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
574810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x0287) {  // doctype version
575810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_docTypeVersion = UnserializeUInt(pReader, pos, size);
57693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
577810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (m_docTypeVersion <= 0)
578810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
579810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x0285) {  // doctype read version
580810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_docTypeReadVersion = UnserializeUInt(pReader, pos, size);
58193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
582810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (m_docTypeReadVersion <= 0)
583810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
58493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
58593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
586810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;
587810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
588810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
589810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos == end);
590810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;
59193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
59293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
593810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgSegment::Segment(IMkvReader* pReader, long long elem_start,
594810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                 // long long elem_size,
595810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                 long long start, long long size)
596810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    : m_pReader(pReader),
597810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_element_start(elem_start),
598810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      // m_element_size(elem_size),
599810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_start(start),
600810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_size(size),
601810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pos(start),
602810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pUnknownSize(0),
603810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pSeekHead(NULL),
604810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pInfo(NULL),
605810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pTracks(NULL),
606810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pCues(NULL),
607810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pChapters(NULL),
608810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_clusters(NULL),
609810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_clusterCount(0),
610810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_clusterPreloadCount(0),
611810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_clusterSize(0) {}
612810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
613810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgSegment::~Segment() {
614810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long count = m_clusterCount + m_clusterPreloadCount;
615810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
616810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** i = m_clusters;
617810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** j = m_clusters + count;
618810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
619810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (i != j) {
620810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster* const p = *i++;
621810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(p);
622810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
623810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    delete p;
624810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
62593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
626810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] m_clusters;
627810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
628810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete m_pTracks;
629810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete m_pInfo;
630810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete m_pCues;
631810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete m_pChapters;
632810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete m_pSeekHead;
63393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
63493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
635810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long Segment::CreateInstance(IMkvReader* pReader, long long pos,
636810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                  Segment*& pSegment) {
637810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pReader);
638810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos >= 0);
63993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
640810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pSegment = NULL;
64193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
642810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long total, available;
64393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
644810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long status = pReader->Length(&total, &available);
64593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
646810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)  // error
647810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
64893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
649810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (available < 0)
650810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
65193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
652810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((total >= 0) && (available > total))
653810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
65493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
655810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // I would assume that in practice this loop would execute
656810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // exactly once, but we allow for other elements (e.g. Void)
657810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // to immediately follow the EBML header.  This is fine for
658810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // the source filter case (since the entire file is available),
659810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // but in the splitter case over a network we should probably
660810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // just give up early.  We could for example decide only to
661810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // execute this loop a maximum of, say, 10 times.
662810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // TODO:
663810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // There is an implied "give up early" by only parsing up
664810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // to the available limit.  We do do that, but only if the
665810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // total file size is unknown.  We could decide to always
666810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // use what's available as our limit (irrespective of whether
667810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // we happen to know the total file length).  This would have
668810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // as its sense "parse this much of the file before giving up",
669810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // which a slightly different sense from "try to parse up to
670810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // 10 EMBL elements before giving up".
671810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
672810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  for (;;) {
673810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((total >= 0) && (pos >= total))
674810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
67593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
676810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // Read ID
677810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long len;
678810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long result = GetUIntLength(pReader, pos, len);
67993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
680810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result)  // error, or too few available bytes
681810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return result;
68293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
683810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((total >= 0) && ((pos + len) > total))
684810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
68593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
686810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > available)
687810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return pos + len;
68893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
689810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long idpos = pos;
690810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long id = ReadUInt(pReader, pos, len);
69193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
692810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id < 0)  // error
693810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return id;
69493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
695810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume ID
69693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
697810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // Read Size
69893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
699810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result = GetUIntLength(pReader, pos, len);
70093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
701810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result)  // error, or too few available bytes
702810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return result;
70393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
704810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((total >= 0) && ((pos + len) > total))
705810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
70693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
707810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > available)
708810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return pos + len;
70993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
710810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long size = ReadUInt(pReader, pos, len);
71193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
712810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size < 0)  // error
713810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return size;
71493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
715810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume length of size of element
71693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
717810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // Pos now points to start of payload
71893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
719810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // Handle "unknown size" for live streaming of webm files.
720810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long unknown_size = (1LL << (7 * len)) - 1;
72193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
722810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x08538067) {  // Segment ID
723810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (size == unknown_size)
724810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        size = -1;
72593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
726810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      else if (total < 0)
727810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        size = -1;
72893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
729810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      else if ((pos + size) > total)
730810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        size = -1;
73193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
732810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pSegment = new (std::nothrow) Segment(pReader, idpos,
733810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                            // elem_size
734810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                            pos, size);
73593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
736810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (pSegment == 0)
737810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return -1;  // generic error
73893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
739810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 0;  // success
740810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
74193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
742810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size == unknown_size)
743810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
74493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
745810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((total >= 0) && ((pos + size) > total))
746810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
74793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
748810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + size) > available)
749810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return pos + size;
75093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
751810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
752810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
75393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
75493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
755810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long Segment::ParseHeaders() {
756810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // Outermost (level 0) segment object has been constructed,
757810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // and pos designates start of payload.  We need to find the
758810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // inner (level 1) elements.
759810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long total, available;
76093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
761810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const int status = m_pReader->Length(&total, &available);
76293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
763810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)  // error
764810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
76593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
766810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((total < 0) || (available <= total));
76793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
768810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
769810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((segment_stop < 0) || (total < 0) || (segment_stop <= total));
770810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((segment_stop < 0) || (m_pos <= segment_stop));
77193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
772810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  for (;;) {
773810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((total >= 0) && (m_pos >= total))
774810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      break;
77593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
776810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((segment_stop >= 0) && (m_pos >= segment_stop))
777810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      break;
77893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
779810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long pos = m_pos;
780810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long element_start = pos;
78193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
782810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > available)
783810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return (pos + 1);
78493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
785810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long len;
786810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long result = GetUIntLength(m_pReader, pos, len);
78793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
788810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error
789810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return result;
79093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
791810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result > 0)  // underflow (weird)
792810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return (pos + 1);
79393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
794810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((segment_stop >= 0) && ((pos + len) > segment_stop))
795810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
79693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
797810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > available)
798810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return pos + len;
79993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
800810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long idpos = pos;
801810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long id = ReadUInt(m_pReader, idpos, len);
80293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
803810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id < 0)  // error
804810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return id;
80593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
806810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x0F43B675)  // Cluster ID
807810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      break;
80893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
809810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume ID
81093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
811810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > available)
812810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return (pos + 1);
81393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
814810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // Read Size
815810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result = GetUIntLength(m_pReader, pos, len);
81693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
817810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error
818810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return result;
81993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
820810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result > 0)  // underflow (weird)
821810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return (pos + 1);
82293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
823810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((segment_stop >= 0) && ((pos + len) > segment_stop))
824810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
82593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
826810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > available)
827810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return pos + len;
82893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
829810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long size = ReadUInt(m_pReader, pos, len);
83093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
831810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size < 0)  // error
832810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return size;
83393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
834810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume length of size of element
83593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
836810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long element_size = size + pos - element_start;
83793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
838810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // Pos now points to start of payload
83993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
840810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((segment_stop >= 0) && ((pos + size) > segment_stop))
841810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
84293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
843810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // We read EBML elements either in total or nothing at all.
84493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
845810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + size) > available)
846810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return pos + size;
84793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
848810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x0549A966) {  // Segment Info ID
849810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (m_pInfo)
850810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
85193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
852810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pInfo = new (std::nothrow)
853810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          SegmentInfo(this, pos, size, element_start, element_size);
85493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
855810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (m_pInfo == NULL)
856810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return -1;
85793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
858810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long status = m_pInfo->Parse();
85993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
860810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status)
861810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
862810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x0654AE6B) {  // Tracks ID
863810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (m_pTracks)
864810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
86593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
866810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pTracks = new (std::nothrow)
867810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          Tracks(this, pos, size, element_start, element_size);
86893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
869810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (m_pTracks == NULL)
870810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return -1;
87193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
872810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long status = m_pTracks->Parse();
87393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
874810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status)
875810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
876810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x0C53BB6B) {  // Cues ID
877810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (m_pCues == NULL) {
878810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        m_pCues = new (std::nothrow)
879810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org            Cues(this, pos, size, element_start, element_size);
88093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
881810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        if (m_pCues == NULL)
882810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          return -1;
883810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      }
884810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x014D9B74) {  // SeekHead ID
885810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (m_pSeekHead == NULL) {
886810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        m_pSeekHead = new (std::nothrow)
887810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org            SeekHead(this, pos, size, element_start, element_size);
88893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
889810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        if (m_pSeekHead == NULL)
890810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          return -1;
89193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
892810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        const long status = m_pSeekHead->Parse();
89393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
894810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        if (status)
895810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          return status;
896810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      }
897810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x0043A770) {  // Chapters ID
898810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (m_pChapters == NULL) {
899810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        m_pChapters = new (std::nothrow)
900810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org            Chapters(this, pos, size, element_start, element_size);
90193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
902810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        if (m_pChapters == NULL)
903810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          return -1;
90493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
905810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        const long status = m_pChapters->Parse();
90693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
907810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        if (status)
908810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          return status;
909810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      }
91093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
91193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
912810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m_pos = pos + size;  // consume payload
913810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
91493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
915810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((segment_stop < 0) || (m_pos <= segment_stop));
91693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
917810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_pInfo == NULL)  // TODO: liberalize this behavior
918810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
91993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
920810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_pTracks == NULL)
921810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
92293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
923810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;  // success
924810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org}
92593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
926810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Segment::LoadCluster(long long& pos, long& len) {
927810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  for (;;) {
928810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long result = DoLoadCluster(pos, len);
92993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
930810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result <= 1)
931810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return result;
932810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
93393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
93493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
935810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Segment::DoLoadCluster(long long& pos, long& len) {
936810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_pos < 0)
937810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return DoLoadClusterUnknownSize(pos, len);
93893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
939810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long total, avail;
94093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
941810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long status = m_pReader->Length(&total, &avail);
94293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
943810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)  // error
944810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
94593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
946810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((total < 0) || (avail <= total));
94793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
948810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
94993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
950810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long cluster_off = -1;  // offset relative to start of segment
951810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long cluster_size = -1;  // size of cluster payload
95293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
953810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  for (;;) {
954810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((total >= 0) && (m_pos >= total))
955810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 1;  // no more clusters
95693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
957810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((segment_stop >= 0) && (m_pos >= segment_stop))
958810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 1;  // no more clusters
95993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
960810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos = m_pos;
96193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
962810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // Read ID
96393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
964810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > avail) {
965810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
966810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
967810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
96893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
969810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long result = GetUIntLength(m_pReader, pos, len);
97093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
971810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error
972810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(result);
97393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
974810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result > 0)  // weird
975810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
97693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
977810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((segment_stop >= 0) && ((pos + len) > segment_stop))
978810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
97993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
980810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > avail)
981810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
98293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
983810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long idpos = pos;
984810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long id = ReadUInt(m_pReader, idpos, len);
98593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
986810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id < 0)  // error (or underflow)
987810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(id);
98893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
989810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume ID
99093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
991810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // Read Size
99293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
993810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > avail) {
994810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
995810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
996810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
99793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
998810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result = GetUIntLength(m_pReader, pos, len);
99993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1000810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error
1001810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(result);
100293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1003810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result > 0)  // weird
1004810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
100593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1006810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((segment_stop >= 0) && ((pos + len) > segment_stop))
1007810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
100893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1009810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > avail)
1010810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
101193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1012810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long size = ReadUInt(m_pReader, pos, len);
101393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1014810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size < 0)  // error
1015810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(size);
101693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1017810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume length of size of element
101893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1019810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // pos now points to start of payload
102093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1021810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size == 0) {  // weird
1022810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pos = pos;
1023810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
1024810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
102593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1026810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long unknown_size = (1LL << (7 * len)) - 1;
102793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1028810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org#if 0  // we must handle this to support live webm
102993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (size == unknown_size)
103093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return E_FILE_FORMAT_INVALID;  //TODO: allow this
103193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
103293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1033810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((segment_stop >= 0) && (size != unknown_size) &&
1034810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        ((pos + size) > segment_stop)) {
1035810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
1036810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
103793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1038810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org#if 0  // commented-out, to support incremental cluster parsing
103993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        len = static_cast<long>(size);
104093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
104193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if ((pos + size) > avail)
104293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return E_BUFFER_NOT_FULL;
104393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
104493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1045810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x0C53BB6B) {  // Cues ID
1046810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (size == unknown_size)
1047810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;  // TODO: liberalize
104893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1049810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (m_pCues == NULL) {
1050810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        const long long element_size = (pos - idpos) + size;
105193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1052810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        m_pCues = new Cues(this, pos, size, idpos, element_size);
1053810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        assert(m_pCues);  // TODO
1054810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      }
105593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1056810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pos = pos + size;  // consume payload
1057810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
1058810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
105993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1060810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id != 0x0F43B675) {  // Cluster ID
1061810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (size == unknown_size)
1062810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;  // TODO: liberalize
106393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1064810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pos = pos + size;  // consume payload
1065810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
106693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
106793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1068810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // We have a cluster.
106993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1070810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    cluster_off = idpos - m_start;  // relative pos
107193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1072810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size != unknown_size)
1073810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      cluster_size = size;
107493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1075810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    break;
1076810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
107793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1078810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(cluster_off >= 0);  // have cluster
107993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1080810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long pos_;
1081810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long len_;
108293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1083810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  status = Cluster::HasBlockEntries(this, cluster_off, pos_, len_);
108493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1085810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0) {  // error, or underflow
1086810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos = pos_;
1087810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    len = len_;
108893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1089810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
1090810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
109193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1092810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // status == 0 means "no block entries found"
1093810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // status > 0 means "found at least one block entry"
1094810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
1095810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // TODO:
1096810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // The issue here is that the segment increments its own
1097810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // pos ptr past the most recent cluster parsed, and then
1098810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // starts from there to parse the next cluster.  If we
1099810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // don't know the size of the current cluster, then we
1100810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // must either parse its payload (as we do below), looking
1101810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // for the cluster (or cues) ID to terminate the parse.
1102810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // This isn't really what we want: rather, we really need
1103810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // a way to create the curr cluster object immediately.
1104810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // The pity is that cluster::parse can determine its own
1105810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // boundary, and we largely duplicate that same logic here.
1106810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  //
1107810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // Maybe we need to get rid of our look-ahead preloading
1108810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // in source::parse???
1109810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  //
1110810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // As we're parsing the blocks in the curr cluster
1111810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  //(in cluster::parse), we should have some way to signal
1112810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // to the segment that we have determined the boundary,
1113810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // so it can adjust its own segment::m_pos member.
1114810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  //
1115810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // The problem is that we're asserting in asyncreadinit,
1116810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // because we adjust the pos down to the curr seek pos,
1117810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // and the resulting adjusted len is > 2GB.  I'm suspicious
1118810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // that this is even correct, but even if it is, we can't
1119810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // be loading that much data in the cache anyway.
1120810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
1121810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long idx = m_clusterCount;
1122810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
1123810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_clusterPreloadCount > 0) {
1124810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(idx < m_clusterSize);
112593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1126810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster* const pCluster = m_clusters[idx];
1127810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pCluster);
1128810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pCluster->m_index < 0);
112993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1130810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long off = pCluster->GetPosition();
1131810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(off >= 0);
113293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1133810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (off == cluster_off) {  // preloaded already
1134810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status == 0)  // no entries found
1135810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
113693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1137810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (cluster_size >= 0)
1138810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        pos += cluster_size;
1139810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      else {
1140810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        const long long element_size = pCluster->GetElementSize();
114193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1142810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        if (element_size <= 0)
1143810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          return E_FILE_FORMAT_INVALID;  // TODO: handle this case
114493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1145810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        pos = pCluster->m_element_start + element_size;
1146810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      }
114793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1148810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pCluster->m_index = idx;  // move from preloaded to loaded
1149810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      ++m_clusterCount;
1150810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      --m_clusterPreloadCount;
115193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1152810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pos = pos;  // consume payload
1153810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert((segment_stop < 0) || (m_pos <= segment_stop));
115493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1155810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 0;  // success
1156810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
1157810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
115893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1159810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status == 0) {  // no entries found
1160810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (cluster_size < 0)
1161810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;  // TODO: handle this
116293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1163810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += cluster_size;
116493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1165810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((total >= 0) && (pos >= total)) {
1166810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pos = total;
1167810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 1;  // no more clusters
116893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
116993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1170810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((segment_stop >= 0) && (pos >= segment_stop)) {
1171810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pos = segment_stop;
1172810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 1;  // no more clusters
1173810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
117493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1175810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m_pos = pos;
1176810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 2;  // try again
1177810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
117893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1179810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // status > 0 means we have an entry
118093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1181810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster* const pCluster = Cluster::Create(this, idx, cluster_off);
1182810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // element_size);
1183810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster);
118493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1185810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  AppendCluster(pCluster);
1186810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_clusters);
1187810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(idx < m_clusterSize);
1188810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_clusters[idx] == pCluster);
118993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1190810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (cluster_size >= 0) {
1191810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += cluster_size;
1192810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
1193810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m_pos = pos;
1194810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((segment_stop < 0) || (m_pos <= segment_stop));
119593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1196810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;
1197810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
119893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1199810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_pUnknownSize = pCluster;
1200810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_pos = -pos;
120193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1202810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;  // partial success, since we have a new cluster
120393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1204810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org// status == 0 means "no block entries found"
1205810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
1206810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org// pos designates start of payload
1207810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org// m_pos has NOT been adjusted yet (in case we need to come back here)
120893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
120993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
121093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1211810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (cluster_size < 0) {  //unknown size
121293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const long long payload_pos = pos;  //absolute pos of cluster payload
121393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1214810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        for (;;) {  //determine cluster size
121593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if ((total >= 0) && (pos >= total))
121693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                break;
121793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
121893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if ((segment_stop >= 0) && (pos >= segment_stop))
121993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                break;  //no more clusters
122093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
122193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            //Read ID
122293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
122393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if ((pos + 1) > avail)
122493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            {
122593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                len = 1;
122693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                return E_BUFFER_NOT_FULL;
122793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            }
122893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
122993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            long long result = GetUIntLength(m_pReader, pos, len);
123093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
123193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if (result < 0)  //error
123293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                return static_cast<long>(result);
123393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
123493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if (result > 0)  //weird
123593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                return E_BUFFER_NOT_FULL;
123693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
123793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if ((segment_stop >= 0) && ((pos + len) > segment_stop))
123893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                return E_FILE_FORMAT_INVALID;
123993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
124093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if ((pos + len) > avail)
124193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                return E_BUFFER_NOT_FULL;
124293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
124393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            const long long idpos = pos;
124493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            const long long id = ReadUInt(m_pReader, idpos, len);
124593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
124693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if (id < 0)  //error (or underflow)
124793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                return static_cast<long>(id);
124893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
124993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            //This is the distinguished set of ID's we use to determine
125093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            //that we have exhausted the sub-element's inside the cluster
125193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            //whose ID we parsed earlier.
125293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
125393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if (id == 0x0F43B675)  //Cluster ID
125493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                break;
125593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
125693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if (id == 0x0C53BB6B)  //Cues ID
125793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                break;
125893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
125993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            switch (id)
126093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            {
126193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                case 0x20:  //BlockGroup
126293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                case 0x23:  //Simple Block
126393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                case 0x67:  //TimeCode
126493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                case 0x2B:  //PrevSize
126593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                    break;
126693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
126793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                default:
126893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                    assert(false);
126993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                    break;
127093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            }
127193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
127293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            pos += len;  //consume ID (of sub-element)
127393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
127493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            //Read Size
127593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
127693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if ((pos + 1) > avail)
127793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            {
127893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                len = 1;
127993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                return E_BUFFER_NOT_FULL;
128093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            }
128193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
128293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            result = GetUIntLength(m_pReader, pos, len);
128393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
128493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if (result < 0)  //error
128593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                return static_cast<long>(result);
128693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
128793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if (result > 0)  //weird
128893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                return E_BUFFER_NOT_FULL;
128993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
129093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if ((segment_stop >= 0) && ((pos + len) > segment_stop))
129193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                return E_FILE_FORMAT_INVALID;
129293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
129393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if ((pos + len) > avail)
129493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                return E_BUFFER_NOT_FULL;
129593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
129693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            const long long size = ReadUInt(m_pReader, pos, len);
129793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
129893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if (size < 0)  //error
129993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                return static_cast<long>(size);
130093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
130193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            pos += len;  //consume size field of element
130293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
130393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            //pos now points to start of sub-element's payload
130493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
130593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if (size == 0)  //weird
130693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                continue;
130793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
130893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            const long long unknown_size = (1LL << (7 * len)) - 1;
130993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
131093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if (size == unknown_size)
131193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                return E_FILE_FORMAT_INVALID;  //not allowed for sub-elements
131293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
131393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if ((segment_stop >= 0) && ((pos + size) > segment_stop))  //weird
131493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                return E_FILE_FORMAT_INVALID;
131593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
131693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            pos += size;  //consume payload of sub-element
131793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            assert((segment_stop < 0) || (pos <= segment_stop));
131893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        }  //determine cluster size
131993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
132093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        cluster_size = pos - payload_pos;
132193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(cluster_size >= 0);
132293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
132393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        pos = payload_pos;  //reset and re-parse original cluster
132493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
132593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
132693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (m_clusterPreloadCount > 0)
132793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    {
132893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(idx < m_clusterSize);
132993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
133093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        Cluster* const pCluster = m_clusters[idx];
133193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(pCluster);
133293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(pCluster->m_index < 0);
133393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
133493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const long long off = pCluster->GetPosition();
133593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(off >= 0);
133693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
133793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (off == cluster_off)  //preloaded already
133893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return E_FILE_FORMAT_INVALID;  //subtle
133993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
134093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
134193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    m_pos = pos + cluster_size;  //consume payload
134293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert((segment_stop < 0) || (m_pos <= segment_stop));
134393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
134493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    return 2;     //try to find another cluster
134593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
134693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
134793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
134893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1349810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Segment::DoLoadClusterUnknownSize(long long& pos, long& len) {
1350810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_pos < 0);
1351810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_pUnknownSize);
135293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
135393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
135493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(m_pUnknownSize->GetElementSize() < 0);  //TODO: verify this
135593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
135693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long element_start = m_pUnknownSize->m_element_start;
135793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
135893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    pos = -m_pos;
135993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pos > element_start);
136093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
136193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //We have already consumed the (cluster) ID and size fields.
136293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //We just need to consume the blocks and other sub-elements
136393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //of this cluster, until we discover the boundary.
136493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
136593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    long long total, avail;
136693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
136793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    long status = m_pReader->Length(&total, &avail);
136893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
136993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (status < 0)  //error
137093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return status;
137193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
137293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert((total < 0) || (avail <= total));
137393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
137493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
137593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
137693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    long long element_size = -1;
137793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1378810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    for (;;) {  //determine cluster size
137993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if ((total >= 0) && (pos >= total))
138093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        {
138193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            element_size = total - element_start;
138293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            assert(element_size > 0);
138393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
138493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            break;
138593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        }
138693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
138793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if ((segment_stop >= 0) && (pos >= segment_stop))
138893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        {
138993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            element_size = segment_stop - element_start;
139093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            assert(element_size > 0);
139193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
139293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            break;
139393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        }
139493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
139593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //Read ID
139693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
139793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if ((pos + 1) > avail)
139893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        {
139993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            len = 1;
140093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return E_BUFFER_NOT_FULL;
140193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        }
140293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
140393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        long long result = GetUIntLength(m_pReader, pos, len);
140493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
140593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (result < 0)  //error
140693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return static_cast<long>(result);
140793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
140893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (result > 0)  //weird
140993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return E_BUFFER_NOT_FULL;
141093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
141193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if ((segment_stop >= 0) && ((pos + len) > segment_stop))
141293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return E_FILE_FORMAT_INVALID;
141393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
141493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if ((pos + len) > avail)
141593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return E_BUFFER_NOT_FULL;
141693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
141793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const long long idpos = pos;
141893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const long long id = ReadUInt(m_pReader, idpos, len);
141993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
142093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (id < 0)  //error (or underflow)
142193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return static_cast<long>(id);
142293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
142393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //This is the distinguished set of ID's we use to determine
142493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //that we have exhausted the sub-element's inside the cluster
142593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //whose ID we parsed earlier.
142693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1427810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        if ((id == 0x0F43B675) || (id == 0x0C53BB6B)) {  //Cluster ID or Cues ID
142893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            element_size = pos - element_start;
142993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            assert(element_size > 0);
143093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
143193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            break;
143293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        }
143393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
143493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#ifdef _DEBUG
143593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        switch (id)
143693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        {
143793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            case 0x20:  //BlockGroup
143893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            case 0x23:  //Simple Block
143993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            case 0x67:  //TimeCode
144093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            case 0x2B:  //PrevSize
144193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                break;
144293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
144393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            default:
144493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                assert(false);
144593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                break;
144693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        }
144793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
144893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
144993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        pos += len;  //consume ID (of sub-element)
145093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
145193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //Read Size
145293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
145393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if ((pos + 1) > avail)
145493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        {
145593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            len = 1;
145693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return E_BUFFER_NOT_FULL;
145793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        }
145893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
145993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        result = GetUIntLength(m_pReader, pos, len);
146093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
146193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (result < 0)  //error
146293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return static_cast<long>(result);
146393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
146493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (result > 0)  //weird
146593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return E_BUFFER_NOT_FULL;
146693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
146793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if ((segment_stop >= 0) && ((pos + len) > segment_stop))
146893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return E_FILE_FORMAT_INVALID;
146993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
147093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if ((pos + len) > avail)
147193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return E_BUFFER_NOT_FULL;
147293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
147393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const long long size = ReadUInt(m_pReader, pos, len);
147493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
147593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (size < 0)  //error
147693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return static_cast<long>(size);
147793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
147893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        pos += len;  //consume size field of element
147993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
148093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //pos now points to start of sub-element's payload
148193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
148293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (size == 0)  //weird
148393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            continue;
148493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
148593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const long long unknown_size = (1LL << (7 * len)) - 1;
148693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
148793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (size == unknown_size)
148893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return E_FILE_FORMAT_INVALID;  //not allowed for sub-elements
148993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
149093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if ((segment_stop >= 0) && ((pos + size) > segment_stop))  //weird
149193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return E_FILE_FORMAT_INVALID;
149293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
149393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        pos += size;  //consume payload of sub-element
149493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert((segment_stop < 0) || (pos <= segment_stop));
149593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }  //determine cluster size
149693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
149793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(element_size >= 0);
149893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
149993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    m_pos = element_start + element_size;
150093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    m_pUnknownSize = 0;
150193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
150293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    return 2;  //continue parsing
150393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#else
1504810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long status = m_pUnknownSize->Parse(pos, len);
150593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1506810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)  // error or underflow
1507810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
150893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1509810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status == 0)  // parsed a block
1510810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 2;  // continue parsing
151193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1512810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(status > 0);  // nothing left to parse of this cluster
151393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1514810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long start = m_pUnknownSize->m_element_start;
151593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1516810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long size = m_pUnknownSize->GetElementSize();
1517810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(size >= 0);
151893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1519810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos = start + size;
1520810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_pos = pos;
152193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1522810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_pUnknownSize = 0;
152393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1524810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 2;  // continue parsing
152593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
152693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
152793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1528810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgvoid Segment::AppendCluster(Cluster* pCluster) {
1529810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster);
1530810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster->m_index >= 0);
153193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1532810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long count = m_clusterCount + m_clusterPreloadCount;
153393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1534810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long& size = m_clusterSize;
1535810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(size >= count);
153693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1537810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long idx = pCluster->m_index;
1538810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(idx == m_clusterCount);
153993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1540810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (count >= size) {
1541810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long n = (size <= 0) ? 2048 : 2 * size;
154293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1543810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster** const qq = new Cluster* [n];
1544810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster** q = qq;
154593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1546810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster** p = m_clusters;
1547810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster** const pp = p + count;
154893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1549810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    while (p != pp)
1550810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      *q++ = *p++;
155193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1552810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    delete[] m_clusters;
155393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1554810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m_clusters = qq;
1555810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    size = n;
1556810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
155793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1558810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_clusterPreloadCount > 0) {
1559810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(m_clusters);
156093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1561810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster** const p = m_clusters + m_clusterCount;
1562810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(*p);
1563810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((*p)->m_index < 0);
156493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1565810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster** q = p + m_clusterPreloadCount;
1566810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(q < (m_clusters + size));
156793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1568810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    for (;;) {
1569810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      Cluster** const qq = q - 1;
1570810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert((*qq)->m_index < 0);
157193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1572810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      *q = *qq;
1573810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      q = qq;
157493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1575810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (q == p)
1576810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        break;
157793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
1578810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
157993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1580810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_clusters[idx] = pCluster;
1581810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  ++m_clusterCount;
158293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
158393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1584810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgvoid Segment::PreloadCluster(Cluster* pCluster, ptrdiff_t idx) {
1585810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster);
1586810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster->m_index < 0);
1587810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(idx >= m_clusterCount);
158893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1589810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long count = m_clusterCount + m_clusterPreloadCount;
159093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1591810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long& size = m_clusterSize;
1592810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(size >= count);
159393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1594810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (count >= size) {
1595810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long n = (size <= 0) ? 2048 : 2 * size;
159693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1597810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster** const qq = new Cluster* [n];
1598810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster** q = qq;
159993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1600810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster** p = m_clusters;
1601810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster** const pp = p + count;
160293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1603810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    while (p != pp)
1604810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      *q++ = *p++;
160593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1606810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    delete[] m_clusters;
160793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1608810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m_clusters = qq;
1609810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    size = n;
1610810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
161193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1612810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_clusters);
161393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1614810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** const p = m_clusters + idx;
161593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1616810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** q = m_clusters + count;
1617810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(q >= p);
1618810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(q < (m_clusters + size));
161993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1620810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (q > p) {
1621810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster** const qq = q - 1;
1622810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((*qq)->m_index < 0);
162393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1624810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    *q = *qq;
1625810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    q = qq;
1626810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
162793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1628810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_clusters[idx] = pCluster;
1629810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  ++m_clusterPreloadCount;
163093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
163193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1632810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Segment::Load() {
1633810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_clusters == NULL);
1634810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_clusterSize == 0);
1635810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_clusterCount == 0);
1636810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // assert(m_size >= 0);
163793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1638810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // Outermost (level 0) segment object has been constructed,
1639810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // and pos designates start of payload.  We need to find the
1640810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // inner (level 1) elements.
164193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1642810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long header_status = ParseHeaders();
164393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1644810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (header_status < 0)  // error
1645810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return static_cast<long>(header_status);
164693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1647810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (header_status > 0)  // underflow
1648810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_BUFFER_NOT_FULL;
164993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1650810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_pInfo);
1651810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_pTracks);
165293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1653810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  for (;;) {
1654810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const int status = LoadCluster();
165593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1656810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
1657810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
165893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1659810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status >= 1)  // no more clusters
1660810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 0;
1661810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
166293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
166393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1664810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgSeekHead::SeekHead(Segment* pSegment, long long start, long long size_,
1665810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                   long long element_start, long long element_size)
1666810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    : m_pSegment(pSegment),
1667810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_start(start),
1668810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_size(size_),
1669810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_element_start(element_start),
1670810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_element_size(element_size),
1671810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_entries(0),
1672810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_entry_count(0),
1673810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_void_elements(0),
1674810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_void_element_count(0) {}
167593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1676810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgSeekHead::~SeekHead() {
1677810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] m_entries;
1678810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] m_void_elements;
167993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
168093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1681810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong SeekHead::Parse() {
1682810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  IMkvReader* const pReader = m_pSegment->m_pReader;
168393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1684810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long pos = m_start;
1685810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long stop = m_start + m_size;
168693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1687810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // first count the seek head entries
168893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1689810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  int entry_count = 0;
1690810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  int void_element_count = 0;
169193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1692810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (pos < stop) {
1693810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long id, size;
169493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1695810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long status = ParseElementHeader(pReader, pos, stop, id, size);
169693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1697810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
1698810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
169993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1700810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x0DBB)  // SeekEntry ID
1701810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      ++entry_count;
1702810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    else if (id == 0x6C)  // Void ID
1703810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      ++void_element_count;
170493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1705810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
1706810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos <= stop);
1707810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
170893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1709810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos == stop);
171093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1711810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_entries = new (std::nothrow) Entry[entry_count];
171293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1713810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_entries == NULL)
1714810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
171593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1716810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_void_elements = new (std::nothrow) VoidElement[void_element_count];
171793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1718810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_void_elements == NULL)
1719810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
172093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1721810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // now parse the entries and void elements
172293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1723810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Entry* pEntry = m_entries;
1724810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  VoidElement* pVoidElement = m_void_elements;
172593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1726810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos = m_start;
172793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1728810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (pos < stop) {
1729810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long idpos = pos;
173093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1731810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long id, size;
173293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1733810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long status = ParseElementHeader(pReader, pos, stop, id, size);
173493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1735810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
1736810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
173793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1738810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x0DBB) {  // SeekEntry ID
1739810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (ParseEntry(pReader, pos, size, pEntry)) {
1740810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        Entry& e = *pEntry++;
174193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1742810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        e.element_start = idpos;
1743810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        e.element_size = (pos + size) - idpos;
1744810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      }
1745810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x6C) {  // Void ID
1746810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      VoidElement& e = *pVoidElement++;
174793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1748810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      e.element_start = idpos;
1749810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      e.element_size = (pos + size) - idpos;
175093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
175193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1752810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
1753810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos <= stop);
1754810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
175593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1756810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos == stop);
175793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1758810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  ptrdiff_t count_ = ptrdiff_t(pEntry - m_entries);
1759810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(count_ >= 0);
1760810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(count_ <= entry_count);
176193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1762810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_entry_count = static_cast<int>(count_);
176393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1764810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  count_ = ptrdiff_t(pVoidElement - m_void_elements);
1765810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(count_ >= 0);
1766810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(count_ <= void_element_count);
176793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1768810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_void_element_count = static_cast<int>(count_);
176993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1770810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;
177193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
177293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1773810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgint SeekHead::GetCount() const { return m_entry_count; }
177493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1775810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst SeekHead::Entry* SeekHead::GetEntry(int idx) const {
1776810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (idx < 0)
1777810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;
177893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1779810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (idx >= m_entry_count)
1780810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;
178193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1782810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return m_entries + idx;
178393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
178493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1785810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgint SeekHead::GetVoidElementCount() const { return m_void_element_count; }
178693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1787810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst SeekHead::VoidElement* SeekHead::GetVoidElement(int idx) const {
1788810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (idx < 0)
1789810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;
179093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1791810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (idx >= m_void_element_count)
1792810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;
179393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1794810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return m_void_elements + idx;
1795810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org}
179693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
179793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
179893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgvoid Segment::ParseCues(long long off)
179993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org{
180093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (m_pCues)
180193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return;
180293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
180393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //odbgstream os;
180493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //os << "Segment::ParseCues (begin)" << endl;
180593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
180693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    long long pos = m_start + off;
180793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long element_start = pos;
180893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long stop = m_start + m_size;
180993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
181093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    long len;
181193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
181293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    long long result = GetUIntLength(m_pReader, pos, len);
181393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(result == 0);
181493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert((pos + len) <= stop);
181593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
181693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long idpos = pos;
181793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
181893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long id = ReadUInt(m_pReader, idpos, len);
181993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(id == 0x0C53BB6B);  //Cues ID
182093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
182193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    pos += len;  //consume ID
182293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pos < stop);
182393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
182493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //Read Size
182593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
182693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    result = GetUIntLength(m_pReader, pos, len);
182793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(result == 0);
182893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert((pos + len) <= stop);
182993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
183093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long size = ReadUInt(m_pReader, pos, len);
183193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(size >= 0);
183293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
183393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    pos += len;  //consume length of size of element
183493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert((pos + size) <= stop);
183593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
183693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long element_size = size + pos - element_start;
183793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
183893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //Pos now points to start of payload
183993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
184093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    m_pCues = new Cues(this, pos, size, element_start, element_size);
184193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(m_pCues);  //TODO
184293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
184393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //os << "Segment::ParseCues (end)" << endl;
184493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
184593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#else
1846810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Segment::ParseCues(long long off, long long& pos, long& len) {
1847810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_pCues)
1848810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;  // success
184993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1850810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (off < 0)
1851810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
185293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1853810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long total, avail;
185493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1855810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const int status = m_pReader->Length(&total, &avail);
185693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1857810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)  // error
1858810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
185993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1860810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((total < 0) || (avail <= total));
186193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1862810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos = m_start + off;
186393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1864810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((total < 0) || (pos >= total))
1865810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 1;  // don't bother parsing cues
186693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1867810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long element_start = pos;
1868810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
186993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1870810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((pos + 1) > avail) {
1871810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    len = 1;
1872810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_BUFFER_NOT_FULL;
1873810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
187493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1875810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long result = GetUIntLength(m_pReader, pos, len);
187693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1877810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (result < 0)  // error
1878810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return static_cast<long>(result);
187993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1880810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (result > 0)  // underflow (weird)
1881810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  {
1882810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    len = 1;
1883810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_BUFFER_NOT_FULL;
1884810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
188593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1886810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((segment_stop >= 0) && ((pos + len) > segment_stop))
1887810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
188893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1889810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((pos + len) > avail)
1890810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_BUFFER_NOT_FULL;
189193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1892810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long idpos = pos;
189393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1894810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long id = ReadUInt(m_pReader, idpos, len);
189593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1896810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (id != 0x0C53BB6B)  // Cues ID
1897810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
189893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1899810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos += len;  // consume ID
1900810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((segment_stop < 0) || (pos <= segment_stop));
190193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1902810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // Read Size
190393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1904810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((pos + 1) > avail) {
1905810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    len = 1;
1906810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_BUFFER_NOT_FULL;
1907810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
190893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1909810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  result = GetUIntLength(m_pReader, pos, len);
191093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1911810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (result < 0)  // error
1912810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return static_cast<long>(result);
191393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1914810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (result > 0)  // underflow (weird)
1915810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  {
1916810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    len = 1;
1917810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_BUFFER_NOT_FULL;
1918810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
191993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1920810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((segment_stop >= 0) && ((pos + len) > segment_stop))
1921810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
192293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1923810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((pos + len) > avail)
1924810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_BUFFER_NOT_FULL;
192593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1926810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long size = ReadUInt(m_pReader, pos, len);
192793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1928810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (size < 0)  // error
1929810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return static_cast<long>(size);
193093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1931810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (size == 0)  // weird, although technically not illegal
1932810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 1;  // done
193393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1934810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos += len;  // consume length of size of element
1935810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((segment_stop < 0) || (pos <= segment_stop));
193693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1937810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // Pos now points to start of payload
193893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1939810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long element_stop = pos + size;
194093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1941810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((segment_stop >= 0) && (element_stop > segment_stop))
1942810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
194393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1944810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((total >= 0) && (element_stop > total))
1945810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 1;  // don't bother parsing anymore
194693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1947810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  len = static_cast<long>(size);
194893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1949810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (element_stop > avail)
1950810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_BUFFER_NOT_FULL;
195193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1952810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long element_size = element_stop - element_start;
195393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1954810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_pCues =
1955810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      new (std::nothrow) Cues(this, pos, size, element_start, element_size);
1956810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_pCues);  // TODO
195793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1958810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;  // success
195993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
196093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
196193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
196293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
196393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgvoid Segment::ParseSeekEntry(
196493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    long long start,
196593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    long long size_)
196693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org{
196793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    long long pos = start;
196893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
196993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long stop = start + size_;
197093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
197193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    long len;
197293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
197393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long seekIdId = ReadUInt(m_pReader, pos, len);
197493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //seekIdId;
197593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(seekIdId == 0x13AB);  //SeekID ID
197693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert((pos + len) <= stop);
197793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
197893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    pos += len;  //consume id
197993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
198093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long seekIdSize = ReadUInt(m_pReader, pos, len);
198193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(seekIdSize >= 0);
198293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert((pos + len) <= stop);
198393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
198493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    pos += len;  //consume size
198593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
198693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long seekId = ReadUInt(m_pReader, pos, len);  //payload
198793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(seekId >= 0);
198893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(len == seekIdSize);
198993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert((pos + len) <= stop);
199093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
199193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    pos += seekIdSize;  //consume payload
199293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
199393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long seekPosId = ReadUInt(m_pReader, pos, len);
199493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //seekPosId;
199593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(seekPosId == 0x13AC);  //SeekPos ID
199693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert((pos + len) <= stop);
199793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
199893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    pos += len;  //consume id
199993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
200093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long seekPosSize = ReadUInt(m_pReader, pos, len);
200193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(seekPosSize >= 0);
200293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert((pos + len) <= stop);
200393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
200493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    pos += len;  //consume size
200593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert((pos + seekPosSize) <= stop);
200693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
200793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long seekOff = UnserializeUInt(m_pReader, pos, seekPosSize);
200893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(seekOff >= 0);
200993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(seekOff < m_size);
201093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
201193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    pos += seekPosSize;  //consume payload
201293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pos == stop);
201393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
201493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long seekPos = m_start + seekOff;
201593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(seekPos < (m_start + m_size));
201693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
201793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (seekId == 0x0C53BB6B)  //Cues ID
201893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        ParseCues(seekOff);
201993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
202093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#else
2021810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgbool SeekHead::ParseEntry(IMkvReader* pReader, long long start, long long size_,
2022810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                          Entry* pEntry) {
2023810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (size_ <= 0)
2024810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
202593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2026810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long pos = start;
2027810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long stop = start + size_;
202893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2029810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long len;
203093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2031810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // parse the container for the level-1 element ID
203293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2033810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long seekIdId = ReadUInt(pReader, pos, len);
2034810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // seekIdId;
203593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2036810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (seekIdId != 0x13AB)  // SeekID ID
2037810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
203893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2039810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((pos + len) > stop)
2040810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
204193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2042810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos += len;  // consume SeekID id
204393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2044810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long seekIdSize = ReadUInt(pReader, pos, len);
204593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2046810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (seekIdSize <= 0)
2047810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
204893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2049810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((pos + len) > stop)
2050810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
205193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2052810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos += len;  // consume size of field
205393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2054810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((pos + seekIdSize) > stop)
2055810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
205693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2057810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // Note that the SeekId payload really is serialized
2058810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // as a "Matroska integer", not as a plain binary value.
2059810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // In fact, Matroska requires that ID values in the
2060810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // stream exactly match the binary representation as listed
2061810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // in the Matroska specification.
2062810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  //
2063810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // This parser is more liberal, and permits IDs to have
2064810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // any width.  (This could make the representation in the stream
2065810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // different from what's in the spec, but it doesn't matter here,
2066810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // since we always normalize "Matroska integer" values.)
206793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2068810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pEntry->id = ReadUInt(pReader, pos, len);  // payload
206993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2070810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pEntry->id <= 0)
2071810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
207293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2073810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (len != seekIdSize)
2074810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
207593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2076810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos += seekIdSize;  // consume SeekID payload
207793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2078810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long seekPosId = ReadUInt(pReader, pos, len);
207993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2080810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (seekPosId != 0x13AC)  // SeekPos ID
2081810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
208293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2083810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((pos + len) > stop)
2084810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
208593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2086810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos += len;  // consume id
208793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2088810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long seekPosSize = ReadUInt(pReader, pos, len);
208993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2090810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (seekPosSize <= 0)
2091810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
209293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2093810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((pos + len) > stop)
2094810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
209593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2096810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos += len;  // consume size
209793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2098810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((pos + seekPosSize) > stop)
2099810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
210093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2101810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pEntry->pos = UnserializeUInt(pReader, pos, seekPosSize);
210293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2103810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pEntry->pos < 0)
2104810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
210593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2106810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos += seekPosSize;  // consume payload
210793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2108810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pos != stop)
2109810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
211093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2111810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return true;
211293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
211393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
211493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2115810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgCues::Cues(Segment* pSegment, long long start_, long long size_,
2116810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org           long long element_start, long long element_size)
2117810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    : m_pSegment(pSegment),
2118810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_start(start_),
2119810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_size(size_),
2120810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_element_start(element_start),
2121810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_element_size(element_size),
2122810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_cue_points(NULL),
2123810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_count(0),
2124810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_preload_count(0),
2125810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pos(start_) {}
2126810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
2127810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgCues::~Cues() {
2128810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long n = m_count + m_preload_count;
2129810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
2130810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  CuePoint** p = m_cue_points;
2131810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  CuePoint** const q = p + n;
2132810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
2133810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (p != q) {
2134810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    CuePoint* const pCP = *p++;
2135810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pCP);
213693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2137810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    delete pCP;
2138810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
2139810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
2140810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] m_cue_points;
214193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
214293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2143810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Cues::GetCount() const {
2144810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_cue_points == NULL)
2145810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
214693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2147810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return m_count;  // TODO: really ignore preload count?
2148810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org}
214993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2150810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgbool Cues::DoneParsing() const {
2151810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long stop = m_start + m_size;
2152810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return (m_pos >= stop);
2153810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org}
215493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2155810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgvoid Cues::Init() const {
2156810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_cue_points)
2157810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return;
215893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2159810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_count == 0);
2160810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_preload_count == 0);
216193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2162810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  IMkvReader* const pReader = m_pSegment->m_pReader;
216393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2164810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long stop = m_start + m_size;
2165810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long pos = m_start;
216693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2167810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long cue_points_size = 0;
216893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2169810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (pos < stop) {
2170810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long idpos = pos;
217193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2172810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long len;
217393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2174810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long id = ReadUInt(pReader, pos, len);
2175810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(id >= 0);  // TODO
2176810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((pos + len) <= stop);
217793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2178810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume ID
217993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2180810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long size = ReadUInt(pReader, pos, len);
2181810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(size >= 0);
2182810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((pos + len) <= stop);
218393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2184810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume Size field
2185810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((pos + size) <= stop);
218693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2187810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x3B)  // CuePoint ID
2188810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      PreloadCuePoint(cue_points_size, idpos);
218993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2190810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
2191810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos <= stop);
2192810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
219393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
219493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2195810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgvoid Cues::PreloadCuePoint(long& cue_points_size, long long pos) const {
2196810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_count == 0);
219793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2198810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_preload_count >= cue_points_size) {
2199810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long n = (cue_points_size <= 0) ? 2048 : 2 * cue_points_size;
220093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2201810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    CuePoint** const qq = new CuePoint* [n];
2202810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    CuePoint** q = qq;  // beginning of target
220393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2204810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    CuePoint** p = m_cue_points;  // beginning of source
2205810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    CuePoint** const pp = p + m_preload_count;  // end of source
220693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2207810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    while (p != pp)
2208810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      *q++ = *p++;
220993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2210810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    delete[] m_cue_points;
221193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2212810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m_cue_points = qq;
2213810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    cue_points_size = n;
2214810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
221593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2216810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  CuePoint* const pCP = new CuePoint(m_preload_count, pos);
2217810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_cue_points[m_preload_count++] = pCP;
221893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
221993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2220810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgbool Cues::LoadCuePoint() const {
2221810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // odbgstream os;
2222810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // os << "Cues::LoadCuePoint" << endl;
222393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2224810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long stop = m_start + m_size;
222593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2226810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_pos >= stop)
2227810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;  // nothing else to do
222893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2229810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Init();
223093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2231810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  IMkvReader* const pReader = m_pSegment->m_pReader;
223293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2233810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (m_pos < stop) {
2234810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long idpos = m_pos;
223593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2236810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long len;
223793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2238810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long id = ReadUInt(pReader, m_pos, len);
2239810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(id >= 0);  // TODO
2240810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((m_pos + len) <= stop);
224193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2242810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m_pos += len;  // consume ID
224393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2244810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long size = ReadUInt(pReader, m_pos, len);
2245810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(size >= 0);
2246810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((m_pos + len) <= stop);
224793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2248810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m_pos += len;  // consume Size field
2249810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((m_pos + size) <= stop);
225093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2251810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id != 0x3B) {  // CuePoint ID
2252810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pos += size;  // consume payload
2253810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(m_pos <= stop);
225493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2255810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
2256810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
225793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2258810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(m_preload_count > 0);
225993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2260810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    CuePoint* const pCP = m_cue_points[m_count];
2261810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pCP);
2262810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((pCP->GetTimeCode() >= 0) || (-pCP->GetTimeCode() == idpos));
2263810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (pCP->GetTimeCode() < 0 && (-pCP->GetTimeCode() != idpos))
2264810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return false;
226593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2266810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pCP->Load(pReader);
2267810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    ++m_count;
2268810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    --m_preload_count;
226993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2270810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m_pos += size;  // consume payload
2271810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(m_pos <= stop);
227293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2273810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return true;  // yes, we loaded a cue point
2274810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
227593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2276810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // return (m_pos < stop);
2277810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return false;  // no, we did not load a cue point
227893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
227993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2280810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgbool Cues::Find(long long time_ns, const Track* pTrack, const CuePoint*& pCP,
2281810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                const CuePoint::TrackPosition*& pTP) const {
2282810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(time_ns >= 0);
2283810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pTrack);
228493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
228593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
228693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    LoadCuePoint();  //establish invariant
228793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
228893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(m_cue_points);
228993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(m_count > 0);
229093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
229193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    CuePoint** const ii = m_cue_points;
229293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    CuePoint** i = ii;
229393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
229493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    CuePoint** const jj = ii + m_count + m_preload_count;
229593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    CuePoint** j = jj;
229693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
229793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    pCP = *i;
229893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pCP);
229993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
230093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (time_ns <= pCP->GetTime(m_pSegment))
230193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    {
230293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        pTP = pCP->Find(pTrack);
230393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return (pTP != NULL);
230493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
230593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
230693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    IMkvReader* const pReader = m_pSegment->m_pReader;
230793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
230893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    while (i < j)
230993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    {
231093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //INVARIANT:
231193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //[ii, i) <= time_ns
231293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //[i, j)  ?
231393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //[j, jj) > time_ns
231493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
231593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        CuePoint** const k = i + (j - i) / 2;
231693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(k < jj);
231793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
231893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        CuePoint* const pCP = *k;
231993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(pCP);
232093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
232193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        pCP->Load(pReader);
232293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
232393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const long long t = pCP->GetTime(m_pSegment);
232493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
232593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (t <= time_ns)
232693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            i = k + 1;
232793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        else
232893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            j = k;
232993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
233093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(i <= j);
233193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
233293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
233393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(i == j);
233493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(i <= jj);
233593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(i > ii);
233693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
233793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    pCP = *--i;
233893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pCP);
233993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pCP->GetTime(m_pSegment) <= time_ns);
234093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#else
2341810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_cue_points == NULL)
2342810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
234393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2344810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_count == 0)
2345810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
234693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2347810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  CuePoint** const ii = m_cue_points;
2348810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  CuePoint** i = ii;
234993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2350810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  CuePoint** const jj = ii + m_count;
2351810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  CuePoint** j = jj;
235293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2353810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pCP = *i;
2354810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCP);
235593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2356810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (time_ns <= pCP->GetTime(m_pSegment)) {
2357810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pTP = pCP->Find(pTrack);
2358810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return (pTP != NULL);
2359810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
236093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2361810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (i < j) {
2362810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // INVARIANT:
2363810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[ii, i) <= time_ns
2364810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[i, j)  ?
2365810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[j, jj) > time_ns
236693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2367810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    CuePoint** const k = i + (j - i) / 2;
2368810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(k < jj);
236993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2370810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    CuePoint* const pCP = *k;
2371810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pCP);
237293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2373810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long t = pCP->GetTime(m_pSegment);
237493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2375810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (t <= time_ns)
2376810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      i = k + 1;
2377810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    else
2378810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      j = k;
237993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2380810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(i <= j);
2381810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
238293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2383810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(i == j);
2384810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(i <= jj);
2385810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(i > ii);
238693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2387810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pCP = *--i;
2388810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCP);
2389810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCP->GetTime(m_pSegment) <= time_ns);
239093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
239193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2392810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // TODO: here and elsewhere, it's probably not correct to search
2393810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // for the cue point with this time, and then search for a matching
2394810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // track.  In principle, the matching track could be on some earlier
2395810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // cue point, and with our current algorithm, we'd miss it.  To make
2396810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // this bullet-proof, we'd need to create a secondary structure,
2397810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // with a list of cue points that apply to a track, and then search
2398810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // that track-based structure for a matching cue point.
239993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2400810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pTP = pCP->Find(pTrack);
2401810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return (pTP != NULL);
240293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
240393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
240493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
240593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgbool Cues::FindNext(
240693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    long long time_ns,
240793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const Track* pTrack,
240893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const CuePoint*& pCP,
240993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const CuePoint::TrackPosition*& pTP) const
241093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org{
241193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    pCP = 0;
241293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    pTP = 0;
241393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
241493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (m_count == 0)
241593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return false;
241693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
241793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(m_cue_points);
241893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
241993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const CuePoint* const* const ii = m_cue_points;
242093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const CuePoint* const* i = ii;
242193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
242293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const CuePoint* const* const jj = ii + m_count;
242393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const CuePoint* const* j = jj;
242493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
242593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    while (i < j)
242693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    {
242793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //INVARIANT:
242893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //[ii, i) <= time_ns
242993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //[i, j)  ?
243093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //[j, jj) > time_ns
243193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
243293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const CuePoint* const* const k = i + (j - i) / 2;
243393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(k < jj);
243493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
243593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        pCP = *k;
243693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(pCP);
243793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
243893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const long long t = pCP->GetTime(m_pSegment);
243993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
244093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (t <= time_ns)
244193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            i = k + 1;
244293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        else
244393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            j = k;
244493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
244593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(i <= j);
244693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
244793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
244893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(i == j);
244993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(i <= jj);
245093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
245193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (i >= jj)  //time_ns is greater than max cue point
245293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return false;
245393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
245493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    pCP = *i;
245593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pCP);
245693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pCP->GetTime(m_pSegment) > time_ns);
245793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
245893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    pTP = pCP->Find(pTrack);
245993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    return (pTP != NULL);
246093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
246193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
246293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2463810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst CuePoint* Cues::GetFirst() const {
2464810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_cue_points == NULL)
2465810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return NULL;
246693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2467810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_count == 0)
2468810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return NULL;
246993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
247093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
247193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    LoadCuePoint();  //init cues
247293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
247393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const size_t count = m_count + m_preload_count;
247493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
247593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (count == 0)  //weird
247693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return NULL;
247793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
247893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2479810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  CuePoint* const* const pp = m_cue_points;
2480810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pp);
248193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2482810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  CuePoint* const pCP = pp[0];
2483810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCP);
2484810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCP->GetTimeCode() >= 0);
248593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2486810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return pCP;
248793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
248893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2489810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst CuePoint* Cues::GetLast() const {
2490810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_cue_points == NULL)
2491810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return NULL;
249293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2493810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_count <= 0)
2494810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return NULL;
249593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
249693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
249793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    LoadCuePoint();  //init cues
249893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
249993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const size_t count = m_count + m_preload_count;
250093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
250193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (count == 0)  //weird
250293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return NULL;
250393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
250493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const size_t index = count - 1;
250593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
250693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    CuePoint* const* const pp = m_cue_points;
250793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pp);
250893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
250993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    CuePoint* const pCP = pp[index];
251093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pCP);
251193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
251293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    pCP->Load(m_pSegment->m_pReader);
251393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pCP->GetTimeCode() >= 0);
251493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#else
2515810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long index = m_count - 1;
251693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2517810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  CuePoint* const* const pp = m_cue_points;
2518810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pp);
251993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2520810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  CuePoint* const pCP = pp[index];
2521810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCP);
2522810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCP->GetTimeCode() >= 0);
252393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
252493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2525810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return pCP;
252693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
252793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2528810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst CuePoint* Cues::GetNext(const CuePoint* pCurr) const {
2529810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pCurr == NULL)
2530810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return NULL;
253193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2532810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCurr->GetTimeCode() >= 0);
2533810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_cue_points);
2534810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_count >= 1);
253593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
253693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
253793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const size_t count = m_count + m_preload_count;
253893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
253993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    size_t index = pCurr->m_index;
254093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(index < count);
254193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
254293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    CuePoint* const* const pp = m_cue_points;
254393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pp);
254493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pp[index] == pCurr);
254593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
254693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    ++index;
254793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
254893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (index >= count)
254993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return NULL;
255093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
255193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    CuePoint* const pNext = pp[index];
255293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pNext);
255393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
255493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    pNext->Load(m_pSegment->m_pReader);
255593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#else
2556810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long index = pCurr->m_index;
2557810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(index < m_count);
255893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2559810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  CuePoint* const* const pp = m_cue_points;
2560810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pp);
2561810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pp[index] == pCurr);
256293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2563810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  ++index;
256493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2565810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (index >= m_count)
2566810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return NULL;
256793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2568810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  CuePoint* const pNext = pp[index];
2569810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pNext);
2570810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pNext->GetTimeCode() >= 0);
257193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
257293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2573810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return pNext;
257493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
257593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2576810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst BlockEntry* Cues::GetBlock(const CuePoint* pCP,
2577810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                 const CuePoint::TrackPosition* pTP) const {
2578810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pCP == NULL)
2579810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return NULL;
258093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2581810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pTP == NULL)
2582810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return NULL;
258393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2584810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return m_pSegment->GetBlock(*pCP, *pTP);
258593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
258693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2587810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst BlockEntry* Segment::GetBlock(const CuePoint& cp,
2588810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                    const CuePoint::TrackPosition& tp) {
2589810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** const ii = m_clusters;
2590810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** i = ii;
259193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2592810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long count = m_clusterCount + m_clusterPreloadCount;
259393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2594810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** const jj = ii + count;
2595810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** j = jj;
259693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2597810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (i < j) {
2598810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // INVARIANT:
2599810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[ii, i) < pTP->m_pos
2600810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[i, j) ?
2601810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[j, jj)  > pTP->m_pos
260293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2603810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster** const k = i + (j - i) / 2;
2604810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(k < jj);
260593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2606810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster* const pCluster = *k;
2607810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pCluster);
260893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2609810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // const long long pos_ = pCluster->m_pos;
2610810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // assert(pos_);
2611810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // const long long pos = pos_ * ((pos_ < 0) ? -1 : 1);
261293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2613810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long pos = pCluster->GetPosition();
2614810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos >= 0);
261593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2616810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (pos < tp.m_pos)
2617810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      i = k + 1;
2618810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    else if (pos > tp.m_pos)
2619810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      j = k;
2620810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    else
2621810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return pCluster->GetEntry(cp, tp);
2622810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
262393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2624810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(i == j);
2625810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // assert(Cluster::HasBlockEntries(this, tp.m_pos));
262693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2627810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster* const pCluster = Cluster::Create(this, -1, tp.m_pos);  //, -1);
2628810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster);
262993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2630810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const ptrdiff_t idx = i - m_clusters;
263193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2632810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  PreloadCluster(pCluster, idx);
2633810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_clusters);
2634810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_clusterPreloadCount > 0);
2635810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_clusters[idx] == pCluster);
263693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2637810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return pCluster->GetEntry(cp, tp);
263893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
263993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2640810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst Cluster* Segment::FindOrPreloadCluster(long long requested_pos) {
2641810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (requested_pos < 0)
2642810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;
264393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2644810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** const ii = m_clusters;
2645810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** i = ii;
264693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2647810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long count = m_clusterCount + m_clusterPreloadCount;
264893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2649810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** const jj = ii + count;
2650810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** j = jj;
265193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2652810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (i < j) {
2653810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // INVARIANT:
2654810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[ii, i) < pTP->m_pos
2655810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[i, j) ?
2656810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[j, jj)  > pTP->m_pos
265793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2658810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster** const k = i + (j - i) / 2;
2659810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(k < jj);
266093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2661810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster* const pCluster = *k;
2662810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pCluster);
266393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2664810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // const long long pos_ = pCluster->m_pos;
2665810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // assert(pos_);
2666810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // const long long pos = pos_ * ((pos_ < 0) ? -1 : 1);
266793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2668810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long pos = pCluster->GetPosition();
2669810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos >= 0);
267093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2671810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (pos < requested_pos)
2672810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      i = k + 1;
2673810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    else if (pos > requested_pos)
2674810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      j = k;
2675810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    else
2676810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return pCluster;
2677810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
267893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2679810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(i == j);
2680810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // assert(Cluster::HasBlockEntries(this, tp.m_pos));
268193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2682810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster* const pCluster = Cluster::Create(this, -1, requested_pos);
2683810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  //-1);
2684810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster);
268593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2686810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const ptrdiff_t idx = i - m_clusters;
268793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2688810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  PreloadCluster(pCluster, idx);
2689810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_clusters);
2690810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_clusterPreloadCount > 0);
2691810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_clusters[idx] == pCluster);
269293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2693810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return pCluster;
269493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
269593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2696810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgCuePoint::CuePoint(long idx, long long pos)
2697810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    : m_element_start(0),
2698810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_element_size(0),
2699810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_index(idx),
2700810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_timecode(-1 * pos),
2701810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_track_positions(NULL),
2702810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_track_positions_count(0) {
2703810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos > 0);
270493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
270593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2706810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgCuePoint::~CuePoint() { delete[] m_track_positions; }
270793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2708810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgvoid CuePoint::Load(IMkvReader* pReader) {
2709810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // odbgstream os;
2710810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // os << "CuePoint::Load(begin): timecode=" << m_timecode << endl;
271193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2712810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_timecode >= 0)  // already loaded
2713810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return;
271493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2715810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_track_positions == NULL);
2716810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_track_positions_count == 0);
271793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2718810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long pos_ = -m_timecode;
2719810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long element_start = pos_;
272093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2721810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long stop;
272293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2723810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  {
2724810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long len;
272593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2726810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long id = ReadUInt(pReader, pos_, len);
2727810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(id == 0x3B);  // CuePoint ID
2728810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id != 0x3B)
2729810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return;
273093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2731810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos_ += len;  // consume ID
273293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2733810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long size = ReadUInt(pReader, pos_, len);
2734810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(size >= 0);
273593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2736810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos_ += len;  // consume Size field
2737810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // pos_ now points to start of payload
273893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2739810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    stop = pos_ + size;
2740810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
274193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2742810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long element_size = stop - element_start;
274393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2744810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long pos = pos_;
274593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2746810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // First count number of track positions
274793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2748810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (pos < stop) {
2749810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long len;
275093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2751810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long id = ReadUInt(pReader, pos, len);
2752810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(id >= 0);  // TODO
2753810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((pos + len) <= stop);
275493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2755810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume ID
275693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2757810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long size = ReadUInt(pReader, pos, len);
2758810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(size >= 0);
2759810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((pos + len) <= stop);
276093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2761810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume Size field
2762810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((pos + size) <= stop);
276393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2764810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x33)  // CueTime ID
2765810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_timecode = UnserializeUInt(pReader, pos, size);
276693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2767810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    else if (id == 0x37)  // CueTrackPosition(s) ID
2768810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      ++m_track_positions_count;
276993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2770810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
2771810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos <= stop);
2772810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
277393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2774810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_timecode >= 0);
2775810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_track_positions_count > 0);
277693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2777810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // os << "CuePoint::Load(cont'd): idpos=" << idpos
2778810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  //   << " timecode=" << m_timecode
2779810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  //   << endl;
278093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2781810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_track_positions = new TrackPosition[m_track_positions_count];
278293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2783810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // Now parse track positions
278493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2785810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  TrackPosition* p = m_track_positions;
2786810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos = pos_;
278793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2788810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (pos < stop) {
2789810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long len;
279093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2791810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long id = ReadUInt(pReader, pos, len);
2792810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(id >= 0);  // TODO
2793810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((pos + len) <= stop);
279493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2795810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume ID
279693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2797810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long size = ReadUInt(pReader, pos, len);
2798810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(size >= 0);
2799810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((pos + len) <= stop);
280093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2801810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume Size field
2802810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((pos + size) <= stop);
280393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2804810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x37) {  // CueTrackPosition(s) ID
2805810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      TrackPosition& tp = *p++;
2806810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      tp.Parse(pReader, pos, size);
2807810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
280893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2809810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
2810810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos <= stop);
2811810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
281293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2813810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(size_t(p - m_track_positions) == m_track_positions_count);
281493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2815810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_element_start = element_start;
2816810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_element_size = element_size;
281793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
281893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2819810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgvoid CuePoint::TrackPosition::Parse(IMkvReader* pReader, long long start_,
2820810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                    long long size_) {
2821810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long stop = start_ + size_;
2822810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long pos = start_;
282393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2824810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_track = -1;
2825810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_pos = -1;
2826810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_block = 1;  // default
282793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2828810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (pos < stop) {
2829810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long len;
283093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2831810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long id = ReadUInt(pReader, pos, len);
2832810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(id >= 0);  // TODO
2833810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((pos + len) <= stop);
283493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2835810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume ID
283693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2837810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long size = ReadUInt(pReader, pos, len);
2838810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(size >= 0);
2839810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((pos + len) <= stop);
284093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2841810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume Size field
2842810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((pos + size) <= stop);
284393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2844810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x77)  // CueTrack ID
2845810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_track = UnserializeUInt(pReader, pos, size);
284693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2847810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    else if (id == 0x71)  // CueClusterPos ID
2848810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pos = UnserializeUInt(pReader, pos, size);
284993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2850810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    else if (id == 0x1378)  // CueBlockNumber
2851810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_block = UnserializeUInt(pReader, pos, size);
285293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2853810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
2854810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos <= stop);
2855810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
285693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2857810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_pos >= 0);
2858810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_track > 0);
2859810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // assert(m_block > 0);
286093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
286193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2862810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst CuePoint::TrackPosition* CuePoint::Find(const Track* pTrack) const {
2863810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pTrack);
286493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2865810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long n = pTrack->GetNumber();
286693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2867810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const TrackPosition* i = m_track_positions;
2868810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const TrackPosition* const j = i + m_track_positions_count;
286993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2870810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (i != j) {
2871810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const TrackPosition& p = *i++;
287293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2873810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (p.m_track == n)
2874810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return &p;
2875810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
287693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2877810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return NULL;  // no matching track number found
287893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
287993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2880810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long CuePoint::GetTimeCode() const { return m_timecode; }
288193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2882810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long CuePoint::GetTime(const Segment* pSegment) const {
2883810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pSegment);
2884810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_timecode >= 0);
288593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2886810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const SegmentInfo* const pInfo = pSegment->GetInfo();
2887810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pInfo);
288893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2889810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long scale = pInfo->GetTimeCodeScale();
2890810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(scale >= 1);
289193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2892810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long time = scale * m_timecode;
289393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2894810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return time;
289593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
289693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
289793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
289893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orglong long Segment::Unparsed() const
289993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org{
290093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (m_size < 0)
290193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return LLONG_MAX;
290293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
290393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long stop = m_start + m_size;
290493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
290593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long result = stop - m_pos;
290693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(result >= 0);
290793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
290893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    return result;
290993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
291093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#else
2911810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgbool Segment::DoneParsing() const {
2912810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_size < 0) {
2913810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long total, avail;
291493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2915810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const int status = m_pReader->Length(&total, &avail);
291693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2917810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
2918810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return true;  // must assume done
291993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2920810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (total < 0)
2921810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return false;  // assume live stream
292293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2923810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return (m_pos >= total);
2924810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
292593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2926810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long stop = m_start + m_size;
292793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2928810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return (m_pos >= stop);
292993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
293093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
293193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2932810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst Cluster* Segment::GetFirst() const {
2933810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((m_clusters == NULL) || (m_clusterCount <= 0))
2934810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return &m_eos;
293593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2936810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster* const pCluster = m_clusters[0];
2937810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster);
293893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2939810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return pCluster;
294093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
294193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2942810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst Cluster* Segment::GetLast() const {
2943810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((m_clusters == NULL) || (m_clusterCount <= 0))
2944810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return &m_eos;
294593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2946810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long idx = m_clusterCount - 1;
294793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2948810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster* const pCluster = m_clusters[idx];
2949810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster);
295093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2951810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return pCluster;
295293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
295393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2954810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgunsigned long Segment::GetCount() const { return m_clusterCount; }
295593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2956810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst Cluster* Segment::GetNext(const Cluster* pCurr) {
2957810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCurr);
2958810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCurr != &m_eos);
2959810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_clusters);
296093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2961810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long idx = pCurr->m_index;
296293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2963810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (idx >= 0) {
2964810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(m_clusterCount > 0);
2965810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(idx < m_clusterCount);
2966810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pCurr == m_clusters[idx]);
296793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2968810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    ++idx;
296993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2970810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (idx >= m_clusterCount)
2971810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return &m_eos;  // caller will LoadCluster as desired
297293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2973810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster* const pNext = m_clusters[idx];
2974810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pNext);
2975810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pNext->m_index >= 0);
2976810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pNext->m_index == idx);
297793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2978810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return pNext;
2979810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
298093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2981810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_clusterPreloadCount > 0);
298293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2983810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long pos = pCurr->m_element_start;
298493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2985810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_size >= 0);  // TODO
2986810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long stop = m_start + m_size;  // end of segment
298793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2988810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  {
2989810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long len;
299093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2991810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long result = GetUIntLength(m_pReader, pos, len);
2992810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(result == 0);
2993810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((pos + len) <= stop);  // TODO
2994810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result != 0)
2995810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return NULL;
299693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
2997810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long id = ReadUInt(m_pReader, pos, len);
2998810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(id == 0x0F43B675);  // Cluster ID
2999810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id != 0x0F43B675)
3000810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return NULL;
300193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3002810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume ID
300393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3004810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // Read Size
3005810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result = GetUIntLength(m_pReader, pos, len);
3006810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(result == 0);  // TODO
3007810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((pos + len) <= stop);  // TODO
300893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3009810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long size = ReadUInt(m_pReader, pos, len);
3010810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(size > 0);  // TODO
3011810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // assert((pCurr->m_size <= 0) || (pCurr->m_size == size));
301293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3013810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume length of size of element
3014810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((pos + size) <= stop);  // TODO
301593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3016810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // Pos now points to start of payload
301793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3018810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
3019810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
302093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3021810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long off_next = 0;
302293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3023810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (pos < stop) {
3024810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long len;
302593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3026810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long result = GetUIntLength(m_pReader, pos, len);
3027810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(result == 0);
3028810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((pos + len) <= stop);  // TODO
3029810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result != 0)
3030810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return NULL;
303193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3032810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long idpos = pos;  // pos of next (potential) cluster
303393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3034810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long id = ReadUInt(m_pReader, idpos, len);
3035810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(id > 0);  // TODO
303693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3037810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume ID
303893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3039810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // Read Size
3040810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result = GetUIntLength(m_pReader, pos, len);
3041810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(result == 0);  // TODO
3042810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((pos + len) <= stop);  // TODO
304393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3044810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long size = ReadUInt(m_pReader, pos, len);
3045810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(size >= 0);  // TODO
304693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3047810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume length of size of element
3048810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((pos + size) <= stop);  // TODO
304993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3050810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // Pos now points to start of payload
305193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3052810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size == 0)  // weird
3053810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
305493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3055810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x0F43B675) {  // Cluster ID
3056810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long off_next_ = idpos - m_start;
305793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3058810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      long long pos_;
3059810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      long len_;
306093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3061810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long status = Cluster::HasBlockEntries(this, off_next_, pos_, len_);
306293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3063810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(status >= 0);
306493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3065810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status > 0) {
3066810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        off_next = off_next_;
3067810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        break;
3068810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      }
306993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
307093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3071810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
3072810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
307393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3074810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (off_next <= 0)
3075810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;
307693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3077810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** const ii = m_clusters + m_clusterCount;
3078810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** i = ii;
307993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3080810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** const jj = ii + m_clusterPreloadCount;
3081810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** j = jj;
308293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3083810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (i < j) {
3084810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // INVARIANT:
3085810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[0, i) < pos_next
3086810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[i, j) ?
3087810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[j, jj)  > pos_next
308893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3089810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster** const k = i + (j - i) / 2;
3090810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(k < jj);
309193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3092810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster* const pNext = *k;
3093810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pNext);
3094810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pNext->m_index < 0);
309593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3096810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // const long long pos_ = pNext->m_pos;
3097810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // assert(pos_);
3098810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // pos = pos_ * ((pos_ < 0) ? -1 : 1);
309993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3100810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos = pNext->GetPosition();
310193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3102810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (pos < off_next)
3103810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      i = k + 1;
3104810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    else if (pos > off_next)
3105810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      j = k;
3106810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    else
3107810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return pNext;
3108810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
310993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3110810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(i == j);
311193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3112810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster* const pNext = Cluster::Create(this, -1, off_next);
3113810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pNext);
311493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3115810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const ptrdiff_t idx_next = i - m_clusters;  // insertion position
311693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3117810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  PreloadCluster(pNext, idx_next);
3118810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_clusters);
3119810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(idx_next < m_clusterSize);
3120810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_clusters[idx_next] == pNext);
312193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3122810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return pNext;
3123810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org}
312493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3125810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Segment::ParseNext(const Cluster* pCurr, const Cluster*& pResult,
3126810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                        long long& pos, long& len) {
3127810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCurr);
3128810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(!pCurr->EOS());
3129810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_clusters);
313093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3131810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pResult = 0;
313293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3133810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pCurr->m_index >= 0) {  // loaded (not merely preloaded)
3134810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(m_clusters[pCurr->m_index] == pCurr);
313593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3136810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long next_idx = pCurr->m_index + 1;
313793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3138810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (next_idx < m_clusterCount) {
3139810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pResult = m_clusters[next_idx];
3140810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 0;  // success
3141810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
314293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3143810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // curr cluster is last among loaded
314493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3145810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long result = LoadCluster(pos, len);
314693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3147810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error or underflow
3148810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return result;
314993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3150810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result > 0)  // no more clusters
3151810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    {
3152810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      // pResult = &m_eos;
3153810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 1;
315493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
315593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3156810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pResult = GetLast();
3157810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;  // success
3158810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
315993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3160810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_pos > 0);
316193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3162810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long total, avail;
316393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3164810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long status = m_pReader->Length(&total, &avail);
316593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3166810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)  // error
3167810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
316893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3169810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((total < 0) || (avail <= total));
317093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3171810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
317293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3173810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // interrogate curr cluster
317493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3175810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos = pCurr->m_element_start;
317693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3177810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pCurr->m_element_size >= 0)
3178810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += pCurr->m_element_size;
3179810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  else {
3180810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > avail) {
3181810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
3182810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
3183810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
318493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3185810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long result = GetUIntLength(m_pReader, pos, len);
318693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3187810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error
3188810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(result);
318993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3190810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result > 0)  // weird
3191810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
319293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3193810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((segment_stop >= 0) && ((pos + len) > segment_stop))
3194810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
319593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3196810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > avail)
3197810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
319893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3199810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long id = ReadUInt(m_pReader, pos, len);
320093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3201810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id != 0x0F43B675)  // weird: not Cluster ID
3202810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return -1;
320393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3204810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume ID
320593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3206810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // Read Size
320793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3208810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > avail) {
3209810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
3210810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
3211810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
321293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3213810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result = GetUIntLength(m_pReader, pos, len);
321493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3215810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error
3216810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(result);
321793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3218810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result > 0)  // weird
3219810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
322093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3221810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((segment_stop >= 0) && ((pos + len) > segment_stop))
3222810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
322393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3224810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > avail)
3225810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
322693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3227810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long size = ReadUInt(m_pReader, pos, len);
322893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3229810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size < 0)  // error
3230810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(size);
323193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3232810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume size field
323393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3234810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long unknown_size = (1LL << (7 * len)) - 1;
323593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3236810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size == unknown_size)  // TODO: should never happen
3237810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;  // TODO: resolve this
323893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3239810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // assert((pCurr->m_size <= 0) || (pCurr->m_size == size));
324093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3241810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((segment_stop >= 0) && ((pos + size) > segment_stop))
3242810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
324393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3244810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // Pos now points to start of payload
324593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3246810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload (that is, the current cluster)
3247810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((segment_stop < 0) || (pos <= segment_stop));
324893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3249810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // By consuming the payload, we are assuming that the curr
3250810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // cluster isn't interesting.  That is, we don't bother checking
3251810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // whether the payload of the curr cluster is less than what
3252810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // happens to be available (obtained via IMkvReader::Length).
3253810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // Presumably the caller has already dispensed with the current
3254810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // cluster, and really does want the next cluster.
3255810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
325693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3257810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // pos now points to just beyond the last fully-loaded cluster
325893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3259810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  for (;;) {
3260810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long status = DoParseNext(pResult, pos, len);
3261810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
3262810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status <= 1)
3263810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
3264810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
326593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
326693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3267810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Segment::DoParseNext(const Cluster*& pResult, long long& pos, long& len) {
3268810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long total, avail;
326993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3270810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long status = m_pReader->Length(&total, &avail);
327193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3272810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)  // error
3273810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
327493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3275810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((total < 0) || (avail <= total));
327693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3277810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
327893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3279810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // Parse next cluster.  This is strictly a parsing activity.
3280810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // Creation of a new cluster object happens later, after the
3281810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // parsing is done.
328293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3283810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long off_next = 0;
3284810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long cluster_size = -1;
328593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3286810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  for (;;) {
3287810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((total >= 0) && (pos >= total))
3288810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 1;  // EOF
328993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3290810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((segment_stop >= 0) && (pos >= segment_stop))
3291810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 1;  // EOF
329293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3293810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > avail) {
3294810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
3295810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
3296810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
329793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3298810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long result = GetUIntLength(m_pReader, pos, len);
329993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3300810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error
3301810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(result);
330293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3303810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result > 0)  // weird
3304810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
330593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3306810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((segment_stop >= 0) && ((pos + len) > segment_stop))
3307810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
330893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3309810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > avail)
3310810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
331193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3312810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long idpos = pos;  // absolute
3313810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long idoff = pos - m_start;  // relative
331493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3315810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long id = ReadUInt(m_pReader, idpos, len);  // absolute
331693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3317810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id < 0)  // error
3318810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(id);
331993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3320810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0)  // weird
3321810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return -1;  // generic error
332293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3323810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume ID
332493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3325810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // Read Size
332693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3327810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > avail) {
3328810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
3329810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
3330810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
333193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3332810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result = GetUIntLength(m_pReader, pos, len);
333393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3334810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error
3335810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(result);
333693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3337810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result > 0)  // weird
3338810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
333993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3340810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((segment_stop >= 0) && ((pos + len) > segment_stop))
3341810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
334293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3343810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > avail)
3344810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
334593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3346810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long size = ReadUInt(m_pReader, pos, len);
334793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3348810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size < 0)  // error
3349810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(size);
335093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3351810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume length of size of element
335293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3353810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // Pos now points to start of payload
335493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3355810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size == 0)  // weird
3356810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
335793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3358810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long unknown_size = (1LL << (7 * len)) - 1;
335993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3360810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((segment_stop >= 0) && (size != unknown_size) &&
3361810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        ((pos + size) > segment_stop)) {
3362810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
3363810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
336493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3365810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x0C53BB6B) {  // Cues ID
3366810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (size == unknown_size)
3367810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
336893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3369810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long element_stop = pos + size;
337093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3371810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if ((segment_stop >= 0) && (element_stop > segment_stop))
3372810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
337393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3374810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long element_start = idpos;
3375810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long element_size = element_stop - element_start;
337693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3377810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (m_pCues == NULL) {
3378810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        m_pCues = new Cues(this, pos, size, element_start, element_size);
3379810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        assert(m_pCues);  // TODO
3380810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      }
338193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3382810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pos += size;  // consume payload
3383810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert((segment_stop < 0) || (pos <= segment_stop));
338493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3385810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
3386810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
338793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3388810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id != 0x0F43B675) {  // not a Cluster ID
3389810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (size == unknown_size)
3390810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
339193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3392810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pos += size;  // consume payload
3393810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert((segment_stop < 0) || (pos <= segment_stop));
339493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3395810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
3396810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
339793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3398810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org#if 0  // this is commented-out to support incremental cluster parsing
339993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        len = static_cast<long>(size);
340093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
340193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (element_stop > avail)
340293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return E_BUFFER_NOT_FULL;
340393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
340493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3405810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // We have a cluster.
340693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3407810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    off_next = idoff;
340893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3409810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size != unknown_size)
3410810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      cluster_size = size;
341193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3412810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    break;
3413810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
341493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3415810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(off_next > 0);  // have cluster
341693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3417810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // We have parsed the next cluster.
3418810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // We have not created a cluster object yet.  What we need
3419810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // to do now is determine whether it has already be preloaded
3420810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  //(in which case, an object for this cluster has already been
3421810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // created), and if not, create a new cluster object.
342293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3423810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** const ii = m_clusters + m_clusterCount;
3424810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** i = ii;
342593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3426810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** const jj = ii + m_clusterPreloadCount;
3427810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** j = jj;
342893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3429810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (i < j) {
3430810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // INVARIANT:
3431810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[0, i) < pos_next
3432810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[i, j) ?
3433810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[j, jj)  > pos_next
343493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3435810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster** const k = i + (j - i) / 2;
3436810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(k < jj);
343793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3438810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const Cluster* const pNext = *k;
3439810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pNext);
3440810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pNext->m_index < 0);
344193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3442810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos = pNext->GetPosition();
3443810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos >= 0);
344493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3445810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (pos < off_next)
3446810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      i = k + 1;
3447810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    else if (pos > off_next)
3448810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      j = k;
3449810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    else {
3450810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pResult = pNext;
3451810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 0;  // success
345293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
3453810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
345493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3455810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(i == j);
345693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3457810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long pos_;
3458810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long len_;
345993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3460810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  status = Cluster::HasBlockEntries(this, off_next, pos_, len_);
346193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3462810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0) {  // error or underflow
3463810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos = pos_;
3464810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    len = len_;
346593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3466810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
3467810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
346893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3469810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status > 0) {  // means "found at least one block entry"
3470810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster* const pNext = Cluster::Create(this,
3471810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                           -1,  // preloaded
3472810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                           off_next);
3473810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // element_size);
3474810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pNext);
347593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3476810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const ptrdiff_t idx_next = i - m_clusters;  // insertion position
347793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3478810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    PreloadCluster(pNext, idx_next);
3479810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(m_clusters);
3480810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(idx_next < m_clusterSize);
3481810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(m_clusters[idx_next] == pNext);
348293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3483810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pResult = pNext;
3484810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;  // success
3485810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
348693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3487810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // status == 0 means "no block entries found"
348893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3489810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (cluster_size < 0) {  // unknown size
3490810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long payload_pos = pos;  // absolute pos of cluster payload
349193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3492810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    for (;;) {  // determine cluster size
3493810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if ((total >= 0) && (pos >= total))
3494810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        break;
349593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3496810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if ((segment_stop >= 0) && (pos >= segment_stop))
3497810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        break;  // no more clusters
349893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3499810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      // Read ID
350093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3501810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if ((pos + 1) > avail) {
3502810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        len = 1;
3503810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_BUFFER_NOT_FULL;
3504810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      }
350593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3506810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      long long result = GetUIntLength(m_pReader, pos, len);
350793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3508810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (result < 0)  // error
3509810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return static_cast<long>(result);
351093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3511810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (result > 0)  // weird
3512810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_BUFFER_NOT_FULL;
351393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3514810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if ((segment_stop >= 0) && ((pos + len) > segment_stop))
3515810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
351693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3517810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if ((pos + len) > avail)
3518810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_BUFFER_NOT_FULL;
351993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3520810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long idpos = pos;
3521810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long id = ReadUInt(m_pReader, idpos, len);
352293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3523810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (id < 0)  // error (or underflow)
3524810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return static_cast<long>(id);
352593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3526810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      // This is the distinguished set of ID's we use to determine
3527810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      // that we have exhausted the sub-element's inside the cluster
3528810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      // whose ID we parsed earlier.
352993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3530810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (id == 0x0F43B675)  // Cluster ID
3531810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        break;
353293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3533810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (id == 0x0C53BB6B)  // Cues ID
3534810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        break;
353593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3536810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pos += len;  // consume ID (of sub-element)
353793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3538810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      // Read Size
353993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3540810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if ((pos + 1) > avail) {
3541810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        len = 1;
3542810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_BUFFER_NOT_FULL;
3543810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      }
354493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3545810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      result = GetUIntLength(m_pReader, pos, len);
354693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3547810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (result < 0)  // error
3548810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return static_cast<long>(result);
354993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3550810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (result > 0)  // weird
3551810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_BUFFER_NOT_FULL;
355293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3553810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if ((segment_stop >= 0) && ((pos + len) > segment_stop))
3554810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
355593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3556810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if ((pos + len) > avail)
3557810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_BUFFER_NOT_FULL;
355893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3559810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long size = ReadUInt(m_pReader, pos, len);
356093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3561810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (size < 0)  // error
3562810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return static_cast<long>(size);
356393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3564810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pos += len;  // consume size field of element
356593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3566810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      // pos now points to start of sub-element's payload
356793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3568810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (size == 0)  // weird
3569810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        continue;
357093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3571810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long unknown_size = (1LL << (7 * len)) - 1;
357293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3573810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (size == unknown_size)
3574810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;  // not allowed for sub-elements
357593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3576810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if ((segment_stop >= 0) && ((pos + size) > segment_stop))  // weird
3577810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
357893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3579810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pos += size;  // consume payload of sub-element
3580810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert((segment_stop < 0) || (pos <= segment_stop));
3581810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }  // determine cluster size
358293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3583810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    cluster_size = pos - payload_pos;
3584810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(cluster_size >= 0);  // TODO: handle cluster_size = 0
358593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3586810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos = payload_pos;  // reset and re-parse original cluster
3587810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
358893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3589810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos += cluster_size;  // consume payload
3590810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((segment_stop < 0) || (pos <= segment_stop));
359193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3592810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 2;  // try to find a cluster that follows next
3593810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org}
359493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3595810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst Cluster* Segment::FindCluster(long long time_ns) const {
3596810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((m_clusters == NULL) || (m_clusterCount <= 0))
3597810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return &m_eos;
359893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3599810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  {
3600810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster* const pCluster = m_clusters[0];
3601810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pCluster);
3602810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pCluster->m_index == 0);
360393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3604810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (time_ns <= pCluster->GetTime())
3605810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return pCluster;
3606810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
360793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3608810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // Binary search of cluster array
360993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3610810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long i = 0;
3611810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long j = m_clusterCount;
361293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3613810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (i < j) {
3614810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // INVARIANT:
3615810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[0, i) <= time_ns
3616810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[i, j) ?
3617810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[j, m_clusterCount)  > time_ns
361893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3619810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long k = i + (j - i) / 2;
3620810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(k < m_clusterCount);
362193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
362293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    Cluster* const pCluster = m_clusters[k];
362393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pCluster);
362493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pCluster->m_index == k);
362593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3626810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long t = pCluster->GetTime();
3627810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
3628810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (t <= time_ns)
3629810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      i = k + 1;
3630810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    else
3631810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      j = k;
3632810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
3633810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(i <= j);
3634810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
3635810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
3636810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(i == j);
3637810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(i > 0);
3638810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(i <= m_clusterCount);
3639810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
3640810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long k = i - 1;
3641810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
3642810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster* const pCluster = m_clusters[k];
3643810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster);
3644810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster->m_index == k);
3645810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster->GetTime() <= time_ns);
364693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3647810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return pCluster;
3648810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org}
364993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
365093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
365193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgconst BlockEntry* Segment::Seek(
365293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    long long time_ns,
365393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const Track* pTrack) const
365493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org{
365593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pTrack);
365693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
365793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if ((m_clusters == NULL) || (m_clusterCount <= 0))
365893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return pTrack->GetEOS();
365993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
366093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    Cluster** const i = m_clusters;
366193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(i);
366293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
366393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    {
366493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        Cluster* const pCluster = *i;
366593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(pCluster);
366693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(pCluster->m_index == 0);  //m_clusterCount > 0
366793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(pCluster->m_pSegment == this);
366893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
366993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (time_ns <= pCluster->GetTime())
367093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return pCluster->GetEntry(pTrack);
367193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
367293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
367393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    Cluster** const j = i + m_clusterCount;
367493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3675810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (pTrack->GetType() == 2) {  //audio
367693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //TODO: we could decide to use cues for this, as we do for video.
367793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //But we only use it for video because looking around for a keyframe
367893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //can get expensive.  Audio doesn't require anything special so a
367993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //straight cluster search is good enough (we assume).
368093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
368193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        Cluster** lo = i;
368293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        Cluster** hi = j;
368393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
368493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        while (lo < hi)
368593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        {
368693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            //INVARIANT:
368793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            //[i, lo) <= time_ns
368893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            //[lo, hi) ?
368993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            //[hi, j)  > time_ns
369093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
369193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            Cluster** const mid = lo + (hi - lo) / 2;
369293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            assert(mid < hi);
369393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
369493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            Cluster* const pCluster = *mid;
369593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            assert(pCluster);
369693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            assert(pCluster->m_index == long(mid - m_clusters));
369793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            assert(pCluster->m_pSegment == this);
369893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
369993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            const long long t = pCluster->GetTime();
370093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
370193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if (t <= time_ns)
370293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                lo = mid + 1;
370393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            else
370493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                hi = mid;
370593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
370693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            assert(lo <= hi);
370793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        }
370893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
370993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(lo == hi);
371093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(lo > i);
371193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(lo <= j);
371293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
371393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        while (lo > i)
371493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        {
371593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            Cluster* const pCluster = *--lo;
371693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            assert(pCluster);
371793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            assert(pCluster->GetTime() <= time_ns);
371893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
371993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            const BlockEntry* const pBE = pCluster->GetEntry(pTrack);
372093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
372193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if ((pBE != 0) && !pBE->EOS())
372293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                return pBE;
372393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
372493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            //landed on empty cluster (no entries)
372593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        }
372693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
372793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return pTrack->GetEOS();  //weird
372893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
372993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
373093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pTrack->GetType() == 1);  //video
373193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
373293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    Cluster** lo = i;
373393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    Cluster** hi = j;
373493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
373593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    while (lo < hi)
373693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    {
373793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //INVARIANT:
373893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //[i, lo) <= time_ns
373993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //[lo, hi) ?
374093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //[hi, j)  > time_ns
374193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
374293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        Cluster** const mid = lo + (hi - lo) / 2;
374393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(mid < hi);
374493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
374593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        Cluster* const pCluster = *mid;
374693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(pCluster);
374793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
374893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const long long t = pCluster->GetTime();
374993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
375093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (t <= time_ns)
375193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            lo = mid + 1;
375293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        else
375393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            hi = mid;
375493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
375593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(lo <= hi);
375693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
375793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
375893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(lo == hi);
375993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(lo > i);
376093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(lo <= j);
376193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
376293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    Cluster* pCluster = *--lo;
376393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pCluster);
376493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pCluster->GetTime() <= time_ns);
376593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
376693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    {
376793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const BlockEntry* const pBE = pCluster->GetEntry(pTrack, time_ns);
376893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
376993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if ((pBE != 0) && !pBE->EOS())  //found a keyframe
377093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return pBE;
377193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
377293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
377393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const VideoTrack* const pVideo = static_cast<const VideoTrack*>(pTrack);
377493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
377593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    while (lo != i)
377693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    {
377793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        pCluster = *--lo;
377893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(pCluster);
377993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(pCluster->GetTime() <= time_ns);
378093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
378193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const BlockEntry* const pBlockEntry = pCluster->GetMaxKey(pVideo);
378293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
378393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if ((pBlockEntry != 0) && !pBlockEntry->EOS())
378493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return pBlockEntry;
378593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
378693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
378793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //weird: we're on the first cluster, but no keyframe found
378893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //should never happen but we must return something anyway
378993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
379093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    return pTrack->GetEOS();
379193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
379293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
379393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
379493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
379593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgbool Segment::SearchCues(
379693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    long long time_ns,
379793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    Track* pTrack,
379893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    Cluster*& pCluster,
379993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const BlockEntry*& pBlockEntry,
380093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const CuePoint*& pCP,
380193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const CuePoint::TrackPosition*& pTP)
380293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org{
380393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (pTrack->GetType() != 1)  //not video
380493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return false;  //TODO: for now, just handle video stream
380593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
380693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (m_pCues == NULL)
380793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return false;
380893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
380993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (!m_pCues->Find(time_ns, pTrack, pCP, pTP))
381093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return false;  //weird
381193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
381293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pCP);
381393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pTP);
381493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pTP->m_track == pTrack->GetNumber());
381593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
381693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //We have the cue point and track position we want,
381793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //so we now need to search for the cluster having
381893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //the indicated position.
381993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
382093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    return GetCluster(pCP, pTP, pCluster, pBlockEntry);
382193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
382293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
382393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3824810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst Tracks* Segment::GetTracks() const { return m_pTracks; }
382593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3826810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst SegmentInfo* Segment::GetInfo() const { return m_pInfo; }
382793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3828810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst Cues* Segment::GetCues() const { return m_pCues; }
382993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3830810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst Chapters* Segment::GetChapters() const { return m_pChapters; }
383193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3832810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst SeekHead* Segment::GetSeekHead() const { return m_pSeekHead; }
383393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3834810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long Segment::GetDuration() const {
3835810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_pInfo);
3836810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return m_pInfo->GetDuration();
383793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
383893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3839810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgChapters::Chapters(Segment* pSegment, long long payload_start,
3840810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                   long long payload_size, long long element_start,
3841810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                   long long element_size)
3842810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    : m_pSegment(pSegment),
3843810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_start(payload_start),
3844810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_size(payload_size),
3845810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_element_start(element_start),
3846810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_element_size(element_size),
3847810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_editions(NULL),
3848810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_editions_size(0),
3849810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_editions_count(0) {}
385093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3851810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgChapters::~Chapters() {
3852810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (m_editions_count > 0) {
3853810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Edition& e = m_editions[--m_editions_count];
3854810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    e.Clear();
3855810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
385693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
385793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3858810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Chapters::Parse() {
3859810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  IMkvReader* const pReader = m_pSegment->m_pReader;
386093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3861810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long pos = m_start;  // payload start
3862810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long stop = pos + m_size;  // payload stop
386393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3864810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (pos < stop) {
3865810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long id, size;
386693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3867810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long status = ParseElementHeader(pReader, pos, stop, id, size);
386893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3869810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
3870810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
387193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3872810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size == 0)  // weird
3873810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
387493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3875810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x05B9) {  // EditionEntry ID
3876810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      status = ParseEdition(pos, size);
387793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3878810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status < 0)  // error
3879810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
388093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
388193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3882810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;
3883810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos <= stop);
3884810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
388593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3886810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos == stop);
3887810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;
388893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
388993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3890810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgint Chapters::GetEditionCount() const { return m_editions_count; }
389193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3892810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst Chapters::Edition* Chapters::GetEdition(int idx) const {
3893810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (idx < 0)
3894810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return NULL;
389593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3896810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (idx >= m_editions_count)
3897810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return NULL;
389893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3899810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return m_editions + idx;
390093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
390193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3902810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgbool Chapters::ExpandEditionsArray() {
3903810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_editions_size > m_editions_count)
3904810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return true;  // nothing else to do
390593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3906810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const int size = (m_editions_size == 0) ? 1 : 2 * m_editions_size;
390793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3908810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Edition* const editions = new (std::nothrow) Edition[size];
390993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3910810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (editions == NULL)
3911810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
391293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3913810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  for (int idx = 0; idx < m_editions_count; ++idx) {
3914810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m_editions[idx].ShallowCopy(editions[idx]);
3915810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
391693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3917810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] m_editions;
3918810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_editions = editions;
391993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3920810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_editions_size = size;
3921810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return true;
392293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
392393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3924810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Chapters::ParseEdition(long long pos, long long size) {
3925810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (!ExpandEditionsArray())
3926810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
392793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3928810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Edition& e = m_editions[m_editions_count++];
3929810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  e.Init();
393093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3931810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return e.Parse(m_pSegment->m_pReader, pos, size);
393293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
393393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3934810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgChapters::Edition::Edition() {}
393593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3936810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgChapters::Edition::~Edition() {}
393793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3938810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgint Chapters::Edition::GetAtomCount() const { return m_atoms_count; }
393993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3940810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst Chapters::Atom* Chapters::Edition::GetAtom(int index) const {
3941810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (index < 0)
3942810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return NULL;
394393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3944810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (index >= m_atoms_count)
3945810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return NULL;
394693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3947810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return m_atoms + index;
394893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
394993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3950810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgvoid Chapters::Edition::Init() {
3951810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_atoms = NULL;
3952810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_atoms_size = 0;
3953810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_atoms_count = 0;
395493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
395593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3956810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgvoid Chapters::Edition::ShallowCopy(Edition& rhs) const {
3957810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  rhs.m_atoms = m_atoms;
3958810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  rhs.m_atoms_size = m_atoms_size;
3959810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  rhs.m_atoms_count = m_atoms_count;
396093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
396193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3962810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgvoid Chapters::Edition::Clear() {
3963810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (m_atoms_count > 0) {
3964810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Atom& a = m_atoms[--m_atoms_count];
3965810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    a.Clear();
3966810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
396793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3968810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] m_atoms;
3969810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_atoms = NULL;
397093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3971810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_atoms_size = 0;
397293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
397393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3974810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Chapters::Edition::Parse(IMkvReader* pReader, long long pos,
3975810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                              long long size) {
3976810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long stop = pos + size;
397793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3978810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (pos < stop) {
3979810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long id, size;
398093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3981810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long status = ParseElementHeader(pReader, pos, stop, id, size);
398293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3983810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
3984810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
398593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3986810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size == 0)  // weird
3987810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
398893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3989810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x36) {  // Atom ID
3990810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      status = ParseAtom(pReader, pos, size);
399193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3992810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status < 0)  // error
3993810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
399493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
399593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3996810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;
3997810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos <= stop);
3998810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
399993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4000810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos == stop);
4001810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;
400293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
400393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4004810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Chapters::Edition::ParseAtom(IMkvReader* pReader, long long pos,
4005810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                  long long size) {
4006810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (!ExpandAtomsArray())
4007810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
400893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4009810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Atom& a = m_atoms[m_atoms_count++];
4010810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  a.Init();
401193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4012810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return a.Parse(pReader, pos, size);
401393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
401493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4015810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgbool Chapters::Edition::ExpandAtomsArray() {
4016810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_atoms_size > m_atoms_count)
4017810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return true;  // nothing else to do
401893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4019810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const int size = (m_atoms_size == 0) ? 1 : 2 * m_atoms_size;
402093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4021810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Atom* const atoms = new (std::nothrow) Atom[size];
402293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4023810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (atoms == NULL)
4024810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
402593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4026810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  for (int idx = 0; idx < m_atoms_count; ++idx) {
4027810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m_atoms[idx].ShallowCopy(atoms[idx]);
4028810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
402993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4030810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] m_atoms;
4031810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_atoms = atoms;
403293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4033810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_atoms_size = size;
4034810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return true;
403593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
403693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4037810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgChapters::Atom::Atom() {}
403893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4039810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgChapters::Atom::~Atom() {}
404093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4041810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgunsigned long long Chapters::Atom::GetUID() const { return m_uid; }
404293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4043810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst char* Chapters::Atom::GetStringUID() const { return m_string_uid; }
404493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4045810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long Chapters::Atom::GetStartTimecode() const { return m_start_timecode; }
404693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4047810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long Chapters::Atom::GetStopTimecode() const { return m_stop_timecode; }
404893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4049810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long Chapters::Atom::GetStartTime(const Chapters* pChapters) const {
4050810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return GetTime(pChapters, m_start_timecode);
405193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
405293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4053810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long Chapters::Atom::GetStopTime(const Chapters* pChapters) const {
4054810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return GetTime(pChapters, m_stop_timecode);
405593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
405693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4057810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgint Chapters::Atom::GetDisplayCount() const { return m_displays_count; }
405893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4059810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst Chapters::Display* Chapters::Atom::GetDisplay(int index) const {
4060810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (index < 0)
4061810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return NULL;
406293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4063810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (index >= m_displays_count)
4064810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return NULL;
406593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4066810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return m_displays + index;
406793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
406893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4069810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgvoid Chapters::Atom::Init() {
4070810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_string_uid = NULL;
4071810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_uid = 0;
4072810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_start_timecode = -1;
4073810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_stop_timecode = -1;
407493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4075810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_displays = NULL;
4076810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_displays_size = 0;
4077810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_displays_count = 0;
407893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
407993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4080810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgvoid Chapters::Atom::ShallowCopy(Atom& rhs) const {
4081810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  rhs.m_string_uid = m_string_uid;
4082810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  rhs.m_uid = m_uid;
4083810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  rhs.m_start_timecode = m_start_timecode;
4084810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  rhs.m_stop_timecode = m_stop_timecode;
408593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4086810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  rhs.m_displays = m_displays;
4087810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  rhs.m_displays_size = m_displays_size;
4088810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  rhs.m_displays_count = m_displays_count;
408993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
409093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4091810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgvoid Chapters::Atom::Clear() {
4092810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] m_string_uid;
4093810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_string_uid = NULL;
409493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4095810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (m_displays_count > 0) {
4096810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Display& d = m_displays[--m_displays_count];
4097810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    d.Clear();
4098810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
409993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4100810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] m_displays;
4101810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_displays = NULL;
410293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4103810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_displays_size = 0;
410493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
410593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4106810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Chapters::Atom::Parse(IMkvReader* pReader, long long pos, long long size) {
4107810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long stop = pos + size;
410893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4109810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (pos < stop) {
4110810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long id, size;
411193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4112810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long status = ParseElementHeader(pReader, pos, stop, id, size);
411393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4114810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
4115810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
411693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4117810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size == 0)  // weird
4118810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
411993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4120810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x00) {  // Display ID
4121810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      status = ParseDisplay(pReader, pos, size);
412293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4123810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status < 0)  // error
4124810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
4125810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x1654) {  // StringUID ID
4126810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      status = UnserializeString(pReader, pos, size, m_string_uid);
412793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4128810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status < 0)  // error
4129810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
4130810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x33C4) {  // UID ID
4131810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long val = UnserializeUInt(pReader, pos, size);
413293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4133810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (val < 0)  // error
4134810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return static_cast<long>(val);
413593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4136810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_uid = val;
4137810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x11) {  // TimeStart ID
4138810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long val = UnserializeUInt(pReader, pos, size);
413993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4140810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (val < 0)  // error
4141810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return static_cast<long>(val);
414293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4143810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_start_timecode = val;
4144810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x12) {  // TimeEnd ID
4145810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long val = UnserializeUInt(pReader, pos, size);
414693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4147810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (val < 0)  // error
4148810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return static_cast<long>(val);
414993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4150810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_stop_timecode = val;
4151810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
415293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4153810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;
4154810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos <= stop);
4155810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
415693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4157810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos == stop);
4158810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;
4159810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org}
416093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4161810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long Chapters::Atom::GetTime(const Chapters* pChapters,
4162810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                  long long timecode) {
4163810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pChapters == NULL)
4164810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
416593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4166810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Segment* const pSegment = pChapters->m_pSegment;
416793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4168810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pSegment == NULL)  // weird
4169810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
417093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4171810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const SegmentInfo* const pInfo = pSegment->GetInfo();
417293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4173810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pInfo == NULL)
4174810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
417593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4176810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long timecode_scale = pInfo->GetTimeCodeScale();
417793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4178810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (timecode_scale < 1)  // weird
4179810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
418093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4181810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (timecode < 0)
4182810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
418393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4184810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long result = timecode_scale * timecode;
418593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4186810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return result;
418793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
418893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4189810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Chapters::Atom::ParseDisplay(IMkvReader* pReader, long long pos,
4190810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                  long long size) {
4191810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (!ExpandDisplaysArray())
4192810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
419393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4194810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Display& d = m_displays[m_displays_count++];
4195810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  d.Init();
4196810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
4197810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return d.Parse(pReader, pos, size);
419893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
419993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4200810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgbool Chapters::Atom::ExpandDisplaysArray() {
4201810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_displays_size > m_displays_count)
4202810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return true;  // nothing else to do
420393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4204810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const int size = (m_displays_size == 0) ? 1 : 2 * m_displays_size;
420593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4206810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Display* const displays = new (std::nothrow) Display[size];
420793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4208810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (displays == NULL)
4209810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
421093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4211810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  for (int idx = 0; idx < m_displays_count; ++idx) {
4212810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m_displays[idx].ShallowCopy(displays[idx]);
4213810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
421493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4215810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] m_displays;
4216810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_displays = displays;
4217810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
4218810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_displays_size = size;
4219810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return true;
422093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
422193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4222810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgChapters::Display::Display() {}
422393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4224810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgChapters::Display::~Display() {}
422593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4226810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst char* Chapters::Display::GetString() const { return m_string; }
422793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4228810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst char* Chapters::Display::GetLanguage() const { return m_language; }
422993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4230810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst char* Chapters::Display::GetCountry() const { return m_country; }
423193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4232810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgvoid Chapters::Display::Init() {
4233810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_string = NULL;
4234810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_language = NULL;
4235810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_country = NULL;
423693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
423793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4238810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgvoid Chapters::Display::ShallowCopy(Display& rhs) const {
4239810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  rhs.m_string = m_string;
4240810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  rhs.m_language = m_language;
4241810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  rhs.m_country = m_country;
4242810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org}
424393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4244810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgvoid Chapters::Display::Clear() {
4245810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] m_string;
4246810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_string = NULL;
424793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4248810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] m_language;
4249810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_language = NULL;
425093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4251810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] m_country;
4252810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_country = NULL;
425393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
425493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4255810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Chapters::Display::Parse(IMkvReader* pReader, long long pos,
4256810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                              long long size) {
4257810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long stop = pos + size;
425893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4259810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (pos < stop) {
4260810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long id, size;
426193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4262810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long status = ParseElementHeader(pReader, pos, stop, id, size);
426393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4264810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
4265810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
426693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4267810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size == 0)  // weird
4268810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
426993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4270810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x05) {  // ChapterString ID
4271810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      status = UnserializeString(pReader, pos, size, m_string);
427293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4273810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status)
4274810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
4275810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x037C) {  // ChapterLanguage ID
4276810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      status = UnserializeString(pReader, pos, size, m_language);
427793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4278810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status)
4279810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
4280810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x037E) {  // ChapterCountry ID
4281810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      status = UnserializeString(pReader, pos, size, m_country);
428293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4283810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status)
4284810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
428593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
428693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4287810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;
4288810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos <= stop);
4289810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
429093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4291810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos == stop);
4292810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;
429393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
429493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4295810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgSegmentInfo::SegmentInfo(Segment* pSegment, long long start, long long size_,
4296810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                         long long element_start, long long element_size)
4297810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    : m_pSegment(pSegment),
4298810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_start(start),
4299810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_size(size_),
4300810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_element_start(element_start),
4301810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_element_size(element_size),
4302810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pMuxingAppAsUTF8(NULL),
4303810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pWritingAppAsUTF8(NULL),
4304810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pTitleAsUTF8(NULL) {}
430593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4306810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgSegmentInfo::~SegmentInfo() {
4307810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] m_pMuxingAppAsUTF8;
4308810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_pMuxingAppAsUTF8 = NULL;
430993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4310810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] m_pWritingAppAsUTF8;
4311810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_pWritingAppAsUTF8 = NULL;
4312810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
4313810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] m_pTitleAsUTF8;
4314810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_pTitleAsUTF8 = NULL;
431593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
431693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4317810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong SegmentInfo::Parse() {
4318810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_pMuxingAppAsUTF8 == NULL);
4319810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_pWritingAppAsUTF8 == NULL);
4320810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_pTitleAsUTF8 == NULL);
432193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4322810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  IMkvReader* const pReader = m_pSegment->m_pReader;
432393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4324810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long pos = m_start;
4325810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long stop = m_start + m_size;
432693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4327810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_timecodeScale = 1000000;
4328810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_duration = -1;
432993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4330810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (pos < stop) {
4331810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long id, size;
433293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4333810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long status = ParseElementHeader(pReader, pos, stop, id, size);
433493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4335810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
4336810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
433793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4338810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x0AD7B1) {  // Timecode Scale
4339810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_timecodeScale = UnserializeUInt(pReader, pos, size);
434093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4341810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (m_timecodeScale <= 0)
4342810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
4343810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x0489) {  // Segment duration
4344810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long status = UnserializeFloat(pReader, pos, size, m_duration);
434593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4346810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status < 0)
4347810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
434893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4349810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (m_duration < 0)
4350810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
4351810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x0D80) {  // MuxingApp
4352810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long status =
4353810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          UnserializeString(pReader, pos, size, m_pMuxingAppAsUTF8);
435493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4355810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status)
4356810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
4357810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x1741) {  // WritingApp
4358810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long status =
4359810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          UnserializeString(pReader, pos, size, m_pWritingAppAsUTF8);
436093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4361810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status)
4362810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
4363810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x3BA9) {  // Title
4364810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long status = UnserializeString(pReader, pos, size, m_pTitleAsUTF8);
436593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4366810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status)
4367810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
4368810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
436993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4370810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;
4371810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos <= stop);
4372810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
437393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4374810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos == stop);
437593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4376810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;
437793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
437893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4379810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long SegmentInfo::GetTimeCodeScale() const { return m_timecodeScale; }
438093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4381810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long SegmentInfo::GetDuration() const {
4382810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_duration < 0)
4383810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
438493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4385810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_timecodeScale >= 1);
438693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4387810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const double dd = double(m_duration) * double(m_timecodeScale);
4388810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long d = static_cast<long long>(dd);
438993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4390810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return d;
439193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
439293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4393810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst char* SegmentInfo::GetMuxingAppAsUTF8() const {
4394810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return m_pMuxingAppAsUTF8;
439593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
439693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4397810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst char* SegmentInfo::GetWritingAppAsUTF8() const {
4398810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return m_pWritingAppAsUTF8;
439993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
440093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4401810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst char* SegmentInfo::GetTitleAsUTF8() const { return m_pTitleAsUTF8; }
440293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
440393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org///////////////////////////////////////////////////////////////
440493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// ContentEncoding element
440593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgContentEncoding::ContentCompression::ContentCompression()
4406810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    : algo(0), settings(NULL), settings_len(0) {}
440793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
440893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgContentEncoding::ContentCompression::~ContentCompression() {
4409810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] settings;
441093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
441193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
441293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgContentEncoding::ContentEncryption::ContentEncryption()
441393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    : algo(0),
441493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      key_id(NULL),
441593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      key_id_len(0),
441693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      signature(NULL),
441793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      signature_len(0),
441893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      sig_key_id(NULL),
441993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      sig_key_id_len(0),
442093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      sig_algo(0),
4421810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      sig_hash_algo(0) {}
442293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
442393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgContentEncoding::ContentEncryption::~ContentEncryption() {
4424810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] key_id;
4425810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] signature;
4426810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] sig_key_id;
442793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
442893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
442993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgContentEncoding::ContentEncoding()
443093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    : compression_entries_(NULL),
443193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      compression_entries_end_(NULL),
443293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      encryption_entries_(NULL),
443393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      encryption_entries_end_(NULL),
443493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      encoding_order_(0),
443593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      encoding_scope_(1),
4436810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      encoding_type_(0) {}
443793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
443893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgContentEncoding::~ContentEncoding() {
443993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  ContentCompression** comp_i = compression_entries_;
444093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  ContentCompression** const comp_j = compression_entries_end_;
444193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
444293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  while (comp_i != comp_j) {
444393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    ContentCompression* const comp = *comp_i++;
444493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    delete comp;
444593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  }
444693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4447810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] compression_entries_;
444893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
444993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  ContentEncryption** enc_i = encryption_entries_;
445093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  ContentEncryption** const enc_j = encryption_entries_end_;
445193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
445293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  while (enc_i != enc_j) {
445393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    ContentEncryption* const enc = *enc_i++;
445493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    delete enc;
445593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  }
445693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4457810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] encryption_entries_;
445893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
445993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
446093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgconst ContentEncoding::ContentCompression*
446193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgContentEncoding::GetCompressionByIndex(unsigned long idx) const {
446293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  const ptrdiff_t count = compression_entries_end_ - compression_entries_;
446393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  assert(count >= 0);
446493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
446593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  if (idx >= static_cast<unsigned long>(count))
446693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    return NULL;
446793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
446893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  return compression_entries_[idx];
446993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
447093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
447193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgunsigned long ContentEncoding::GetCompressionCount() const {
447293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  const ptrdiff_t count = compression_entries_end_ - compression_entries_;
447393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  assert(count >= 0);
447493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
447593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  return static_cast<unsigned long>(count);
447693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
447793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4478810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst ContentEncoding::ContentEncryption* ContentEncoding::GetEncryptionByIndex(
4479810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    unsigned long idx) const {
448093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  const ptrdiff_t count = encryption_entries_end_ - encryption_entries_;
448193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  assert(count >= 0);
448293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
448393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  if (idx >= static_cast<unsigned long>(count))
448493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    return NULL;
448593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
448693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  return encryption_entries_[idx];
448793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
448893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
448993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgunsigned long ContentEncoding::GetEncryptionCount() const {
449093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  const ptrdiff_t count = encryption_entries_end_ - encryption_entries_;
449193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  assert(count >= 0);
449293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
449393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  return static_cast<unsigned long>(count);
449493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
449593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
449693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orglong ContentEncoding::ParseContentEncAESSettingsEntry(
4497810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long start, long long size, IMkvReader* pReader,
449893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    ContentEncAESSettings* aes) {
449993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  assert(pReader);
450093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  assert(aes);
450193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
450293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  long long pos = start;
450393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  const long long stop = start + size;
450493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
450593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  while (pos < stop) {
450693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    long long id, size;
4507810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long status = ParseElementHeader(pReader, pos, stop, id, size);
4508810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
450993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      return status;
451093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
451193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (id == 0x7E8) {
451293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      // AESSettingsCipherMode
451393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      aes->cipher_mode = UnserializeUInt(pReader, pos, size);
451493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (aes->cipher_mode != 1)
451593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return E_FILE_FORMAT_INVALID;
451693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
451793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4518810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
451993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pos <= stop);
452093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  }
452193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
452293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  return 0;
452393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
452493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4525810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong ContentEncoding::ParseContentEncodingEntry(long long start, long long size,
452693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                                                IMkvReader* pReader) {
452793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  assert(pReader);
452893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
452993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  long long pos = start;
453093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  const long long stop = start + size;
453193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
453293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  // Count ContentCompression and ContentEncryption elements.
453393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  int compression_count = 0;
453493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  int encryption_count = 0;
453593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
453693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  while (pos < stop) {
453793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    long long id, size;
4538810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long status = ParseElementHeader(pReader, pos, stop, id, size);
4539810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
454093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      return status;
454193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
454293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (id == 0x1034)  // ContentCompression ID
454393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      ++compression_count;
454493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
454593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (id == 0x1035)  // ContentEncryption ID
454693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      ++encryption_count;
454793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4548810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
454993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pos <= stop);
455093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  }
455193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
455293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  if (compression_count <= 0 && encryption_count <= 0)
455393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    return -1;
455493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
455593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  if (compression_count > 0) {
455693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    compression_entries_ =
4557810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        new (std::nothrow) ContentCompression* [compression_count];
455893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (!compression_entries_)
455993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      return -1;
456093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    compression_entries_end_ = compression_entries_;
456193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  }
456293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
456393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  if (encryption_count > 0) {
456493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    encryption_entries_ =
4565810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        new (std::nothrow) ContentEncryption* [encryption_count];
456693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (!encryption_entries_) {
4567810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      delete[] compression_entries_;
456893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      return -1;
456993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
457093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    encryption_entries_end_ = encryption_entries_;
457193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  }
457293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
457393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  pos = start;
457493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  while (pos < stop) {
457593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    long long id, size;
4576810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long status = ParseElementHeader(pReader, pos, stop, id, size);
4577810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
457893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      return status;
457993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
458093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (id == 0x1031) {
458193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      // ContentEncodingOrder
458293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      encoding_order_ = UnserializeUInt(pReader, pos, size);
458393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    } else if (id == 0x1032) {
458493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      // ContentEncodingScope
458593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      encoding_scope_ = UnserializeUInt(pReader, pos, size);
458693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (encoding_scope_ < 1)
458793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return -1;
458893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    } else if (id == 0x1033) {
458993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      // ContentEncodingType
459093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      encoding_type_ = UnserializeUInt(pReader, pos, size);
459193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    } else if (id == 0x1034) {
459293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      // ContentCompression ID
459393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      ContentCompression* const compression =
4594810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          new (std::nothrow) ContentCompression();
459593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (!compression)
459693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return -1;
459793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
459893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      status = ParseCompressionEntry(pos, size, pReader, compression);
459993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (status) {
460093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        delete compression;
460193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return status;
460293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      }
460393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      *compression_entries_end_++ = compression;
460493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    } else if (id == 0x1035) {
460593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      // ContentEncryption ID
460693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      ContentEncryption* const encryption =
460793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org          new (std::nothrow) ContentEncryption();
460893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (!encryption)
460993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return -1;
461093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
461193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      status = ParseEncryptionEntry(pos, size, pReader, encryption);
461293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (status) {
461393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        delete encryption;
461493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return status;
461593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      }
461693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      *encryption_entries_end_++ = encryption;
461793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
461893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4619810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
462093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pos <= stop);
462193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  }
462293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
462393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  assert(pos == stop);
462493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  return 0;
462593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
462693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4627810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong ContentEncoding::ParseCompressionEntry(long long start, long long size,
4628810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                            IMkvReader* pReader,
4629810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                            ContentCompression* compression) {
463093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  assert(pReader);
463193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  assert(compression);
463293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
463393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  long long pos = start;
463493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  const long long stop = start + size;
463593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
463693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  bool valid = false;
463793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
463893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  while (pos < stop) {
463993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    long long id, size;
4640810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long status = ParseElementHeader(pReader, pos, stop, id, size);
4641810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
464293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      return status;
464393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
464493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (id == 0x254) {
464593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      // ContentCompAlgo
464693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      long long algo = UnserializeUInt(pReader, pos, size);
464793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (algo < 0)
464893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return E_FILE_FORMAT_INVALID;
464993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      compression->algo = algo;
465093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      valid = true;
465193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    } else if (id == 0x255) {
465293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      // ContentCompSettings
465393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (size <= 0)
465493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return E_FILE_FORMAT_INVALID;
465593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
465693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      const size_t buflen = static_cast<size_t>(size);
465793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      typedef unsigned char* buf_t;
465893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      const buf_t buf = new (std::nothrow) unsigned char[buflen];
465993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (buf == NULL)
466093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return -1;
466193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4662810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const int read_status =
4663810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          pReader->Read(pos, static_cast<long>(buflen), buf);
466493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (read_status) {
4665810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        delete[] buf;
466693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return status;
466793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      }
466893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
466993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      compression->settings = buf;
467093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      compression->settings_len = buflen;
467193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
467293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4673810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
467493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pos <= stop);
467593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  }
467693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
467793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  // ContentCompAlgo is mandatory
467893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  if (!valid)
467993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    return E_FILE_FORMAT_INVALID;
468093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
468193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  return 0;
468293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
468393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4684810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong ContentEncoding::ParseEncryptionEntry(long long start, long long size,
4685810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                           IMkvReader* pReader,
4686810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                           ContentEncryption* encryption) {
468793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  assert(pReader);
468893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  assert(encryption);
468993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
469093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  long long pos = start;
469193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  const long long stop = start + size;
469293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
469393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  while (pos < stop) {
469493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    long long id, size;
4695810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long status = ParseElementHeader(pReader, pos, stop, id, size);
4696810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
469793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      return status;
469893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
469993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (id == 0x7E1) {
470093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      // ContentEncAlgo
470193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      encryption->algo = UnserializeUInt(pReader, pos, size);
470293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (encryption->algo != 5)
470393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return E_FILE_FORMAT_INVALID;
470493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    } else if (id == 0x7E2) {
470593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      // ContentEncKeyID
4706810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      delete[] encryption -> key_id;
470793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      encryption->key_id = NULL;
470893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      encryption->key_id_len = 0;
470993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
471093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (size <= 0)
471193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return E_FILE_FORMAT_INVALID;
471293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
471393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      const size_t buflen = static_cast<size_t>(size);
471493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      typedef unsigned char* buf_t;
471593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      const buf_t buf = new (std::nothrow) unsigned char[buflen];
471693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (buf == NULL)
471793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return -1;
471893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4719810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const int read_status =
4720810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          pReader->Read(pos, static_cast<long>(buflen), buf);
472193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (read_status) {
4722810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        delete[] buf;
472393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return status;
472493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      }
472593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
472693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      encryption->key_id = buf;
472793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      encryption->key_id_len = buflen;
472893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    } else if (id == 0x7E3) {
472993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      // ContentSignature
4730810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      delete[] encryption -> signature;
473193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      encryption->signature = NULL;
473293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      encryption->signature_len = 0;
473393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
473493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (size <= 0)
473593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return E_FILE_FORMAT_INVALID;
473693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
473793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      const size_t buflen = static_cast<size_t>(size);
473893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      typedef unsigned char* buf_t;
473993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      const buf_t buf = new (std::nothrow) unsigned char[buflen];
474093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (buf == NULL)
474193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return -1;
474293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4743810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const int read_status =
4744810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          pReader->Read(pos, static_cast<long>(buflen), buf);
474593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (read_status) {
4746810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        delete[] buf;
474793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return status;
474893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      }
474993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
475093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      encryption->signature = buf;
475193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      encryption->signature_len = buflen;
475293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    } else if (id == 0x7E4) {
475393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      // ContentSigKeyID
4754810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      delete[] encryption -> sig_key_id;
475593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      encryption->sig_key_id = NULL;
475693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      encryption->sig_key_id_len = 0;
475793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
475893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (size <= 0)
475993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return E_FILE_FORMAT_INVALID;
476093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
476193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      const size_t buflen = static_cast<size_t>(size);
476293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      typedef unsigned char* buf_t;
476393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      const buf_t buf = new (std::nothrow) unsigned char[buflen];
476493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (buf == NULL)
476593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return -1;
476693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4767810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const int read_status =
4768810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          pReader->Read(pos, static_cast<long>(buflen), buf);
476993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (read_status) {
4770810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        delete[] buf;
477193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return status;
477293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      }
477393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
477493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      encryption->sig_key_id = buf;
477593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      encryption->sig_key_id_len = buflen;
477693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    } else if (id == 0x7E5) {
477793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      // ContentSigAlgo
477893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      encryption->sig_algo = UnserializeUInt(pReader, pos, size);
477993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    } else if (id == 0x7E6) {
478093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      // ContentSigHashAlgo
478193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      encryption->sig_hash_algo = UnserializeUInt(pReader, pos, size);
478293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    } else if (id == 0x7E7) {
478393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      // ContentEncAESSettings
478493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      const long status = ParseContentEncAESSettingsEntry(
4785810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          pos, size, pReader, &encryption->aes_settings);
478693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (status)
478793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return status;
478893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
478993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4790810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
479193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pos <= stop);
479293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  }
479393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
479493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  return 0;
479593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
479693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4797810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgTrack::Track(Segment* pSegment, long long element_start, long long element_size)
4798810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    : m_pSegment(pSegment),
4799810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_element_start(element_start),
4800810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_element_size(element_size),
4801810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      content_encoding_entries_(NULL),
4802810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      content_encoding_entries_end_(NULL) {}
480393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4804810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgTrack::~Track() {
4805810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Info& info = const_cast<Info&>(m_info);
4806810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  info.Clear();
480793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4808810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  ContentEncoding** i = content_encoding_entries_;
4809810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  ContentEncoding** const j = content_encoding_entries_end_;
481093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4811810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (i != j) {
4812810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    ContentEncoding* const encoding = *i++;
4813810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    delete encoding;
4814810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
481593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4816810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] content_encoding_entries_;
481793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
481893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4819810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Track::Create(Segment* pSegment, const Info& info, long long element_start,
4820810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                   long long element_size, Track*& pResult) {
4821810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pResult)
4822810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
482393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4824810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Track* const pTrack =
4825810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      new (std::nothrow) Track(pSegment, element_start, element_size);
482693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4827810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pTrack == NULL)
4828810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;  // generic error
482993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4830810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const int status = info.Copy(pTrack->m_info);
483193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4832810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status) {  // error
4833810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    delete pTrack;
4834810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
4835810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
483693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4837810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pResult = pTrack;
4838810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;  // success
483993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
484093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4841810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgTrack::Info::Info()
4842810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    : uid(0),
4843810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      defaultDuration(0),
4844810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      codecDelay(0),
4845810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      seekPreRoll(0),
4846810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      nameAsUTF8(NULL),
4847810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      language(NULL),
4848810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      codecId(NULL),
4849810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      codecNameAsUTF8(NULL),
4850810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      codecPrivate(NULL),
4851810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      codecPrivateSize(0),
4852810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      lacing(false) {}
485393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4854810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgTrack::Info::~Info() { Clear(); }
485593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4856810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgvoid Track::Info::Clear() {
4857810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] nameAsUTF8;
4858810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  nameAsUTF8 = NULL;
485993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4860810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] language;
4861810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  language = NULL;
486293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4863810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] codecId;
4864810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  codecId = NULL;
486593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4866810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] codecPrivate;
4867810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  codecPrivate = NULL;
4868810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  codecPrivateSize = 0;
4869810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
4870810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] codecNameAsUTF8;
4871810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  codecNameAsUTF8 = NULL;
487293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
487393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4874810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgint Track::Info::CopyStr(char* Info::*str, Info& dst_) const {
4875810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (str == static_cast<char * Info::*>(NULL))
4876810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
487793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4878810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  char*& dst = dst_.*str;
487993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4880810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (dst)  // should be NULL already
4881810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
488293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4883810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const char* const src = this->*str;
488493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4885810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (src == NULL)
4886810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;
488793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4888810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const size_t len = strlen(src);
488993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4890810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  dst = new (std::nothrow) char[len + 1];
489193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4892810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (dst == NULL)
4893810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
489493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4895810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  strcpy(dst, src);
489693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4897810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;
489893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
489993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4900810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgint Track::Info::Copy(Info& dst) const {
4901810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (&dst == this)
4902810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;
490393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4904810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  dst.type = type;
4905810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  dst.number = number;
4906810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  dst.defaultDuration = defaultDuration;
4907810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  dst.codecDelay = codecDelay;
4908810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  dst.seekPreRoll = seekPreRoll;
4909810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  dst.uid = uid;
4910810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  dst.lacing = lacing;
4911810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  dst.settings = settings;
4912810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
4913810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // We now copy the string member variables from src to dst.
4914810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // This involves memory allocation so in principle the operation
4915810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // can fail (indeed, that's why we have Info::Copy), so we must
4916810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // report this to the caller.  An error return from this function
4917810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // therefore implies that the copy was only partially successful.
4918810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
4919810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (int status = CopyStr(&Info::nameAsUTF8, dst))
4920810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
492193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4922810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (int status = CopyStr(&Info::language, dst))
4923810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
492493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4925810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (int status = CopyStr(&Info::codecId, dst))
4926810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
492793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4928810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (int status = CopyStr(&Info::codecNameAsUTF8, dst))
4929810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
493093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4931810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (codecPrivateSize > 0) {
4932810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (codecPrivate == NULL)
4933810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return -1;
493493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4935810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (dst.codecPrivate)
4936810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return -1;
493793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4938810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (dst.codecPrivateSize != 0)
4939810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return -1;
494093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4941810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    dst.codecPrivate = new (std::nothrow) unsigned char[codecPrivateSize];
494293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4943810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (dst.codecPrivate == NULL)
4944810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return -1;
494593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4946810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    memcpy(dst.codecPrivate, codecPrivate, codecPrivateSize);
4947810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    dst.codecPrivateSize = codecPrivateSize;
4948810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
494993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4950810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;
495193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
495293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4953810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst BlockEntry* Track::GetEOS() const { return &m_eos; }
495493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4955810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Track::GetType() const { return m_info.type; }
495693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4957810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Track::GetNumber() const { return m_info.number; }
495893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4959810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgunsigned long long Track::GetUid() const { return m_info.uid; }
496093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4961810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst char* Track::GetNameAsUTF8() const { return m_info.nameAsUTF8; }
496293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4963810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst char* Track::GetLanguage() const { return m_info.language; }
496493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4965810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst char* Track::GetCodecNameAsUTF8() const { return m_info.codecNameAsUTF8; }
496693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4967810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst char* Track::GetCodecId() const { return m_info.codecId; }
496893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4969810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst unsigned char* Track::GetCodecPrivate(size_t& size) const {
4970810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  size = m_info.codecPrivateSize;
4971810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return m_info.codecPrivate;
497293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
497393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4974810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgbool Track::GetLacing() const { return m_info.lacing; }
497593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4976810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgunsigned long long Track::GetDefaultDuration() const {
4977810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return m_info.defaultDuration;
497893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
497993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4980810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgunsigned long long Track::GetCodecDelay() const { return m_info.codecDelay; }
498193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4982810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgunsigned long long Track::GetSeekPreRoll() const { return m_info.seekPreRoll; }
498393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4984810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Track::GetFirst(const BlockEntry*& pBlockEntry) const {
4985810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const Cluster* pCluster = m_pSegment->GetFirst();
498693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4987810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  for (int i = 0;;) {
4988810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (pCluster == NULL) {
4989810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pBlockEntry = GetEOS();
4990810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 1;
4991810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
499293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4993810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (pCluster->EOS()) {
499493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
4995810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org            if (m_pSegment->Unparsed() <= 0) {  //all clusters have been loaded
499693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                pBlockEntry = GetEOS();
499793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                return 1;
499893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            }
499993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#else
5000810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (m_pSegment->DoneParsing()) {
5001810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        pBlockEntry = GetEOS();
5002810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return 1;
5003810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      }
500493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
500593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5006810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pBlockEntry = 0;
5007810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
5008810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
500993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5010810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long status = pCluster->GetFirst(pBlockEntry);
501193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5012810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
5013810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
501493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5015810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (pBlockEntry == 0) {  // empty cluster
5016810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pCluster = m_pSegment->GetNext(pCluster);
5017810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
5018810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
501993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5020810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    for (;;) {
5021810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const Block* const pBlock = pBlockEntry->GetBlock();
5022810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(pBlock);
502393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5024810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long tn = pBlock->GetTrackNumber();
502593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5026810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if ((tn == m_info.number) && VetEntry(pBlockEntry))
5027810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return 0;
502893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5029810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const BlockEntry* pNextEntry;
503093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5031810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      status = pCluster->GetNext(pBlockEntry, pNextEntry);
503293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5033810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status < 0)  // error
5034810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
503593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5036810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (pNextEntry == 0)
5037810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        break;
503893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5039810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pBlockEntry = pNextEntry;
5040810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
504193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5042810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    ++i;
504393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5044810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (i >= 100)
5045810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      break;
504693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5047810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pCluster = m_pSegment->GetNext(pCluster);
5048810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
504993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5050810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // NOTE: if we get here, it means that we didn't find a block with
5051810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // a matching track number.  We interpret that as an error (which
5052810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // might be too conservative).
505393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5054810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pBlockEntry = GetEOS();  // so we can return a non-NULL value
5055810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 1;
505693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
505793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5058810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Track::GetNext(const BlockEntry* pCurrEntry,
5059810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                    const BlockEntry*& pNextEntry) const {
5060810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCurrEntry);
5061810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(!pCurrEntry->EOS());  //?
506293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5063810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const Block* const pCurrBlock = pCurrEntry->GetBlock();
5064810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCurrBlock && pCurrBlock->GetTrackNumber() == m_info.number);
5065810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (!pCurrBlock || pCurrBlock->GetTrackNumber() != m_info.number)
5066810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
506793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5068810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const Cluster* pCluster = pCurrEntry->GetCluster();
5069810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster);
5070810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(!pCluster->EOS());
507193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5072810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long status = pCluster->GetNext(pCurrEntry, pNextEntry);
507393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5074810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)  // error
5075810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
507693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5077810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  for (int i = 0;;) {
5078810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    while (pNextEntry) {
5079810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const Block* const pNextBlock = pNextEntry->GetBlock();
5080810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(pNextBlock);
508193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5082810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (pNextBlock->GetTrackNumber() == m_info.number)
5083810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return 0;
508493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5085810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pCurrEntry = pNextEntry;
508693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5087810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      status = pCluster->GetNext(pCurrEntry, pNextEntry);
508893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5089810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status < 0)  // error
5090810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
5091810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
509293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5093810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pCluster = m_pSegment->GetNext(pCluster);
509493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5095810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (pCluster == NULL) {
5096810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pNextEntry = GetEOS();
5097810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 1;
5098810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
509993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5100810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (pCluster->EOS()) {
510193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
510293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if (m_pSegment->Unparsed() <= 0)   //all clusters have been loaded
510393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            {
510493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                pNextEntry = GetEOS();
510593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                return 1;
510693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            }
510793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#else
5108810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (m_pSegment->DoneParsing()) {
5109810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        pNextEntry = GetEOS();
5110810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return 1;
5111810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      }
511293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
511393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5114810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      // TODO: there is a potential O(n^2) problem here: we tell the
5115810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      // caller to (pre)load another cluster, which he does, but then he
5116810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      // calls GetNext again, which repeats the same search.  This is
5117810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      // a pathological case, since the only way it can happen is if
5118810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      // there exists a long sequence of clusters none of which contain a
5119810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      // block from this track.  One way around this problem is for the
5120810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      // caller to be smarter when he loads another cluster: don't call
5121810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      // us back until you have a cluster that contains a block from this
5122810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      // track. (Of course, that's not cheap either, since our caller
5123810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      // would have to scan the each cluster as it's loaded, so that
5124810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      // would just push back the problem.)
512593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5126810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pNextEntry = NULL;
5127810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
5128810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
512993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5130810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    status = pCluster->GetFirst(pNextEntry);
513193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5132810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
5133810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
513493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5135810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (pNextEntry == NULL)  // empty cluster
5136810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
513793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5138810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    ++i;
5139810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
5140810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (i >= 100)
5141810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      break;
5142810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
514393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5144810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // NOTE: if we get here, it means that we didn't find a block with
5145810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // a matching track number after lots of searching, so we give
5146810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // up trying.
514793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5148810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pNextEntry = GetEOS();  // so we can return a non-NULL value
5149810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 1;
515093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
515193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5152810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgbool Track::VetEntry(const BlockEntry* pBlockEntry) const {
5153810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pBlockEntry);
5154810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const Block* const pBlock = pBlockEntry->GetBlock();
5155810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pBlock);
5156810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pBlock->GetTrackNumber() == m_info.number);
5157810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (!pBlock || pBlock->GetTrackNumber() != m_info.number)
5158810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return false;
515993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5160810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // This function is used during a seek to determine whether the
5161810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // frame is a valid seek target.  This default function simply
5162810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // returns true, which means all frames are valid seek targets.
5163810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // It gets overridden by the VideoTrack class, because only video
5164810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // keyframes can be used as seek target.
516593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5166810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return true;
516793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
516893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5169810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Track::Seek(long long time_ns, const BlockEntry*& pResult) const {
5170810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long status = GetFirst(pResult);
517193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5172810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)  // buffer underflow, etc
5173810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
517493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5175810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pResult);
517693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5177810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pResult->EOS())
5178810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;
517993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5180810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const Cluster* pCluster = pResult->GetCluster();
5181810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster);
5182810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster->GetIndex() >= 0);
518393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5184810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (time_ns <= pResult->GetBlock()->GetTime(pCluster))
5185810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;
518693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5187810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** const clusters = m_pSegment->m_clusters;
5188810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(clusters);
518993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5190810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long count = m_pSegment->GetCount();  // loaded only, not preloaded
5191810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(count > 0);
519293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5193810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** const i = clusters + pCluster->GetIndex();
5194810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(i);
5195810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(*i == pCluster);
5196810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster->GetTime() <= time_ns);
519793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5198810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** const j = clusters + count;
519993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5200810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** lo = i;
5201810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** hi = j;
520293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5203810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (lo < hi) {
5204810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // INVARIANT:
5205810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[i, lo) <= time_ns
5206810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[lo, hi) ?
5207810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[hi, j)  > time_ns
520893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5209810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster** const mid = lo + (hi - lo) / 2;
5210810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(mid < hi);
521193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5212810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pCluster = *mid;
5213810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pCluster);
5214810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pCluster->GetIndex() >= 0);
5215810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pCluster->GetIndex() == long(mid - m_pSegment->m_clusters));
521693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5217810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long t = pCluster->GetTime();
521893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5219810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (t <= time_ns)
5220810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      lo = mid + 1;
5221810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    else
5222810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      hi = mid;
522393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5224810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(lo <= hi);
5225810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
522693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5227810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(lo == hi);
5228810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(lo > i);
5229810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(lo <= j);
523093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5231810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (lo > i) {
5232810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pCluster = *--lo;
5233810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pCluster);
5234810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pCluster->GetTime() <= time_ns);
523593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5236810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pResult = pCluster->GetEntry(this);
523793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5238810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pResult != 0) && !pResult->EOS())
5239810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 0;
524093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5241810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // landed on empty cluster (no entries)
5242810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
524393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5244810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pResult = GetEOS();  // weird
5245810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;
524693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
524793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5248810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst ContentEncoding* Track::GetContentEncodingByIndex(
5249810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    unsigned long idx) const {
525093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  const ptrdiff_t count =
525193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      content_encoding_entries_end_ - content_encoding_entries_;
525293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  assert(count >= 0);
525393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
525493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  if (idx >= static_cast<unsigned long>(count))
525593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    return NULL;
525693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
525793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  return content_encoding_entries_[idx];
525893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
525993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
526093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgunsigned long Track::GetContentEncodingCount() const {
526193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  const ptrdiff_t count =
526293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      content_encoding_entries_end_ - content_encoding_entries_;
526393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  assert(count >= 0);
526493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
526593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  return static_cast<unsigned long>(count);
526693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
526793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
526893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orglong Track::ParseContentEncodingsEntry(long long start, long long size) {
526993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  IMkvReader* const pReader = m_pSegment->m_pReader;
527093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  assert(pReader);
527193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
527293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  long long pos = start;
527393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  const long long stop = start + size;
527493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
527593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  // Count ContentEncoding elements.
527693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  int count = 0;
527793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  while (pos < stop) {
527893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    long long id, size;
5279810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long status = ParseElementHeader(pReader, pos, stop, id, size);
5280810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
528193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      return status;
528293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5283810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // pos now designates start of element
528493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (id == 0x2240)  // ContentEncoding ID
528593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      ++count;
528693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5287810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
528893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pos <= stop);
528993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  }
529093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
529193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  if (count <= 0)
529293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    return -1;
529393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5294810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  content_encoding_entries_ = new (std::nothrow) ContentEncoding* [count];
529593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  if (!content_encoding_entries_)
529693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    return -1;
529793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
529893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  content_encoding_entries_end_ = content_encoding_entries_;
529993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
530093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  pos = start;
530193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  while (pos < stop) {
530293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    long long id, size;
5303810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long status = ParseElementHeader(pReader, pos, stop, id, size);
5304810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
530593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      return status;
530693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5307810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // pos now designates start of element
5308810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x2240) {  // ContentEncoding ID
530993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      ContentEncoding* const content_encoding =
531093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org          new (std::nothrow) ContentEncoding();
531193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (!content_encoding)
531293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return -1;
531393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5314810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      status = content_encoding->ParseContentEncodingEntry(pos, size, pReader);
531593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      if (status) {
531693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        delete content_encoding;
531793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return status;
531893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      }
531993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
532093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      *content_encoding_entries_end_++ = content_encoding;
532193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
532293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5323810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
532493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pos <= stop);
532593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  }
532693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
532793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  assert(pos == stop);
532893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
532993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  return 0;
533093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
533193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5332810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgTrack::EOSBlock::EOSBlock() : BlockEntry(NULL, LONG_MIN) {}
533393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5334810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgBlockEntry::Kind Track::EOSBlock::GetKind() const { return kBlockEOS; }
533593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5336810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst Block* Track::EOSBlock::GetBlock() const { return NULL; }
533793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5338810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgVideoTrack::VideoTrack(Segment* pSegment, long long element_start,
5339810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                       long long element_size)
5340810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    : Track(pSegment, element_start, element_size) {}
534193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5342810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong VideoTrack::Parse(Segment* pSegment, const Info& info,
5343810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                       long long element_start, long long element_size,
5344810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                       VideoTrack*& pResult) {
5345810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pResult)
5346810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
534793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5348810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (info.type != Track::kVideo)
5349810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
535093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5351810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long width = 0;
5352810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long height = 0;
5353810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  double rate = 0.0;
535493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5355810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  IMkvReader* const pReader = pSegment->m_pReader;
535693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5357810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const Settings& s = info.settings;
5358810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(s.start >= 0);
5359810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(s.size >= 0);
536093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5361810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long pos = s.start;
5362810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos >= 0);
536393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5364810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long stop = pos + s.size;
536593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5366810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (pos < stop) {
5367810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long id, size;
536893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5369810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long status = ParseElementHeader(pReader, pos, stop, id, size);
537093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5371810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
5372810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
537393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5374810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x30) {  // pixel width
5375810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      width = UnserializeUInt(pReader, pos, size);
537693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5377810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (width <= 0)
5378810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
5379810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x3A) {  // pixel height
5380810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      height = UnserializeUInt(pReader, pos, size);
538193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5382810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (height <= 0)
5383810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
5384810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x0383E3) {  // frame rate
5385810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long status = UnserializeFloat(pReader, pos, size, rate);
538693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5387810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status < 0)
5388810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
538993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5390810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (rate <= 0)
5391810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
5392810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
539393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5394810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
5395810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos <= stop);
5396810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
539793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5398810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos == stop);
539993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5400810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  VideoTrack* const pTrack =
5401810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      new (std::nothrow) VideoTrack(pSegment, element_start, element_size);
540293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5403810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pTrack == NULL)
5404810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;  // generic error
540593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5406810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const int status = info.Copy(pTrack->m_info);
540793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5408810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status) {  // error
5409810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    delete pTrack;
5410810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
5411810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
541293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5413810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pTrack->m_width = width;
5414810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pTrack->m_height = height;
5415810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pTrack->m_rate = rate;
541693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5417810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pResult = pTrack;
5418810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;  // success
5419810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org}
542093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5421810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgbool VideoTrack::VetEntry(const BlockEntry* pBlockEntry) const {
5422810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return Track::VetEntry(pBlockEntry) && pBlockEntry->GetBlock()->IsKey();
542393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
542493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5425810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong VideoTrack::Seek(long long time_ns, const BlockEntry*& pResult) const {
5426810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long status = GetFirst(pResult);
542793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5428810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)  // buffer underflow, etc
5429810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
543093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5431810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pResult);
543293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5433810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pResult->EOS())
5434810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;
543593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5436810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const Cluster* pCluster = pResult->GetCluster();
5437810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster);
5438810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster->GetIndex() >= 0);
543993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5440810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (time_ns <= pResult->GetBlock()->GetTime(pCluster))
5441810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;
544293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5443810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** const clusters = m_pSegment->m_clusters;
5444810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(clusters);
544593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5446810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long count = m_pSegment->GetCount();  // loaded only, not pre-loaded
5447810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(count > 0);
544893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5449810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** const i = clusters + pCluster->GetIndex();
5450810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(i);
5451810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(*i == pCluster);
5452810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster->GetTime() <= time_ns);
545393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5454810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** const j = clusters + count;
545593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5456810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** lo = i;
5457810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster** hi = j;
545893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5459810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (lo < hi) {
5460810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // INVARIANT:
5461810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[i, lo) <= time_ns
5462810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[lo, hi) ?
5463810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //[hi, j)  > time_ns
546493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5465810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster** const mid = lo + (hi - lo) / 2;
5466810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(mid < hi);
546793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5468810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pCluster = *mid;
5469810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pCluster);
5470810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pCluster->GetIndex() >= 0);
5471810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pCluster->GetIndex() == long(mid - m_pSegment->m_clusters));
547293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5473810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long t = pCluster->GetTime();
547493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5475810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (t <= time_ns)
5476810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      lo = mid + 1;
5477810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    else
5478810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      hi = mid;
547993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5480810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(lo <= hi);
5481810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
548293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5483810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(lo == hi);
5484810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(lo > i);
5485810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(lo <= j);
548693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5487810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pCluster = *--lo;
5488810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster);
5489810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster->GetTime() <= time_ns);
549093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5491810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pResult = pCluster->GetEntry(this, time_ns);
549293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5493810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((pResult != 0) && !pResult->EOS())  // found a keyframe
5494810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;
5495810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
5496810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (lo != i) {
549793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    pCluster = *--lo;
549893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pCluster);
549993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pCluster->GetTime() <= time_ns);
550093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
550193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
550293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //TODO:
550393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //We need to handle the case when a cluster
550493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //contains multiple keyframes.  Simply returning
550593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //the largest keyframe on the cluster isn't
550693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //good enough.
550793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        pResult = pCluster->GetMaxKey(this);
550893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#else
5509810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pResult = pCluster->GetEntry(this, time_ns);
551093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
551193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5512810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pResult != 0) && !pResult->EOS())
5513810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 0;
5514810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
551593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5516810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // weird: we're on the first cluster, but no keyframe found
5517810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // should never happen but we must return something anyway
551893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5519810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pResult = GetEOS();
5520810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;
552193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
552293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5523810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long VideoTrack::GetWidth() const { return m_width; }
552493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5525810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long VideoTrack::GetHeight() const { return m_height; }
552693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5527810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgdouble VideoTrack::GetFrameRate() const { return m_rate; }
552893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5529810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgAudioTrack::AudioTrack(Segment* pSegment, long long element_start,
5530810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                       long long element_size)
5531810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    : Track(pSegment, element_start, element_size) {}
553293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5533810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong AudioTrack::Parse(Segment* pSegment, const Info& info,
5534810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                       long long element_start, long long element_size,
5535810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                       AudioTrack*& pResult) {
5536810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pResult)
5537810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
553893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5539810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (info.type != Track::kAudio)
5540810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
554193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5542810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  IMkvReader* const pReader = pSegment->m_pReader;
554393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5544810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const Settings& s = info.settings;
5545810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(s.start >= 0);
5546810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(s.size >= 0);
554793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5548810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long pos = s.start;
5549810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos >= 0);
555093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5551810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long stop = pos + s.size;
555293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5553810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  double rate = 8000.0;  // MKV default
5554810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long channels = 1;
5555810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long bit_depth = 0;
555693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5557810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (pos < stop) {
5558810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long id, size;
555993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5560810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long status = ParseElementHeader(pReader, pos, stop, id, size);
556193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5562810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
5563810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
556493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5565810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x35) {  // Sample Rate
5566810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      status = UnserializeFloat(pReader, pos, size, rate);
556793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5568810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status < 0)
5569810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
557093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5571810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (rate <= 0)
5572810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
5573810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x1F) {  // Channel Count
5574810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      channels = UnserializeUInt(pReader, pos, size);
557593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5576810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (channels <= 0)
5577810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
5578810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x2264) {  // Bit Depth
5579810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      bit_depth = UnserializeUInt(pReader, pos, size);
558093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5581810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (bit_depth <= 0)
5582810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
558393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
558493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5585810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
5586810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos <= stop);
5587810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
558893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5589810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos == stop);
559093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5591810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  AudioTrack* const pTrack =
5592810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      new (std::nothrow) AudioTrack(pSegment, element_start, element_size);
559393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5594810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pTrack == NULL)
5595810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;  // generic error
559693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5597810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const int status = info.Copy(pTrack->m_info);
559893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5599810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status) {
5600810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    delete pTrack;
5601810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
5602810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
560393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5604810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pTrack->m_rate = rate;
5605810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pTrack->m_channels = channels;
5606810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pTrack->m_bitDepth = bit_depth;
560793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5608810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pResult = pTrack;
5609810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;  // success
561093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
561193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5612810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgdouble AudioTrack::GetSamplingRate() const { return m_rate; }
561393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5614810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long AudioTrack::GetChannels() const { return m_channels; }
561593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5616810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long AudioTrack::GetBitDepth() const { return m_bitDepth; }
561793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5618810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgTracks::Tracks(Segment* pSegment, long long start, long long size_,
5619810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org               long long element_start, long long element_size)
5620810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    : m_pSegment(pSegment),
5621810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_start(start),
5622810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_size(size_),
5623810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_element_start(element_start),
5624810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_element_size(element_size),
5625810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_trackEntries(NULL),
5626810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_trackEntriesEnd(NULL) {}
562793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5628810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Tracks::Parse() {
5629810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_trackEntries == NULL);
5630810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_trackEntriesEnd == NULL);
563193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5632810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long stop = m_start + m_size;
5633810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  IMkvReader* const pReader = m_pSegment->m_pReader;
563493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5635810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  int count = 0;
5636810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long pos = m_start;
563793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5638810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (pos < stop) {
5639810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long id, size;
564093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5641810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long status = ParseElementHeader(pReader, pos, stop, id, size);
564293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5643810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
5644810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
564593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5646810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size == 0)  // weird
5647810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
564893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5649810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x2E)  // TrackEntry ID
5650810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      ++count;
565193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5652810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
5653810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos <= stop);
5654810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
565593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5656810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos == stop);
565793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5658810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (count <= 0)
5659810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;  // success
566093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5661810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_trackEntries = new (std::nothrow) Track* [count];
566293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5663810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_trackEntries == NULL)
5664810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
566593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5666810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_trackEntriesEnd = m_trackEntries;
566793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5668810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos = m_start;
566993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5670810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (pos < stop) {
5671810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long element_start = pos;
567293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5673810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long id, payload_size;
567493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5675810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long status =
5676810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        ParseElementHeader(pReader, pos, stop, id, payload_size);
567793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5678810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
5679810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
568093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5681810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (payload_size == 0)  // weird
5682810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
568393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5684810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long payload_stop = pos + payload_size;
5685810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(payload_stop <= stop);  // checked in ParseElement
568693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5687810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long element_size = payload_stop - element_start;
568893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5689810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x2E) {  // TrackEntry ID
5690810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      Track*& pTrack = *m_trackEntriesEnd;
5691810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pTrack = NULL;
569293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5693810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long status = ParseTrackEntry(pos, payload_size, element_start,
5694810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                          element_size, pTrack);
569593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5696810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status)
5697810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
569893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5699810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (pTrack)
5700810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        ++m_trackEntriesEnd;
570193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
570293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5703810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos = payload_stop;
5704810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos <= stop);
5705810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
570693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5707810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos == stop);
570893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5709810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;  // success
5710810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org}
571193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5712810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgunsigned long Tracks::GetTracksCount() const {
5713810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const ptrdiff_t result = m_trackEntriesEnd - m_trackEntries;
5714810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(result >= 0);
571593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5716810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return static_cast<unsigned long>(result);
571793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
571893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5719810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Tracks::ParseTrackEntry(long long track_start, long long track_size,
5720810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                             long long element_start, long long element_size,
5721810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                             Track*& pResult) const {
5722810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pResult)
5723810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
572493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5725810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  IMkvReader* const pReader = m_pSegment->m_pReader;
572693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5727810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long pos = track_start;
5728810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long track_stop = track_start + track_size;
572993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5730810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Track::Info info;
573193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5732810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  info.type = 0;
5733810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  info.number = 0;
5734810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  info.uid = 0;
5735810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  info.defaultDuration = 0;
573693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5737810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Track::Settings v;
5738810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  v.start = -1;
5739810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  v.size = -1;
574093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5741810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Track::Settings a;
5742810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  a.start = -1;
5743810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  a.size = -1;
574493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5745810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Track::Settings e;  // content_encodings_settings;
5746810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  e.start = -1;
5747810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  e.size = -1;
574893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5749810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long lacing = 1;  // default is true
575093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5751810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (pos < track_stop) {
5752810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long id, size;
575393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5754810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long status = ParseElementHeader(pReader, pos, track_stop, id, size);
575593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5756810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0)  // error
5757810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
575893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5759810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size < 0)
5760810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
5761810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
5762810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long start = pos;
5763810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
5764810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x60) {  // VideoSettings ID
5765810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      v.start = start;
5766810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      v.size = size;
5767810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x61) {  // AudioSettings ID
5768810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      a.start = start;
5769810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      a.size = size;
5770810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x2D80) {  // ContentEncodings ID
5771810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      e.start = start;
5772810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      e.size = size;
5773810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x33C5) {  // Track UID
5774810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (size > 8)
5775810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
577693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5777810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      info.uid = 0;
577893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5779810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      long long pos_ = start;
5780810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long pos_end = start + size;
578193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5782810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      while (pos_ != pos_end) {
5783810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        unsigned char b;
578493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5785810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        const int status = pReader->Read(pos_, 1, &b);
578693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5787810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        if (status)
5788810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          return status;
578993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5790810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        info.uid <<= 8;
5791810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        info.uid |= b;
579293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5793810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        ++pos_;
5794810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      }
5795810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x57) {  // Track Number
5796810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long num = UnserializeUInt(pReader, pos, size);
579793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5798810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if ((num <= 0) || (num > 127))
5799810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
580093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5801810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      info.number = static_cast<long>(num);
5802810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x03) {  // Track Type
5803810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long type = UnserializeUInt(pReader, pos, size);
580493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5805810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if ((type <= 0) || (type > 254))
5806810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
580793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5808810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      info.type = static_cast<long>(type);
5809810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x136E) {  // Track Name
5810810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long status =
5811810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          UnserializeString(pReader, pos, size, info.nameAsUTF8);
581293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5813810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status)
5814810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
5815810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x02B59C) {  // Track Language
5816810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long status = UnserializeString(pReader, pos, size, info.language);
581793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5818810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status)
5819810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
5820810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x03E383) {  // Default Duration
5821810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long duration = UnserializeUInt(pReader, pos, size);
582293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5823810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (duration < 0)
5824810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
582593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5826810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      info.defaultDuration = static_cast<unsigned long long>(duration);
5827810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x06) {  // CodecID
5828810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long status = UnserializeString(pReader, pos, size, info.codecId);
582993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5830810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status)
5831810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
5832810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x1C) {  // lacing
5833810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      lacing = UnserializeUInt(pReader, pos, size);
583493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5835810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if ((lacing < 0) || (lacing > 1))
5836810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
5837810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x23A2) {  // Codec Private
5838810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      delete[] info.codecPrivate;
5839810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      info.codecPrivate = NULL;
5840810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      info.codecPrivateSize = 0;
584193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5842810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const size_t buflen = static_cast<size_t>(size);
584393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5844810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (buflen) {
5845810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        typedef unsigned char* buf_t;
584693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5847810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        const buf_t buf = new (std::nothrow) unsigned char[buflen];
584893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5849810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        if (buf == NULL)
5850810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          return -1;
585193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5852810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        const int status = pReader->Read(pos, static_cast<long>(buflen), buf);
585393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5854810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        if (status) {
5855810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          delete[] buf;
5856810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          return status;
585793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        }
585893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5859810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        info.codecPrivate = buf;
5860810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        info.codecPrivateSize = buflen;
5861810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      }
5862810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x058688) {  // Codec Name
5863810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long status =
5864810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          UnserializeString(pReader, pos, size, info.codecNameAsUTF8);
586593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5866810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status)
5867810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
5868810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x16AA) {  // Codec Delay
5869810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      info.codecDelay = UnserializeUInt(pReader, pos, size);
5870810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x16BB) {  // Seek Pre Roll
5871810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      info.seekPreRoll = UnserializeUInt(pReader, pos, size);
587293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
587393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5874810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
5875810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos <= track_stop);
5876810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
587793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5878810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos == track_stop);
587993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5880810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (info.number <= 0)  // not specified
5881810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
588293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5883810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (GetTrackByNumber(info.number))
5884810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
588593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5886810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (info.type <= 0)  // not specified
5887810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
588893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5889810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  info.lacing = (lacing > 0) ? true : false;
589093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5891810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (info.type == Track::kVideo) {
5892810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (v.start < 0)
5893810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
589493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5895810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (a.start >= 0)
5896810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
589793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5898810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    info.settings = v;
589993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5900810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    VideoTrack* pTrack = NULL;
590193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5902810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long status = VideoTrack::Parse(m_pSegment, info, element_start,
5903810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                          element_size, pTrack);
590493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5905810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status)
5906810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
590793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5908810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pResult = pTrack;
5909810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pResult);
591093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5911810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (e.start >= 0)
5912810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pResult->ParseContentEncodingsEntry(e.start, e.size);
5913810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  } else if (info.type == Track::kAudio) {
5914810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (a.start < 0)
5915810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
591693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5917810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (v.start >= 0)
5918810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
591993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5920810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    info.settings = a;
592193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5922810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    AudioTrack* pTrack = NULL;
592393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5924810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long status = AudioTrack::Parse(m_pSegment, info, element_start,
5925810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                          element_size, pTrack);
592693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5927810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status)
5928810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
592993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5930810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pResult = pTrack;
5931810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pResult);
593293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5933810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (e.start >= 0)
5934810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pResult->ParseContentEncodingsEntry(e.start, e.size);
5935810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  } else {
5936810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // neither video nor audio - probably metadata or subtitles
593793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5938810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (a.start >= 0)
5939810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
594093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5941810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (v.start >= 0)
5942810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
594393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5944810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (e.start >= 0)
5945810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
594693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5947810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    info.settings.start = -1;
5948810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    info.settings.size = 0;
594993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5950810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Track* pTrack = NULL;
595193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5952810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long status =
5953810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        Track::Create(m_pSegment, info, element_start, element_size, pTrack);
595493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5955810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status)
5956810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
595793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5958810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pResult = pTrack;
5959810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pResult);
5960810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
596193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5962810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;  // success
5963810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org}
596493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5965810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgTracks::~Tracks() {
5966810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Track** i = m_trackEntries;
5967810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Track** const j = m_trackEntriesEnd;
596893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5969810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (i != j) {
5970810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Track* const pTrack = *i++;
5971810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    delete pTrack;
5972810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
597393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5974810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] m_trackEntries;
597593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
597693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5977810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst Track* Tracks::GetTrackByNumber(long tn) const {
5978810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (tn < 0)
5979810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return NULL;
598093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5981810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Track** i = m_trackEntries;
5982810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Track** const j = m_trackEntriesEnd;
598393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5984810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (i != j) {
5985810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Track* const pTrack = *i++;
598693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5987810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (pTrack == NULL)
5988810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
598993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5990810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (tn == pTrack->GetNumber())
5991810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return pTrack;
5992810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
599393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5994810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return NULL;  // not found
599593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
599693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5997810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst Track* Tracks::GetTrackByIndex(unsigned long idx) const {
5998810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const ptrdiff_t count = m_trackEntriesEnd - m_trackEntries;
599993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6000810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (idx >= static_cast<unsigned long>(count))
6001810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return NULL;
600293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6003810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return m_trackEntries[idx];
600493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
600593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
600693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
600793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orglong long Cluster::Unparsed() const
600893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org{
600993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (m_timecode < 0)  //not even partially loaded
601093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return LLONG_MAX;
601193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
601293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(m_pos >= m_element_start);
601393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //assert(m_element_size > m_size);
601493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
601593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long element_stop = m_element_start + m_element_size;
601693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(m_pos <= element_stop);
601793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
601893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long result = element_stop - m_pos;
601993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(result >= 0);
602093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
602193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    return result;
602293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
602393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
602493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6025810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Cluster::Load(long long& pos, long& len) const {
6026810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_pSegment);
6027810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_pos >= m_element_start);
602893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6029810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_timecode >= 0)  // at least partially loaded
6030810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;
603193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6032810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_pos == m_element_start);
6033810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_element_size < 0);
603493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6035810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  IMkvReader* const pReader = m_pSegment->m_pReader;
603693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6037810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long total, avail;
603893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6039810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const int status = pReader->Length(&total, &avail);
604093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6041810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)  // error
6042810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
604393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6044810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((total < 0) || (avail <= total));
6045810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((total < 0) || (m_pos <= total));  // TODO: verify this
604693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6047810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos = m_pos;
604893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6049810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long cluster_size = -1;
605093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6051810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  {
6052810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > avail) {
6053810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
6054810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
6055810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
605693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6057810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long result = GetUIntLength(pReader, pos, len);
605893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6059810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error or underflow
6060810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(result);
606193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6062810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result > 0)  // underflow (weird)
6063810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
606493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6065810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // if ((pos + len) > segment_stop)
6066810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //    return E_FILE_FORMAT_INVALID;
606793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6068810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > avail)
6069810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
607093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6071810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long id_ = ReadUInt(pReader, pos, len);
607293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6073810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id_ < 0)  // error
6074810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(id_);
607593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6076810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id_ != 0x0F43B675)  // Cluster ID
6077810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
607893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6079810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume id
608093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6081810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // read cluster size
608293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6083810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > avail) {
6084810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
6085810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
6086810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
608793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6088810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result = GetUIntLength(pReader, pos, len);
608993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6090810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error
6091810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(result);
609293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6093810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result > 0)  // weird
6094810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
609593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6096810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // if ((pos + len) > segment_stop)
6097810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    //    return E_FILE_FORMAT_INVALID;
609893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6099810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > avail)
6100810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
610193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6102810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long size = ReadUInt(pReader, pos, len);
610393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6104810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size < 0)  // error
6105810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(cluster_size);
610693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6107810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size == 0)
6108810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;  // TODO: verify this
610993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6110810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume length of size of element
611193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6112810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long unknown_size = (1LL << (7 * len)) - 1;
611393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6114810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size != unknown_size)
6115810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      cluster_size = size;
6116810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
611793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6118810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org// pos points to start of payload
611993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
612093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
612193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    len = static_cast<long>(size_);
612293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
612393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (cluster_stop > avail)
612493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return E_BUFFER_NOT_FULL;
612593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
612693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6127810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long timecode = -1;
6128810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long new_pos = -1;
6129810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  bool bBlock = false;
613093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6131810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long cluster_stop = (cluster_size < 0) ? -1 : pos + cluster_size;
613293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6133810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  for (;;) {
6134810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((cluster_stop >= 0) && (pos >= cluster_stop))
6135810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      break;
613693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6137810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // Parse ID
613893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6139810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > avail) {
6140810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
6141810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
6142810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
614393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6144810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long result = GetUIntLength(pReader, pos, len);
614593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6146810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error
6147810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(result);
614893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6149810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result > 0)  // weird
6150810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
615193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6152810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
6153810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
615493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6155810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > avail)
6156810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
615793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6158810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long id = ReadUInt(pReader, pos, len);
615993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6160810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id < 0)  // error
6161810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(id);
616293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6163810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0)
6164810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
616593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6166810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // This is the distinguished set of ID's we use to determine
6167810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // that we have exhausted the sub-element's inside the cluster
6168810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // whose ID we parsed earlier.
616993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6170810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x0F43B675)  // Cluster ID
6171810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      break;
617293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6173810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x0C53BB6B)  // Cues ID
6174810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      break;
617593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6176810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume ID field
617793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6178810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // Parse Size
617993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6180810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > avail) {
6181810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
6182810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
6183810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
618493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6185810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result = GetUIntLength(pReader, pos, len);
618693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6187810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error
6188810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(result);
618993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6190810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result > 0)  // weird
6191810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
619293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6193810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
6194810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
619593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6196810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > avail)
6197810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
619893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6199810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long size = ReadUInt(pReader, pos, len);
620093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6201810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size < 0)  // error
6202810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(size);
620393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6204810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long unknown_size = (1LL << (7 * len)) - 1;
620593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6206810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size == unknown_size)
6207810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
620893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6209810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume size field
621093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6211810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((cluster_stop >= 0) && (pos > cluster_stop))
6212810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
621393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6214810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // pos now points to start of payload
621593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6216810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size == 0)  // weird
6217810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
621893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6219810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((cluster_stop >= 0) && ((pos + size) > cluster_stop))
6220810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
622193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6222810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x67) {  // TimeCode ID
6223810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = static_cast<long>(size);
622493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6225810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if ((pos + size) > avail)
6226810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_BUFFER_NOT_FULL;
622793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6228810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      timecode = UnserializeUInt(pReader, pos, size);
622993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6230810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (timecode < 0)  // error (or underflow)
6231810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return static_cast<long>(timecode);
623293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6233810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      new_pos = pos + size;
623493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6235810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (bBlock)
6236810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        break;
6237810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x20) {  // BlockGroup ID
6238810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      bBlock = true;
6239810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      break;
6240810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x23) {  // SimpleBlock ID
6241810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      bBlock = true;
6242810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      break;
624393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
624493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6245810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
624693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert((cluster_stop < 0) || (pos <= cluster_stop));
6247810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
624893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6249810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((cluster_stop < 0) || (pos <= cluster_stop));
625093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6251810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (timecode < 0)  // no timecode found
6252810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
625393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6254810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (!bBlock)
6255810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
625693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6257810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_pos = new_pos;  // designates position just beyond timecode payload
6258810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_timecode = timecode;  // m_timecode >= 0 means we're partially loaded
625993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6260810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (cluster_size >= 0)
6261810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m_element_size = cluster_stop - m_element_start;
626293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6263810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;
6264810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org}
626593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6266810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Cluster::Parse(long long& pos, long& len) const {
6267810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long status = Load(pos, len);
626893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6269810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)
6270810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
627193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6272810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_pos >= m_element_start);
6273810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_timecode >= 0);
6274810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // assert(m_size > 0);
6275810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // assert(m_element_size > m_size);
627693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6277810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long cluster_stop =
6278810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      (m_element_size < 0) ? -1 : m_element_start + m_element_size;
627993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6280810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((cluster_stop >= 0) && (m_pos >= cluster_stop))
6281810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 1;  // nothing else to do
628293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6283810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  IMkvReader* const pReader = m_pSegment->m_pReader;
628493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6285810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long total, avail;
628693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6287810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  status = pReader->Length(&total, &avail);
628893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6289810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)  // error
6290810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
629193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6292810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((total < 0) || (avail <= total));
629393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6294810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos = m_pos;
629593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6296810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  for (;;) {
6297810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((cluster_stop >= 0) && (pos >= cluster_stop))
6298810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      break;
629993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6300810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((total >= 0) && (pos >= total)) {
6301810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (m_element_size < 0)
6302810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        m_element_size = pos - m_element_start;
630393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6304810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      break;
6305810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
630693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6307810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // Parse ID
630893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6309810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > avail) {
6310810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
6311810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
6312810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
631393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6314810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long result = GetUIntLength(pReader, pos, len);
631593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6316810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error
6317810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(result);
631893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6319810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result > 0)  // weird
6320810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
632193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6322810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
6323810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
632493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6325810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > avail)
6326810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
632793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6328810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long id = ReadUInt(pReader, pos, len);
632993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6330810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id < 0)  // error
6331810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(id);
633293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6333810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0)  // weird
6334810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
633593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6336810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // This is the distinguished set of ID's we use to determine
6337810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // that we have exhausted the sub-element's inside the cluster
6338810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // whose ID we parsed earlier.
633993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6340810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((id == 0x0F43B675) || (id == 0x0C53BB6B)) {  // Cluster or Cues ID
6341810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (m_element_size < 0)
6342810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        m_element_size = pos - m_element_start;
634393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6344810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      break;
6345810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
634693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6347810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume ID field
634893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6349810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // Parse Size
635093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6351810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > avail) {
6352810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
6353810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
6354810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
635593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6356810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result = GetUIntLength(pReader, pos, len);
635793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6358810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error
6359810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(result);
636093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6361810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result > 0)  // weird
6362810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
636393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6364810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
6365810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
636693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6367810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > avail)
6368810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
636993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6370810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long size = ReadUInt(pReader, pos, len);
637193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6372810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size < 0)  // error
6373810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(size);
637493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6375810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long unknown_size = (1LL << (7 * len)) - 1;
637693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6377810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size == unknown_size)
6378810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
637993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6380810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume size field
638193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6382810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((cluster_stop >= 0) && (pos > cluster_stop))
6383810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
638493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6385810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // pos now points to start of payload
638693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6387810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size == 0)  // weird
6388810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
638993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6390810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // const long long block_start = pos;
6391810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long block_stop = pos + size;
639293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6393810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (cluster_stop >= 0) {
6394810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (block_stop > cluster_stop) {
6395810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        if ((id == 0x20) || (id == 0x23))
6396810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          return E_FILE_FORMAT_INVALID;
639793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6398810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        pos = cluster_stop;
6399810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        break;
6400810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      }
6401810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if ((total >= 0) && (block_stop > total)) {
6402810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_element_size = total - m_element_start;
6403810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pos = total;
6404810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      break;
6405810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (block_stop > avail) {
6406810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = static_cast<long>(size);
6407810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
6408810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
640993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6410810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Cluster* const this_ = const_cast<Cluster*>(this);
641193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6412810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x20)  // BlockGroup
6413810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return this_->ParseBlockGroup(size, pos, len);
641493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6415810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x23)  // SimpleBlock
6416810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return this_->ParseSimpleBlock(size, pos, len);
641793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6418810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
6419810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((cluster_stop < 0) || (pos <= cluster_stop));
6420810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
642193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6422810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_element_size > 0);
642393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6424810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_pos = pos;
6425810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((cluster_stop < 0) || (m_pos <= cluster_stop));
642693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6427810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_entries_count > 0) {
6428810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long idx = m_entries_count - 1;
642993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6430810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const BlockEntry* const pLast = m_entries[idx];
6431810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pLast);
643293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6433810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const Block* const pBlock = pLast->GetBlock();
6434810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pBlock);
643593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6436810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long start = pBlock->m_start;
643793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6438810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((total >= 0) && (start > total))
6439810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return -1;  // defend against trucated stream
644093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6441810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long size = pBlock->m_size;
644293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6443810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long stop = start + size;
6444810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((cluster_stop < 0) || (stop <= cluster_stop));
644593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6446810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((total >= 0) && (stop > total))
6447810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return -1;  // defend against trucated stream
6448810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
644993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6450810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 1;  // no more entries
645193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
645293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6453810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Cluster::ParseSimpleBlock(long long block_size, long long& pos,
6454810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                               long& len) {
6455810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long block_start = pos;
6456810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long block_stop = pos + block_size;
645793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6458810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  IMkvReader* const pReader = m_pSegment->m_pReader;
645993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6460810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long total, avail;
646193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6462810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long status = pReader->Length(&total, &avail);
646393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6464810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)  // error
6465810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
646693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6467810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((total < 0) || (avail <= total));
646893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6469810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // parse track number
647093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6471810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((pos + 1) > avail) {
6472810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    len = 1;
6473810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_BUFFER_NOT_FULL;
6474810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
647593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6476810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long result = GetUIntLength(pReader, pos, len);
647793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6478810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (result < 0)  // error
6479810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return static_cast<long>(result);
648093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6481810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (result > 0)  // weird
6482810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_BUFFER_NOT_FULL;
648393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6484810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((pos + len) > block_stop)
6485810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
648693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6487810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((pos + len) > avail)
6488810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_BUFFER_NOT_FULL;
648993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6490810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long track = ReadUInt(pReader, pos, len);
649193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6492810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (track < 0)  // error
6493810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return static_cast<long>(track);
649493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6495810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (track == 0)
6496810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
649793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
649893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
649993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //TODO(matthewjheaney)
650093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //This turned out to be too conservative.  The problem is that
650193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //if we see a track header in the tracks element with an unsupported
650293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //track type, we throw that track header away, so it is not present
650393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //in the track map.  But even though we don't understand the track
650493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //header, there are still blocks in the cluster with that track
650593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //number.  It was our decision to ignore that track header, so it's
650693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //up to us to deal with blocks associated with that track -- we
650793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //cannot simply report an error since technically there's nothing
650893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //wrong with the file.
650993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //
651093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //For now we go ahead and finish the parse, creating a block entry
651193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //for this block.  This is somewhat wasteful, because without a
651293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //track header there's nothing you can do with the block. What
651393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //we really need here is a special return value that indicates to
651493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //the caller that he should ignore this particular block, and
651593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //continue parsing.
651693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
651793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const Tracks* const pTracks = m_pSegment->GetTracks();
651893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pTracks);
651993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
652093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long tn = static_cast<long>(track);
652193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
652293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const Track* const pTrack = pTracks->GetTrackByNumber(tn);
652393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
652493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (pTrack == NULL)
652593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return E_FILE_FORMAT_INVALID;
652693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
652793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6528810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos += len;  // consume track number
652993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6530810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((pos + 2) > block_stop)
6531810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
653293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6533810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((pos + 2) > avail) {
6534810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    len = 2;
6535810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_BUFFER_NOT_FULL;
6536810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
653793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6538810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos += 2;  // consume timecode
653993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6540810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((pos + 1) > block_stop)
6541810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
654293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6543810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((pos + 1) > avail) {
6544810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    len = 1;
6545810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_BUFFER_NOT_FULL;
6546810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
654793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6548810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  unsigned char flags;
654993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6550810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  status = pReader->Read(pos, 1, &flags);
655193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6552810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0) {  // error or underflow
6553810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    len = 1;
6554810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
6555810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
655693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6557810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  ++pos;  // consume flags byte
6558810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos <= avail);
655993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6560810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pos >= block_stop)
6561810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
656293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6563810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const int lacing = int(flags & 0x06) >> 1;
656493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6565810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((lacing != 0) && (block_stop > avail)) {
6566810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    len = static_cast<long>(block_stop - pos);
6567810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_BUFFER_NOT_FULL;
6568810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
656993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6570810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  status = CreateBlock(0x23,  // simple block id
6571810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                       block_start, block_size,
6572810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                       0);  // DiscardPadding
657393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6574810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status != 0)
6575810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
657693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6577810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_pos = block_stop;
657893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6579810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;  // success
658093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
658193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6582810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Cluster::ParseBlockGroup(long long payload_size, long long& pos,
6583810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                              long& len) {
6584810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long payload_start = pos;
6585810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long payload_stop = pos + payload_size;
658693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6587810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  IMkvReader* const pReader = m_pSegment->m_pReader;
658893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6589810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long total, avail;
659093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6591810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long status = pReader->Length(&total, &avail);
659293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6593810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)  // error
6594810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
659593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6596810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((total < 0) || (avail <= total));
659793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6598810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((total >= 0) && (payload_stop > total))
6599810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
660093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6601810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (payload_stop > avail) {
6602810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    len = static_cast<long>(payload_size);
6603810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_BUFFER_NOT_FULL;
6604810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
660593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6606810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long discard_padding = 0;
660793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6608810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (pos < payload_stop) {
6609810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // parse sub-block element ID
661093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6611810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > avail) {
6612810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
6613810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
6614810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
661593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6616810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long result = GetUIntLength(pReader, pos, len);
661793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6618810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error
6619810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(result);
662093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6621810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result > 0)  // weird
6622810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
662393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6624810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > payload_stop)
6625810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
662693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6627810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > avail)
6628810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
662993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6630810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long id = ReadUInt(pReader, pos, len);
663193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6632810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id < 0)  // error
6633810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(id);
663493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6635810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0)  // not a value ID
6636810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
663793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6638810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume ID field
663993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6640810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // Parse Size
664193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6642810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > avail) {
6643810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
6644810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
6645810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
664693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6647810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result = GetUIntLength(pReader, pos, len);
664893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6649810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error
6650810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(result);
665193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6652810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result > 0)  // weird
6653810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
665493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6655810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > payload_stop)
6656810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
665793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6658810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > avail)
6659810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
666093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6661810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long size = ReadUInt(pReader, pos, len);
666293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6663810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size < 0)  // error
6664810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(size);
666593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6666810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume size field
666793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6668810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // pos now points to start of sub-block group payload
666993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6670810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (pos > payload_stop)
6671810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
667293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6673810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size == 0)  // weird
6674810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
667593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6676810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long unknown_size = (1LL << (7 * len)) - 1;
667793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6678810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size == unknown_size)
6679810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
668093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6681810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x35A2) {  // DiscardPadding
6682810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      result = GetUIntLength(pReader, pos, len);
668393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6684810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (result < 0)  // error
6685810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return static_cast<long>(result);
668693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6687810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      status = UnserializeInt(pReader, pos, len, discard_padding);
668893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6689810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status < 0)  // error
6690810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return status;
6691810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
669293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6693810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id != 0x21) {  // sub-part of BlockGroup is not a Block
6694810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pos += size;  // consume sub-part of block group
669593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6696810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (pos > payload_stop)
6697810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
669893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6699810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
6700810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
670193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6702810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long block_stop = pos + size;
670393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6704810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (block_stop > payload_stop)
6705810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
670693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6707810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // parse track number
670893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6709810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > avail) {
6710810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
6711810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
6712810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
671393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6714810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result = GetUIntLength(pReader, pos, len);
671593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6716810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error
6717810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(result);
671893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6719810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result > 0)  // weird
6720810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
672193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6722810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > block_stop)
6723810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
672493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6725810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > avail)
6726810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
6727810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
6728810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long track = ReadUInt(pReader, pos, len);
672993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6730810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (track < 0)  // error
6731810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(track);
673293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6733810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (track == 0)
6734810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
673593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
673693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
673793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //TODO(matthewjheaney)
673893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //This turned out to be too conservative.  The problem is that
673993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //if we see a track header in the tracks element with an unsupported
674093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //track type, we throw that track header away, so it is not present
674193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //in the track map.  But even though we don't understand the track
674293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //header, there are still blocks in the cluster with that track
674393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //number.  It was our decision to ignore that track header, so it's
674493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //up to us to deal with blocks associated with that track -- we
674593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //cannot simply report an error since technically there's nothing
674693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //wrong with the file.
674793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //
674893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //For now we go ahead and finish the parse, creating a block entry
674993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //for this block.  This is somewhat wasteful, because without a
675093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //track header there's nothing you can do with the block. What
675193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //we really need here is a special return value that indicates to
675293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //the caller that he should ignore this particular block, and
675393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //continue parsing.
675493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
675593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const Tracks* const pTracks = m_pSegment->GetTracks();
675693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(pTracks);
675793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
675893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const long tn = static_cast<long>(track);
675993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
676093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const Track* const pTrack = pTracks->GetTrackByNumber(tn);
676193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
676293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (pTrack == NULL)
676393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return E_FILE_FORMAT_INVALID;
676493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
676593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6766810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume track number
676793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6768810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 2) > block_stop)
6769810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
677093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6771810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 2) > avail) {
6772810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 2;
6773810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
6774810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
677593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6776810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += 2;  // consume timecode
677793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6778810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > block_stop)
6779810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
678093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6781810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > avail) {
6782810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
6783810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
6784810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
678593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6786810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    unsigned char flags;
678793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6788810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    status = pReader->Read(pos, 1, &flags);
678993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6790810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0) {  // error or underflow
6791810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
6792810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
6793810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
679493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6795810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    ++pos;  // consume flags byte
6796810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos <= avail);
679793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6798810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (pos >= block_stop)
6799810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
680093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6801810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const int lacing = int(flags & 0x06) >> 1;
680293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6803810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((lacing != 0) && (block_stop > avail)) {
6804810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = static_cast<long>(block_stop - pos);
6805810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
680693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
680793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6808810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos = block_stop;  // consume block-part of block group
6809810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos <= payload_stop);
6810810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
681193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6812810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos == payload_stop);
681393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6814810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  status = CreateBlock(0x20,  // BlockGroup ID
6815810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                       payload_start, payload_size, discard_padding);
6816810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status != 0)
6817810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
681893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6819810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_pos = payload_stop;
682093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6821810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;  // success
6822810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org}
682393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6824810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Cluster::GetEntry(long index, const mkvparser::BlockEntry*& pEntry) const {
6825810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_pos >= m_element_start);
682693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6827810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pEntry = NULL;
682893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6829810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (index < 0)
6830810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;  // generic error
683193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6832810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_entries_count < 0)
6833810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_BUFFER_NOT_FULL;
683493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6835810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_entries);
6836810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_entries_size > 0);
6837810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_entries_count <= m_entries_size);
683893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6839810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (index < m_entries_count) {
6840810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pEntry = m_entries[index];
6841810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pEntry);
684293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6843810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 1;  // found entry
6844810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
684593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6846810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_element_size < 0)  // we don't know cluster end yet
6847810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_BUFFER_NOT_FULL;  // underflow
684893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6849810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long element_stop = m_element_start + m_element_size;
685093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6851810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_pos >= element_stop)
6852810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;  // nothing left to parse
685393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6854810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return E_BUFFER_NOT_FULL;  // underflow, since more remains to be parsed
685593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
685693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6857810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgCluster* Cluster::Create(Segment* pSegment, long idx, long long off)
6858810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org// long long element_size)
685993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org{
6860810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pSegment);
6861810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(off >= 0);
686293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6863810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long element_start = pSegment->m_start + off;
686493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6865810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  Cluster* const pCluster = new Cluster(pSegment, idx, element_start);
6866810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // element_size);
6867810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster);
686893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6869810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return pCluster;
687093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
687193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6872810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgCluster::Cluster()
6873810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    : m_pSegment(NULL),
6874810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_element_start(0),
6875810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_index(0),
6876810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pos(0),
6877810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_element_size(0),
6878810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_timecode(0),
6879810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_entries(NULL),
6880810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_entries_size(0),
6881810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_entries_count(0)  // means "no entries"
6882810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org{}
688393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6884810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgCluster::Cluster(Segment* pSegment, long idx, long long element_start
6885810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                 /* long long element_size */)
6886810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    : m_pSegment(pSegment),
6887810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_element_start(element_start),
6888810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_index(idx),
6889810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_pos(element_start),
6890810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_element_size(-1 /* element_size */),
6891810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_timecode(-1),
6892810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_entries(NULL),
6893810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_entries_size(0),
6894810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_entries_count(-1)  // means "has not been parsed yet"
6895810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org{}
689693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6897810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgCluster::~Cluster() {
6898810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_entries_count <= 0)
6899810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return;
690093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6901810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  BlockEntry** i = m_entries;
6902810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  BlockEntry** const j = m_entries + m_entries_count;
690393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6904810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (i != j) {
6905810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    BlockEntry* p = *i++;
6906810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(p);
690793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6908810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    delete p;
6909810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
691093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6911810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete[] m_entries;
691293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
691393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6914810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgbool Cluster::EOS() const { return (m_pSegment == NULL); }
691593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6916810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Cluster::GetIndex() const { return m_index; }
691793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6918810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long Cluster::GetPosition() const {
6919810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long pos = m_element_start - m_pSegment->m_start;
6920810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos >= 0);
692193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6922810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return pos;
692393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
692493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6925810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long Cluster::GetElementSize() const { return m_element_size; }
692693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
692793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
692893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgbool Cluster::HasBlockEntries(
692993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const Segment* pSegment,
6930810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long off) {
693193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pSegment);
6932810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(off >= 0);  //relative to start of segment payload
693393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
693493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    IMkvReader* const pReader = pSegment->m_pReader;
693593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
693693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    long long pos = pSegment->m_start + off;  //absolute
693793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    long long size;
693893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
693993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    {
694093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        long len;
694193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
694293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const long long id = ReadUInt(pReader, pos, len);
694393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        (void)id;
694493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(id >= 0);
694593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(id == 0x0F43B675);  //Cluster ID
694693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
694793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        pos += len;  //consume id
694893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
694993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        size = ReadUInt(pReader, pos, len);
695093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(size > 0);
695193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
695293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        pos += len;  //consume size
695393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
695493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        //pos now points to start of payload
695593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
695693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
695793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long stop = pos + size;
695893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
695993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    while (pos < stop)
696093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    {
696193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        long len;
696293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
696393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const long long id = ReadUInt(pReader, pos, len);
696493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(id >= 0);  //TODO
696593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert((pos + len) <= stop);
696693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
696793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        pos += len;  //consume id
696893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
696993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const long long size = ReadUInt(pReader, pos, len);
697093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(size >= 0);  //TODO
697193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert((pos + len) <= stop);
697293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
697393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        pos += len;  //consume size
697493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
697593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (id == 0x20)  //BlockGroup ID
697693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return true;
697793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
697893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (id == 0x23)  //SimpleBlock ID
697993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return true;
698093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
698193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        pos += size;  //consume payload
698293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(pos <= stop);
698393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
698493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
698593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    return false;
698693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
698793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
698893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
698993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orglong Cluster::HasBlockEntries(
699093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const Segment* pSegment,
6991810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long off,  // relative to start of segment payload
6992810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long& pos, long& len) {
6993810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pSegment);
6994810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(off >= 0);  // relative to segment
699593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6996810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  IMkvReader* const pReader = pSegment->m_pReader;
699793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
6998810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long total, avail;
699993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7000810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long status = pReader->Length(&total, &avail);
700193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7002810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)  // error
7003810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
700493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7005810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((total < 0) || (avail <= total));
700693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7007810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos = pSegment->m_start + off;  // absolute
700893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7009810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((total >= 0) && (pos >= total))
7010810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;  // we don't even have a complete cluster
701193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7012810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long segment_stop =
7013810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      (pSegment->m_size < 0) ? -1 : pSegment->m_start + pSegment->m_size;
701493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7015810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long cluster_stop = -1;  // interpreted later to mean "unknown size"
701693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7017810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  {
7018810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > avail) {
7019810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
7020810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
7021810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
702293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7023810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long result = GetUIntLength(pReader, pos, len);
702493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7025810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error
7026810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(result);
702793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7028810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result > 0)  // need more data
7029810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
703093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7031810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((segment_stop >= 0) && ((pos + len) > segment_stop))
7032810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
703393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7034810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((total >= 0) && ((pos + len) > total))
7035810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 0;
703693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7037810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > avail)
7038810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
703993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7040810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long id = ReadUInt(pReader, pos, len);
704193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7042810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id < 0)  // error
7043810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(id);
704493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7045810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id != 0x0F43B675)  // weird: not cluster ID
7046810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return -1;  // generic error
704793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7048810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume Cluster ID field
704993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7050810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // read size field
705193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7052810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > avail) {
7053810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
7054810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
7055810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
705693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7057810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result = GetUIntLength(pReader, pos, len);
705893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7059810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error
7060810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(result);
706193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7062810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result > 0)  // weird
7063810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
706493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7065810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((segment_stop >= 0) && ((pos + len) > segment_stop))
7066810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
706793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7068810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((total >= 0) && ((pos + len) > total))
7069810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 0;
707093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7071810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > avail)
7072810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
707393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7074810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long size = ReadUInt(pReader, pos, len);
707593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7076810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size < 0)  // error
7077810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(size);
707893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7079810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size == 0)
7080810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 0;  // cluster does not have entries
708193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7082810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume size field
708393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7084810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // pos now points to start of payload
708593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7086810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long unknown_size = (1LL << (7 * len)) - 1;
708793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7088810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size != unknown_size) {
7089810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      cluster_stop = pos + size;
7090810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(cluster_stop >= 0);
709193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7092810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if ((segment_stop >= 0) && (cluster_stop > segment_stop))
7093810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
709493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7095810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if ((total >= 0) && (cluster_stop > total))
7096810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        // return E_FILE_FORMAT_INVALID;  //too conservative
7097810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return 0;  // cluster does not have any entries
709893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
7099810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
710093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7101810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  for (;;) {
7102810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((cluster_stop >= 0) && (pos >= cluster_stop))
7103810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 0;  // no entries detected
710493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7105810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > avail) {
7106810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
7107810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
7108810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
710993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7110810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long result = GetUIntLength(pReader, pos, len);
711193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7112810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error
7113810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(result);
711493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7115810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result > 0)  // need more data
7116810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
711793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7118810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
7119810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
712093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7121810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > avail)
7122810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
712393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7124810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long id = ReadUInt(pReader, pos, len);
712593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7126810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id < 0)  // error
7127810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(id);
712893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7129810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // This is the distinguished set of ID's we use to determine
7130810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // that we have exhausted the sub-element's inside the cluster
7131810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // whose ID we parsed earlier.
713293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7133810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x0F43B675)  // Cluster ID
7134810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 0;  // no entries found
713593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7136810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x0C53BB6B)  // Cues ID
7137810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 0;  // no entries found
713893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7139810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume id field
714093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7141810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((cluster_stop >= 0) && (pos >= cluster_stop))
7142810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
714393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7144810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // read size field
714593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7146810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + 1) > avail) {
7147810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      len = 1;
7148810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
7149810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
715093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7151810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    result = GetUIntLength(pReader, pos, len);
715293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7153810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result < 0)  // error
7154810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(result);
715593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7156810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (result > 0)  // underflow
7157810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
715893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7159810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
7160810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
716193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7162810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > avail)
7163810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_BUFFER_NOT_FULL;
716493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7165810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long size = ReadUInt(pReader, pos, len);
716693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7167810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size < 0)  // error
7168810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return static_cast<long>(size);
716993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7170810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume size field
717193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7172810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    // pos now points to start of payload
717393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7174810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((cluster_stop >= 0) && (pos > cluster_stop))
7175810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
717693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7177810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size == 0)  // weird
7178810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
717993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7180810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long unknown_size = (1LL << (7 * len)) - 1;
718193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7182810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (size == unknown_size)
7183810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;  // not supported inside cluster
718493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7185810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((cluster_stop >= 0) && ((pos + size) > cluster_stop))
7186810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
718793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7188810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x20)  // BlockGroup ID
7189810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 1;  // have at least one entry
719093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7191810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x23)  // SimpleBlock ID
7192810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 1;  // have at least one entry
719393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7194810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
7195810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((cluster_stop < 0) || (pos <= cluster_stop));
7196810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
719793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
719893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7199810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long Cluster::GetTimeCode() const {
7200810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long pos;
7201810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long len;
720293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7203810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long status = Load(pos, len);
720493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7205810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)  // error
7206810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
720793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7208810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return m_timecode;
720993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
721093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7211810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long Cluster::GetTime() const {
7212810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long tc = GetTimeCode();
721393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7214810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (tc < 0)
7215810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return tc;
721693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7217810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const SegmentInfo* const pInfo = m_pSegment->GetInfo();
7218810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pInfo);
721993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7220810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long scale = pInfo->GetTimeCodeScale();
7221810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(scale >= 1);
722293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7223810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long t = m_timecode * scale;
722493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7225810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return t;
722693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
722793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7228810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long Cluster::GetFirstTime() const {
7229810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const BlockEntry* pEntry;
723093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7231810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long status = GetFirst(pEntry);
723293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7233810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)  // error
7234810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
723593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7236810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pEntry == NULL)  // empty cluster
7237810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return GetTime();
723893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7239810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const Block* const pBlock = pEntry->GetBlock();
7240810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pBlock);
724193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7242810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return pBlock->GetTime(this);
7243810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org}
724493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7245810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long Cluster::GetLastTime() const {
7246810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const BlockEntry* pEntry;
724793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7248810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long status = GetLast(pEntry);
724993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7250810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status < 0)  // error
7251810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
725293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7253810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pEntry == NULL)  // empty cluster
7254810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return GetTime();
725593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7256810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const Block* const pBlock = pEntry->GetBlock();
7257810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pBlock);
725893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7259810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return pBlock->GetTime(this);
726093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
726193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7262810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Cluster::CreateBlock(long long id,
7263810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                          long long pos,  // absolute pos of payload
7264810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                          long long size, long long discard_padding) {
7265810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert((id == 0x20) || (id == 0x23));  // BlockGroup or SimpleBlock
726693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7267810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_entries_count < 0) {  // haven't parsed anything yet
7268810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(m_entries == NULL);
7269810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(m_entries_size == 0);
7270810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7271810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m_entries_size = 1024;
7272810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m_entries = new BlockEntry* [m_entries_size];
7273810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7274810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m_entries_count = 0;
7275810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  } else {
727693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(m_entries);
727793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(m_entries_size > 0);
7278810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(m_entries_count <= m_entries_size);
727993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7280810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (m_entries_count >= m_entries_size) {
7281810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long entries_size = 2 * m_entries_size;
728293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7283810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      BlockEntry** const entries = new BlockEntry* [entries_size];
7284810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(entries);
728593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7286810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      BlockEntry** src = m_entries;
7287810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      BlockEntry** const src_end = src + m_entries_count;
728893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7289810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      BlockEntry** dst = entries;
729093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7291810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      while (src != src_end)
7292810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        *dst++ = *src++;
729393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7294810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      delete[] m_entries;
729593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7296810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_entries = entries;
7297810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_entries_size = entries_size;
7298810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
7299810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
730093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7301810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (id == 0x20)  // BlockGroup ID
7302810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return CreateBlockGroup(pos, size, discard_padding);
7303810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  else  // SimpleBlock ID
7304810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return CreateSimpleBlock(pos, size);
7305810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org}
730693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7307810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Cluster::CreateBlockGroup(long long start_offset, long long size,
7308810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                               long long discard_padding) {
7309810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_entries);
7310810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_entries_size > 0);
7311810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_entries_count >= 0);
7312810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_entries_count < m_entries_size);
731393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7314810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  IMkvReader* const pReader = m_pSegment->m_pReader;
731593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7316810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long pos = start_offset;
7317810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long stop = start_offset + size;
731893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7319810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // For WebM files, there is a bias towards previous reference times
7320810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  //(in order to support alt-ref frames, which refer back to the previous
7321810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // keyframe).  Normally a 0 value is not possible, but here we tenatively
7322810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // allow 0 as the value of a reference frame, with the interpretation
7323810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  // that this is a "previous" reference time.
732493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7325810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long prev = 1;  // nonce
7326810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long next = 0;  // nonce
7327810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long duration = -1;  // really, this is unsigned
732893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7329810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long bpos = -1;
7330810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long bsize = -1;
733193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7332810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  while (pos < stop) {
7333810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long len;
7334810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long id = ReadUInt(pReader, pos, len);
7335810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(id >= 0);  // TODO
7336810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((pos + len) <= stop);
733793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7338810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume ID
733993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7340810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long size = ReadUInt(pReader, pos, len);
7341810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(size >= 0);  // TODO
7342810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert((pos + len) <= stop);
734393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7344810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume size
734593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7346810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (id == 0x21) {  // Block ID
7347810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (bpos < 0) {  // Block ID
7348810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        bpos = pos;
7349810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        bsize = size;
7350810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      }
7351810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x1B) {  // Duration ID
7352810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(size <= 8);
735393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7354810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      duration = UnserializeUInt(pReader, pos, size);
7355810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(duration >= 0);  // TODO
7356810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (id == 0x7B) {  // ReferenceBlock
7357810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(size <= 8);
7358810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long size_ = static_cast<long>(size);
735993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7360810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      long long time;
736193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7362810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      long status = UnserializeInt(pReader, pos, size_, time);
7363810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(status == 0);
7364810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status != 0)
7365810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return -1;
736693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7367810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (time <= 0)  // see note above
7368810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        prev = time;
7369810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      else  // weird
7370810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        next = time;
737193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
737293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7373810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += size;  // consume payload
7374810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos <= stop);
7375810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
737693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7377810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos == stop);
7378810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(bpos >= 0);
7379810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(bsize >= 0);
738093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7381810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long idx = m_entries_count;
738293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7383810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  BlockEntry** const ppEntry = m_entries + idx;
7384810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  BlockEntry*& pEntry = *ppEntry;
738593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7386810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pEntry = new (std::nothrow)
7387810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      BlockGroup(this, idx, bpos, bsize, prev, next, duration, discard_padding);
738893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7389810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pEntry == NULL)
7390810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;  // generic error
739193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7392810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  BlockGroup* const p = static_cast<BlockGroup*>(pEntry);
739393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7394810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long status = p->Parse();
739593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7396810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status == 0) {  // success
7397810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    ++m_entries_count;
7398810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;
7399810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
740093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7401810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete pEntry;
7402810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pEntry = 0;
740393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7404810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return status;
7405810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org}
740693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7407810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Cluster::CreateSimpleBlock(long long st, long long sz) {
7408810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_entries);
7409810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_entries_size > 0);
7410810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_entries_count >= 0);
7411810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_entries_count < m_entries_size);
741293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7413810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long idx = m_entries_count;
741493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7415810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  BlockEntry** const ppEntry = m_entries + idx;
7416810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  BlockEntry*& pEntry = *ppEntry;
741793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7418810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pEntry = new (std::nothrow) SimpleBlock(this, idx, st, sz);
741993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7420810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pEntry == NULL)
7421810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;  // generic error
742293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7423810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  SimpleBlock* const p = static_cast<SimpleBlock*>(pEntry);
742493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7425810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long status = p->Parse();
742693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7427810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status == 0) {
7428810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    ++m_entries_count;
7429810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;
7430810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
743193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7432810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  delete pEntry;
7433810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pEntry = 0;
743493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7435810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return status;
743693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
743793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7438810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Cluster::GetFirst(const BlockEntry*& pFirst) const {
7439810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_entries_count <= 0) {
7440810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long pos;
7441810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long len;
744293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7443810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long status = Parse(pos, len);
744493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7445810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0) {  // error
7446810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pFirst = NULL;
7447810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
744893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
744993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7450810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (m_entries_count <= 0) {  // empty cluster
7451810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pFirst = NULL;
7452810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 0;
745393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
7454810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
745593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7456810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_entries);
745793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7458810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pFirst = m_entries[0];
7459810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pFirst);
746093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7461810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;  // success
7462810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org}
746393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7464810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Cluster::GetLast(const BlockEntry*& pLast) const {
7465810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  for (;;) {
7466810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long pos;
7467810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long len;
7468810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7469810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long status = Parse(pos, len);
7470810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7471810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0) {  // error
7472810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pLast = NULL;
7473810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
7474810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
7475810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7476810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status > 0)  // no new block
7477810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      break;
7478810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
7479810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7480810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_entries_count <= 0) {
7481810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pLast = NULL;
748293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    return 0;
7483810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
748493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7485810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_entries);
748693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7487810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long idx = m_entries_count - 1;
748893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7489810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pLast = m_entries[idx];
7490810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pLast);
749193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7492810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;
7493810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org}
749493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7495810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Cluster::GetNext(const BlockEntry* pCurr, const BlockEntry*& pNext) const {
7496810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCurr);
7497810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_entries);
7498810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_entries_count > 0);
749993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7500810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  size_t idx = pCurr->GetIndex();
7501810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(idx < size_t(m_entries_count));
7502810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_entries[idx] == pCurr);
750393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7504810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  ++idx;
750593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7506810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (idx >= size_t(m_entries_count)) {
7507810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long pos;
7508810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long len;
750993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7510810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long status = Parse(pos, len);
7511810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7512810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status < 0) {  // error
7513810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pNext = NULL;
7514810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return status;
751593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
751693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7517810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (status > 0) {
7518810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pNext = NULL;
7519810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return 0;
7520810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
752193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7522810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(m_entries);
7523810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(m_entries_count > 0);
7524810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(idx < size_t(m_entries_count));
7525810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
752693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7527810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pNext = m_entries[idx];
7528810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pNext);
752993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7530810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;
753193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
753293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7533810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Cluster::GetEntryCount() const { return m_entries_count; }
753493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7535810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst BlockEntry* Cluster::GetEntry(const Track* pTrack,
7536810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                    long long time_ns) const {
7537810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pTrack);
753893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7539810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_pSegment == NULL)  // this is the special EOS cluster
7540810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return pTrack->GetEOS();
754193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
754293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
754393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
754493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    LoadBlockEntries();
754593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
754693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if ((m_entries == NULL) || (m_entries_count <= 0))
754793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return NULL;  //return EOS here?
754893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
754993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const BlockEntry* pResult = pTrack->GetEOS();
755093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
755193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    BlockEntry** i = m_entries;
755293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(i);
755393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
755493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    BlockEntry** const j = i + m_entries_count;
755593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
755693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    while (i != j)
755793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    {
755893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const BlockEntry* const pEntry = *i++;
755993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(pEntry);
756093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(!pEntry->EOS());
756193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
756293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const Block* const pBlock = pEntry->GetBlock();
756393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(pBlock);
756493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
756593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (pBlock->GetTrackNumber() != pTrack->GetNumber())
756693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            continue;
756793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
756893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (pTrack->VetEntry(pEntry))
756993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        {
757093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if (time_ns < 0)  //just want first candidate block
757193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                return pEntry;
757293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
757393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            const long long ns = pBlock->GetTime(this);
757493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
757593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if (ns > time_ns)
757693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                break;
757793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
757893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            pResult = pEntry;
757993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        }
758093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        else if (time_ns >= 0)
758193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        {
758293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            const long long ns = pBlock->GetTime(this);
758393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
758493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            if (ns > time_ns)
758593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                break;
758693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        }
758793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
758893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
758993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    return pResult;
759093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
759193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#else
759293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7593810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const BlockEntry* pResult = pTrack->GetEOS();
759493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7595810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long index = 0;
759693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7597810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  for (;;) {
7598810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (index >= m_entries_count) {
7599810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      long long pos;
7600810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      long len;
760193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7602810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long status = Parse(pos, len);
7603810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(status >= 0);
760493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7605810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status > 0)  // completely parsed, and no more entries
7606810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return pResult;
760793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7608810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status < 0)  // should never happen
7609810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return 0;
761093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7611810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(m_entries);
7612810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(index < m_entries_count);
7613810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
761493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7615810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const BlockEntry* const pEntry = m_entries[index];
7616810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pEntry);
7617810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(!pEntry->EOS());
761893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7619810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const Block* const pBlock = pEntry->GetBlock();
7620810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pBlock);
762193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7622810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (pBlock->GetTrackNumber() != pTrack->GetNumber()) {
7623810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      ++index;
7624810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
7625810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
762693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7627810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (pTrack->VetEntry(pEntry)) {
7628810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (time_ns < 0)  // just want first candidate block
7629810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return pEntry;
763093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7631810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long ns = pBlock->GetTime(this);
763293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7633810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (ns > time_ns)
7634810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return pResult;
763593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7636810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pResult = pEntry;  // have a candidate
7637810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    } else if (time_ns >= 0) {
7638810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long ns = pBlock->GetTime(this);
763993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7640810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (ns > time_ns)
7641810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return pResult;
764293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
764393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7644810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    ++index;
7645810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
7646810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
764793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
764893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
764993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7650810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst BlockEntry* Cluster::GetEntry(const CuePoint& cp,
7651810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                                    const CuePoint::TrackPosition& tp) const {
7652810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_pSegment);
765393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
765493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
765593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
765693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    LoadBlockEntries();
765793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
765893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (m_entries == NULL)
765993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return NULL;
766093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
766193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long count = m_entries_count;
766293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
766393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (count <= 0)
766493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return NULL;
766593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
766693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const long long tc = cp.GetTimeCode();
766793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
766893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if ((tp.m_block > 0) && (tp.m_block <= count))
766993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    {
767093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const size_t block = static_cast<size_t>(tp.m_block);
767193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const size_t index = block - 1;
767293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
767393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const BlockEntry* const pEntry = m_entries[index];
767493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(pEntry);
767593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(!pEntry->EOS());
767693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
767793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const Block* const pBlock = pEntry->GetBlock();
767893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(pBlock);
767993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
768093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if ((pBlock->GetTrackNumber() == tp.m_track) &&
768193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            (pBlock->GetTimeCode(this) == tc))
768293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        {
768393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return pEntry;
768493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        }
768593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
768693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
768793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const BlockEntry* const* i = m_entries;
768893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    const BlockEntry* const* const j = i + count;
768993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
769093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    while (i != j)
769193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    {
769293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#ifdef _DEBUG
769393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const ptrdiff_t idx = i - m_entries;
769493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        idx;
769593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
769693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
769793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const BlockEntry* const pEntry = *i++;
769893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(pEntry);
769993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(!pEntry->EOS());
770093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
770193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const Block* const pBlock = pEntry->GetBlock();
770293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(pBlock);
770393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
770493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (pBlock->GetTrackNumber() != tp.m_track)
770593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            continue;
770693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
770793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const long long tc_ = pBlock->GetTimeCode(this);
7708810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        assert(tc_ >= 0);
770993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
771093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (tc_ < tc)
771193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            continue;
771293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
771393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (tc_ > tc)
771493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return NULL;
771593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
771693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const Tracks* const pTracks = m_pSegment->GetTracks();
771793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(pTracks);
771893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
771993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const long tn = static_cast<long>(tp.m_track);
772093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const Track* const pTrack = pTracks->GetTrackByNumber(tn);
772193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
772293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (pTrack == NULL)
772393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return NULL;
772493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
772593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const long long type = pTrack->GetType();
772693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
772793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (type == 2)  //audio
772893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return pEntry;
772993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
773093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (type != 1)  //not video
773193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return NULL;
773293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
773393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (!pBlock->IsKey())
773493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return NULL;
773593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
773693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return pEntry;
773793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
773893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7739810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return NULL;
774093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7741810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org#else
7742810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7743810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long tc = cp.GetTimeCode();
7744810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7745810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (tp.m_block > 0) {
7746810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long block = static_cast<long>(tp.m_block);
7747810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long index = block - 1;
7748810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7749810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    while (index >= m_entries_count) {
7750810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      long long pos;
7751810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      long len;
7752810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7753810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long status = Parse(pos, len);
7754810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7755810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status < 0)  // TODO: can this happen?
7756810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return NULL;
7757810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7758810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status > 0)  // nothing remains to be parsed
7759810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return NULL;
7760810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
7761810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7762810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const BlockEntry* const pEntry = m_entries[index];
7763810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pEntry);
7764810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(!pEntry->EOS());
7765810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7766810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const Block* const pBlock = pEntry->GetBlock();
7767810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pBlock);
7768810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7769810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pBlock->GetTrackNumber() == tp.m_track) &&
7770810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        (pBlock->GetTimeCode(this) == tc)) {
7771810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return pEntry;
7772810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
7773810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
7774810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7775810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long index = 0;
7776810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7777810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  for (;;) {
7778810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (index >= m_entries_count) {
7779810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      long long pos;
7780810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      long len;
7781810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7782810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long status = Parse(pos, len);
7783810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7784810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status < 0)  // TODO: can this happen?
7785810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return NULL;
7786810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7787810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (status > 0)  // nothing remains to be parsed
7788810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return NULL;
7789810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7790810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(m_entries);
7791810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(index < m_entries_count);
7792810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
7793810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7794810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const BlockEntry* const pEntry = m_entries[index];
7795810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pEntry);
7796810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(!pEntry->EOS());
7797810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7798810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const Block* const pBlock = pEntry->GetBlock();
7799810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pBlock);
7800810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7801810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (pBlock->GetTrackNumber() != tp.m_track) {
7802810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      ++index;
7803810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
7804810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
7805810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7806810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long tc_ = pBlock->GetTimeCode(this);
7807810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7808810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (tc_ < tc) {
7809810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      ++index;
7810810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      continue;
7811810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
7812810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7813810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (tc_ > tc)
7814810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return NULL;
7815810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7816810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const Tracks* const pTracks = m_pSegment->GetTracks();
7817810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pTracks);
7818810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7819810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long tn = static_cast<long>(tp.m_track);
7820810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const Track* const pTrack = pTracks->GetTrackByNumber(tn);
782193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7822810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (pTrack == NULL)
7823810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return NULL;
7824810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7825810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long type = pTrack->GetType();
7826810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7827810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (type == 2)  // audio
7828810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return pEntry;
7829810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7830810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (type != 1)  // not video
7831810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return NULL;
7832810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7833810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (!pBlock->IsKey())
7834810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return NULL;
7835810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7836810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return pEntry;
7837810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
7838810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org
7839810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org#endif
7840810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org}
784193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
784293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
784393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgconst BlockEntry* Cluster::GetMaxKey(const VideoTrack* pTrack) const
784493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org{
784593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pTrack);
784693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
784793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (m_pSegment == NULL)  //EOS
784893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return pTrack->GetEOS();
784993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
785093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    LoadBlockEntries();
785193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
785293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if ((m_entries == NULL) || (m_entries_count <= 0))
785393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        return pTrack->GetEOS();
785493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
785593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    BlockEntry** i = m_entries + m_entries_count;
785693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    BlockEntry** const j = m_entries;
785793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
785893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    while (i != j)
785993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    {
786093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const BlockEntry* const pEntry = *--i;
786193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(pEntry);
786293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(!pEntry->EOS());
786393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
786493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        const Block* const pBlock = pEntry->GetBlock();
786593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        assert(pBlock);
786693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
786793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (pBlock->GetTrackNumber() != pTrack->GetNumber())
786893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            continue;
786993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
787093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        if (pBlock->IsKey())
787193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org            return pEntry;
787293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
787393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
787493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    return pTrack->GetEOS();  //no satisfactory block found
787593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
787693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
787793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7878810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgBlockEntry::BlockEntry(Cluster* p, long idx) : m_pCluster(p), m_index(idx) {}
787993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7880810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgBlockEntry::~BlockEntry() {}
788193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7882810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgbool BlockEntry::EOS() const { return (GetKind() == kBlockEOS); }
788393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7884810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst Cluster* BlockEntry::GetCluster() const { return m_pCluster; }
788593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7886810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong BlockEntry::GetIndex() const { return m_index; }
788793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7888810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgSimpleBlock::SimpleBlock(Cluster* pCluster, long idx, long long start,
7889810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                         long long size)
7890810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    : BlockEntry(pCluster, idx), m_block(start, size, 0) {}
789193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7892810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong SimpleBlock::Parse() { return m_block.Parse(m_pCluster); }
789393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7894810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgBlockEntry::Kind SimpleBlock::GetKind() const { return kBlockSimple; }
789593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7896810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst Block* SimpleBlock::GetBlock() const { return &m_block; }
789793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7898810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgBlockGroup::BlockGroup(Cluster* pCluster, long idx, long long block_start,
7899810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                       long long block_size, long long prev, long long next,
7900810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org                       long long duration, long long discard_padding)
7901810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    : BlockEntry(pCluster, idx),
7902810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_block(block_start, block_size, discard_padding),
7903810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_prev(prev),
7904810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_next(next),
7905810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_duration(duration) {}
790693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7907810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong BlockGroup::Parse() {
7908810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long status = m_block.Parse(m_pCluster);
790993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7910810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status)
7911810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return status;
791293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7913810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_block.SetKey((m_prev > 0) && (m_next <= 0));
791493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7915810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;
791693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
791793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
791893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if 0
791993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgvoid BlockGroup::ParseBlock(long long start, long long size)
792093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org{
792193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    IMkvReader* const pReader = m_pCluster->m_pSegment->m_pReader;
792293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
792393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    Block* const pBlock = new Block(start, size, pReader);
792493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(pBlock);  //TODO
792593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
792693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //TODO: the Matroska spec says you have multiple blocks within the
792793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    //same block group, with blocks ranked by priority (the flag bits).
792893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
792993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    assert(m_pBlock == NULL);
793093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    m_pBlock = pBlock;
793193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
793293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
793393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7934810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgBlockEntry::Kind BlockGroup::GetKind() const { return kBlockGroup; }
793593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7936810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst Block* BlockGroup::GetBlock() const { return &m_block; }
793793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7938810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long BlockGroup::GetPrevTimeCode() const { return m_prev; }
793993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7940810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long BlockGroup::GetNextTimeCode() const { return m_next; }
794193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7942810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long BlockGroup::GetDurationTimeCode() const { return m_duration; }
794393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7944810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgBlock::Block(long long start, long long size_, long long discard_padding)
7945810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    : m_start(start),
7946810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_size(size_),
7947810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_track(0),
7948810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_timecode(-1),
7949810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_flags(0),
7950810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_frames(NULL),
7951810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_frame_count(-1),
7952810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      m_discard_padding(discard_padding) {}
795393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7954810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgBlock::~Block() { delete[] m_frames; }
795593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7956810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Block::Parse(const Cluster* pCluster) {
7957810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pCluster == NULL)
7958810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
795993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7960810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pCluster->m_pSegment == NULL)
7961810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return -1;
796293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7963810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_start >= 0);
7964810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_size >= 0);
7965810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_track <= 0);
7966810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_frames == NULL);
7967810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_frame_count <= 0);
796893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7969810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long pos = m_start;
7970810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long stop = m_start + m_size;
797193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7972810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long len;
797393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7974810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  IMkvReader* const pReader = pCluster->m_pSegment->m_pReader;
797593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7976810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_track = ReadUInt(pReader, pos, len);
797793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7978810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (m_track <= 0)
7979810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
798093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7981810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((pos + len) > stop)
7982810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
798393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7984810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos += len;  // consume track number
798593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7986810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((stop - pos) < 2)
7987810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
798893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7989810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long status;
7990810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  long long value;
799193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7992810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  status = UnserializeInt(pReader, pos, 2, value);
799393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7994810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status)
7995810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
799693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
7997810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (value < SHRT_MIN)
7998810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
799993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8000810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (value > SHRT_MAX)
8001810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
800293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8003810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_timecode = static_cast<short>(value);
800493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8005810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  pos += 2;
800693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8007810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if ((stop - pos) <= 0)
8008810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
800993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8010810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  status = pReader->Read(pos, 1, &m_flags);
801193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8012810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status)
8013810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
801493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8015810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const int lacing = int(m_flags & 0x06) >> 1;
801693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8017810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  ++pos;  // consume flags byte
801893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8019810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (lacing == 0) {  // no lacing
8020810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (pos > stop)
8021810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
802293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8023810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m_frame_count = 1;
8024810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m_frames = new Frame[m_frame_count];
802593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8026810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Frame& f = m_frames[0];
8027810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    f.pos = pos;
802893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8029810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long frame_size = stop - pos;
803093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8031810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (frame_size > LONG_MAX)
8032810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
803393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8034810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    f.len = static_cast<long>(frame_size);
803593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8036810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return 0;  // success
8037810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
803893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8039810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pos >= stop)
8040810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
804193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8042810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  unsigned char biased_count;
804393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8044810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  status = pReader->Read(pos, 1, &biased_count);
804593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8046810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (status)
8047810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return E_FILE_FORMAT_INVALID;
804893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8049810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  ++pos;  // consume frame count
8050810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pos <= stop);
805193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8052810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_frame_count = int(biased_count) + 1;
805393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8054810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  m_frames = new Frame[m_frame_count];
8055810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(m_frames);
805693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8057810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (lacing == 1) {  // Xiph
8058810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Frame* pf = m_frames;
8059810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Frame* const pf_end = pf + m_frame_count;
806093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8061810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long size = 0;
8062810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    int frame_count = m_frame_count;
806393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8064810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    while (frame_count > 1) {
8065810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      long frame_size = 0;
806693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8067810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      for (;;) {
8068810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        unsigned char val;
806993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8070810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        if (pos >= stop)
8071810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          return E_FILE_FORMAT_INVALID;
807293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8073810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        status = pReader->Read(pos, 1, &val);
807493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8075810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        if (status)
8076810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          return E_FILE_FORMAT_INVALID;
807793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8078810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        ++pos;  // consume xiph size byte
807993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8080810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        frame_size += val;
808193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8082810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        if (val < 255)
8083810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org          break;
8084810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      }
808593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8086810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      Frame& f = *pf++;
8087810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(pf < pf_end);
808893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8089810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      f.pos = 0;  // patch later
809093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8091810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      f.len = frame_size;
8092810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      size += frame_size;  // contribution of this frame
809393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8094810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      --frame_count;
8095810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
809693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8097810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pf < pf_end);
8098810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos <= stop);
809993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8100810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    {
8101810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      Frame& f = *pf++;
810293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8103810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (pf != pf_end)
8104810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
810593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8106810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      f.pos = 0;  // patch later
810793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8108810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long total_size = stop - pos;
810993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8110810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (total_size < size)
8111810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
811293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8113810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long frame_size = total_size - size;
811493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8115810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (frame_size > LONG_MAX)
8116810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
811793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8118810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      f.len = static_cast<long>(frame_size);
8119810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
812093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8121810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pf = m_frames;
8122810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    while (pf != pf_end) {
8123810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      Frame& f = *pf++;
8124810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert((pos + f.len) <= stop);
812593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8126810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      f.pos = pos;
8127810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pos += f.len;
812893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
812993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8130810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos == stop);
8131810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  } else if (lacing == 2) {  // fixed-size lacing
8132810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long total_size = stop - pos;
813393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8134810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((total_size % m_frame_count) != 0)
8135810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
813693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8137810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    const long long frame_size = total_size / m_frame_count;
813893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8139810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (frame_size > LONG_MAX)
8140810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
814193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8142810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Frame* pf = m_frames;
8143810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Frame* const pf_end = pf + m_frame_count;
814493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8145810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    while (pf != pf_end) {
8146810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert((pos + frame_size) <= stop);
814793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8148810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      Frame& f = *pf++;
814993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8150810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      f.pos = pos;
8151810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      f.len = static_cast<long>(frame_size);
815293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8153810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pos += frame_size;
815493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
815593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8156810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos == stop);
8157810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  } else {
8158810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(lacing == 3);  // EBML lacing
815993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8160810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (pos >= stop)
8161810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
816293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8163810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long size = 0;
8164810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    int frame_count = m_frame_count;
816593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8166810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    long long frame_size = ReadUInt(pReader, pos, len);
816793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8168810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (frame_size < 0)
8169810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
817093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8171810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if (frame_size > LONG_MAX)
8172810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
817393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8174810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + len) > stop)
8175810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
817693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8177810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pos += len;  // consume length of size of first frame
817893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8179810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    if ((pos + frame_size) > stop)
8180810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      return E_FILE_FORMAT_INVALID;
818193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8182810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Frame* pf = m_frames;
8183810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    Frame* const pf_end = pf + m_frame_count;
818493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8185810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    {
8186810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      Frame& curr = *pf;
818793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8188810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      curr.pos = 0;  // patch later
818993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8190810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      curr.len = static_cast<long>(frame_size);
8191810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      size += curr.len;  // contribution of this frame
8192810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
819393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8194810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    --frame_count;
819593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8196810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    while (frame_count > 1) {
8197810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (pos >= stop)
8198810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
819993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8200810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(pf < pf_end);
820193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8202810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const Frame& prev = *pf++;
8203810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(prev.len == frame_size);
8204810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (prev.len != frame_size)
8205810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
820693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8207810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(pf < pf_end);
820893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8209810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      Frame& curr = *pf;
821093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8211810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      curr.pos = 0;  // patch later
821293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8213810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long delta_size_ = ReadUInt(pReader, pos, len);
821493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8215810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (delta_size_ < 0)
8216810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
821793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8218810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if ((pos + len) > stop)
8219810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
822093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8221810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pos += len;  // consume length of (delta) size
8222810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(pos <= stop);
822393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8224810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const int exp = 7 * len - 1;
8225810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long bias = (1LL << exp) - 1LL;
8226810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long delta_size = delta_size_ - bias;
822793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8228810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      frame_size += delta_size;
822993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8230810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (frame_size < 0)
8231810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
823293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8233810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (frame_size > LONG_MAX)
8234810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
823593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8236810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      curr.len = static_cast<long>(frame_size);
8237810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      size += curr.len;  // contribution of this frame
823893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8239810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      --frame_count;
8240810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
824193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8242810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    {
8243810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(pos <= stop);
8244810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(pf < pf_end);
824593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8246810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const Frame& prev = *pf++;
8247810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(prev.len == frame_size);
8248810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (prev.len != frame_size)
8249810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
825093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8251810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(pf < pf_end);
825293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8253810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      Frame& curr = *pf++;
8254810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert(pf == pf_end);
825593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8256810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      curr.pos = 0;  // patch later
825793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8258810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      const long long total_size = stop - pos;
825993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8260810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (total_size < size)
8261810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
826293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8263810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      frame_size = total_size - size;
826493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8265810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      if (frame_size > LONG_MAX)
8266810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org        return E_FILE_FORMAT_INVALID;
826793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8268810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      curr.len = static_cast<long>(frame_size);
826993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
827093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8271810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    pf = m_frames;
8272810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    while (pf != pf_end) {
8273810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      Frame& f = *pf++;
8274810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      assert((pos + f.len) <= stop);
827593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8276810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      f.pos = pos;
8277810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org      pos += f.len;
8278810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    }
827993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8280810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    assert(pos == stop);
8281810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  }
828293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8283810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return 0;  // success
828493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
828593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8286810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long Block::GetTimeCode(const Cluster* pCluster) const {
8287810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (pCluster == 0)
8288810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    return m_timecode;
828993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8290810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long tc0 = pCluster->GetTimeCode();
8291810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(tc0 >= 0);
829293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8293810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long tc = tc0 + m_timecode;
829493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8295810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return tc;  // unscaled timecode units
829693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
829793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8298810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long Block::GetTime(const Cluster* pCluster) const {
8299810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pCluster);
830093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8301810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long tc = GetTimeCode(pCluster);
830293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8303810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const Segment* const pSegment = pCluster->m_pSegment;
8304810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const SegmentInfo* const pInfo = pSegment->GetInfo();
8305810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pInfo);
830693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8307810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long scale = pInfo->GetTimeCodeScale();
8308810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(scale >= 1);
830993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8310810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long long ns = tc * scale;
831193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8312810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return ns;
831393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
831493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8315810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long Block::GetTrackNumber() const { return m_track; }
831693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8317810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgbool Block::IsKey() const {
8318810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return ((m_flags & static_cast<unsigned char>(1 << 7)) != 0);
831993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
832093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8321810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgvoid Block::SetKey(bool bKey) {
8322810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  if (bKey)
8323810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m_flags |= static_cast<unsigned char>(1 << 7);
8324810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  else
8325810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org    m_flags &= 0x7F;
832693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
832793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8328810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgbool Block::IsInvisible() const { return bool(int(m_flags & 0x08) != 0); }
832993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8330810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgBlock::Lacing Block::GetLacing() const {
8331810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const int value = int(m_flags & 0x06) >> 1;
8332810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return static_cast<Lacing>(value);
833393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
833493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8335810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgint Block::GetFrameCount() const { return m_frame_count; }
833693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8337810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orgconst Block::Frame& Block::GetFrame(int idx) const {
8338810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(idx >= 0);
8339810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(idx < m_frame_count);
834093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8341810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const Frame& f = m_frames[idx];
8342810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(f.pos > 0);
8343810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(f.len > 0);
834493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8345810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return f;
834693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
834793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8348810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong Block::Frame::Read(IMkvReader* pReader, unsigned char* buf) const {
8349810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(pReader);
8350810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  assert(buf);
835193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8352810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  const long status = pReader->Read(pos, len, buf);
8353810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org  return status;
835493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
835593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8356810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.orglong long Block::GetDiscardPadding() const { return m_discard_padding; }
835793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8358810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org}  // end namespace mkvparser
8359