Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(443)

Side by Side Diff: source/libvpx/third_party/libwebm/mkvparser.cpp

Issue 1302353004: libvpx: Pull from upstream (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/libvpx.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The WebM project authors. All Rights Reserved. 1 // Copyright (c) 2012 The WebM project authors. All Rights Reserved.
2 // 2 //
3 // Use of this source code is governed by a BSD-style license 3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the LICENSE file in the root of the source 4 // that can be found in the LICENSE file in the root of the source
5 // tree. An additional intellectual property rights grant can be found 5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may 6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree. 7 // be found in the AUTHORS file in the root of the source tree.
8 8
9 #include "mkvparser.hpp" 9 #include "mkvparser.hpp"
10 #include <cassert> 10 #include <cassert>
11 #include <cstring> 11 #include <cstring>
12 #include <new> 12 #include <new>
13 #include <climits> 13 #include <climits>
14 14
15 #ifdef _MSC_VER 15 #ifdef _MSC_VER
16 // Disable MSVC warnings that suggest making code non-portable. 16 // Disable MSVC warnings that suggest making code non-portable.
17 #pragma warning(disable : 4996) 17 #pragma warning(disable : 4996)
18 #endif 18 #endif
19 19
20 mkvparser::IMkvReader::~IMkvReader() {} 20 mkvparser::IMkvReader::~IMkvReader() {}
21 21
22 void mkvparser::GetVersion(int& major, int& minor, int& build, int& revision) { 22 void mkvparser::GetVersion(int& major, int& minor, int& build, int& revision) {
23 major = 1; 23 major = 1;
24 minor = 0; 24 minor = 0;
25 build = 0; 25 build = 0;
26 revision = 28; 26 revision = 30;
27 } 27 }
28 28
29 long long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len) { 29 long long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len) {
30 assert(pReader); 30 assert(pReader);
31 assert(pos >= 0); 31 assert(pos >= 0);
32 32
33 int status; 33 int status;
34 34
35 //#ifdef _DEBUG 35 //#ifdef _DEBUG
36 // long long total, available; 36 // long long total, available;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 unsigned char m = 0x80; 123 unsigned char m = 0x80;
124 124
125 while (!(b & m)) { 125 while (!(b & m)) {
126 m >>= 1; 126 m >>= 1;
127 ++len; 127 ++len;
128 } 128 }
129 129
130 return 0; // success 130 return 0; // success
131 } 131 }
132 132
133 // TODO(vigneshv): This function assumes that unsigned values never have their
134 // high bit set.
133 long long mkvparser::UnserializeUInt(IMkvReader* pReader, long long pos, 135 long long mkvparser::UnserializeUInt(IMkvReader* pReader, long long pos,
134 long long size) { 136 long long size) {
135 assert(pReader); 137 assert(pReader);
136 assert(pos >= 0); 138 assert(pos >= 0);
137 139
138 if ((size <= 0) || (size > 8)) 140 if ((size <= 0) || (size > 8))
139 return E_FILE_FORMAT_INVALID; 141 return E_FILE_FORMAT_INVALID;
140 142
141 long long result = 0; 143 long long result = 0;
142 144
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 212
211 dd <<= 8; 213 dd <<= 8;
212 } 214 }
213 215
214 result = d; 216 result = d;
215 } 217 }
216 218
217 return 0; 219 return 0;
218 } 220 }
219 221
220 long mkvparser::UnserializeInt(IMkvReader* pReader, long long pos, long size, 222 long mkvparser::UnserializeInt(IMkvReader* pReader, long long pos,
221 long long& result) { 223 long long size, long long& result) {
222 assert(pReader); 224 assert(pReader);
223 assert(pos >= 0); 225 assert(pos >= 0);
224 assert(size > 0); 226 assert(size > 0);
225 assert(size <= 8); 227 assert(size <= 8);
226 228
227 { 229 {
228 signed char b; 230 signed char b;
229 231
230 const long status = pReader->Read(pos, 1, (unsigned char*)&b); 232 const long status = pReader->Read(pos, 1, (unsigned char*)&b);
231 233
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
598 // m_element_size(elem_size), 600 // m_element_size(elem_size),
599 m_start(start), 601 m_start(start),
600 m_size(size), 602 m_size(size),
601 m_pos(start), 603 m_pos(start),
602 m_pUnknownSize(0), 604 m_pUnknownSize(0),
603 m_pSeekHead(NULL), 605 m_pSeekHead(NULL),
604 m_pInfo(NULL), 606 m_pInfo(NULL),
605 m_pTracks(NULL), 607 m_pTracks(NULL),
606 m_pCues(NULL), 608 m_pCues(NULL),
607 m_pChapters(NULL), 609 m_pChapters(NULL),
610 m_pTags(NULL),
608 m_clusters(NULL), 611 m_clusters(NULL),
609 m_clusterCount(0), 612 m_clusterCount(0),
610 m_clusterPreloadCount(0), 613 m_clusterPreloadCount(0),
611 m_clusterSize(0) {} 614 m_clusterSize(0) {}
612 615
613 Segment::~Segment() { 616 Segment::~Segment() {
614 const long count = m_clusterCount + m_clusterPreloadCount; 617 const long count = m_clusterCount + m_clusterPreloadCount;
615 618
616 Cluster** i = m_clusters; 619 Cluster** i = m_clusters;
617 Cluster** j = m_clusters + count; 620 Cluster** j = m_clusters + count;
618 621
619 while (i != j) { 622 while (i != j) {
620 Cluster* const p = *i++; 623 Cluster* const p = *i++;
621 assert(p); 624 assert(p);
622 625
623 delete p; 626 delete p;
624 } 627 }
625 628
626 delete[] m_clusters; 629 delete[] m_clusters;
627 630
628 delete m_pTracks; 631 delete m_pTracks;
629 delete m_pInfo; 632 delete m_pInfo;
630 delete m_pCues; 633 delete m_pCues;
631 delete m_pChapters; 634 delete m_pChapters;
635 delete m_pTags;
632 delete m_pSeekHead; 636 delete m_pSeekHead;
633 } 637 }
634 638
635 long long Segment::CreateInstance(IMkvReader* pReader, long long pos, 639 long long Segment::CreateInstance(IMkvReader* pReader, long long pos,
636 Segment*& pSegment) { 640 Segment*& pSegment) {
637 assert(pReader); 641 assert(pReader);
638 assert(pos >= 0); 642 assert(pos >= 0);
639 643
640 pSegment = NULL; 644 pSegment = NULL;
641 645
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
900 Chapters(this, pos, size, element_start, element_size); 904 Chapters(this, pos, size, element_start, element_size);
901 905
902 if (m_pChapters == NULL) 906 if (m_pChapters == NULL)
903 return -1; 907 return -1;
904 908
905 const long status = m_pChapters->Parse(); 909 const long status = m_pChapters->Parse();
906 910
907 if (status) 911 if (status)
908 return status; 912 return status;
909 } 913 }
914 } else if (id == 0x0254C367) { // Tags ID
915 if (m_pTags == NULL) {
916 m_pTags = new (std::nothrow)
917 Tags(this, pos, size, element_start, element_size);
918
919 if (m_pTags == NULL)
920 return -1;
921
922 const long status = m_pTags->Parse();
923
924 if (status)
925 return status;
926 }
910 } 927 }
911 928
912 m_pos = pos + size; // consume payload 929 m_pos = pos + size; // consume payload
913 } 930 }
914 931
915 assert((segment_stop < 0) || (m_pos <= segment_stop)); 932 assert((segment_stop < 0) || (m_pos <= segment_stop));
916 933
917 if (m_pInfo == NULL) // TODO: liberalize this behavior 934 if (m_pInfo == NULL) // TODO: liberalize this behavior
918 return E_FILE_FORMAT_INVALID; 935 return E_FILE_FORMAT_INVALID;
919 936
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
1018 1035
1019 // pos now points to start of payload 1036 // pos now points to start of payload
1020 1037
1021 if (size == 0) { // weird 1038 if (size == 0) { // weird
1022 m_pos = pos; 1039 m_pos = pos;
1023 continue; 1040 continue;
1024 } 1041 }
1025 1042
1026 const long long unknown_size = (1LL << (7 * len)) - 1; 1043 const long long unknown_size = (1LL << (7 * len)) - 1;
1027 1044
1028 #if 0 // we must handle this to support live webm
1029 if (size == unknown_size)
1030 return E_FILE_FORMAT_INVALID; //TODO: allow this
1031 #endif
1032
1033 if ((segment_stop >= 0) && (size != unknown_size) && 1045 if ((segment_stop >= 0) && (size != unknown_size) &&
1034 ((pos + size) > segment_stop)) { 1046 ((pos + size) > segment_stop)) {
1035 return E_FILE_FORMAT_INVALID; 1047 return E_FILE_FORMAT_INVALID;
1036 } 1048 }
1037 1049
1038 #if 0 // commented-out, to support incremental cluster parsing
1039 len = static_cast<long>(size);
1040
1041 if ((pos + size) > avail)
1042 return E_BUFFER_NOT_FULL;
1043 #endif
1044
1045 if (id == 0x0C53BB6B) { // Cues ID 1050 if (id == 0x0C53BB6B) { // Cues ID
1046 if (size == unknown_size) 1051 if (size == unknown_size)
1047 return E_FILE_FORMAT_INVALID; // TODO: liberalize 1052 return E_FILE_FORMAT_INVALID; // TODO: liberalize
1048 1053
1049 if (m_pCues == NULL) { 1054 if (m_pCues == NULL) {
1050 const long long element_size = (pos - idpos) + size; 1055 const long long element_size = (pos - idpos) + size;
1051 1056
1052 m_pCues = new Cues(this, pos, size, idpos, element_size); 1057 m_pCues = new Cues(this, pos, size, idpos, element_size);
1053 assert(m_pCues); // TODO 1058 assert(m_pCues); // TODO
1054 } 1059 }
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
1150 --m_clusterPreloadCount; 1155 --m_clusterPreloadCount;
1151 1156
1152 m_pos = pos; // consume payload 1157 m_pos = pos; // consume payload
1153 assert((segment_stop < 0) || (m_pos <= segment_stop)); 1158 assert((segment_stop < 0) || (m_pos <= segment_stop));
1154 1159
1155 return 0; // success 1160 return 0; // success
1156 } 1161 }
1157 } 1162 }
1158 1163
1159 if (status == 0) { // no entries found 1164 if (status == 0) { // no entries found
1160 if (cluster_size < 0) 1165 if (cluster_size >= 0)
1161 return E_FILE_FORMAT_INVALID; // TODO: handle this 1166 pos += cluster_size;
1162
1163 pos += cluster_size;
1164 1167
1165 if ((total >= 0) && (pos >= total)) { 1168 if ((total >= 0) && (pos >= total)) {
1166 m_pos = total; 1169 m_pos = total;
1167 return 1; // no more clusters 1170 return 1; // no more clusters
1168 } 1171 }
1169 1172
1170 if ((segment_stop >= 0) && (pos >= segment_stop)) { 1173 if ((segment_stop >= 0) && (pos >= segment_stop)) {
1171 m_pos = segment_stop; 1174 m_pos = segment_stop;
1172 return 1; // no more clusters 1175 return 1; // no more clusters
1173 } 1176 }
(...skipping 20 matching lines...) Expand all
1194 assert((segment_stop < 0) || (m_pos <= segment_stop)); 1197 assert((segment_stop < 0) || (m_pos <= segment_stop));
1195 1198
1196 return 0; 1199 return 0;
1197 } 1200 }
1198 1201
1199 m_pUnknownSize = pCluster; 1202 m_pUnknownSize = pCluster;
1200 m_pos = -pos; 1203 m_pos = -pos;
1201 1204
1202 return 0; // partial success, since we have a new cluster 1205 return 0; // partial success, since we have a new cluster
1203 1206
1204 // status == 0 means "no block entries found" 1207 // status == 0 means "no block entries found"
1205 1208 // pos designates start of payload
1206 // pos designates start of payload 1209 // m_pos has NOT been adjusted yet (in case we need to come back here)
1207 // m_pos has NOT been adjusted yet (in case we need to come back here)
1208
1209 #if 0
1210
1211 if (cluster_size < 0) { //unknown size
1212 const long long payload_pos = pos; //absolute pos of cluster payload
1213
1214 for (;;) { //determine cluster size
1215 if ((total >= 0) && (pos >= total))
1216 break;
1217
1218 if ((segment_stop >= 0) && (pos >= segment_stop))
1219 break; //no more clusters
1220
1221 //Read ID
1222
1223 if ((pos + 1) > avail)
1224 {
1225 len = 1;
1226 return E_BUFFER_NOT_FULL;
1227 }
1228
1229 long long result = GetUIntLength(m_pReader, pos, len);
1230
1231 if (result < 0) //error
1232 return static_cast<long>(result);
1233
1234 if (result > 0) //weird
1235 return E_BUFFER_NOT_FULL;
1236
1237 if ((segment_stop >= 0) && ((pos + len) > segment_stop))
1238 return E_FILE_FORMAT_INVALID;
1239
1240 if ((pos + len) > avail)
1241 return E_BUFFER_NOT_FULL;
1242
1243 const long long idpos = pos;
1244 const long long id = ReadUInt(m_pReader, idpos, len);
1245
1246 if (id < 0) //error (or underflow)
1247 return static_cast<long>(id);
1248
1249 //This is the distinguished set of ID's we use to determine
1250 //that we have exhausted the sub-element's inside the cluster
1251 //whose ID we parsed earlier.
1252
1253 if (id == 0x0F43B675) //Cluster ID
1254 break;
1255
1256 if (id == 0x0C53BB6B) //Cues ID
1257 break;
1258
1259 switch (id)
1260 {
1261 case 0x20: //BlockGroup
1262 case 0x23: //Simple Block
1263 case 0x67: //TimeCode
1264 case 0x2B: //PrevSize
1265 break;
1266
1267 default:
1268 assert(false);
1269 break;
1270 }
1271
1272 pos += len; //consume ID (of sub-element)
1273
1274 //Read Size
1275
1276 if ((pos + 1) > avail)
1277 {
1278 len = 1;
1279 return E_BUFFER_NOT_FULL;
1280 }
1281
1282 result = GetUIntLength(m_pReader, pos, len);
1283
1284 if (result < 0) //error
1285 return static_cast<long>(result);
1286
1287 if (result > 0) //weird
1288 return E_BUFFER_NOT_FULL;
1289
1290 if ((segment_stop >= 0) && ((pos + len) > segment_stop))
1291 return E_FILE_FORMAT_INVALID;
1292
1293 if ((pos + len) > avail)
1294 return E_BUFFER_NOT_FULL;
1295
1296 const long long size = ReadUInt(m_pReader, pos, len);
1297
1298 if (size < 0) //error
1299 return static_cast<long>(size);
1300
1301 pos += len; //consume size field of element
1302
1303 //pos now points to start of sub-element's payload
1304
1305 if (size == 0) //weird
1306 continue;
1307
1308 const long long unknown_size = (1LL << (7 * len)) - 1;
1309
1310 if (size == unknown_size)
1311 return E_FILE_FORMAT_INVALID; //not allowed for sub-elements
1312
1313 if ((segment_stop >= 0) && ((pos + size) > segment_stop)) //weird
1314 return E_FILE_FORMAT_INVALID;
1315
1316 pos += size; //consume payload of sub-element
1317 assert((segment_stop < 0) || (pos <= segment_stop));
1318 } //determine cluster size
1319
1320 cluster_size = pos - payload_pos;
1321 assert(cluster_size >= 0);
1322
1323 pos = payload_pos; //reset and re-parse original cluster
1324 }
1325
1326 if (m_clusterPreloadCount > 0)
1327 {
1328 assert(idx < m_clusterSize);
1329
1330 Cluster* const pCluster = m_clusters[idx];
1331 assert(pCluster);
1332 assert(pCluster->m_index < 0);
1333
1334 const long long off = pCluster->GetPosition();
1335 assert(off >= 0);
1336
1337 if (off == cluster_off) //preloaded already
1338 return E_FILE_FORMAT_INVALID; //subtle
1339 }
1340
1341 m_pos = pos + cluster_size; //consume payload
1342 assert((segment_stop < 0) || (m_pos <= segment_stop));
1343
1344 return 2; //try to find another cluster
1345
1346 #endif
1347 } 1210 }
1348 1211
1349 long Segment::DoLoadClusterUnknownSize(long long& pos, long& len) { 1212 long Segment::DoLoadClusterUnknownSize(long long& pos, long& len) {
1350 assert(m_pos < 0); 1213 assert(m_pos < 0);
1351 assert(m_pUnknownSize); 1214 assert(m_pUnknownSize);
1352 1215
1353 #if 0
1354 assert(m_pUnknownSize->GetElementSize() < 0); //TODO: verify this
1355
1356 const long long element_start = m_pUnknownSize->m_element_start;
1357
1358 pos = -m_pos;
1359 assert(pos > element_start);
1360
1361 //We have already consumed the (cluster) ID and size fields.
1362 //We just need to consume the blocks and other sub-elements
1363 //of this cluster, until we discover the boundary.
1364
1365 long long total, avail;
1366
1367 long status = m_pReader->Length(&total, &avail);
1368
1369 if (status < 0) //error
1370 return status;
1371
1372 assert((total < 0) || (avail <= total));
1373
1374 const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
1375
1376 long long element_size = -1;
1377
1378 for (;;) { //determine cluster size
1379 if ((total >= 0) && (pos >= total))
1380 {
1381 element_size = total - element_start;
1382 assert(element_size > 0);
1383
1384 break;
1385 }
1386
1387 if ((segment_stop >= 0) && (pos >= segment_stop))
1388 {
1389 element_size = segment_stop - element_start;
1390 assert(element_size > 0);
1391
1392 break;
1393 }
1394
1395 //Read ID
1396
1397 if ((pos + 1) > avail)
1398 {
1399 len = 1;
1400 return E_BUFFER_NOT_FULL;
1401 }
1402
1403 long long result = GetUIntLength(m_pReader, pos, len);
1404
1405 if (result < 0) //error
1406 return static_cast<long>(result);
1407
1408 if (result > 0) //weird
1409 return E_BUFFER_NOT_FULL;
1410
1411 if ((segment_stop >= 0) && ((pos + len) > segment_stop))
1412 return E_FILE_FORMAT_INVALID;
1413
1414 if ((pos + len) > avail)
1415 return E_BUFFER_NOT_FULL;
1416
1417 const long long idpos = pos;
1418 const long long id = ReadUInt(m_pReader, idpos, len);
1419
1420 if (id < 0) //error (or underflow)
1421 return static_cast<long>(id);
1422
1423 //This is the distinguished set of ID's we use to determine
1424 //that we have exhausted the sub-element's inside the cluster
1425 //whose ID we parsed earlier.
1426
1427 if ((id == 0x0F43B675) || (id == 0x0C53BB6B)) { //Cluster ID or Cues ID
1428 element_size = pos - element_start;
1429 assert(element_size > 0);
1430
1431 break;
1432 }
1433
1434 #ifdef _DEBUG
1435 switch (id)
1436 {
1437 case 0x20: //BlockGroup
1438 case 0x23: //Simple Block
1439 case 0x67: //TimeCode
1440 case 0x2B: //PrevSize
1441 break;
1442
1443 default:
1444 assert(false);
1445 break;
1446 }
1447 #endif
1448
1449 pos += len; //consume ID (of sub-element)
1450
1451 //Read Size
1452
1453 if ((pos + 1) > avail)
1454 {
1455 len = 1;
1456 return E_BUFFER_NOT_FULL;
1457 }
1458
1459 result = GetUIntLength(m_pReader, pos, len);
1460
1461 if (result < 0) //error
1462 return static_cast<long>(result);
1463
1464 if (result > 0) //weird
1465 return E_BUFFER_NOT_FULL;
1466
1467 if ((segment_stop >= 0) && ((pos + len) > segment_stop))
1468 return E_FILE_FORMAT_INVALID;
1469
1470 if ((pos + len) > avail)
1471 return E_BUFFER_NOT_FULL;
1472
1473 const long long size = ReadUInt(m_pReader, pos, len);
1474
1475 if (size < 0) //error
1476 return static_cast<long>(size);
1477
1478 pos += len; //consume size field of element
1479
1480 //pos now points to start of sub-element's payload
1481
1482 if (size == 0) //weird
1483 continue;
1484
1485 const long long unknown_size = (1LL << (7 * len)) - 1;
1486
1487 if (size == unknown_size)
1488 return E_FILE_FORMAT_INVALID; //not allowed for sub-elements
1489
1490 if ((segment_stop >= 0) && ((pos + size) > segment_stop)) //weird
1491 return E_FILE_FORMAT_INVALID;
1492
1493 pos += size; //consume payload of sub-element
1494 assert((segment_stop < 0) || (pos <= segment_stop));
1495 } //determine cluster size
1496
1497 assert(element_size >= 0);
1498
1499 m_pos = element_start + element_size;
1500 m_pUnknownSize = 0;
1501
1502 return 2; //continue parsing
1503 #else
1504 const long status = m_pUnknownSize->Parse(pos, len); 1216 const long status = m_pUnknownSize->Parse(pos, len);
1505 1217
1506 if (status < 0) // error or underflow 1218 if (status < 0) // error or underflow
1507 return status; 1219 return status;
1508 1220
1509 if (status == 0) // parsed a block 1221 if (status == 0) // parsed a block
1510 return 2; // continue parsing 1222 return 2; // continue parsing
1511 1223
1512 assert(status > 0); // nothing left to parse of this cluster 1224 assert(status > 0); // nothing left to parse of this cluster
1513 1225
1514 const long long start = m_pUnknownSize->m_element_start; 1226 const long long start = m_pUnknownSize->m_element_start;
1515 1227
1516 const long long size = m_pUnknownSize->GetElementSize(); 1228 const long long size = m_pUnknownSize->GetElementSize();
1517 assert(size >= 0); 1229 assert(size >= 0);
1518 1230
1519 pos = start + size; 1231 pos = start + size;
1520 m_pos = pos; 1232 m_pos = pos;
1521 1233
1522 m_pUnknownSize = 0; 1234 m_pUnknownSize = 0;
1523 1235
1524 return 2; // continue parsing 1236 return 2; // continue parsing
1525 #endif
1526 } 1237 }
1527 1238
1528 void Segment::AppendCluster(Cluster* pCluster) { 1239 void Segment::AppendCluster(Cluster* pCluster) {
1529 assert(pCluster); 1240 assert(pCluster);
1530 assert(pCluster->m_index >= 0); 1241 assert(pCluster->m_index >= 0);
1531 1242
1532 const long count = m_clusterCount + m_clusterPreloadCount; 1243 const long count = m_clusterCount + m_clusterPreloadCount;
1533 1244
1534 long& size = m_clusterSize; 1245 long& size = m_clusterSize;
1535 assert(size >= count); 1246 assert(size >= count);
1536 1247
1537 const long idx = pCluster->m_index; 1248 const long idx = pCluster->m_index;
1538 assert(idx == m_clusterCount); 1249 assert(idx == m_clusterCount);
1539 1250
1540 if (count >= size) { 1251 if (count >= size) {
1541 const long n = (size <= 0) ? 2048 : 2 * size; 1252 const long n = (size <= 0) ? 2048 : 2 * size;
1542 1253
1543 Cluster** const qq = new Cluster* [n]; 1254 Cluster** const qq = new Cluster*[n];
1544 Cluster** q = qq; 1255 Cluster** q = qq;
1545 1256
1546 Cluster** p = m_clusters; 1257 Cluster** p = m_clusters;
1547 Cluster** const pp = p + count; 1258 Cluster** const pp = p + count;
1548 1259
1549 while (p != pp) 1260 while (p != pp)
1550 *q++ = *p++; 1261 *q++ = *p++;
1551 1262
1552 delete[] m_clusters; 1263 delete[] m_clusters;
1553 1264
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1587 assert(idx >= m_clusterCount); 1298 assert(idx >= m_clusterCount);
1588 1299
1589 const long count = m_clusterCount + m_clusterPreloadCount; 1300 const long count = m_clusterCount + m_clusterPreloadCount;
1590 1301
1591 long& size = m_clusterSize; 1302 long& size = m_clusterSize;
1592 assert(size >= count); 1303 assert(size >= count);
1593 1304
1594 if (count >= size) { 1305 if (count >= size) {
1595 const long n = (size <= 0) ? 2048 : 2 * size; 1306 const long n = (size <= 0) ? 2048 : 2 * size;
1596 1307
1597 Cluster** const qq = new Cluster* [n]; 1308 Cluster** const qq = new Cluster*[n];
1598 Cluster** q = qq; 1309 Cluster** q = qq;
1599 1310
1600 Cluster** p = m_clusters; 1311 Cluster** p = m_clusters;
1601 Cluster** const pp = p + count; 1312 Cluster** const pp = p + count;
1602 1313
1603 while (p != pp) 1314 while (p != pp)
1604 *q++ = *p++; 1315 *q++ = *p++;
1605 1316
1606 delete[] m_clusters; 1317 delete[] m_clusters;
1607 1318
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
1787 const SeekHead::VoidElement* SeekHead::GetVoidElement(int idx) const { 1498 const SeekHead::VoidElement* SeekHead::GetVoidElement(int idx) const {
1788 if (idx < 0) 1499 if (idx < 0)
1789 return 0; 1500 return 0;
1790 1501
1791 if (idx >= m_void_element_count) 1502 if (idx >= m_void_element_count)
1792 return 0; 1503 return 0;
1793 1504
1794 return m_void_elements + idx; 1505 return m_void_elements + idx;
1795 } 1506 }
1796 1507
1797 #if 0
1798 void Segment::ParseCues(long long off)
1799 {
1800 if (m_pCues)
1801 return;
1802
1803 //odbgstream os;
1804 //os << "Segment::ParseCues (begin)" << endl;
1805
1806 long long pos = m_start + off;
1807 const long long element_start = pos;
1808 const long long stop = m_start + m_size;
1809
1810 long len;
1811
1812 long long result = GetUIntLength(m_pReader, pos, len);
1813 assert(result == 0);
1814 assert((pos + len) <= stop);
1815
1816 const long long idpos = pos;
1817
1818 const long long id = ReadUInt(m_pReader, idpos, len);
1819 assert(id == 0x0C53BB6B); //Cues ID
1820
1821 pos += len; //consume ID
1822 assert(pos < stop);
1823
1824 //Read Size
1825
1826 result = GetUIntLength(m_pReader, pos, len);
1827 assert(result == 0);
1828 assert((pos + len) <= stop);
1829
1830 const long long size = ReadUInt(m_pReader, pos, len);
1831 assert(size >= 0);
1832
1833 pos += len; //consume length of size of element
1834 assert((pos + size) <= stop);
1835
1836 const long long element_size = size + pos - element_start;
1837
1838 //Pos now points to start of payload
1839
1840 m_pCues = new Cues(this, pos, size, element_start, element_size);
1841 assert(m_pCues); //TODO
1842
1843 //os << "Segment::ParseCues (end)" << endl;
1844 }
1845 #else
1846 long Segment::ParseCues(long long off, long long& pos, long& len) { 1508 long Segment::ParseCues(long long off, long long& pos, long& len) {
1847 if (m_pCues) 1509 if (m_pCues)
1848 return 0; // success 1510 return 0; // success
1849 1511
1850 if (off < 0) 1512 if (off < 0)
1851 return -1; 1513 return -1;
1852 1514
1853 long long total, avail; 1515 long long total, avail;
1854 1516
1855 const int status = m_pReader->Length(&total, &avail); 1517 const int status = m_pReader->Length(&total, &avail);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1950 return E_BUFFER_NOT_FULL; 1612 return E_BUFFER_NOT_FULL;
1951 1613
1952 const long long element_size = element_stop - element_start; 1614 const long long element_size = element_stop - element_start;
1953 1615
1954 m_pCues = 1616 m_pCues =
1955 new (std::nothrow) Cues(this, pos, size, element_start, element_size); 1617 new (std::nothrow) Cues(this, pos, size, element_start, element_size);
1956 assert(m_pCues); // TODO 1618 assert(m_pCues); // TODO
1957 1619
1958 return 0; // success 1620 return 0; // success
1959 } 1621 }
1960 #endif
1961 1622
1962 #if 0
1963 void Segment::ParseSeekEntry(
1964 long long start,
1965 long long size_)
1966 {
1967 long long pos = start;
1968
1969 const long long stop = start + size_;
1970
1971 long len;
1972
1973 const long long seekIdId = ReadUInt(m_pReader, pos, len);
1974 //seekIdId;
1975 assert(seekIdId == 0x13AB); //SeekID ID
1976 assert((pos + len) <= stop);
1977
1978 pos += len; //consume id
1979
1980 const long long seekIdSize = ReadUInt(m_pReader, pos, len);
1981 assert(seekIdSize >= 0);
1982 assert((pos + len) <= stop);
1983
1984 pos += len; //consume size
1985
1986 const long long seekId = ReadUInt(m_pReader, pos, len); //payload
1987 assert(seekId >= 0);
1988 assert(len == seekIdSize);
1989 assert((pos + len) <= stop);
1990
1991 pos += seekIdSize; //consume payload
1992
1993 const long long seekPosId = ReadUInt(m_pReader, pos, len);
1994 //seekPosId;
1995 assert(seekPosId == 0x13AC); //SeekPos ID
1996 assert((pos + len) <= stop);
1997
1998 pos += len; //consume id
1999
2000 const long long seekPosSize = ReadUInt(m_pReader, pos, len);
2001 assert(seekPosSize >= 0);
2002 assert((pos + len) <= stop);
2003
2004 pos += len; //consume size
2005 assert((pos + seekPosSize) <= stop);
2006
2007 const long long seekOff = UnserializeUInt(m_pReader, pos, seekPosSize);
2008 assert(seekOff >= 0);
2009 assert(seekOff < m_size);
2010
2011 pos += seekPosSize; //consume payload
2012 assert(pos == stop);
2013
2014 const long long seekPos = m_start + seekOff;
2015 assert(seekPos < (m_start + m_size));
2016
2017 if (seekId == 0x0C53BB6B) //Cues ID
2018 ParseCues(seekOff);
2019 }
2020 #else
2021 bool SeekHead::ParseEntry(IMkvReader* pReader, long long start, long long size_, 1623 bool SeekHead::ParseEntry(IMkvReader* pReader, long long start, long long size_,
2022 Entry* pEntry) { 1624 Entry* pEntry) {
2023 if (size_ <= 0) 1625 if (size_ <= 0)
2024 return false; 1626 return false;
2025 1627
2026 long long pos = start; 1628 long long pos = start;
2027 const long long stop = start + size_; 1629 const long long stop = start + size_;
2028 1630
2029 long len; 1631 long len;
2030 1632
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
2103 if (pEntry->pos < 0) 1705 if (pEntry->pos < 0)
2104 return false; 1706 return false;
2105 1707
2106 pos += seekPosSize; // consume payload 1708 pos += seekPosSize; // consume payload
2107 1709
2108 if (pos != stop) 1710 if (pos != stop)
2109 return false; 1711 return false;
2110 1712
2111 return true; 1713 return true;
2112 } 1714 }
2113 #endif
2114 1715
2115 Cues::Cues(Segment* pSegment, long long start_, long long size_, 1716 Cues::Cues(Segment* pSegment, long long start_, long long size_,
2116 long long element_start, long long element_size) 1717 long long element_start, long long element_size)
2117 : m_pSegment(pSegment), 1718 : m_pSegment(pSegment),
2118 m_start(start_), 1719 m_start(start_),
2119 m_size(size_), 1720 m_size(size_),
2120 m_element_start(element_start), 1721 m_element_start(element_start),
2121 m_element_size(element_size), 1722 m_element_size(element_size),
2122 m_cue_points(NULL), 1723 m_cue_points(NULL),
2123 m_count(0), 1724 m_count(0),
(...skipping 21 matching lines...) Expand all
2145 return -1; 1746 return -1;
2146 1747
2147 return m_count; // TODO: really ignore preload count? 1748 return m_count; // TODO: really ignore preload count?
2148 } 1749 }
2149 1750
2150 bool Cues::DoneParsing() const { 1751 bool Cues::DoneParsing() const {
2151 const long long stop = m_start + m_size; 1752 const long long stop = m_start + m_size;
2152 return (m_pos >= stop); 1753 return (m_pos >= stop);
2153 } 1754 }
2154 1755
2155 void Cues::Init() const { 1756 bool Cues::Init() const {
2156 if (m_cue_points) 1757 if (m_cue_points)
2157 return; 1758 return true;
2158 1759
2159 assert(m_count == 0); 1760 assert(m_count == 0);
2160 assert(m_preload_count == 0); 1761 assert(m_preload_count == 0);
2161 1762
2162 IMkvReader* const pReader = m_pSegment->m_pReader; 1763 IMkvReader* const pReader = m_pSegment->m_pReader;
2163 1764
2164 const long long stop = m_start + m_size; 1765 const long long stop = m_start + m_size;
2165 long long pos = m_start; 1766 long long pos = m_start;
2166 1767
2167 long cue_points_size = 0; 1768 long cue_points_size = 0;
2168 1769
2169 while (pos < stop) { 1770 while (pos < stop) {
2170 const long long idpos = pos; 1771 const long long idpos = pos;
2171 1772
2172 long len; 1773 long len;
2173 1774
2174 const long long id = ReadUInt(pReader, pos, len); 1775 const long long id = ReadUInt(pReader, pos, len);
2175 assert(id >= 0); // TODO 1776 if (id < 0 || (pos + len) > stop) {
2176 assert((pos + len) <= stop); 1777 return false;
1778 }
2177 1779
2178 pos += len; // consume ID 1780 pos += len; // consume ID
2179 1781
2180 const long long size = ReadUInt(pReader, pos, len); 1782 const long long size = ReadUInt(pReader, pos, len);
2181 assert(size >= 0); 1783 if (size < 0 || (pos + len > stop)) {
2182 assert((pos + len) <= stop); 1784 return false;
1785 }
2183 1786
2184 pos += len; // consume Size field 1787 pos += len; // consume Size field
2185 assert((pos + size) <= stop); 1788 if (pos + size > stop) {
1789 return false;
1790 }
2186 1791
2187 if (id == 0x3B) // CuePoint ID 1792 if (id == 0x3B) // CuePoint ID
2188 PreloadCuePoint(cue_points_size, idpos); 1793 PreloadCuePoint(cue_points_size, idpos);
2189 1794
2190 pos += size; // consume payload 1795 pos += size; // skip payload
2191 assert(pos <= stop);
2192 } 1796 }
1797 return true;
2193 } 1798 }
2194 1799
2195 void Cues::PreloadCuePoint(long& cue_points_size, long long pos) const { 1800 void Cues::PreloadCuePoint(long& cue_points_size, long long pos) const {
2196 assert(m_count == 0); 1801 assert(m_count == 0);
2197 1802
2198 if (m_preload_count >= cue_points_size) { 1803 if (m_preload_count >= cue_points_size) {
2199 const long n = (cue_points_size <= 0) ? 2048 : 2 * cue_points_size; 1804 const long n = (cue_points_size <= 0) ? 2048 : 2 * cue_points_size;
2200 1805
2201 CuePoint** const qq = new CuePoint* [n]; 1806 CuePoint** const qq = new CuePoint*[n];
2202 CuePoint** q = qq; // beginning of target 1807 CuePoint** q = qq; // beginning of target
2203 1808
2204 CuePoint** p = m_cue_points; // beginning of source 1809 CuePoint** p = m_cue_points; // beginning of source
2205 CuePoint** const pp = p + m_preload_count; // end of source 1810 CuePoint** const pp = p + m_preload_count; // end of source
2206 1811
2207 while (p != pp) 1812 while (p != pp)
2208 *q++ = *p++; 1813 *q++ = *p++;
2209 1814
2210 delete[] m_cue_points; 1815 delete[] m_cue_points;
2211 1816
2212 m_cue_points = qq; 1817 m_cue_points = qq;
2213 cue_points_size = n; 1818 cue_points_size = n;
2214 } 1819 }
2215 1820
2216 CuePoint* const pCP = new CuePoint(m_preload_count, pos); 1821 CuePoint* const pCP = new CuePoint(m_preload_count, pos);
2217 m_cue_points[m_preload_count++] = pCP; 1822 m_cue_points[m_preload_count++] = pCP;
2218 } 1823 }
2219 1824
2220 bool Cues::LoadCuePoint() const { 1825 bool Cues::LoadCuePoint() const {
2221 // odbgstream os; 1826 // odbgstream os;
2222 // os << "Cues::LoadCuePoint" << endl; 1827 // os << "Cues::LoadCuePoint" << endl;
2223 1828
2224 const long long stop = m_start + m_size; 1829 const long long stop = m_start + m_size;
2225 1830
2226 if (m_pos >= stop) 1831 if (m_pos >= stop)
2227 return false; // nothing else to do 1832 return false; // nothing else to do
2228 1833
2229 Init(); 1834 if (!Init()) {
1835 m_pos = stop;
1836 return false;
1837 }
2230 1838
2231 IMkvReader* const pReader = m_pSegment->m_pReader; 1839 IMkvReader* const pReader = m_pSegment->m_pReader;
2232 1840
2233 while (m_pos < stop) { 1841 while (m_pos < stop) {
2234 const long long idpos = m_pos; 1842 const long long idpos = m_pos;
2235 1843
2236 long len; 1844 long len;
2237 1845
2238 const long long id = ReadUInt(pReader, m_pos, len); 1846 const long long id = ReadUInt(pReader, m_pos, len);
2239 assert(id >= 0); // TODO 1847 assert(id >= 0); // TODO
(...skipping 16 matching lines...) Expand all
2256 } 1864 }
2257 1865
2258 assert(m_preload_count > 0); 1866 assert(m_preload_count > 0);
2259 1867
2260 CuePoint* const pCP = m_cue_points[m_count]; 1868 CuePoint* const pCP = m_cue_points[m_count];
2261 assert(pCP); 1869 assert(pCP);
2262 assert((pCP->GetTimeCode() >= 0) || (-pCP->GetTimeCode() == idpos)); 1870 assert((pCP->GetTimeCode() >= 0) || (-pCP->GetTimeCode() == idpos));
2263 if (pCP->GetTimeCode() < 0 && (-pCP->GetTimeCode() != idpos)) 1871 if (pCP->GetTimeCode() < 0 && (-pCP->GetTimeCode() != idpos))
2264 return false; 1872 return false;
2265 1873
2266 pCP->Load(pReader); 1874 if (!pCP->Load(pReader)) {
1875 m_pos = stop;
1876 return false;
1877 }
2267 ++m_count; 1878 ++m_count;
2268 --m_preload_count; 1879 --m_preload_count;
2269 1880
2270 m_pos += size; // consume payload 1881 m_pos += size; // consume payload
2271 assert(m_pos <= stop); 1882 assert(m_pos <= stop);
2272 1883
2273 return true; // yes, we loaded a cue point 1884 return true; // yes, we loaded a cue point
2274 } 1885 }
2275 1886
2276 // return (m_pos < stop); 1887 // return (m_pos < stop);
2277 return false; // no, we did not load a cue point 1888 return false; // no, we did not load a cue point
2278 } 1889 }
2279 1890
2280 bool Cues::Find(long long time_ns, const Track* pTrack, const CuePoint*& pCP, 1891 bool Cues::Find(long long time_ns, const Track* pTrack, const CuePoint*& pCP,
2281 const CuePoint::TrackPosition*& pTP) const { 1892 const CuePoint::TrackPosition*& pTP) const {
2282 assert(time_ns >= 0); 1893 assert(time_ns >= 0);
2283 assert(pTrack); 1894 assert(pTrack);
2284 1895
2285 #if 0
2286 LoadCuePoint(); //establish invariant
2287
2288 assert(m_cue_points);
2289 assert(m_count > 0);
2290
2291 CuePoint** const ii = m_cue_points;
2292 CuePoint** i = ii;
2293
2294 CuePoint** const jj = ii + m_count + m_preload_count;
2295 CuePoint** j = jj;
2296
2297 pCP = *i;
2298 assert(pCP);
2299
2300 if (time_ns <= pCP->GetTime(m_pSegment))
2301 {
2302 pTP = pCP->Find(pTrack);
2303 return (pTP != NULL);
2304 }
2305
2306 IMkvReader* const pReader = m_pSegment->m_pReader;
2307
2308 while (i < j)
2309 {
2310 //INVARIANT:
2311 //[ii, i) <= time_ns
2312 //[i, j) ?
2313 //[j, jj) > time_ns
2314
2315 CuePoint** const k = i + (j - i) / 2;
2316 assert(k < jj);
2317
2318 CuePoint* const pCP = *k;
2319 assert(pCP);
2320
2321 pCP->Load(pReader);
2322
2323 const long long t = pCP->GetTime(m_pSegment);
2324
2325 if (t <= time_ns)
2326 i = k + 1;
2327 else
2328 j = k;
2329
2330 assert(i <= j);
2331 }
2332
2333 assert(i == j);
2334 assert(i <= jj);
2335 assert(i > ii);
2336
2337 pCP = *--i;
2338 assert(pCP);
2339 assert(pCP->GetTime(m_pSegment) <= time_ns);
2340 #else
2341 if (m_cue_points == NULL) 1896 if (m_cue_points == NULL)
2342 return false; 1897 return false;
2343 1898
2344 if (m_count == 0) 1899 if (m_count == 0)
2345 return false; 1900 return false;
2346 1901
2347 CuePoint** const ii = m_cue_points; 1902 CuePoint** const ii = m_cue_points;
2348 CuePoint** i = ii; 1903 CuePoint** i = ii;
2349 1904
2350 CuePoint** const jj = ii + m_count; 1905 CuePoint** const jj = ii + m_count;
(...skipping 29 matching lines...) Expand all
2380 assert(i <= j); 1935 assert(i <= j);
2381 } 1936 }
2382 1937
2383 assert(i == j); 1938 assert(i == j);
2384 assert(i <= jj); 1939 assert(i <= jj);
2385 assert(i > ii); 1940 assert(i > ii);
2386 1941
2387 pCP = *--i; 1942 pCP = *--i;
2388 assert(pCP); 1943 assert(pCP);
2389 assert(pCP->GetTime(m_pSegment) <= time_ns); 1944 assert(pCP->GetTime(m_pSegment) <= time_ns);
2390 #endif
2391 1945
2392 // TODO: here and elsewhere, it's probably not correct to search 1946 // TODO: here and elsewhere, it's probably not correct to search
2393 // for the cue point with this time, and then search for a matching 1947 // for the cue point with this time, and then search for a matching
2394 // track. In principle, the matching track could be on some earlier 1948 // track. In principle, the matching track could be on some earlier
2395 // cue point, and with our current algorithm, we'd miss it. To make 1949 // cue point, and with our current algorithm, we'd miss it. To make
2396 // this bullet-proof, we'd need to create a secondary structure, 1950 // this bullet-proof, we'd need to create a secondary structure,
2397 // with a list of cue points that apply to a track, and then search 1951 // with a list of cue points that apply to a track, and then search
2398 // that track-based structure for a matching cue point. 1952 // that track-based structure for a matching cue point.
2399 1953
2400 pTP = pCP->Find(pTrack); 1954 pTP = pCP->Find(pTrack);
2401 return (pTP != NULL); 1955 return (pTP != NULL);
2402 } 1956 }
2403 1957
2404 #if 0
2405 bool Cues::FindNext(
2406 long long time_ns,
2407 const Track* pTrack,
2408 const CuePoint*& pCP,
2409 const CuePoint::TrackPosition*& pTP) const
2410 {
2411 pCP = 0;
2412 pTP = 0;
2413
2414 if (m_count == 0)
2415 return false;
2416
2417 assert(m_cue_points);
2418
2419 const CuePoint* const* const ii = m_cue_points;
2420 const CuePoint* const* i = ii;
2421
2422 const CuePoint* const* const jj = ii + m_count;
2423 const CuePoint* const* j = jj;
2424
2425 while (i < j)
2426 {
2427 //INVARIANT:
2428 //[ii, i) <= time_ns
2429 //[i, j) ?
2430 //[j, jj) > time_ns
2431
2432 const CuePoint* const* const k = i + (j - i) / 2;
2433 assert(k < jj);
2434
2435 pCP = *k;
2436 assert(pCP);
2437
2438 const long long t = pCP->GetTime(m_pSegment);
2439
2440 if (t <= time_ns)
2441 i = k + 1;
2442 else
2443 j = k;
2444
2445 assert(i <= j);
2446 }
2447
2448 assert(i == j);
2449 assert(i <= jj);
2450
2451 if (i >= jj) //time_ns is greater than max cue point
2452 return false;
2453
2454 pCP = *i;
2455 assert(pCP);
2456 assert(pCP->GetTime(m_pSegment) > time_ns);
2457
2458 pTP = pCP->Find(pTrack);
2459 return (pTP != NULL);
2460 }
2461 #endif
2462
2463 const CuePoint* Cues::GetFirst() const { 1958 const CuePoint* Cues::GetFirst() const {
2464 if (m_cue_points == NULL) 1959 if (m_cue_points == NULL)
2465 return NULL; 1960 return NULL;
2466 1961
2467 if (m_count == 0) 1962 if (m_count == 0)
2468 return NULL; 1963 return NULL;
2469 1964
2470 #if 0
2471 LoadCuePoint(); //init cues
2472
2473 const size_t count = m_count + m_preload_count;
2474
2475 if (count == 0) //weird
2476 return NULL;
2477 #endif
2478
2479 CuePoint* const* const pp = m_cue_points; 1965 CuePoint* const* const pp = m_cue_points;
2480 assert(pp); 1966 assert(pp);
2481 1967
2482 CuePoint* const pCP = pp[0]; 1968 CuePoint* const pCP = pp[0];
2483 assert(pCP); 1969 assert(pCP);
2484 assert(pCP->GetTimeCode() >= 0); 1970 assert(pCP->GetTimeCode() >= 0);
2485 1971
2486 return pCP; 1972 return pCP;
2487 } 1973 }
2488 1974
2489 const CuePoint* Cues::GetLast() const { 1975 const CuePoint* Cues::GetLast() const {
2490 if (m_cue_points == NULL) 1976 if (m_cue_points == NULL)
2491 return NULL; 1977 return NULL;
2492 1978
2493 if (m_count <= 0) 1979 if (m_count <= 0)
2494 return NULL; 1980 return NULL;
2495 1981
2496 #if 0
2497 LoadCuePoint(); //init cues
2498
2499 const size_t count = m_count + m_preload_count;
2500
2501 if (count == 0) //weird
2502 return NULL;
2503
2504 const size_t index = count - 1;
2505
2506 CuePoint* const* const pp = m_cue_points;
2507 assert(pp);
2508
2509 CuePoint* const pCP = pp[index];
2510 assert(pCP);
2511
2512 pCP->Load(m_pSegment->m_pReader);
2513 assert(pCP->GetTimeCode() >= 0);
2514 #else
2515 const long index = m_count - 1; 1982 const long index = m_count - 1;
2516 1983
2517 CuePoint* const* const pp = m_cue_points; 1984 CuePoint* const* const pp = m_cue_points;
2518 assert(pp); 1985 assert(pp);
2519 1986
2520 CuePoint* const pCP = pp[index]; 1987 CuePoint* const pCP = pp[index];
2521 assert(pCP); 1988 assert(pCP);
2522 assert(pCP->GetTimeCode() >= 0); 1989 assert(pCP->GetTimeCode() >= 0);
2523 #endif
2524 1990
2525 return pCP; 1991 return pCP;
2526 } 1992 }
2527 1993
2528 const CuePoint* Cues::GetNext(const CuePoint* pCurr) const { 1994 const CuePoint* Cues::GetNext(const CuePoint* pCurr) const {
2529 if (pCurr == NULL) 1995 if (pCurr == NULL)
2530 return NULL; 1996 return NULL;
2531 1997
2532 assert(pCurr->GetTimeCode() >= 0); 1998 assert(pCurr->GetTimeCode() >= 0);
2533 assert(m_cue_points); 1999 assert(m_cue_points);
2534 assert(m_count >= 1); 2000 assert(m_count >= 1);
2535 2001
2536 #if 0
2537 const size_t count = m_count + m_preload_count;
2538
2539 size_t index = pCurr->m_index;
2540 assert(index < count);
2541
2542 CuePoint* const* const pp = m_cue_points;
2543 assert(pp);
2544 assert(pp[index] == pCurr);
2545
2546 ++index;
2547
2548 if (index >= count)
2549 return NULL;
2550
2551 CuePoint* const pNext = pp[index];
2552 assert(pNext);
2553
2554 pNext->Load(m_pSegment->m_pReader);
2555 #else
2556 long index = pCurr->m_index; 2002 long index = pCurr->m_index;
2557 assert(index < m_count); 2003 assert(index < m_count);
2558 2004
2559 CuePoint* const* const pp = m_cue_points; 2005 CuePoint* const* const pp = m_cue_points;
2560 assert(pp); 2006 assert(pp);
2561 assert(pp[index] == pCurr); 2007 assert(pp[index] == pCurr);
2562 2008
2563 ++index; 2009 ++index;
2564 2010
2565 if (index >= m_count) 2011 if (index >= m_count)
2566 return NULL; 2012 return NULL;
2567 2013
2568 CuePoint* const pNext = pp[index]; 2014 CuePoint* const pNext = pp[index];
2569 assert(pNext); 2015 assert(pNext);
2570 assert(pNext->GetTimeCode() >= 0); 2016 assert(pNext->GetTimeCode() >= 0);
2571 #endif
2572 2017
2573 return pNext; 2018 return pNext;
2574 } 2019 }
2575 2020
2576 const BlockEntry* Cues::GetBlock(const CuePoint* pCP, 2021 const BlockEntry* Cues::GetBlock(const CuePoint* pCP,
2577 const CuePoint::TrackPosition* pTP) const { 2022 const CuePoint::TrackPosition* pTP) const {
2578 if (pCP == NULL) 2023 if (pCP == NULL)
2579 return NULL; 2024 return NULL;
2580 2025
2581 if (pTP == NULL) 2026 if (pTP == NULL)
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
2698 m_element_size(0), 2143 m_element_size(0),
2699 m_index(idx), 2144 m_index(idx),
2700 m_timecode(-1 * pos), 2145 m_timecode(-1 * pos),
2701 m_track_positions(NULL), 2146 m_track_positions(NULL),
2702 m_track_positions_count(0) { 2147 m_track_positions_count(0) {
2703 assert(pos > 0); 2148 assert(pos > 0);
2704 } 2149 }
2705 2150
2706 CuePoint::~CuePoint() { delete[] m_track_positions; } 2151 CuePoint::~CuePoint() { delete[] m_track_positions; }
2707 2152
2708 void CuePoint::Load(IMkvReader* pReader) { 2153 bool CuePoint::Load(IMkvReader* pReader) {
2709 // odbgstream os; 2154 // odbgstream os;
2710 // os << "CuePoint::Load(begin): timecode=" << m_timecode << endl; 2155 // os << "CuePoint::Load(begin): timecode=" << m_timecode << endl;
2711 2156
2712 if (m_timecode >= 0) // already loaded 2157 if (m_timecode >= 0) // already loaded
2713 return; 2158 return true;
2714 2159
2715 assert(m_track_positions == NULL); 2160 assert(m_track_positions == NULL);
2716 assert(m_track_positions_count == 0); 2161 assert(m_track_positions_count == 0);
2717 2162
2718 long long pos_ = -m_timecode; 2163 long long pos_ = -m_timecode;
2719 const long long element_start = pos_; 2164 const long long element_start = pos_;
2720 2165
2721 long long stop; 2166 long long stop;
2722 2167
2723 { 2168 {
2724 long len; 2169 long len;
2725 2170
2726 const long long id = ReadUInt(pReader, pos_, len); 2171 const long long id = ReadUInt(pReader, pos_, len);
2727 assert(id == 0x3B); // CuePoint ID 2172 assert(id == 0x3B); // CuePoint ID
2728 if (id != 0x3B) 2173 if (id != 0x3B)
2729 return; 2174 return false;
2730 2175
2731 pos_ += len; // consume ID 2176 pos_ += len; // consume ID
2732 2177
2733 const long long size = ReadUInt(pReader, pos_, len); 2178 const long long size = ReadUInt(pReader, pos_, len);
2734 assert(size >= 0); 2179 assert(size >= 0);
2735 2180
2736 pos_ += len; // consume Size field 2181 pos_ += len; // consume Size field
2737 // pos_ now points to start of payload 2182 // pos_ now points to start of payload
2738 2183
2739 stop = pos_ + size; 2184 stop = pos_ + size;
2740 } 2185 }
2741 2186
2742 const long long element_size = stop - element_start; 2187 const long long element_size = stop - element_start;
2743 2188
2744 long long pos = pos_; 2189 long long pos = pos_;
2745 2190
2746 // First count number of track positions 2191 // First count number of track positions
2747 2192
2748 while (pos < stop) { 2193 while (pos < stop) {
2749 long len; 2194 long len;
2750 2195
2751 const long long id = ReadUInt(pReader, pos, len); 2196 const long long id = ReadUInt(pReader, pos, len);
2752 assert(id >= 0); // TODO 2197 if ((id < 0) || (pos + len > stop)) {
2753 assert((pos + len) <= stop); 2198 return false;
2199 }
2754 2200
2755 pos += len; // consume ID 2201 pos += len; // consume ID
2756 2202
2757 const long long size = ReadUInt(pReader, pos, len); 2203 const long long size = ReadUInt(pReader, pos, len);
2758 assert(size >= 0); 2204 if ((size < 0) || (pos + len > stop)) {
2759 assert((pos + len) <= stop); 2205 return false;
2206 }
2760 2207
2761 pos += len; // consume Size field 2208 pos += len; // consume Size field
2762 assert((pos + size) <= stop); 2209 if ((pos + size) > stop) {
2210 return false;
2211 }
2763 2212
2764 if (id == 0x33) // CueTime ID 2213 if (id == 0x33) // CueTime ID
2765 m_timecode = UnserializeUInt(pReader, pos, size); 2214 m_timecode = UnserializeUInt(pReader, pos, size);
2766 2215
2767 else if (id == 0x37) // CueTrackPosition(s) ID 2216 else if (id == 0x37) // CueTrackPosition(s) ID
2768 ++m_track_positions_count; 2217 ++m_track_positions_count;
2769 2218
2770 pos += size; // consume payload 2219 pos += size; // consume payload
2771 assert(pos <= stop);
2772 } 2220 }
2773 2221
2774 assert(m_timecode >= 0); 2222 if (m_timecode < 0 || m_track_positions_count <= 0) {
2775 assert(m_track_positions_count > 0); 2223 return false;
2224 }
2776 2225
2777 // os << "CuePoint::Load(cont'd): idpos=" << idpos 2226 // os << "CuePoint::Load(cont'd): idpos=" << idpos
2778 // << " timecode=" << m_timecode 2227 // << " timecode=" << m_timecode
2779 // << endl; 2228 // << endl;
2780 2229
2781 m_track_positions = new TrackPosition[m_track_positions_count]; 2230 m_track_positions = new TrackPosition[m_track_positions_count];
2782 2231
2783 // Now parse track positions 2232 // Now parse track positions
2784 2233
2785 TrackPosition* p = m_track_positions; 2234 TrackPosition* p = m_track_positions;
2786 pos = pos_; 2235 pos = pos_;
2787 2236
2788 while (pos < stop) { 2237 while (pos < stop) {
2789 long len; 2238 long len;
2790 2239
2791 const long long id = ReadUInt(pReader, pos, len); 2240 const long long id = ReadUInt(pReader, pos, len);
2792 assert(id >= 0); // TODO 2241 assert(id >= 0);
2793 assert((pos + len) <= stop); 2242 assert((pos + len) <= stop);
2794 2243
2795 pos += len; // consume ID 2244 pos += len; // consume ID
2796 2245
2797 const long long size = ReadUInt(pReader, pos, len); 2246 const long long size = ReadUInt(pReader, pos, len);
2798 assert(size >= 0); 2247 assert(size >= 0);
2799 assert((pos + len) <= stop); 2248 assert((pos + len) <= stop);
2800 2249
2801 pos += len; // consume Size field 2250 pos += len; // consume Size field
2802 assert((pos + size) <= stop); 2251 assert((pos + size) <= stop);
2803 2252
2804 if (id == 0x37) { // CueTrackPosition(s) ID 2253 if (id == 0x37) { // CueTrackPosition(s) ID
2805 TrackPosition& tp = *p++; 2254 TrackPosition& tp = *p++;
2806 tp.Parse(pReader, pos, size); 2255 if (!tp.Parse(pReader, pos, size)) {
2256 return false;
2257 }
2807 } 2258 }
2808 2259
2809 pos += size; // consume payload 2260 pos += size; // consume payload
2810 assert(pos <= stop); 2261 assert(pos <= stop);
2811 } 2262 }
2812 2263
2813 assert(size_t(p - m_track_positions) == m_track_positions_count); 2264 assert(size_t(p - m_track_positions) == m_track_positions_count);
2814 2265
2815 m_element_start = element_start; 2266 m_element_start = element_start;
2816 m_element_size = element_size; 2267 m_element_size = element_size;
2268
2269 return true;
2817 } 2270 }
2818 2271
2819 void CuePoint::TrackPosition::Parse(IMkvReader* pReader, long long start_, 2272 bool CuePoint::TrackPosition::Parse(IMkvReader* pReader, long long start_,
2820 long long size_) { 2273 long long size_) {
2821 const long long stop = start_ + size_; 2274 const long long stop = start_ + size_;
2822 long long pos = start_; 2275 long long pos = start_;
2823 2276
2824 m_track = -1; 2277 m_track = -1;
2825 m_pos = -1; 2278 m_pos = -1;
2826 m_block = 1; // default 2279 m_block = 1; // default
2827 2280
2828 while (pos < stop) { 2281 while (pos < stop) {
2829 long len; 2282 long len;
2830 2283
2831 const long long id = ReadUInt(pReader, pos, len); 2284 const long long id = ReadUInt(pReader, pos, len);
2832 assert(id >= 0); // TODO 2285 if ((id < 0) || ((pos + len) > stop)) {
2833 assert((pos + len) <= stop); 2286 return false;
2287 }
2834 2288
2835 pos += len; // consume ID 2289 pos += len; // consume ID
2836 2290
2837 const long long size = ReadUInt(pReader, pos, len); 2291 const long long size = ReadUInt(pReader, pos, len);
2838 assert(size >= 0); 2292 if ((size < 0) || ((pos + len) > stop)) {
2839 assert((pos + len) <= stop); 2293 return false;
2294 }
2840 2295
2841 pos += len; // consume Size field 2296 pos += len; // consume Size field
2842 assert((pos + size) <= stop); 2297 if ((pos + size) > stop) {
2298 return false;
2299 }
2843 2300
2844 if (id == 0x77) // CueTrack ID 2301 if (id == 0x77) // CueTrack ID
2845 m_track = UnserializeUInt(pReader, pos, size); 2302 m_track = UnserializeUInt(pReader, pos, size);
2846 2303
2847 else if (id == 0x71) // CueClusterPos ID 2304 else if (id == 0x71) // CueClusterPos ID
2848 m_pos = UnserializeUInt(pReader, pos, size); 2305 m_pos = UnserializeUInt(pReader, pos, size);
2849 2306
2850 else if (id == 0x1378) // CueBlockNumber 2307 else if (id == 0x1378) // CueBlockNumber
2851 m_block = UnserializeUInt(pReader, pos, size); 2308 m_block = UnserializeUInt(pReader, pos, size);
2852 2309
2853 pos += size; // consume payload 2310 pos += size; // consume payload
2854 assert(pos <= stop);
2855 } 2311 }
2856 2312
2857 assert(m_pos >= 0); 2313 if ((m_pos < 0) || (m_track <= 0)) {
2858 assert(m_track > 0); 2314 return false;
2859 // assert(m_block > 0); 2315 }
2316
2317 return true;
2860 } 2318 }
2861 2319
2862 const CuePoint::TrackPosition* CuePoint::Find(const Track* pTrack) const { 2320 const CuePoint::TrackPosition* CuePoint::Find(const Track* pTrack) const {
2863 assert(pTrack); 2321 assert(pTrack);
2864 2322
2865 const long long n = pTrack->GetNumber(); 2323 const long long n = pTrack->GetNumber();
2866 2324
2867 const TrackPosition* i = m_track_positions; 2325 const TrackPosition* i = m_track_positions;
2868 const TrackPosition* const j = i + m_track_positions_count; 2326 const TrackPosition* const j = i + m_track_positions_count;
2869 2327
(...skipping 17 matching lines...) Expand all
2887 assert(pInfo); 2345 assert(pInfo);
2888 2346
2889 const long long scale = pInfo->GetTimeCodeScale(); 2347 const long long scale = pInfo->GetTimeCodeScale();
2890 assert(scale >= 1); 2348 assert(scale >= 1);
2891 2349
2892 const long long time = scale * m_timecode; 2350 const long long time = scale * m_timecode;
2893 2351
2894 return time; 2352 return time;
2895 } 2353 }
2896 2354
2897 #if 0
2898 long long Segment::Unparsed() const
2899 {
2900 if (m_size < 0)
2901 return LLONG_MAX;
2902
2903 const long long stop = m_start + m_size;
2904
2905 const long long result = stop - m_pos;
2906 assert(result >= 0);
2907
2908 return result;
2909 }
2910 #else
2911 bool Segment::DoneParsing() const { 2355 bool Segment::DoneParsing() const {
2912 if (m_size < 0) { 2356 if (m_size < 0) {
2913 long long total, avail; 2357 long long total, avail;
2914 2358
2915 const int status = m_pReader->Length(&total, &avail); 2359 const int status = m_pReader->Length(&total, &avail);
2916 2360
2917 if (status < 0) // error 2361 if (status < 0) // error
2918 return true; // must assume done 2362 return true; // must assume done
2919 2363
2920 if (total < 0) 2364 if (total < 0)
2921 return false; // assume live stream 2365 return false; // assume live stream
2922 2366
2923 return (m_pos >= total); 2367 return (m_pos >= total);
2924 } 2368 }
2925 2369
2926 const long long stop = m_start + m_size; 2370 const long long stop = m_start + m_size;
2927 2371
2928 return (m_pos >= stop); 2372 return (m_pos >= stop);
2929 } 2373 }
2930 #endif
2931 2374
2932 const Cluster* Segment::GetFirst() const { 2375 const Cluster* Segment::GetFirst() const {
2933 if ((m_clusters == NULL) || (m_clusterCount <= 0)) 2376 if ((m_clusters == NULL) || (m_clusterCount <= 0))
2934 return &m_eos; 2377 return &m_eos;
2935 2378
2936 Cluster* const pCluster = m_clusters[0]; 2379 Cluster* const pCluster = m_clusters[0];
2937 assert(pCluster); 2380 assert(pCluster);
2938 2381
2939 return pCluster; 2382 return pCluster;
2940 } 2383 }
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after
3388 if (id != 0x0F43B675) { // not a Cluster ID 2831 if (id != 0x0F43B675) { // not a Cluster ID
3389 if (size == unknown_size) 2832 if (size == unknown_size)
3390 return E_FILE_FORMAT_INVALID; 2833 return E_FILE_FORMAT_INVALID;
3391 2834
3392 pos += size; // consume payload 2835 pos += size; // consume payload
3393 assert((segment_stop < 0) || (pos <= segment_stop)); 2836 assert((segment_stop < 0) || (pos <= segment_stop));
3394 2837
3395 continue; 2838 continue;
3396 } 2839 }
3397 2840
3398 #if 0 // this is commented-out to support incremental cluster parsing
3399 len = static_cast<long>(size);
3400
3401 if (element_stop > avail)
3402 return E_BUFFER_NOT_FULL;
3403 #endif
3404
3405 // We have a cluster. 2841 // We have a cluster.
3406
3407 off_next = idoff; 2842 off_next = idoff;
3408 2843
3409 if (size != unknown_size) 2844 if (size != unknown_size)
3410 cluster_size = size; 2845 cluster_size = size;
3411 2846
3412 break; 2847 break;
3413 } 2848 }
3414 2849
3415 assert(off_next > 0); // have cluster 2850 assert(off_next > 0); // have cluster
3416 2851
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
3640 const long k = i - 1; 3075 const long k = i - 1;
3641 3076
3642 Cluster* const pCluster = m_clusters[k]; 3077 Cluster* const pCluster = m_clusters[k];
3643 assert(pCluster); 3078 assert(pCluster);
3644 assert(pCluster->m_index == k); 3079 assert(pCluster->m_index == k);
3645 assert(pCluster->GetTime() <= time_ns); 3080 assert(pCluster->GetTime() <= time_ns);
3646 3081
3647 return pCluster; 3082 return pCluster;
3648 } 3083 }
3649 3084
3650 #if 0
3651 const BlockEntry* Segment::Seek(
3652 long long time_ns,
3653 const Track* pTrack) const
3654 {
3655 assert(pTrack);
3656
3657 if ((m_clusters == NULL) || (m_clusterCount <= 0))
3658 return pTrack->GetEOS();
3659
3660 Cluster** const i = m_clusters;
3661 assert(i);
3662
3663 {
3664 Cluster* const pCluster = *i;
3665 assert(pCluster);
3666 assert(pCluster->m_index == 0); //m_clusterCount > 0
3667 assert(pCluster->m_pSegment == this);
3668
3669 if (time_ns <= pCluster->GetTime())
3670 return pCluster->GetEntry(pTrack);
3671 }
3672
3673 Cluster** const j = i + m_clusterCount;
3674
3675 if (pTrack->GetType() == 2) { //audio
3676 //TODO: we could decide to use cues for this, as we do for video.
3677 //But we only use it for video because looking around for a keyframe
3678 //can get expensive. Audio doesn't require anything special so a
3679 //straight cluster search is good enough (we assume).
3680
3681 Cluster** lo = i;
3682 Cluster** hi = j;
3683
3684 while (lo < hi)
3685 {
3686 //INVARIANT:
3687 //[i, lo) <= time_ns
3688 //[lo, hi) ?
3689 //[hi, j) > time_ns
3690
3691 Cluster** const mid = lo + (hi - lo) / 2;
3692 assert(mid < hi);
3693
3694 Cluster* const pCluster = *mid;
3695 assert(pCluster);
3696 assert(pCluster->m_index == long(mid - m_clusters));
3697 assert(pCluster->m_pSegment == this);
3698
3699 const long long t = pCluster->GetTime();
3700
3701 if (t <= time_ns)
3702 lo = mid + 1;
3703 else
3704 hi = mid;
3705
3706 assert(lo <= hi);
3707 }
3708
3709 assert(lo == hi);
3710 assert(lo > i);
3711 assert(lo <= j);
3712
3713 while (lo > i)
3714 {
3715 Cluster* const pCluster = *--lo;
3716 assert(pCluster);
3717 assert(pCluster->GetTime() <= time_ns);
3718
3719 const BlockEntry* const pBE = pCluster->GetEntry(pTrack);
3720
3721 if ((pBE != 0) && !pBE->EOS())
3722 return pBE;
3723
3724 //landed on empty cluster (no entries)
3725 }
3726
3727 return pTrack->GetEOS(); //weird
3728 }
3729
3730 assert(pTrack->GetType() == 1); //video
3731
3732 Cluster** lo = i;
3733 Cluster** hi = j;
3734
3735 while (lo < hi)
3736 {
3737 //INVARIANT:
3738 //[i, lo) <= time_ns
3739 //[lo, hi) ?
3740 //[hi, j) > time_ns
3741
3742 Cluster** const mid = lo + (hi - lo) / 2;
3743 assert(mid < hi);
3744
3745 Cluster* const pCluster = *mid;
3746 assert(pCluster);
3747
3748 const long long t = pCluster->GetTime();
3749
3750 if (t <= time_ns)
3751 lo = mid + 1;
3752 else
3753 hi = mid;
3754
3755 assert(lo <= hi);
3756 }
3757
3758 assert(lo == hi);
3759 assert(lo > i);
3760 assert(lo <= j);
3761
3762 Cluster* pCluster = *--lo;
3763 assert(pCluster);
3764 assert(pCluster->GetTime() <= time_ns);
3765
3766 {
3767 const BlockEntry* const pBE = pCluster->GetEntry(pTrack, time_ns);
3768
3769 if ((pBE != 0) && !pBE->EOS()) //found a keyframe
3770 return pBE;
3771 }
3772
3773 const VideoTrack* const pVideo = static_cast<const VideoTrack*>(pTrack);
3774
3775 while (lo != i)
3776 {
3777 pCluster = *--lo;
3778 assert(pCluster);
3779 assert(pCluster->GetTime() <= time_ns);
3780
3781 const BlockEntry* const pBlockEntry = pCluster->GetMaxKey(pVideo);
3782
3783 if ((pBlockEntry != 0) && !pBlockEntry->EOS())
3784 return pBlockEntry;
3785 }
3786
3787 //weird: we're on the first cluster, but no keyframe found
3788 //should never happen but we must return something anyway
3789
3790 return pTrack->GetEOS();
3791 }
3792 #endif
3793
3794 #if 0
3795 bool Segment::SearchCues(
3796 long long time_ns,
3797 Track* pTrack,
3798 Cluster*& pCluster,
3799 const BlockEntry*& pBlockEntry,
3800 const CuePoint*& pCP,
3801 const CuePoint::TrackPosition*& pTP)
3802 {
3803 if (pTrack->GetType() != 1) //not video
3804 return false; //TODO: for now, just handle video stream
3805
3806 if (m_pCues == NULL)
3807 return false;
3808
3809 if (!m_pCues->Find(time_ns, pTrack, pCP, pTP))
3810 return false; //weird
3811
3812 assert(pCP);
3813 assert(pTP);
3814 assert(pTP->m_track == pTrack->GetNumber());
3815
3816 //We have the cue point and track position we want,
3817 //so we now need to search for the cluster having
3818 //the indicated position.
3819
3820 return GetCluster(pCP, pTP, pCluster, pBlockEntry);
3821 }
3822 #endif
3823
3824 const Tracks* Segment::GetTracks() const { return m_pTracks; } 3085 const Tracks* Segment::GetTracks() const { return m_pTracks; }
3825
3826 const SegmentInfo* Segment::GetInfo() const { return m_pInfo; } 3086 const SegmentInfo* Segment::GetInfo() const { return m_pInfo; }
3827
3828 const Cues* Segment::GetCues() const { return m_pCues; } 3087 const Cues* Segment::GetCues() const { return m_pCues; }
3829
3830 const Chapters* Segment::GetChapters() const { return m_pChapters; } 3088 const Chapters* Segment::GetChapters() const { return m_pChapters; }
3831 3089 const Tags* Segment::GetTags() const { return m_pTags; }
3832 const SeekHead* Segment::GetSeekHead() const { return m_pSeekHead; } 3090 const SeekHead* Segment::GetSeekHead() const { return m_pSeekHead; }
3833 3091
3834 long long Segment::GetDuration() const { 3092 long long Segment::GetDuration() const {
3835 assert(m_pInfo); 3093 assert(m_pInfo);
3836 return m_pInfo->GetDuration(); 3094 return m_pInfo->GetDuration();
3837 } 3095 }
3838 3096
3839 Chapters::Chapters(Segment* pSegment, long long payload_start, 3097 Chapters::Chapters(Segment* pSegment, long long payload_start,
3840 long long payload_size, long long element_start, 3098 long long payload_size, long long element_start,
3841 long long element_size) 3099 long long element_size)
3842 : m_pSegment(pSegment), 3100 : m_pSegment(pSegment),
3843 m_start(payload_start), 3101 m_start(payload_start),
3844 m_size(payload_size), 3102 m_size(payload_size),
3845 m_element_start(element_start), 3103 m_element_start(element_start),
3846 m_element_size(element_size), 3104 m_element_size(element_size),
3847 m_editions(NULL), 3105 m_editions(NULL),
3848 m_editions_size(0), 3106 m_editions_size(0),
3849 m_editions_count(0) {} 3107 m_editions_count(0) {}
3850 3108
3851 Chapters::~Chapters() { 3109 Chapters::~Chapters() {
3852 while (m_editions_count > 0) { 3110 while (m_editions_count > 0) {
3853 Edition& e = m_editions[--m_editions_count]; 3111 Edition& e = m_editions[--m_editions_count];
3854 e.Clear(); 3112 e.Clear();
3855 } 3113 }
3114 delete[] m_editions;
3856 } 3115 }
3857 3116
3858 long Chapters::Parse() { 3117 long Chapters::Parse() {
3859 IMkvReader* const pReader = m_pSegment->m_pReader; 3118 IMkvReader* const pReader = m_pSegment->m_pReader;
3860 3119
3861 long long pos = m_start; // payload start 3120 long long pos = m_start; // payload start
3862 const long long stop = pos + m_size; // payload stop 3121 const long long stop = pos + m_size; // payload stop
3863 3122
3864 while (pos < stop) { 3123 while (pos < stop) {
3865 long long id, size; 3124 long long id, size;
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
4121 status = ParseDisplay(pReader, pos, size); 3380 status = ParseDisplay(pReader, pos, size);
4122 3381
4123 if (status < 0) // error 3382 if (status < 0) // error
4124 return status; 3383 return status;
4125 } else if (id == 0x1654) { // StringUID ID 3384 } else if (id == 0x1654) { // StringUID ID
4126 status = UnserializeString(pReader, pos, size, m_string_uid); 3385 status = UnserializeString(pReader, pos, size, m_string_uid);
4127 3386
4128 if (status < 0) // error 3387 if (status < 0) // error
4129 return status; 3388 return status;
4130 } else if (id == 0x33C4) { // UID ID 3389 } else if (id == 0x33C4) { // UID ID
4131 const long long val = UnserializeUInt(pReader, pos, size); 3390 long long val;
3391 status = UnserializeInt(pReader, pos, size, val);
4132 3392
4133 if (val < 0) // error 3393 if (status < 0) // error
4134 return static_cast<long>(val); 3394 return status;
4135 3395
4136 m_uid = val; 3396 m_uid = static_cast<unsigned long long>(val);
4137 } else if (id == 0x11) { // TimeStart ID 3397 } else if (id == 0x11) { // TimeStart ID
4138 const long long val = UnserializeUInt(pReader, pos, size); 3398 const long long val = UnserializeUInt(pReader, pos, size);
4139 3399
4140 if (val < 0) // error 3400 if (val < 0) // error
4141 return static_cast<long>(val); 3401 return static_cast<long>(val);
4142 3402
4143 m_start_timecode = val; 3403 m_start_timecode = val;
4144 } else if (id == 0x12) { // TimeEnd ID 3404 } else if (id == 0x12) { // TimeEnd ID
4145 const long long val = UnserializeUInt(pReader, pos, size); 3405 const long long val = UnserializeUInt(pReader, pos, size);
4146 3406
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
4250 3510
4251 delete[] m_country; 3511 delete[] m_country;
4252 m_country = NULL; 3512 m_country = NULL;
4253 } 3513 }
4254 3514
4255 long Chapters::Display::Parse(IMkvReader* pReader, long long pos, 3515 long Chapters::Display::Parse(IMkvReader* pReader, long long pos,
4256 long long size) { 3516 long long size) {
4257 const long long stop = pos + size; 3517 const long long stop = pos + size;
4258 3518
4259 while (pos < stop) { 3519 while (pos < stop) {
3520 long long id, size;
3521
3522 long status = ParseElementHeader(pReader, pos, stop, id, size);
3523
3524 if (status < 0) // error
3525 return status;
3526
3527 if (size == 0) // weird
3528 continue;
3529
3530 if (id == 0x05) { // ChapterString ID
3531 status = UnserializeString(pReader, pos, size, m_string);
3532
3533 if (status)
3534 return status;
3535 } else if (id == 0x037C) { // ChapterLanguage ID
3536 status = UnserializeString(pReader, pos, size, m_language);
3537
3538 if (status)
3539 return status;
3540 } else if (id == 0x037E) { // ChapterCountry ID
3541 status = UnserializeString(pReader, pos, size, m_country);
3542
3543 if (status)
3544 return status;
3545 }
3546
3547 pos += size;
3548 assert(pos <= stop);
3549 }
3550
3551 assert(pos == stop);
3552 return 0;
3553 }
3554
3555 Tags::Tags(Segment* pSegment, long long payload_start, long long payload_size,
3556 long long element_start, long long element_size)
3557 : m_pSegment(pSegment),
3558 m_start(payload_start),
3559 m_size(payload_size),
3560 m_element_start(element_start),
3561 m_element_size(element_size),
3562 m_tags(NULL),
3563 m_tags_size(0),
3564 m_tags_count(0) {}
3565
3566 Tags::~Tags() {
3567 while (m_tags_count > 0) {
3568 Tag& t = m_tags[--m_tags_count];
3569 t.Clear();
3570 }
3571 delete[] m_tags;
3572 }
3573
3574 long Tags::Parse() {
3575 IMkvReader* const pReader = m_pSegment->m_pReader;
3576
3577 long long pos = m_start; // payload start
3578 const long long stop = pos + m_size; // payload stop
3579
3580 while (pos < stop) {
3581 long long id, size;
3582
3583 long status = ParseElementHeader(pReader, pos, stop, id, size);
3584
3585 if (status < 0)
3586 return status;
3587
3588 if (size == 0) // 0 length tag, read another
3589 continue;
3590
3591 if (id == 0x3373) { // Tag ID
3592 status = ParseTag(pos, size);
3593
3594 if (status < 0)
3595 return status;
3596 }
3597
3598 pos += size;
3599 assert(pos <= stop);
3600 if (pos > stop)
3601 return -1;
3602 }
3603
3604 assert(pos == stop);
3605 if (pos != stop)
3606 return -1;
3607
3608 return 0;
3609 }
3610
3611 int Tags::GetTagCount() const { return m_tags_count; }
3612
3613 const Tags::Tag* Tags::GetTag(int idx) const {
3614 if (idx < 0)
3615 return NULL;
3616
3617 if (idx >= m_tags_count)
3618 return NULL;
3619
3620 return m_tags + idx;
3621 }
3622
3623 bool Tags::ExpandTagsArray() {
3624 if (m_tags_size > m_tags_count)
3625 return true; // nothing else to do
3626
3627 const int size = (m_tags_size == 0) ? 1 : 2 * m_tags_size;
3628
3629 Tag* const tags = new (std::nothrow) Tag[size];
3630
3631 if (tags == NULL)
3632 return false;
3633
3634 for (int idx = 0; idx < m_tags_count; ++idx) {
3635 m_tags[idx].ShallowCopy(tags[idx]);
3636 }
3637
3638 delete[] m_tags;
3639 m_tags = tags;
3640
3641 m_tags_size = size;
3642 return true;
3643 }
3644
3645 long Tags::ParseTag(long long pos, long long size) {
3646 if (!ExpandTagsArray())
3647 return -1;
3648
3649 Tag& t = m_tags[m_tags_count++];
3650 t.Init();
3651
3652 return t.Parse(m_pSegment->m_pReader, pos, size);
3653 }
3654
3655 Tags::Tag::Tag() {}
3656
3657 Tags::Tag::~Tag() {}
3658
3659 int Tags::Tag::GetSimpleTagCount() const { return m_simple_tags_count; }
3660
3661 const Tags::SimpleTag* Tags::Tag::GetSimpleTag(int index) const {
3662 if (index < 0)
3663 return NULL;
3664
3665 if (index >= m_simple_tags_count)
3666 return NULL;
3667
3668 return m_simple_tags + index;
3669 }
3670
3671 void Tags::Tag::Init() {
3672 m_simple_tags = NULL;
3673 m_simple_tags_size = 0;
3674 m_simple_tags_count = 0;
3675 }
3676
3677 void Tags::Tag::ShallowCopy(Tag& rhs) const {
3678 rhs.m_simple_tags = m_simple_tags;
3679 rhs.m_simple_tags_size = m_simple_tags_size;
3680 rhs.m_simple_tags_count = m_simple_tags_count;
3681 }
3682
3683 void Tags::Tag::Clear() {
3684 while (m_simple_tags_count > 0) {
3685 SimpleTag& d = m_simple_tags[--m_simple_tags_count];
3686 d.Clear();
3687 }
3688
3689 delete[] m_simple_tags;
3690 m_simple_tags = NULL;
3691
3692 m_simple_tags_size = 0;
3693 }
3694
3695 long Tags::Tag::Parse(IMkvReader* pReader, long long pos, long long size) {
3696 const long long stop = pos + size;
3697
3698 while (pos < stop) {
3699 long long id, size;
3700
3701 long status = ParseElementHeader(pReader, pos, stop, id, size);
3702
3703 if (status < 0)
3704 return status;
3705
3706 if (size == 0) // 0 length tag, read another
3707 continue;
3708
3709 if (id == 0x27C8) { // SimpleTag ID
3710 status = ParseSimpleTag(pReader, pos, size);
3711
3712 if (status < 0)
3713 return status;
3714 }
3715
3716 pos += size;
3717 assert(pos <= stop);
3718 if (pos > stop)
3719 return -1;
3720 }
3721
3722 assert(pos == stop);
3723 if (pos != stop)
3724 return -1;
3725 return 0;
3726 }
3727
3728 long Tags::Tag::ParseSimpleTag(IMkvReader* pReader, long long pos,
3729 long long size) {
3730 if (!ExpandSimpleTagsArray())
3731 return -1;
3732
3733 SimpleTag& st = m_simple_tags[m_simple_tags_count++];
3734 st.Init();
3735
3736 return st.Parse(pReader, pos, size);
3737 }
3738
3739 bool Tags::Tag::ExpandSimpleTagsArray() {
3740 if (m_simple_tags_size > m_simple_tags_count)
3741 return true; // nothing else to do
3742
3743 const int size = (m_simple_tags_size == 0) ? 1 : 2 * m_simple_tags_size;
3744
3745 SimpleTag* const displays = new (std::nothrow) SimpleTag[size];
3746
3747 if (displays == NULL)
3748 return false;
3749
3750 for (int idx = 0; idx < m_simple_tags_count; ++idx) {
3751 m_simple_tags[idx].ShallowCopy(displays[idx]);
3752 }
3753
3754 delete[] m_simple_tags;
3755 m_simple_tags = displays;
3756
3757 m_simple_tags_size = size;
3758 return true;
3759 }
3760
3761 Tags::SimpleTag::SimpleTag() {}
3762
3763 Tags::SimpleTag::~SimpleTag() {}
3764
3765 const char* Tags::SimpleTag::GetTagName() const { return m_tag_name; }
3766
3767 const char* Tags::SimpleTag::GetTagString() const { return m_tag_string; }
3768
3769 void Tags::SimpleTag::Init() {
3770 m_tag_name = NULL;
3771 m_tag_string = NULL;
3772 }
3773
3774 void Tags::SimpleTag::ShallowCopy(SimpleTag& rhs) const {
3775 rhs.m_tag_name = m_tag_name;
3776 rhs.m_tag_string = m_tag_string;
3777 }
3778
3779 void Tags::SimpleTag::Clear() {
3780 delete[] m_tag_name;
3781 m_tag_name = NULL;
3782
3783 delete[] m_tag_string;
3784 m_tag_string = NULL;
3785 }
3786
3787 long Tags::SimpleTag::Parse(IMkvReader* pReader, long long pos,
3788 long long size) {
3789 const long long stop = pos + size;
3790
3791 while (pos < stop) {
4260 long long id, size; 3792 long long id, size;
4261 3793
4262 long status = ParseElementHeader(pReader, pos, stop, id, size); 3794 long status = ParseElementHeader(pReader, pos, stop, id, size);
4263 3795
4264 if (status < 0) // error 3796 if (status < 0) // error
4265 return status; 3797 return status;
4266 3798
4267 if (size == 0) // weird 3799 if (size == 0) // weird
4268 continue; 3800 continue;
4269 3801
4270 if (id == 0x05) { // ChapterString ID 3802 if (id == 0x5A3) { // TagName ID
4271 status = UnserializeString(pReader, pos, size, m_string); 3803 status = UnserializeString(pReader, pos, size, m_tag_name);
4272 3804
4273 if (status) 3805 if (status)
4274 return status; 3806 return status;
4275 } else if (id == 0x037C) { // ChapterLanguage ID 3807 } else if (id == 0x487) { // TagString ID
4276 status = UnserializeString(pReader, pos, size, m_language); 3808 status = UnserializeString(pReader, pos, size, m_tag_string);
4277 3809
4278 if (status) 3810 if (status)
4279 return status; 3811 return status;
4280 } else if (id == 0x037E) { // ChapterCountry ID
4281 status = UnserializeString(pReader, pos, size, m_country);
4282
4283 if (status)
4284 return status;
4285 } 3812 }
4286 3813
4287 pos += size; 3814 pos += size;
4288 assert(pos <= stop); 3815 assert(pos <= stop);
3816 if (pos > stop)
3817 return -1;
4289 } 3818 }
4290 3819
4291 assert(pos == stop); 3820 assert(pos == stop);
3821 if (pos != stop)
3822 return -1;
4292 return 0; 3823 return 0;
4293 } 3824 }
4294 3825
4295 SegmentInfo::SegmentInfo(Segment* pSegment, long long start, long long size_, 3826 SegmentInfo::SegmentInfo(Segment* pSegment, long long start, long long size_,
4296 long long element_start, long long element_size) 3827 long long element_start, long long element_size)
4297 : m_pSegment(pSegment), 3828 : m_pSegment(pSegment),
4298 m_start(start), 3829 m_start(start),
4299 m_size(size_), 3830 m_size(size_),
4300 m_element_start(element_start), 3831 m_element_start(element_start),
4301 m_element_size(element_size), 3832 m_element_size(element_size),
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
4451 3982
4452 while (enc_i != enc_j) { 3983 while (enc_i != enc_j) {
4453 ContentEncryption* const enc = *enc_i++; 3984 ContentEncryption* const enc = *enc_i++;
4454 delete enc; 3985 delete enc;
4455 } 3986 }
4456 3987
4457 delete[] encryption_entries_; 3988 delete[] encryption_entries_;
4458 } 3989 }
4459 3990
4460 const ContentEncoding::ContentCompression* 3991 const ContentEncoding::ContentCompression*
4461 ContentEncoding::GetCompressionByIndex(unsigned long idx) const { 3992 ContentEncoding::GetCompressionByIndex(unsigned long idx) const {
4462 const ptrdiff_t count = compression_entries_end_ - compression_entries_; 3993 const ptrdiff_t count = compression_entries_end_ - compression_entries_;
4463 assert(count >= 0); 3994 assert(count >= 0);
4464 3995
4465 if (idx >= static_cast<unsigned long>(count)) 3996 if (idx >= static_cast<unsigned long>(count))
4466 return NULL; 3997 return NULL;
4467 3998
4468 return compression_entries_[idx]; 3999 return compression_entries_[idx];
4469 } 4000 }
4470 4001
4471 unsigned long ContentEncoding::GetCompressionCount() const { 4002 unsigned long ContentEncoding::GetCompressionCount() const {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
4547 4078
4548 pos += size; // consume payload 4079 pos += size; // consume payload
4549 assert(pos <= stop); 4080 assert(pos <= stop);
4550 } 4081 }
4551 4082
4552 if (compression_count <= 0 && encryption_count <= 0) 4083 if (compression_count <= 0 && encryption_count <= 0)
4553 return -1; 4084 return -1;
4554 4085
4555 if (compression_count > 0) { 4086 if (compression_count > 0) {
4556 compression_entries_ = 4087 compression_entries_ =
4557 new (std::nothrow) ContentCompression* [compression_count]; 4088 new (std::nothrow) ContentCompression*[compression_count];
4558 if (!compression_entries_) 4089 if (!compression_entries_)
4559 return -1; 4090 return -1;
4560 compression_entries_end_ = compression_entries_; 4091 compression_entries_end_ = compression_entries_;
4561 } 4092 }
4562 4093
4563 if (encryption_count > 0) { 4094 if (encryption_count > 0) {
4564 encryption_entries_ = 4095 encryption_entries_ =
4565 new (std::nothrow) ContentEncryption* [encryption_count]; 4096 new (std::nothrow) ContentEncryption*[encryption_count];
4566 if (!encryption_entries_) { 4097 if (!encryption_entries_) {
4567 delete[] compression_entries_; 4098 delete[] compression_entries_;
4568 return -1; 4099 return -1;
4569 } 4100 }
4570 encryption_entries_end_ = encryption_entries_; 4101 encryption_entries_end_ = encryption_entries_;
4571 } 4102 }
4572 4103
4573 pos = start; 4104 pos = start;
4574 while (pos < stop) { 4105 while (pos < stop) {
4575 long long id, size; 4106 long long id, size;
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
4696 if (status < 0) // error 4227 if (status < 0) // error
4697 return status; 4228 return status;
4698 4229
4699 if (id == 0x7E1) { 4230 if (id == 0x7E1) {
4700 // ContentEncAlgo 4231 // ContentEncAlgo
4701 encryption->algo = UnserializeUInt(pReader, pos, size); 4232 encryption->algo = UnserializeUInt(pReader, pos, size);
4702 if (encryption->algo != 5) 4233 if (encryption->algo != 5)
4703 return E_FILE_FORMAT_INVALID; 4234 return E_FILE_FORMAT_INVALID;
4704 } else if (id == 0x7E2) { 4235 } else if (id == 0x7E2) {
4705 // ContentEncKeyID 4236 // ContentEncKeyID
4706 delete[] encryption -> key_id; 4237 delete[] encryption->key_id;
4707 encryption->key_id = NULL; 4238 encryption->key_id = NULL;
4708 encryption->key_id_len = 0; 4239 encryption->key_id_len = 0;
4709 4240
4710 if (size <= 0) 4241 if (size <= 0)
4711 return E_FILE_FORMAT_INVALID; 4242 return E_FILE_FORMAT_INVALID;
4712 4243
4713 const size_t buflen = static_cast<size_t>(size); 4244 const size_t buflen = static_cast<size_t>(size);
4714 typedef unsigned char* buf_t; 4245 typedef unsigned char* buf_t;
4715 const buf_t buf = new (std::nothrow) unsigned char[buflen]; 4246 const buf_t buf = new (std::nothrow) unsigned char[buflen];
4716 if (buf == NULL) 4247 if (buf == NULL)
4717 return -1; 4248 return -1;
4718 4249
4719 const int read_status = 4250 const int read_status =
4720 pReader->Read(pos, static_cast<long>(buflen), buf); 4251 pReader->Read(pos, static_cast<long>(buflen), buf);
4721 if (read_status) { 4252 if (read_status) {
4722 delete[] buf; 4253 delete[] buf;
4723 return status; 4254 return status;
4724 } 4255 }
4725 4256
4726 encryption->key_id = buf; 4257 encryption->key_id = buf;
4727 encryption->key_id_len = buflen; 4258 encryption->key_id_len = buflen;
4728 } else if (id == 0x7E3) { 4259 } else if (id == 0x7E3) {
4729 // ContentSignature 4260 // ContentSignature
4730 delete[] encryption -> signature; 4261 delete[] encryption->signature;
4731 encryption->signature = NULL; 4262 encryption->signature = NULL;
4732 encryption->signature_len = 0; 4263 encryption->signature_len = 0;
4733 4264
4734 if (size <= 0) 4265 if (size <= 0)
4735 return E_FILE_FORMAT_INVALID; 4266 return E_FILE_FORMAT_INVALID;
4736 4267
4737 const size_t buflen = static_cast<size_t>(size); 4268 const size_t buflen = static_cast<size_t>(size);
4738 typedef unsigned char* buf_t; 4269 typedef unsigned char* buf_t;
4739 const buf_t buf = new (std::nothrow) unsigned char[buflen]; 4270 const buf_t buf = new (std::nothrow) unsigned char[buflen];
4740 if (buf == NULL) 4271 if (buf == NULL)
4741 return -1; 4272 return -1;
4742 4273
4743 const int read_status = 4274 const int read_status =
4744 pReader->Read(pos, static_cast<long>(buflen), buf); 4275 pReader->Read(pos, static_cast<long>(buflen), buf);
4745 if (read_status) { 4276 if (read_status) {
4746 delete[] buf; 4277 delete[] buf;
4747 return status; 4278 return status;
4748 } 4279 }
4749 4280
4750 encryption->signature = buf; 4281 encryption->signature = buf;
4751 encryption->signature_len = buflen; 4282 encryption->signature_len = buflen;
4752 } else if (id == 0x7E4) { 4283 } else if (id == 0x7E4) {
4753 // ContentSigKeyID 4284 // ContentSigKeyID
4754 delete[] encryption -> sig_key_id; 4285 delete[] encryption->sig_key_id;
4755 encryption->sig_key_id = NULL; 4286 encryption->sig_key_id = NULL;
4756 encryption->sig_key_id_len = 0; 4287 encryption->sig_key_id_len = 0;
4757 4288
4758 if (size <= 0) 4289 if (size <= 0)
4759 return E_FILE_FORMAT_INVALID; 4290 return E_FILE_FORMAT_INVALID;
4760 4291
4761 const size_t buflen = static_cast<size_t>(size); 4292 const size_t buflen = static_cast<size_t>(size);
4762 typedef unsigned char* buf_t; 4293 typedef unsigned char* buf_t;
4763 const buf_t buf = new (std::nothrow) unsigned char[buflen]; 4294 const buf_t buf = new (std::nothrow) unsigned char[buflen];
4764 if (buf == NULL) 4295 if (buf == NULL)
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
4984 long Track::GetFirst(const BlockEntry*& pBlockEntry) const { 4515 long Track::GetFirst(const BlockEntry*& pBlockEntry) const {
4985 const Cluster* pCluster = m_pSegment->GetFirst(); 4516 const Cluster* pCluster = m_pSegment->GetFirst();
4986 4517
4987 for (int i = 0;;) { 4518 for (int i = 0;;) {
4988 if (pCluster == NULL) { 4519 if (pCluster == NULL) {
4989 pBlockEntry = GetEOS(); 4520 pBlockEntry = GetEOS();
4990 return 1; 4521 return 1;
4991 } 4522 }
4992 4523
4993 if (pCluster->EOS()) { 4524 if (pCluster->EOS()) {
4994 #if 0
4995 if (m_pSegment->Unparsed() <= 0) { //all clusters have been loaded
4996 pBlockEntry = GetEOS();
4997 return 1;
4998 }
4999 #else
5000 if (m_pSegment->DoneParsing()) { 4525 if (m_pSegment->DoneParsing()) {
5001 pBlockEntry = GetEOS(); 4526 pBlockEntry = GetEOS();
5002 return 1; 4527 return 1;
5003 } 4528 }
5004 #endif
5005 4529
5006 pBlockEntry = 0; 4530 pBlockEntry = 0;
5007 return E_BUFFER_NOT_FULL; 4531 return E_BUFFER_NOT_FULL;
5008 } 4532 }
5009 4533
5010 long status = pCluster->GetFirst(pBlockEntry); 4534 long status = pCluster->GetFirst(pBlockEntry);
5011 4535
5012 if (status < 0) // error 4536 if (status < 0) // error
5013 return status; 4537 return status;
5014 4538
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
5091 } 4615 }
5092 4616
5093 pCluster = m_pSegment->GetNext(pCluster); 4617 pCluster = m_pSegment->GetNext(pCluster);
5094 4618
5095 if (pCluster == NULL) { 4619 if (pCluster == NULL) {
5096 pNextEntry = GetEOS(); 4620 pNextEntry = GetEOS();
5097 return 1; 4621 return 1;
5098 } 4622 }
5099 4623
5100 if (pCluster->EOS()) { 4624 if (pCluster->EOS()) {
5101 #if 0
5102 if (m_pSegment->Unparsed() <= 0) //all clusters have been loaded
5103 {
5104 pNextEntry = GetEOS();
5105 return 1;
5106 }
5107 #else
5108 if (m_pSegment->DoneParsing()) { 4625 if (m_pSegment->DoneParsing()) {
5109 pNextEntry = GetEOS(); 4626 pNextEntry = GetEOS();
5110 return 1; 4627 return 1;
5111 } 4628 }
5112 #endif
5113 4629
5114 // TODO: there is a potential O(n^2) problem here: we tell the 4630 // TODO: there is a potential O(n^2) problem here: we tell the
5115 // caller to (pre)load another cluster, which he does, but then he 4631 // caller to (pre)load another cluster, which he does, but then he
5116 // calls GetNext again, which repeats the same search. This is 4632 // calls GetNext again, which repeats the same search. This is
5117 // a pathological case, since the only way it can happen is if 4633 // a pathological case, since the only way it can happen is if
5118 // there exists a long sequence of clusters none of which contain a 4634 // there exists a long sequence of clusters none of which contain a
5119 // block from this track. One way around this problem is for the 4635 // block from this track. One way around this problem is for the
5120 // caller to be smarter when he loads another cluster: don't call 4636 // caller to be smarter when he loads another cluster: don't call
5121 // us back until you have a cluster that contains a block from this 4637 // us back until you have a cluster that contains a block from this
5122 // track. (Of course, that's not cheap either, since our caller 4638 // track. (Of course, that's not cheap either, since our caller
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
5284 if (id == 0x2240) // ContentEncoding ID 4800 if (id == 0x2240) // ContentEncoding ID
5285 ++count; 4801 ++count;
5286 4802
5287 pos += size; // consume payload 4803 pos += size; // consume payload
5288 assert(pos <= stop); 4804 assert(pos <= stop);
5289 } 4805 }
5290 4806
5291 if (count <= 0) 4807 if (count <= 0)
5292 return -1; 4808 return -1;
5293 4809
5294 content_encoding_entries_ = new (std::nothrow) ContentEncoding* [count]; 4810 content_encoding_entries_ = new (std::nothrow) ContentEncoding*[count];
5295 if (!content_encoding_entries_) 4811 if (!content_encoding_entries_)
5296 return -1; 4812 return -1;
5297 4813
5298 content_encoding_entries_end_ = content_encoding_entries_; 4814 content_encoding_entries_end_ = content_encoding_entries_;
5299 4815
5300 pos = start; 4816 pos = start;
5301 while (pos < stop) { 4817 while (pos < stop) {
5302 long long id, size; 4818 long long id, size;
5303 long status = ParseElementHeader(pReader, pos, stop, id, size); 4819 long status = ParseElementHeader(pReader, pos, stop, id, size);
5304 if (status < 0) // error 4820 if (status < 0) // error
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
5343 long long element_start, long long element_size, 4859 long long element_start, long long element_size,
5344 VideoTrack*& pResult) { 4860 VideoTrack*& pResult) {
5345 if (pResult) 4861 if (pResult)
5346 return -1; 4862 return -1;
5347 4863
5348 if (info.type != Track::kVideo) 4864 if (info.type != Track::kVideo)
5349 return -1; 4865 return -1;
5350 4866
5351 long long width = 0; 4867 long long width = 0;
5352 long long height = 0; 4868 long long height = 0;
4869 long long display_width = 0;
4870 long long display_height = 0;
4871 long long display_unit = 0;
4872 long long stereo_mode = 0;
4873
5353 double rate = 0.0; 4874 double rate = 0.0;
5354 4875
5355 IMkvReader* const pReader = pSegment->m_pReader; 4876 IMkvReader* const pReader = pSegment->m_pReader;
5356 4877
5357 const Settings& s = info.settings; 4878 const Settings& s = info.settings;
5358 assert(s.start >= 0); 4879 assert(s.start >= 0);
5359 assert(s.size >= 0); 4880 assert(s.size >= 0);
5360 4881
5361 long long pos = s.start; 4882 long long pos = s.start;
5362 assert(pos >= 0); 4883 assert(pos >= 0);
(...skipping 11 matching lines...) Expand all
5374 if (id == 0x30) { // pixel width 4895 if (id == 0x30) { // pixel width
5375 width = UnserializeUInt(pReader, pos, size); 4896 width = UnserializeUInt(pReader, pos, size);
5376 4897
5377 if (width <= 0) 4898 if (width <= 0)
5378 return E_FILE_FORMAT_INVALID; 4899 return E_FILE_FORMAT_INVALID;
5379 } else if (id == 0x3A) { // pixel height 4900 } else if (id == 0x3A) { // pixel height
5380 height = UnserializeUInt(pReader, pos, size); 4901 height = UnserializeUInt(pReader, pos, size);
5381 4902
5382 if (height <= 0) 4903 if (height <= 0)
5383 return E_FILE_FORMAT_INVALID; 4904 return E_FILE_FORMAT_INVALID;
4905 } else if (id == 0x14B0) { // display width
4906 display_width = UnserializeUInt(pReader, pos, size);
4907
4908 if (display_width <= 0)
4909 return E_FILE_FORMAT_INVALID;
4910 } else if (id == 0x14BA) { // display height
4911 display_height = UnserializeUInt(pReader, pos, size);
4912
4913 if (display_height <= 0)
4914 return E_FILE_FORMAT_INVALID;
4915 } else if (id == 0x14B2) { // display unit
4916 display_unit = UnserializeUInt(pReader, pos, size);
4917
4918 if (display_unit < 0)
4919 return E_FILE_FORMAT_INVALID;
4920 } else if (id == 0x13B8) { // stereo mode
4921 stereo_mode = UnserializeUInt(pReader, pos, size);
4922
4923 if (stereo_mode < 0)
4924 return E_FILE_FORMAT_INVALID;
5384 } else if (id == 0x0383E3) { // frame rate 4925 } else if (id == 0x0383E3) { // frame rate
5385 const long status = UnserializeFloat(pReader, pos, size, rate); 4926 const long status = UnserializeFloat(pReader, pos, size, rate);
5386 4927
5387 if (status < 0) 4928 if (status < 0)
5388 return status; 4929 return status;
5389 4930
5390 if (rate <= 0) 4931 if (rate <= 0)
5391 return E_FILE_FORMAT_INVALID; 4932 return E_FILE_FORMAT_INVALID;
5392 } 4933 }
5393 4934
(...skipping 11 matching lines...) Expand all
5405 4946
5406 const int status = info.Copy(pTrack->m_info); 4947 const int status = info.Copy(pTrack->m_info);
5407 4948
5408 if (status) { // error 4949 if (status) { // error
5409 delete pTrack; 4950 delete pTrack;
5410 return status; 4951 return status;
5411 } 4952 }
5412 4953
5413 pTrack->m_width = width; 4954 pTrack->m_width = width;
5414 pTrack->m_height = height; 4955 pTrack->m_height = height;
4956 pTrack->m_display_width = display_width;
4957 pTrack->m_display_height = display_height;
4958 pTrack->m_display_unit = display_unit;
4959 pTrack->m_stereo_mode = stereo_mode;
5415 pTrack->m_rate = rate; 4960 pTrack->m_rate = rate;
5416 4961
5417 pResult = pTrack; 4962 pResult = pTrack;
5418 return 0; // success 4963 return 0; // success
5419 } 4964 }
5420 4965
5421 bool VideoTrack::VetEntry(const BlockEntry* pBlockEntry) const { 4966 bool VideoTrack::VetEntry(const BlockEntry* pBlockEntry) const {
5422 return Track::VetEntry(pBlockEntry) && pBlockEntry->GetBlock()->IsKey(); 4967 return Track::VetEntry(pBlockEntry) && pBlockEntry->GetBlock()->IsKey();
5423 } 4968 }
5424 4969
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
5491 pResult = pCluster->GetEntry(this, time_ns); 5036 pResult = pCluster->GetEntry(this, time_ns);
5492 5037
5493 if ((pResult != 0) && !pResult->EOS()) // found a keyframe 5038 if ((pResult != 0) && !pResult->EOS()) // found a keyframe
5494 return 0; 5039 return 0;
5495 5040
5496 while (lo != i) { 5041 while (lo != i) {
5497 pCluster = *--lo; 5042 pCluster = *--lo;
5498 assert(pCluster); 5043 assert(pCluster);
5499 assert(pCluster->GetTime() <= time_ns); 5044 assert(pCluster->GetTime() <= time_ns);
5500 5045
5501 #if 0
5502 //TODO:
5503 //We need to handle the case when a cluster
5504 //contains multiple keyframes. Simply returning
5505 //the largest keyframe on the cluster isn't
5506 //good enough.
5507 pResult = pCluster->GetMaxKey(this);
5508 #else
5509 pResult = pCluster->GetEntry(this, time_ns); 5046 pResult = pCluster->GetEntry(this, time_ns);
5510 #endif
5511 5047
5512 if ((pResult != 0) && !pResult->EOS()) 5048 if ((pResult != 0) && !pResult->EOS())
5513 return 0; 5049 return 0;
5514 } 5050 }
5515 5051
5516 // weird: we're on the first cluster, but no keyframe found 5052 // weird: we're on the first cluster, but no keyframe found
5517 // should never happen but we must return something anyway 5053 // should never happen but we must return something anyway
5518 5054
5519 pResult = GetEOS(); 5055 pResult = GetEOS();
5520 return 0; 5056 return 0;
5521 } 5057 }
5522 5058
5523 long long VideoTrack::GetWidth() const { return m_width; } 5059 long long VideoTrack::GetWidth() const { return m_width; }
5524 5060
5525 long long VideoTrack::GetHeight() const { return m_height; } 5061 long long VideoTrack::GetHeight() const { return m_height; }
5526 5062
5063 long long VideoTrack::GetDisplayWidth() const {
5064 return m_display_width > 0 ? m_display_width : GetWidth();
5065 }
5066
5067 long long VideoTrack::GetDisplayHeight() const {
5068 return m_display_height > 0 ? m_display_height : GetHeight();
5069 }
5070
5071 long long VideoTrack::GetDisplayUnit() const { return m_display_unit; }
5072
5073 long long VideoTrack::GetStereoMode() const { return m_stereo_mode; }
5074
5527 double VideoTrack::GetFrameRate() const { return m_rate; } 5075 double VideoTrack::GetFrameRate() const { return m_rate; }
5528 5076
5529 AudioTrack::AudioTrack(Segment* pSegment, long long element_start, 5077 AudioTrack::AudioTrack(Segment* pSegment, long long element_start,
5530 long long element_size) 5078 long long element_size)
5531 : Track(pSegment, element_start, element_size) {} 5079 : Track(pSegment, element_start, element_size) {}
5532 5080
5533 long AudioTrack::Parse(Segment* pSegment, const Info& info, 5081 long AudioTrack::Parse(Segment* pSegment, const Info& info,
5534 long long element_start, long long element_size, 5082 long long element_start, long long element_size,
5535 AudioTrack*& pResult) { 5083 AudioTrack*& pResult) {
5536 if (pResult) 5084 if (pResult)
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
5651 5199
5652 pos += size; // consume payload 5200 pos += size; // consume payload
5653 assert(pos <= stop); 5201 assert(pos <= stop);
5654 } 5202 }
5655 5203
5656 assert(pos == stop); 5204 assert(pos == stop);
5657 5205
5658 if (count <= 0) 5206 if (count <= 0)
5659 return 0; // success 5207 return 0; // success
5660 5208
5661 m_trackEntries = new (std::nothrow) Track* [count]; 5209 m_trackEntries = new (std::nothrow) Track*[count];
5662 5210
5663 if (m_trackEntries == NULL) 5211 if (m_trackEntries == NULL)
5664 return -1; 5212 return -1;
5665 5213
5666 m_trackEntriesEnd = m_trackEntries; 5214 m_trackEntriesEnd = m_trackEntries;
5667 5215
5668 pos = m_start; 5216 pos = m_start;
5669 5217
5670 while (pos < stop) { 5218 while (pos < stop) {
5671 const long long element_start = pos; 5219 const long long element_start = pos;
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
5934 pResult->ParseContentEncodingsEntry(e.start, e.size); 5482 pResult->ParseContentEncodingsEntry(e.start, e.size);
5935 } else { 5483 } else {
5936 // neither video nor audio - probably metadata or subtitles 5484 // neither video nor audio - probably metadata or subtitles
5937 5485
5938 if (a.start >= 0) 5486 if (a.start >= 0)
5939 return E_FILE_FORMAT_INVALID; 5487 return E_FILE_FORMAT_INVALID;
5940 5488
5941 if (v.start >= 0) 5489 if (v.start >= 0)
5942 return E_FILE_FORMAT_INVALID; 5490 return E_FILE_FORMAT_INVALID;
5943 5491
5944 if (e.start >= 0) 5492 if (info.type == Track::kMetadata && e.start >= 0)
5945 return E_FILE_FORMAT_INVALID; 5493 return E_FILE_FORMAT_INVALID;
5946 5494
5947 info.settings.start = -1; 5495 info.settings.start = -1;
5948 info.settings.size = 0; 5496 info.settings.size = 0;
5949 5497
5950 Track* pTrack = NULL; 5498 Track* pTrack = NULL;
5951 5499
5952 const long status = 5500 const long status =
5953 Track::Create(m_pSegment, info, element_start, element_size, pTrack); 5501 Track::Create(m_pSegment, info, element_start, element_size, pTrack);
5954 5502
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
5996 5544
5997 const Track* Tracks::GetTrackByIndex(unsigned long idx) const { 5545 const Track* Tracks::GetTrackByIndex(unsigned long idx) const {
5998 const ptrdiff_t count = m_trackEntriesEnd - m_trackEntries; 5546 const ptrdiff_t count = m_trackEntriesEnd - m_trackEntries;
5999 5547
6000 if (idx >= static_cast<unsigned long>(count)) 5548 if (idx >= static_cast<unsigned long>(count))
6001 return NULL; 5549 return NULL;
6002 5550
6003 return m_trackEntries[idx]; 5551 return m_trackEntries[idx];
6004 } 5552 }
6005 5553
6006 #if 0
6007 long long Cluster::Unparsed() const
6008 {
6009 if (m_timecode < 0) //not even partially loaded
6010 return LLONG_MAX;
6011
6012 assert(m_pos >= m_element_start);
6013 //assert(m_element_size > m_size);
6014
6015 const long long element_stop = m_element_start + m_element_size;
6016 assert(m_pos <= element_stop);
6017
6018 const long long result = element_stop - m_pos;
6019 assert(result >= 0);
6020
6021 return result;
6022 }
6023 #endif
6024
6025 long Cluster::Load(long long& pos, long& len) const { 5554 long Cluster::Load(long long& pos, long& len) const {
6026 assert(m_pSegment); 5555 assert(m_pSegment);
6027 assert(m_pos >= m_element_start); 5556 assert(m_pos >= m_element_start);
6028 5557
6029 if (m_timecode >= 0) // at least partially loaded 5558 if (m_timecode >= 0) // at least partially loaded
6030 return 0; 5559 return 0;
6031 5560
6032 assert(m_pos == m_element_start); 5561 assert(m_pos == m_element_start);
6033 assert(m_element_size < 0); 5562 assert(m_element_size < 0);
6034 5563
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
6108 return E_FILE_FORMAT_INVALID; // TODO: verify this 5637 return E_FILE_FORMAT_INVALID; // TODO: verify this
6109 5638
6110 pos += len; // consume length of size of element 5639 pos += len; // consume length of size of element
6111 5640
6112 const long long unknown_size = (1LL << (7 * len)) - 1; 5641 const long long unknown_size = (1LL << (7 * len)) - 1;
6113 5642
6114 if (size != unknown_size) 5643 if (size != unknown_size)
6115 cluster_size = size; 5644 cluster_size = size;
6116 } 5645 }
6117 5646
6118 // pos points to start of payload 5647 // pos points to start of payload
6119
6120 #if 0
6121 len = static_cast<long>(size_);
6122
6123 if (cluster_stop > avail)
6124 return E_BUFFER_NOT_FULL;
6125 #endif
6126
6127 long long timecode = -1; 5648 long long timecode = -1;
6128 long long new_pos = -1; 5649 long long new_pos = -1;
6129 bool bBlock = false; 5650 bool bBlock = false;
6130 5651
6131 long long cluster_stop = (cluster_size < 0) ? -1 : pos + cluster_size; 5652 long long cluster_stop = (cluster_size < 0) ? -1 : pos + cluster_size;
6132 5653
6133 for (;;) { 5654 for (;;) {
6134 if ((cluster_stop >= 0) && (pos >= cluster_stop)) 5655 if ((cluster_stop >= 0) && (pos >= cluster_stop))
6135 break; 5656 break;
6136 5657
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
6488 return E_BUFFER_NOT_FULL; 6009 return E_BUFFER_NOT_FULL;
6489 6010
6490 const long long track = ReadUInt(pReader, pos, len); 6011 const long long track = ReadUInt(pReader, pos, len);
6491 6012
6492 if (track < 0) // error 6013 if (track < 0) // error
6493 return static_cast<long>(track); 6014 return static_cast<long>(track);
6494 6015
6495 if (track == 0) 6016 if (track == 0)
6496 return E_FILE_FORMAT_INVALID; 6017 return E_FILE_FORMAT_INVALID;
6497 6018
6498 #if 0
6499 //TODO(matthewjheaney)
6500 //This turned out to be too conservative. The problem is that
6501 //if we see a track header in the tracks element with an unsupported
6502 //track type, we throw that track header away, so it is not present
6503 //in the track map. But even though we don't understand the track
6504 //header, there are still blocks in the cluster with that track
6505 //number. It was our decision to ignore that track header, so it's
6506 //up to us to deal with blocks associated with that track -- we
6507 //cannot simply report an error since technically there's nothing
6508 //wrong with the file.
6509 //
6510 //For now we go ahead and finish the parse, creating a block entry
6511 //for this block. This is somewhat wasteful, because without a
6512 //track header there's nothing you can do with the block. What
6513 //we really need here is a special return value that indicates to
6514 //the caller that he should ignore this particular block, and
6515 //continue parsing.
6516
6517 const Tracks* const pTracks = m_pSegment->GetTracks();
6518 assert(pTracks);
6519
6520 const long tn = static_cast<long>(track);
6521
6522 const Track* const pTrack = pTracks->GetTrackByNumber(tn);
6523
6524 if (pTrack == NULL)
6525 return E_FILE_FORMAT_INVALID;
6526 #endif
6527
6528 pos += len; // consume track number 6019 pos += len; // consume track number
6529 6020
6530 if ((pos + 2) > block_stop) 6021 if ((pos + 2) > block_stop)
6531 return E_FILE_FORMAT_INVALID; 6022 return E_FILE_FORMAT_INVALID;
6532 6023
6533 if ((pos + 2) > avail) { 6024 if ((pos + 2) > avail) {
6534 len = 2; 6025 len = 2;
6535 return E_BUFFER_NOT_FULL; 6026 return E_BUFFER_NOT_FULL;
6536 } 6027 }
6537 6028
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
6672 6163
6673 if (size == 0) // weird 6164 if (size == 0) // weird
6674 continue; 6165 continue;
6675 6166
6676 const long long unknown_size = (1LL << (7 * len)) - 1; 6167 const long long unknown_size = (1LL << (7 * len)) - 1;
6677 6168
6678 if (size == unknown_size) 6169 if (size == unknown_size)
6679 return E_FILE_FORMAT_INVALID; 6170 return E_FILE_FORMAT_INVALID;
6680 6171
6681 if (id == 0x35A2) { // DiscardPadding 6172 if (id == 0x35A2) { // DiscardPadding
6682 result = GetUIntLength(pReader, pos, len); 6173 status = UnserializeInt(pReader, pos, size, discard_padding);
6683
6684 if (result < 0) // error
6685 return static_cast<long>(result);
6686
6687 status = UnserializeInt(pReader, pos, len, discard_padding);
6688 6174
6689 if (status < 0) // error 6175 if (status < 0) // error
6690 return status; 6176 return status;
6691 } 6177 }
6692 6178
6693 if (id != 0x21) { // sub-part of BlockGroup is not a Block 6179 if (id != 0x21) { // sub-part of BlockGroup is not a Block
6694 pos += size; // consume sub-part of block group 6180 pos += size; // consume sub-part of block group
6695 6181
6696 if (pos > payload_stop) 6182 if (pos > payload_stop)
6697 return E_FILE_FORMAT_INVALID; 6183 return E_FILE_FORMAT_INVALID;
(...skipping 28 matching lines...) Expand all
6726 return E_BUFFER_NOT_FULL; 6212 return E_BUFFER_NOT_FULL;
6727 6213
6728 const long long track = ReadUInt(pReader, pos, len); 6214 const long long track = ReadUInt(pReader, pos, len);
6729 6215
6730 if (track < 0) // error 6216 if (track < 0) // error
6731 return static_cast<long>(track); 6217 return static_cast<long>(track);
6732 6218
6733 if (track == 0) 6219 if (track == 0)
6734 return E_FILE_FORMAT_INVALID; 6220 return E_FILE_FORMAT_INVALID;
6735 6221
6736 #if 0
6737 //TODO(matthewjheaney)
6738 //This turned out to be too conservative. The problem is that
6739 //if we see a track header in the tracks element with an unsupported
6740 //track type, we throw that track header away, so it is not present
6741 //in the track map. But even though we don't understand the track
6742 //header, there are still blocks in the cluster with that track
6743 //number. It was our decision to ignore that track header, so it's
6744 //up to us to deal with blocks associated with that track -- we
6745 //cannot simply report an error since technically there's nothing
6746 //wrong with the file.
6747 //
6748 //For now we go ahead and finish the parse, creating a block entry
6749 //for this block. This is somewhat wasteful, because without a
6750 //track header there's nothing you can do with the block. What
6751 //we really need here is a special return value that indicates to
6752 //the caller that he should ignore this particular block, and
6753 //continue parsing.
6754
6755 const Tracks* const pTracks = m_pSegment->GetTracks();
6756 assert(pTracks);
6757
6758 const long tn = static_cast<long>(track);
6759
6760 const Track* const pTrack = pTracks->GetTrackByNumber(tn);
6761
6762 if (pTrack == NULL)
6763 return E_FILE_FORMAT_INVALID;
6764 #endif
6765
6766 pos += len; // consume track number 6222 pos += len; // consume track number
6767 6223
6768 if ((pos + 2) > block_stop) 6224 if ((pos + 2) > block_stop)
6769 return E_FILE_FORMAT_INVALID; 6225 return E_FILE_FORMAT_INVALID;
6770 6226
6771 if ((pos + 2) > avail) { 6227 if ((pos + 2) > avail) {
6772 len = 2; 6228 len = 2;
6773 return E_BUFFER_NOT_FULL; 6229 return E_BUFFER_NOT_FULL;
6774 } 6230 }
6775 6231
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
6917 6373
6918 long long Cluster::GetPosition() const { 6374 long long Cluster::GetPosition() const {
6919 const long long pos = m_element_start - m_pSegment->m_start; 6375 const long long pos = m_element_start - m_pSegment->m_start;
6920 assert(pos >= 0); 6376 assert(pos >= 0);
6921 6377
6922 return pos; 6378 return pos;
6923 } 6379 }
6924 6380
6925 long long Cluster::GetElementSize() const { return m_element_size; } 6381 long long Cluster::GetElementSize() const { return m_element_size; }
6926 6382
6927 #if 0
6928 bool Cluster::HasBlockEntries(
6929 const Segment* pSegment,
6930 long long off) {
6931 assert(pSegment);
6932 assert(off >= 0); //relative to start of segment payload
6933
6934 IMkvReader* const pReader = pSegment->m_pReader;
6935
6936 long long pos = pSegment->m_start + off; //absolute
6937 long long size;
6938
6939 {
6940 long len;
6941
6942 const long long id = ReadUInt(pReader, pos, len);
6943 (void)id;
6944 assert(id >= 0);
6945 assert(id == 0x0F43B675); //Cluster ID
6946
6947 pos += len; //consume id
6948
6949 size = ReadUInt(pReader, pos, len);
6950 assert(size > 0);
6951
6952 pos += len; //consume size
6953
6954 //pos now points to start of payload
6955 }
6956
6957 const long long stop = pos + size;
6958
6959 while (pos < stop)
6960 {
6961 long len;
6962
6963 const long long id = ReadUInt(pReader, pos, len);
6964 assert(id >= 0); //TODO
6965 assert((pos + len) <= stop);
6966
6967 pos += len; //consume id
6968
6969 const long long size = ReadUInt(pReader, pos, len);
6970 assert(size >= 0); //TODO
6971 assert((pos + len) <= stop);
6972
6973 pos += len; //consume size
6974
6975 if (id == 0x20) //BlockGroup ID
6976 return true;
6977
6978 if (id == 0x23) //SimpleBlock ID
6979 return true;
6980
6981 pos += size; //consume payload
6982 assert(pos <= stop);
6983 }
6984
6985 return false;
6986 }
6987 #endif
6988
6989 long Cluster::HasBlockEntries( 6383 long Cluster::HasBlockEntries(
6990 const Segment* pSegment, 6384 const Segment* pSegment,
6991 long long off, // relative to start of segment payload 6385 long long off, // relative to start of segment payload
6992 long long& pos, long& len) { 6386 long long& pos, long& len) {
6993 assert(pSegment); 6387 assert(pSegment);
6994 assert(off >= 0); // relative to segment 6388 assert(off >= 0); // relative to segment
6995 6389
6996 IMkvReader* const pReader = pSegment->m_pReader; 6390 IMkvReader* const pReader = pSegment->m_pReader;
6997 6391
6998 long long total, avail; 6392 long long total, avail;
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
7262 long Cluster::CreateBlock(long long id, 6656 long Cluster::CreateBlock(long long id,
7263 long long pos, // absolute pos of payload 6657 long long pos, // absolute pos of payload
7264 long long size, long long discard_padding) { 6658 long long size, long long discard_padding) {
7265 assert((id == 0x20) || (id == 0x23)); // BlockGroup or SimpleBlock 6659 assert((id == 0x20) || (id == 0x23)); // BlockGroup or SimpleBlock
7266 6660
7267 if (m_entries_count < 0) { // haven't parsed anything yet 6661 if (m_entries_count < 0) { // haven't parsed anything yet
7268 assert(m_entries == NULL); 6662 assert(m_entries == NULL);
7269 assert(m_entries_size == 0); 6663 assert(m_entries_size == 0);
7270 6664
7271 m_entries_size = 1024; 6665 m_entries_size = 1024;
7272 m_entries = new BlockEntry* [m_entries_size]; 6666 m_entries = new BlockEntry*[m_entries_size];
7273 6667
7274 m_entries_count = 0; 6668 m_entries_count = 0;
7275 } else { 6669 } else {
7276 assert(m_entries); 6670 assert(m_entries);
7277 assert(m_entries_size > 0); 6671 assert(m_entries_size > 0);
7278 assert(m_entries_count <= m_entries_size); 6672 assert(m_entries_count <= m_entries_size);
7279 6673
7280 if (m_entries_count >= m_entries_size) { 6674 if (m_entries_count >= m_entries_size) {
7281 const long entries_size = 2 * m_entries_size; 6675 const long entries_size = 2 * m_entries_size;
7282 6676
7283 BlockEntry** const entries = new BlockEntry* [entries_size]; 6677 BlockEntry** const entries = new BlockEntry*[entries_size];
7284 assert(entries); 6678 assert(entries);
7285 6679
7286 BlockEntry** src = m_entries; 6680 BlockEntry** src = m_entries;
7287 BlockEntry** const src_end = src + m_entries_count; 6681 BlockEntry** const src_end = src + m_entries_count;
7288 6682
7289 BlockEntry** dst = entries; 6683 BlockEntry** dst = entries;
7290 6684
7291 while (src != src_end) 6685 while (src != src_end)
7292 *dst++ = *src++; 6686 *dst++ = *src++;
7293 6687
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
7342 assert((pos + len) <= stop); 6736 assert((pos + len) <= stop);
7343 6737
7344 pos += len; // consume size 6738 pos += len; // consume size
7345 6739
7346 if (id == 0x21) { // Block ID 6740 if (id == 0x21) { // Block ID
7347 if (bpos < 0) { // Block ID 6741 if (bpos < 0) { // Block ID
7348 bpos = pos; 6742 bpos = pos;
7349 bsize = size; 6743 bsize = size;
7350 } 6744 }
7351 } else if (id == 0x1B) { // Duration ID 6745 } else if (id == 0x1B) { // Duration ID
7352 assert(size <= 8); 6746 if (size > 8)
6747 return E_FILE_FORMAT_INVALID;
7353 6748
7354 duration = UnserializeUInt(pReader, pos, size); 6749 duration = UnserializeUInt(pReader, pos, size);
7355 assert(duration >= 0); // TODO 6750
6751 if (duration < 0)
6752 return E_FILE_FORMAT_INVALID;
7356 } else if (id == 0x7B) { // ReferenceBlock 6753 } else if (id == 0x7B) { // ReferenceBlock
7357 assert(size <= 8); 6754 if (size > 8 || size <= 0)
6755 return E_FILE_FORMAT_INVALID;
7358 const long size_ = static_cast<long>(size); 6756 const long size_ = static_cast<long>(size);
7359 6757
7360 long long time; 6758 long long time;
7361 6759
7362 long status = UnserializeInt(pReader, pos, size_, time); 6760 long status = UnserializeInt(pReader, pos, size_, time);
7363 assert(status == 0); 6761 assert(status == 0);
7364 if (status != 0) 6762 if (status != 0)
7365 return -1; 6763 return -1;
7366 6764
7367 if (time <= 0) // see note above 6765 if (time <= 0) // see note above
7368 prev = time; 6766 prev = time;
7369 else // weird 6767 else // weird
7370 next = time; 6768 next = time;
7371 } 6769 }
7372 6770
7373 pos += size; // consume payload 6771 pos += size; // consume payload
7374 assert(pos <= stop); 6772 assert(pos <= stop);
7375 } 6773 }
6774 if (bpos < 0)
6775 return E_FILE_FORMAT_INVALID;
7376 6776
7377 assert(pos == stop); 6777 assert(pos == stop);
7378 assert(bpos >= 0);
7379 assert(bsize >= 0); 6778 assert(bsize >= 0);
7380 6779
7381 const long idx = m_entries_count; 6780 const long idx = m_entries_count;
7382 6781
7383 BlockEntry** const ppEntry = m_entries + idx; 6782 BlockEntry** const ppEntry = m_entries + idx;
7384 BlockEntry*& pEntry = *ppEntry; 6783 BlockEntry*& pEntry = *ppEntry;
7385 6784
7386 pEntry = new (std::nothrow) 6785 pEntry = new (std::nothrow)
7387 BlockGroup(this, idx, bpos, bsize, prev, next, duration, discard_padding); 6786 BlockGroup(this, idx, bpos, bsize, prev, next, duration, discard_padding);
7388 6787
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
7532 6931
7533 long Cluster::GetEntryCount() const { return m_entries_count; } 6932 long Cluster::GetEntryCount() const { return m_entries_count; }
7534 6933
7535 const BlockEntry* Cluster::GetEntry(const Track* pTrack, 6934 const BlockEntry* Cluster::GetEntry(const Track* pTrack,
7536 long long time_ns) const { 6935 long long time_ns) const {
7537 assert(pTrack); 6936 assert(pTrack);
7538 6937
7539 if (m_pSegment == NULL) // this is the special EOS cluster 6938 if (m_pSegment == NULL) // this is the special EOS cluster
7540 return pTrack->GetEOS(); 6939 return pTrack->GetEOS();
7541 6940
7542 #if 0
7543
7544 LoadBlockEntries();
7545
7546 if ((m_entries == NULL) || (m_entries_count <= 0))
7547 return NULL; //return EOS here?
7548
7549 const BlockEntry* pResult = pTrack->GetEOS();
7550
7551 BlockEntry** i = m_entries;
7552 assert(i);
7553
7554 BlockEntry** const j = i + m_entries_count;
7555
7556 while (i != j)
7557 {
7558 const BlockEntry* const pEntry = *i++;
7559 assert(pEntry);
7560 assert(!pEntry->EOS());
7561
7562 const Block* const pBlock = pEntry->GetBlock();
7563 assert(pBlock);
7564
7565 if (pBlock->GetTrackNumber() != pTrack->GetNumber())
7566 continue;
7567
7568 if (pTrack->VetEntry(pEntry))
7569 {
7570 if (time_ns < 0) //just want first candidate block
7571 return pEntry;
7572
7573 const long long ns = pBlock->GetTime(this);
7574
7575 if (ns > time_ns)
7576 break;
7577
7578 pResult = pEntry;
7579 }
7580 else if (time_ns >= 0)
7581 {
7582 const long long ns = pBlock->GetTime(this);
7583
7584 if (ns > time_ns)
7585 break;
7586 }
7587 }
7588
7589 return pResult;
7590
7591 #else
7592
7593 const BlockEntry* pResult = pTrack->GetEOS(); 6941 const BlockEntry* pResult = pTrack->GetEOS();
7594 6942
7595 long index = 0; 6943 long index = 0;
7596 6944
7597 for (;;) { 6945 for (;;) {
7598 if (index >= m_entries_count) { 6946 if (index >= m_entries_count) {
7599 long long pos; 6947 long long pos;
7600 long len; 6948 long len;
7601 6949
7602 const long status = Parse(pos, len); 6950 const long status = Parse(pos, len);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
7636 pResult = pEntry; // have a candidate 6984 pResult = pEntry; // have a candidate
7637 } else if (time_ns >= 0) { 6985 } else if (time_ns >= 0) {
7638 const long long ns = pBlock->GetTime(this); 6986 const long long ns = pBlock->GetTime(this);
7639 6987
7640 if (ns > time_ns) 6988 if (ns > time_ns)
7641 return pResult; 6989 return pResult;
7642 } 6990 }
7643 6991
7644 ++index; 6992 ++index;
7645 } 6993 }
7646
7647 #endif
7648 } 6994 }
7649 6995
7650 const BlockEntry* Cluster::GetEntry(const CuePoint& cp, 6996 const BlockEntry* Cluster::GetEntry(const CuePoint& cp,
7651 const CuePoint::TrackPosition& tp) const { 6997 const CuePoint::TrackPosition& tp) const {
7652 assert(m_pSegment); 6998 assert(m_pSegment);
7653
7654 #if 0
7655
7656 LoadBlockEntries();
7657
7658 if (m_entries == NULL)
7659 return NULL;
7660
7661 const long long count = m_entries_count;
7662
7663 if (count <= 0)
7664 return NULL;
7665
7666 const long long tc = cp.GetTimeCode();
7667
7668 if ((tp.m_block > 0) && (tp.m_block <= count))
7669 {
7670 const size_t block = static_cast<size_t>(tp.m_block);
7671 const size_t index = block - 1;
7672
7673 const BlockEntry* const pEntry = m_entries[index];
7674 assert(pEntry);
7675 assert(!pEntry->EOS());
7676
7677 const Block* const pBlock = pEntry->GetBlock();
7678 assert(pBlock);
7679
7680 if ((pBlock->GetTrackNumber() == tp.m_track) &&
7681 (pBlock->GetTimeCode(this) == tc))
7682 {
7683 return pEntry;
7684 }
7685 }
7686
7687 const BlockEntry* const* i = m_entries;
7688 const BlockEntry* const* const j = i + count;
7689
7690 while (i != j)
7691 {
7692 #ifdef _DEBUG
7693 const ptrdiff_t idx = i - m_entries;
7694 idx;
7695 #endif
7696
7697 const BlockEntry* const pEntry = *i++;
7698 assert(pEntry);
7699 assert(!pEntry->EOS());
7700
7701 const Block* const pBlock = pEntry->GetBlock();
7702 assert(pBlock);
7703
7704 if (pBlock->GetTrackNumber() != tp.m_track)
7705 continue;
7706
7707 const long long tc_ = pBlock->GetTimeCode(this);
7708 assert(tc_ >= 0);
7709
7710 if (tc_ < tc)
7711 continue;
7712
7713 if (tc_ > tc)
7714 return NULL;
7715
7716 const Tracks* const pTracks = m_pSegment->GetTracks();
7717 assert(pTracks);
7718
7719 const long tn = static_cast<long>(tp.m_track);
7720 const Track* const pTrack = pTracks->GetTrackByNumber(tn);
7721
7722 if (pTrack == NULL)
7723 return NULL;
7724
7725 const long long type = pTrack->GetType();
7726
7727 if (type == 2) //audio
7728 return pEntry;
7729
7730 if (type != 1) //not video
7731 return NULL;
7732
7733 if (!pBlock->IsKey())
7734 return NULL;
7735
7736 return pEntry;
7737 }
7738
7739 return NULL;
7740
7741 #else
7742
7743 const long long tc = cp.GetTimeCode(); 6999 const long long tc = cp.GetTimeCode();
7744 7000
7745 if (tp.m_block > 0) { 7001 if (tp.m_block > 0) {
7746 const long block = static_cast<long>(tp.m_block); 7002 const long block = static_cast<long>(tp.m_block);
7747 const long index = block - 1; 7003 const long index = block - 1;
7748 7004
7749 while (index >= m_entries_count) { 7005 while (index >= m_entries_count) {
7750 long long pos; 7006 long long pos;
7751 long len; 7007 long len;
7752 7008
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
7828 return pEntry; 7084 return pEntry;
7829 7085
7830 if (type != 1) // not video 7086 if (type != 1) // not video
7831 return NULL; 7087 return NULL;
7832 7088
7833 if (!pBlock->IsKey()) 7089 if (!pBlock->IsKey())
7834 return NULL; 7090 return NULL;
7835 7091
7836 return pEntry; 7092 return pEntry;
7837 } 7093 }
7838
7839 #endif
7840 } 7094 }
7841 7095
7842 #if 0
7843 const BlockEntry* Cluster::GetMaxKey(const VideoTrack* pTrack) const
7844 {
7845 assert(pTrack);
7846
7847 if (m_pSegment == NULL) //EOS
7848 return pTrack->GetEOS();
7849
7850 LoadBlockEntries();
7851
7852 if ((m_entries == NULL) || (m_entries_count <= 0))
7853 return pTrack->GetEOS();
7854
7855 BlockEntry** i = m_entries + m_entries_count;
7856 BlockEntry** const j = m_entries;
7857
7858 while (i != j)
7859 {
7860 const BlockEntry* const pEntry = *--i;
7861 assert(pEntry);
7862 assert(!pEntry->EOS());
7863
7864 const Block* const pBlock = pEntry->GetBlock();
7865 assert(pBlock);
7866
7867 if (pBlock->GetTrackNumber() != pTrack->GetNumber())
7868 continue;
7869
7870 if (pBlock->IsKey())
7871 return pEntry;
7872 }
7873
7874 return pTrack->GetEOS(); //no satisfactory block found
7875 }
7876 #endif
7877
7878 BlockEntry::BlockEntry(Cluster* p, long idx) : m_pCluster(p), m_index(idx) {} 7096 BlockEntry::BlockEntry(Cluster* p, long idx) : m_pCluster(p), m_index(idx) {}
7879
7880 BlockEntry::~BlockEntry() {} 7097 BlockEntry::~BlockEntry() {}
7881
7882 bool BlockEntry::EOS() const { return (GetKind() == kBlockEOS); } 7098 bool BlockEntry::EOS() const { return (GetKind() == kBlockEOS); }
7883
7884 const Cluster* BlockEntry::GetCluster() const { return m_pCluster; } 7099 const Cluster* BlockEntry::GetCluster() const { return m_pCluster; }
7885
7886 long BlockEntry::GetIndex() const { return m_index; } 7100 long BlockEntry::GetIndex() const { return m_index; }
7887 7101
7888 SimpleBlock::SimpleBlock(Cluster* pCluster, long idx, long long start, 7102 SimpleBlock::SimpleBlock(Cluster* pCluster, long idx, long long start,
7889 long long size) 7103 long long size)
7890 : BlockEntry(pCluster, idx), m_block(start, size, 0) {} 7104 : BlockEntry(pCluster, idx), m_block(start, size, 0) {}
7891 7105
7892 long SimpleBlock::Parse() { return m_block.Parse(m_pCluster); } 7106 long SimpleBlock::Parse() { return m_block.Parse(m_pCluster); }
7893
7894 BlockEntry::Kind SimpleBlock::GetKind() const { return kBlockSimple; } 7107 BlockEntry::Kind SimpleBlock::GetKind() const { return kBlockSimple; }
7895
7896 const Block* SimpleBlock::GetBlock() const { return &m_block; } 7108 const Block* SimpleBlock::GetBlock() const { return &m_block; }
7897 7109
7898 BlockGroup::BlockGroup(Cluster* pCluster, long idx, long long block_start, 7110 BlockGroup::BlockGroup(Cluster* pCluster, long idx, long long block_start,
7899 long long block_size, long long prev, long long next, 7111 long long block_size, long long prev, long long next,
7900 long long duration, long long discard_padding) 7112 long long duration, long long discard_padding)
7901 : BlockEntry(pCluster, idx), 7113 : BlockEntry(pCluster, idx),
7902 m_block(block_start, block_size, discard_padding), 7114 m_block(block_start, block_size, discard_padding),
7903 m_prev(prev), 7115 m_prev(prev),
7904 m_next(next), 7116 m_next(next),
7905 m_duration(duration) {} 7117 m_duration(duration) {}
7906 7118
7907 long BlockGroup::Parse() { 7119 long BlockGroup::Parse() {
7908 const long status = m_block.Parse(m_pCluster); 7120 const long status = m_block.Parse(m_pCluster);
7909 7121
7910 if (status) 7122 if (status)
7911 return status; 7123 return status;
7912 7124
7913 m_block.SetKey((m_prev > 0) && (m_next <= 0)); 7125 m_block.SetKey((m_prev > 0) && (m_next <= 0));
7914 7126
7915 return 0; 7127 return 0;
7916 } 7128 }
7917 7129
7918 #if 0
7919 void BlockGroup::ParseBlock(long long start, long long size)
7920 {
7921 IMkvReader* const pReader = m_pCluster->m_pSegment->m_pReader;
7922
7923 Block* const pBlock = new Block(start, size, pReader);
7924 assert(pBlock); //TODO
7925
7926 //TODO: the Matroska spec says you have multiple blocks within the
7927 //same block group, with blocks ranked by priority (the flag bits).
7928
7929 assert(m_pBlock == NULL);
7930 m_pBlock = pBlock;
7931 }
7932 #endif
7933
7934 BlockEntry::Kind BlockGroup::GetKind() const { return kBlockGroup; } 7130 BlockEntry::Kind BlockGroup::GetKind() const { return kBlockGroup; }
7935
7936 const Block* BlockGroup::GetBlock() const { return &m_block; } 7131 const Block* BlockGroup::GetBlock() const { return &m_block; }
7937
7938 long long BlockGroup::GetPrevTimeCode() const { return m_prev; } 7132 long long BlockGroup::GetPrevTimeCode() const { return m_prev; }
7939
7940 long long BlockGroup::GetNextTimeCode() const { return m_next; } 7133 long long BlockGroup::GetNextTimeCode() const { return m_next; }
7941
7942 long long BlockGroup::GetDurationTimeCode() const { return m_duration; } 7134 long long BlockGroup::GetDurationTimeCode() const { return m_duration; }
7943 7135
7944 Block::Block(long long start, long long size_, long long discard_padding) 7136 Block::Block(long long start, long long size_, long long discard_padding)
7945 : m_start(start), 7137 : m_start(start),
7946 m_size(size_), 7138 m_size(size_),
7947 m_track(0), 7139 m_track(0),
7948 m_timecode(-1), 7140 m_timecode(-1),
7949 m_flags(0), 7141 m_flags(0),
7950 m_frames(NULL), 7142 m_frames(NULL),
7951 m_frame_count(-1), 7143 m_frame_count(-1),
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
8021 return E_FILE_FORMAT_INVALID; 7213 return E_FILE_FORMAT_INVALID;
8022 7214
8023 m_frame_count = 1; 7215 m_frame_count = 1;
8024 m_frames = new Frame[m_frame_count]; 7216 m_frames = new Frame[m_frame_count];
8025 7217
8026 Frame& f = m_frames[0]; 7218 Frame& f = m_frames[0];
8027 f.pos = pos; 7219 f.pos = pos;
8028 7220
8029 const long long frame_size = stop - pos; 7221 const long long frame_size = stop - pos;
8030 7222
8031 if (frame_size > LONG_MAX) 7223 if (frame_size > LONG_MAX || frame_size <= 0)
8032 return E_FILE_FORMAT_INVALID; 7224 return E_FILE_FORMAT_INVALID;
8033 7225
8034 f.len = static_cast<long>(frame_size); 7226 f.len = static_cast<long>(frame_size);
8035 7227
8036 return 0; // success 7228 return 0; // success
8037 } 7229 }
8038 7230
8039 if (pos >= stop) 7231 if (pos >= stop)
8040 return E_FILE_FORMAT_INVALID; 7232 return E_FILE_FORMAT_INVALID;
8041 7233
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
8081 7273
8082 if (val < 255) 7274 if (val < 255)
8083 break; 7275 break;
8084 } 7276 }
8085 7277
8086 Frame& f = *pf++; 7278 Frame& f = *pf++;
8087 assert(pf < pf_end); 7279 assert(pf < pf_end);
8088 7280
8089 f.pos = 0; // patch later 7281 f.pos = 0; // patch later
8090 7282
7283 if (frame_size <= 0)
7284 return E_FILE_FORMAT_INVALID;
7285
8091 f.len = frame_size; 7286 f.len = frame_size;
8092 size += frame_size; // contribution of this frame 7287 size += frame_size; // contribution of this frame
8093 7288
8094 --frame_count; 7289 --frame_count;
8095 } 7290 }
8096 7291
8097 assert(pf < pf_end); 7292 assert(pf < pf_end);
8098 assert(pos <= stop); 7293 assert(pos <= stop);
8099 7294
8100 { 7295 {
8101 Frame& f = *pf++; 7296 Frame& f = *pf++;
8102 7297
8103 if (pf != pf_end) 7298 if (pf != pf_end)
8104 return E_FILE_FORMAT_INVALID; 7299 return E_FILE_FORMAT_INVALID;
8105 7300
8106 f.pos = 0; // patch later 7301 f.pos = 0; // patch later
8107 7302
8108 const long long total_size = stop - pos; 7303 const long long total_size = stop - pos;
8109 7304
8110 if (total_size < size) 7305 if (total_size < size)
8111 return E_FILE_FORMAT_INVALID; 7306 return E_FILE_FORMAT_INVALID;
8112 7307
8113 const long long frame_size = total_size - size; 7308 const long long frame_size = total_size - size;
8114 7309
8115 if (frame_size > LONG_MAX) 7310 if (frame_size > LONG_MAX || frame_size <= 0)
8116 return E_FILE_FORMAT_INVALID; 7311 return E_FILE_FORMAT_INVALID;
8117 7312
8118 f.len = static_cast<long>(frame_size); 7313 f.len = static_cast<long>(frame_size);
8119 } 7314 }
8120 7315
8121 pf = m_frames; 7316 pf = m_frames;
8122 while (pf != pf_end) { 7317 while (pf != pf_end) {
8123 Frame& f = *pf++; 7318 Frame& f = *pf++;
8124 assert((pos + f.len) <= stop); 7319 assert((pos + f.len) <= stop);
8125 7320
8126 f.pos = pos; 7321 f.pos = pos;
8127 pos += f.len; 7322 pos += f.len;
8128 } 7323 }
8129 7324
8130 assert(pos == stop); 7325 assert(pos == stop);
8131 } else if (lacing == 2) { // fixed-size lacing 7326 } else if (lacing == 2) { // fixed-size lacing
7327 if (pos >= stop)
7328 return E_FILE_FORMAT_INVALID;
7329
8132 const long long total_size = stop - pos; 7330 const long long total_size = stop - pos;
8133 7331
8134 if ((total_size % m_frame_count) != 0) 7332 if ((total_size % m_frame_count) != 0)
8135 return E_FILE_FORMAT_INVALID; 7333 return E_FILE_FORMAT_INVALID;
8136 7334
8137 const long long frame_size = total_size / m_frame_count; 7335 const long long frame_size = total_size / m_frame_count;
8138 7336
8139 if (frame_size > LONG_MAX) 7337 if (frame_size > LONG_MAX || frame_size <= 0)
8140 return E_FILE_FORMAT_INVALID; 7338 return E_FILE_FORMAT_INVALID;
8141 7339
8142 Frame* pf = m_frames; 7340 Frame* pf = m_frames;
8143 Frame* const pf_end = pf + m_frame_count; 7341 Frame* const pf_end = pf + m_frame_count;
8144 7342
8145 while (pf != pf_end) { 7343 while (pf != pf_end) {
8146 assert((pos + frame_size) <= stop); 7344 assert((pos + frame_size) <= stop);
8147 7345
8148 Frame& f = *pf++; 7346 Frame& f = *pf++;
8149 7347
8150 f.pos = pos; 7348 f.pos = pos;
8151 f.len = static_cast<long>(frame_size); 7349 f.len = static_cast<long>(frame_size);
8152 7350
8153 pos += frame_size; 7351 pos += frame_size;
8154 } 7352 }
8155 7353
8156 assert(pos == stop); 7354 assert(pos == stop);
8157 } else { 7355 } else {
8158 assert(lacing == 3); // EBML lacing 7356 assert(lacing == 3); // EBML lacing
8159 7357
8160 if (pos >= stop) 7358 if (pos >= stop)
8161 return E_FILE_FORMAT_INVALID; 7359 return E_FILE_FORMAT_INVALID;
8162 7360
8163 long size = 0; 7361 long size = 0;
8164 int frame_count = m_frame_count; 7362 int frame_count = m_frame_count;
8165 7363
8166 long long frame_size = ReadUInt(pReader, pos, len); 7364 long long frame_size = ReadUInt(pReader, pos, len);
8167 7365
8168 if (frame_size < 0) 7366 if (frame_size <= 0)
8169 return E_FILE_FORMAT_INVALID; 7367 return E_FILE_FORMAT_INVALID;
8170 7368
8171 if (frame_size > LONG_MAX) 7369 if (frame_size > LONG_MAX)
8172 return E_FILE_FORMAT_INVALID; 7370 return E_FILE_FORMAT_INVALID;
8173 7371
8174 if ((pos + len) > stop) 7372 if ((pos + len) > stop)
8175 return E_FILE_FORMAT_INVALID; 7373 return E_FILE_FORMAT_INVALID;
8176 7374
8177 pos += len; // consume length of size of first frame 7375 pos += len; // consume length of size of first frame
8178 7376
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
8220 7418
8221 pos += len; // consume length of (delta) size 7419 pos += len; // consume length of (delta) size
8222 assert(pos <= stop); 7420 assert(pos <= stop);
8223 7421
8224 const int exp = 7 * len - 1; 7422 const int exp = 7 * len - 1;
8225 const long long bias = (1LL << exp) - 1LL; 7423 const long long bias = (1LL << exp) - 1LL;
8226 const long long delta_size = delta_size_ - bias; 7424 const long long delta_size = delta_size_ - bias;
8227 7425
8228 frame_size += delta_size; 7426 frame_size += delta_size;
8229 7427
8230 if (frame_size < 0) 7428 if (frame_size <= 0)
8231 return E_FILE_FORMAT_INVALID; 7429 return E_FILE_FORMAT_INVALID;
8232 7430
8233 if (frame_size > LONG_MAX) 7431 if (frame_size > LONG_MAX)
8234 return E_FILE_FORMAT_INVALID; 7432 return E_FILE_FORMAT_INVALID;
8235 7433
8236 curr.len = static_cast<long>(frame_size); 7434 curr.len = static_cast<long>(frame_size);
8237 size += curr.len; // contribution of this frame 7435 size += curr.len; // contribution of this frame
8238 7436
8239 --frame_count; 7437 --frame_count;
8240 } 7438 }
8241 7439
8242 { 7440 // parse last frame
7441 if (frame_count > 0) {
8243 assert(pos <= stop); 7442 assert(pos <= stop);
8244 assert(pf < pf_end); 7443 assert(pf < pf_end);
8245 7444
8246 const Frame& prev = *pf++; 7445 const Frame& prev = *pf++;
8247 assert(prev.len == frame_size); 7446 assert(prev.len == frame_size);
8248 if (prev.len != frame_size) 7447 if (prev.len != frame_size)
8249 return E_FILE_FORMAT_INVALID; 7448 return E_FILE_FORMAT_INVALID;
8250 7449
8251 assert(pf < pf_end); 7450 assert(pf < pf_end);
8252 7451
8253 Frame& curr = *pf++; 7452 Frame& curr = *pf++;
8254 assert(pf == pf_end); 7453 assert(pf == pf_end);
8255 7454
8256 curr.pos = 0; // patch later 7455 curr.pos = 0; // patch later
8257 7456
8258 const long long total_size = stop - pos; 7457 const long long total_size = stop - pos;
8259 7458
8260 if (total_size < size) 7459 if (total_size < size)
8261 return E_FILE_FORMAT_INVALID; 7460 return E_FILE_FORMAT_INVALID;
8262 7461
8263 frame_size = total_size - size; 7462 frame_size = total_size - size;
8264 7463
8265 if (frame_size > LONG_MAX) 7464 if (frame_size > LONG_MAX || frame_size <= 0)
8266 return E_FILE_FORMAT_INVALID; 7465 return E_FILE_FORMAT_INVALID;
8267 7466
8268 curr.len = static_cast<long>(frame_size); 7467 curr.len = static_cast<long>(frame_size);
8269 } 7468 }
8270 7469
8271 pf = m_frames; 7470 pf = m_frames;
8272 while (pf != pf_end) { 7471 while (pf != pf_end) {
8273 Frame& f = *pf++; 7472 Frame& f = *pf++;
8274 assert((pos + f.len) <= stop); 7473 assert((pos + f.len) <= stop);
8275 7474
8276 f.pos = pos; 7475 f.pos = pos;
8277 pos += f.len; 7476 pos += f.len;
8278 } 7477 }
8279 7478
8280 assert(pos == stop); 7479 if (pos != stop)
7480 return E_FILE_FORMAT_INVALID;
8281 } 7481 }
8282 7482
8283 return 0; // success 7483 return 0; // success
8284 } 7484 }
8285 7485
8286 long long Block::GetTimeCode(const Cluster* pCluster) const { 7486 long long Block::GetTimeCode(const Cluster* pCluster) const {
8287 if (pCluster == 0) 7487 if (pCluster == 0)
8288 return m_timecode; 7488 return m_timecode;
8289 7489
8290 const long long tc0 = pCluster->GetTimeCode(); 7490 const long long tc0 = pCluster->GetTimeCode();
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
8349 assert(pReader); 7549 assert(pReader);
8350 assert(buf); 7550 assert(buf);
8351 7551
8352 const long status = pReader->Read(pos, len, buf); 7552 const long status = pReader->Read(pos, len, buf);
8353 return status; 7553 return status;
8354 } 7554 }
8355 7555
8356 long long Block::GetDiscardPadding() const { return m_discard_padding; } 7556 long long Block::GetDiscardPadding() const { return m_discard_padding; }
8357 7557
8358 } // end namespace mkvparser 7558 } // end namespace mkvparser
OLDNEW
« no previous file with comments | « source/libvpx/third_party/libwebm/mkvparser.hpp ('k') | source/libvpx/third_party/libwebm/webmids.hpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698