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