1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "media/webm/webm_parser.h" 6 7 // This file contains code to parse WebM file elements. It was created 8 // from information in the Matroska spec. 9 // http://www.matroska.org/technical/specs/index.html 10 // This file contains code for encrypted WebM. Current WebM 11 // encrypted request for comments specification is here 12 // http://wiki.webmproject.org/encryption/webm-encryption-rfc 13 14 #include <iomanip> 15 16 #include "base/logging.h" 17 #include "media/webm/webm_constants.h" 18 19 namespace media { 20 21 enum ElementType { 22 UNKNOWN, 23 LIST, // Referred to as Master Element in the Matroska spec. 24 UINT, 25 FLOAT, 26 BINARY, 27 STRING, 28 SKIP, 29 }; 30 31 struct ElementIdInfo { 32 ElementType type_; 33 int id_; 34 }; 35 36 struct ListElementInfo { 37 int id_; 38 int level_; 39 const ElementIdInfo* id_info_; 40 int id_info_count_; 41 }; 42 43 // The following are tables indicating what IDs are valid sub-elements 44 // of particular elements. If an element is encountered that doesn't 45 // appear in the list, a parsing error is signalled. Some elements are 46 // marked as SKIP because they are valid, but we don't care about them 47 // right now. 48 static const ElementIdInfo kEBMLHeaderIds[] = { 49 {UINT, kWebMIdEBMLVersion}, 50 {UINT, kWebMIdEBMLReadVersion}, 51 {UINT, kWebMIdEBMLMaxIDLength}, 52 {UINT, kWebMIdEBMLMaxSizeLength}, 53 {STRING, kWebMIdDocType}, 54 {UINT, kWebMIdDocTypeVersion}, 55 {UINT, kWebMIdDocTypeReadVersion}, 56 }; 57 58 static const ElementIdInfo kSegmentIds[] = { 59 {LIST, kWebMIdSeekHead}, 60 {LIST, kWebMIdInfo}, 61 {LIST, kWebMIdCluster}, 62 {LIST, kWebMIdTracks}, 63 {LIST, kWebMIdCues}, 64 {LIST, kWebMIdAttachments}, 65 {LIST, kWebMIdChapters}, 66 {LIST, kWebMIdTags}, 67 }; 68 69 static const ElementIdInfo kSeekHeadIds[] = { 70 {LIST, kWebMIdSeek}, 71 }; 72 73 static const ElementIdInfo kSeekIds[] = { 74 {BINARY, kWebMIdSeekID}, 75 {UINT, kWebMIdSeekPosition}, 76 }; 77 78 static const ElementIdInfo kInfoIds[] = { 79 {BINARY, kWebMIdSegmentUID}, 80 {STRING, kWebMIdSegmentFilename}, 81 {BINARY, kWebMIdPrevUID}, 82 {STRING, kWebMIdPrevFilename}, 83 {BINARY, kWebMIdNextUID}, 84 {STRING, kWebMIdNextFilename}, 85 {BINARY, kWebMIdSegmentFamily}, 86 {LIST, kWebMIdChapterTranslate}, 87 {UINT, kWebMIdTimecodeScale}, 88 {FLOAT, kWebMIdDuration}, 89 {BINARY, kWebMIdDateUTC}, 90 {STRING, kWebMIdTitle}, 91 {STRING, kWebMIdMuxingApp}, 92 {STRING, kWebMIdWritingApp}, 93 }; 94 95 static const ElementIdInfo kChapterTranslateIds[] = { 96 {UINT, kWebMIdChapterTranslateEditionUID}, 97 {UINT, kWebMIdChapterTranslateCodec}, 98 {BINARY, kWebMIdChapterTranslateID}, 99 }; 100 101 static const ElementIdInfo kClusterIds[] = { 102 {BINARY, kWebMIdSimpleBlock}, 103 {UINT, kWebMIdTimecode}, 104 {LIST, kWebMIdSilentTracks}, 105 {UINT, kWebMIdPosition}, 106 {UINT, kWebMIdPrevSize}, 107 {LIST, kWebMIdBlockGroup}, 108 }; 109 110 static const ElementIdInfo kSilentTracksIds[] = { 111 {UINT, kWebMIdSilentTrackNumber}, 112 }; 113 114 static const ElementIdInfo kBlockGroupIds[] = { 115 {BINARY, kWebMIdBlock}, 116 {LIST, kWebMIdBlockAdditions}, 117 {UINT, kWebMIdBlockDuration}, 118 {UINT, kWebMIdReferencePriority}, 119 {BINARY, kWebMIdReferenceBlock}, 120 {BINARY, kWebMIdCodecState}, 121 {UINT, kWebMIdDiscardPadding}, 122 {LIST, kWebMIdSlices}, 123 }; 124 125 static const ElementIdInfo kBlockAdditionsIds[] = { 126 {LIST, kWebMIdBlockMore}, 127 }; 128 129 static const ElementIdInfo kBlockMoreIds[] = { 130 {UINT, kWebMIdBlockAddID}, 131 {BINARY, kWebMIdBlockAdditional}, 132 }; 133 134 static const ElementIdInfo kSlicesIds[] = { 135 {LIST, kWebMIdTimeSlice}, 136 }; 137 138 static const ElementIdInfo kTimeSliceIds[] = { 139 {UINT, kWebMIdLaceNumber}, 140 }; 141 142 static const ElementIdInfo kTracksIds[] = { 143 {LIST, kWebMIdTrackEntry}, 144 }; 145 146 static const ElementIdInfo kTrackEntryIds[] = { 147 {UINT, kWebMIdTrackNumber}, 148 {UINT, kWebMIdTrackUID}, 149 {UINT, kWebMIdTrackType}, 150 {UINT, kWebMIdFlagEnabled}, 151 {UINT, kWebMIdFlagDefault}, 152 {UINT, kWebMIdFlagForced}, 153 {UINT, kWebMIdFlagLacing}, 154 {UINT, kWebMIdMinCache}, 155 {UINT, kWebMIdMaxCache}, 156 {UINT, kWebMIdDefaultDuration}, 157 {FLOAT, kWebMIdTrackTimecodeScale}, 158 {UINT, kWebMIdMaxBlockAdditionId}, 159 {STRING, kWebMIdName}, 160 {STRING, kWebMIdLanguage}, 161 {STRING, kWebMIdCodecID}, 162 {BINARY, kWebMIdCodecPrivate}, 163 {STRING, kWebMIdCodecName}, 164 {UINT, kWebMIdAttachmentLink}, 165 {UINT, kWebMIdCodecDecodeAll}, 166 {UINT, kWebMIdTrackOverlay}, 167 {UINT, kWebMIdCodecDelay}, 168 {UINT, kWebMIdSeekPreRoll}, 169 {LIST, kWebMIdTrackTranslate}, 170 {LIST, kWebMIdVideo}, 171 {LIST, kWebMIdAudio}, 172 {LIST, kWebMIdTrackOperation}, 173 {LIST, kWebMIdContentEncodings}, 174 }; 175 176 static const ElementIdInfo kTrackTranslateIds[] = { 177 {UINT, kWebMIdTrackTranslateEditionUID}, 178 {UINT, kWebMIdTrackTranslateCodec}, 179 {BINARY, kWebMIdTrackTranslateTrackID}, 180 }; 181 182 static const ElementIdInfo kVideoIds[] = { 183 {UINT, kWebMIdFlagInterlaced}, 184 {UINT, kWebMIdStereoMode}, 185 {UINT, kWebMIdAlphaMode}, 186 {UINT, kWebMIdPixelWidth}, 187 {UINT, kWebMIdPixelHeight}, 188 {UINT, kWebMIdPixelCropBottom}, 189 {UINT, kWebMIdPixelCropTop}, 190 {UINT, kWebMIdPixelCropLeft}, 191 {UINT, kWebMIdPixelCropRight}, 192 {UINT, kWebMIdDisplayWidth}, 193 {UINT, kWebMIdDisplayHeight}, 194 {UINT, kWebMIdDisplayUnit}, 195 {UINT, kWebMIdAspectRatioType}, 196 {BINARY, kWebMIdColorSpace}, 197 {FLOAT, kWebMIdFrameRate}, 198 }; 199 200 static const ElementIdInfo kAudioIds[] = { 201 {FLOAT, kWebMIdSamplingFrequency}, 202 {FLOAT, kWebMIdOutputSamplingFrequency}, 203 {UINT, kWebMIdChannels}, 204 {UINT, kWebMIdBitDepth}, 205 }; 206 207 static const ElementIdInfo kTrackOperationIds[] = { 208 {LIST, kWebMIdTrackCombinePlanes}, 209 {LIST, kWebMIdJoinBlocks}, 210 }; 211 212 static const ElementIdInfo kTrackCombinePlanesIds[] = { 213 {LIST, kWebMIdTrackPlane}, 214 }; 215 216 static const ElementIdInfo kTrackPlaneIds[] = { 217 {UINT, kWebMIdTrackPlaneUID}, 218 {UINT, kWebMIdTrackPlaneType}, 219 }; 220 221 static const ElementIdInfo kJoinBlocksIds[] = { 222 {UINT, kWebMIdTrackJoinUID}, 223 }; 224 225 static const ElementIdInfo kContentEncodingsIds[] = { 226 {LIST, kWebMIdContentEncoding}, 227 }; 228 229 static const ElementIdInfo kContentEncodingIds[] = { 230 {UINT, kWebMIdContentEncodingOrder}, 231 {UINT, kWebMIdContentEncodingScope}, 232 {UINT, kWebMIdContentEncodingType}, 233 {LIST, kWebMIdContentCompression}, 234 {LIST, kWebMIdContentEncryption}, 235 }; 236 237 static const ElementIdInfo kContentCompressionIds[] = { 238 {UINT, kWebMIdContentCompAlgo}, 239 {BINARY, kWebMIdContentCompSettings}, 240 }; 241 242 static const ElementIdInfo kContentEncryptionIds[] = { 243 {LIST, kWebMIdContentEncAESSettings}, 244 {UINT, kWebMIdContentEncAlgo}, 245 {BINARY, kWebMIdContentEncKeyID}, 246 {BINARY, kWebMIdContentSignature}, 247 {BINARY, kWebMIdContentSigKeyID}, 248 {UINT, kWebMIdContentSigAlgo}, 249 {UINT, kWebMIdContentSigHashAlgo}, 250 }; 251 252 static const ElementIdInfo kContentEncAESSettingsIds[] = { 253 {UINT, kWebMIdAESSettingsCipherMode}, 254 }; 255 256 static const ElementIdInfo kCuesIds[] = { 257 {LIST, kWebMIdCuePoint}, 258 }; 259 260 static const ElementIdInfo kCuePointIds[] = { 261 {UINT, kWebMIdCueTime}, 262 {LIST, kWebMIdCueTrackPositions}, 263 }; 264 265 static const ElementIdInfo kCueTrackPositionsIds[] = { 266 {UINT, kWebMIdCueTrack}, 267 {UINT, kWebMIdCueClusterPosition}, 268 {UINT, kWebMIdCueBlockNumber}, 269 {UINT, kWebMIdCueCodecState}, 270 {LIST, kWebMIdCueReference}, 271 }; 272 273 static const ElementIdInfo kCueReferenceIds[] = { 274 {UINT, kWebMIdCueRefTime}, 275 }; 276 277 static const ElementIdInfo kAttachmentsIds[] = { 278 {LIST, kWebMIdAttachedFile}, 279 }; 280 281 static const ElementIdInfo kAttachedFileIds[] = { 282 {STRING, kWebMIdFileDescription}, 283 {STRING, kWebMIdFileName}, 284 {STRING, kWebMIdFileMimeType}, 285 {BINARY, kWebMIdFileData}, 286 {UINT, kWebMIdFileUID}, 287 }; 288 289 static const ElementIdInfo kChaptersIds[] = { 290 {LIST, kWebMIdEditionEntry}, 291 }; 292 293 static const ElementIdInfo kEditionEntryIds[] = { 294 {UINT, kWebMIdEditionUID}, 295 {UINT, kWebMIdEditionFlagHidden}, 296 {UINT, kWebMIdEditionFlagDefault}, 297 {UINT, kWebMIdEditionFlagOrdered}, 298 {LIST, kWebMIdChapterAtom}, 299 }; 300 301 static const ElementIdInfo kChapterAtomIds[] = { 302 {UINT, kWebMIdChapterUID}, 303 {UINT, kWebMIdChapterTimeStart}, 304 {UINT, kWebMIdChapterTimeEnd}, 305 {UINT, kWebMIdChapterFlagHidden}, 306 {UINT, kWebMIdChapterFlagEnabled}, 307 {BINARY, kWebMIdChapterSegmentUID}, 308 {UINT, kWebMIdChapterSegmentEditionUID}, 309 {UINT, kWebMIdChapterPhysicalEquiv}, 310 {LIST, kWebMIdChapterTrack}, 311 {LIST, kWebMIdChapterDisplay}, 312 {LIST, kWebMIdChapProcess}, 313 }; 314 315 static const ElementIdInfo kChapterTrackIds[] = { 316 {UINT, kWebMIdChapterTrackNumber}, 317 }; 318 319 static const ElementIdInfo kChapterDisplayIds[] = { 320 {STRING, kWebMIdChapString}, 321 {STRING, kWebMIdChapLanguage}, 322 {STRING, kWebMIdChapCountry}, 323 }; 324 325 static const ElementIdInfo kChapProcessIds[] = { 326 {UINT, kWebMIdChapProcessCodecID}, 327 {BINARY, kWebMIdChapProcessPrivate}, 328 {LIST, kWebMIdChapProcessCommand}, 329 }; 330 331 static const ElementIdInfo kChapProcessCommandIds[] = { 332 {UINT, kWebMIdChapProcessTime}, 333 {BINARY, kWebMIdChapProcessData}, 334 }; 335 336 static const ElementIdInfo kTagsIds[] = { 337 {LIST, kWebMIdTag}, 338 }; 339 340 static const ElementIdInfo kTagIds[] = { 341 {LIST, kWebMIdTargets}, 342 {LIST, kWebMIdSimpleTag}, 343 }; 344 345 static const ElementIdInfo kTargetsIds[] = { 346 {UINT, kWebMIdTargetTypeValue}, 347 {STRING, kWebMIdTargetType}, 348 {UINT, kWebMIdTagTrackUID}, 349 {UINT, kWebMIdTagEditionUID}, 350 {UINT, kWebMIdTagChapterUID}, 351 {UINT, kWebMIdTagAttachmentUID}, 352 }; 353 354 static const ElementIdInfo kSimpleTagIds[] = { 355 {STRING, kWebMIdTagName}, 356 {STRING, kWebMIdTagLanguage}, 357 {UINT, kWebMIdTagDefault}, 358 {STRING, kWebMIdTagString}, 359 {BINARY, kWebMIdTagBinary}, 360 }; 361 362 #define LIST_ELEMENT_INFO(id, level, id_info) \ 363 { (id), (level), (id_info), arraysize(id_info) } 364 365 static const ListElementInfo kListElementInfo[] = { 366 LIST_ELEMENT_INFO(kWebMIdCluster, 1, kClusterIds), 367 LIST_ELEMENT_INFO(kWebMIdEBMLHeader, 0, kEBMLHeaderIds), 368 LIST_ELEMENT_INFO(kWebMIdSegment, 0, kSegmentIds), 369 LIST_ELEMENT_INFO(kWebMIdSeekHead, 1, kSeekHeadIds), 370 LIST_ELEMENT_INFO(kWebMIdSeek, 2, kSeekIds), 371 LIST_ELEMENT_INFO(kWebMIdInfo, 1, kInfoIds), 372 LIST_ELEMENT_INFO(kWebMIdChapterTranslate, 2, kChapterTranslateIds), 373 LIST_ELEMENT_INFO(kWebMIdSilentTracks, 2, kSilentTracksIds), 374 LIST_ELEMENT_INFO(kWebMIdBlockGroup, 2, kBlockGroupIds), 375 LIST_ELEMENT_INFO(kWebMIdBlockAdditions, 3, kBlockAdditionsIds), 376 LIST_ELEMENT_INFO(kWebMIdBlockMore, 4, kBlockMoreIds), 377 LIST_ELEMENT_INFO(kWebMIdSlices, 3, kSlicesIds), 378 LIST_ELEMENT_INFO(kWebMIdTimeSlice, 4, kTimeSliceIds), 379 LIST_ELEMENT_INFO(kWebMIdTracks, 1, kTracksIds), 380 LIST_ELEMENT_INFO(kWebMIdTrackEntry, 2, kTrackEntryIds), 381 LIST_ELEMENT_INFO(kWebMIdTrackTranslate, 3, kTrackTranslateIds), 382 LIST_ELEMENT_INFO(kWebMIdVideo, 3, kVideoIds), 383 LIST_ELEMENT_INFO(kWebMIdAudio, 3, kAudioIds), 384 LIST_ELEMENT_INFO(kWebMIdTrackOperation, 3, kTrackOperationIds), 385 LIST_ELEMENT_INFO(kWebMIdTrackCombinePlanes, 4, kTrackCombinePlanesIds), 386 LIST_ELEMENT_INFO(kWebMIdTrackPlane, 5, kTrackPlaneIds), 387 LIST_ELEMENT_INFO(kWebMIdJoinBlocks, 4, kJoinBlocksIds), 388 LIST_ELEMENT_INFO(kWebMIdContentEncodings, 3, kContentEncodingsIds), 389 LIST_ELEMENT_INFO(kWebMIdContentEncoding, 4, kContentEncodingIds), 390 LIST_ELEMENT_INFO(kWebMIdContentCompression, 5, kContentCompressionIds), 391 LIST_ELEMENT_INFO(kWebMIdContentEncryption, 5, kContentEncryptionIds), 392 LIST_ELEMENT_INFO(kWebMIdContentEncAESSettings, 6, kContentEncAESSettingsIds), 393 LIST_ELEMENT_INFO(kWebMIdCues, 1, kCuesIds), 394 LIST_ELEMENT_INFO(kWebMIdCuePoint, 2, kCuePointIds), 395 LIST_ELEMENT_INFO(kWebMIdCueTrackPositions, 3, kCueTrackPositionsIds), 396 LIST_ELEMENT_INFO(kWebMIdCueReference, 4, kCueReferenceIds), 397 LIST_ELEMENT_INFO(kWebMIdAttachments, 1, kAttachmentsIds), 398 LIST_ELEMENT_INFO(kWebMIdAttachedFile, 2, kAttachedFileIds), 399 LIST_ELEMENT_INFO(kWebMIdChapters, 1, kChaptersIds), 400 LIST_ELEMENT_INFO(kWebMIdEditionEntry, 2, kEditionEntryIds), 401 LIST_ELEMENT_INFO(kWebMIdChapterAtom, 3, kChapterAtomIds), 402 LIST_ELEMENT_INFO(kWebMIdChapterTrack, 4, kChapterTrackIds), 403 LIST_ELEMENT_INFO(kWebMIdChapterDisplay, 4, kChapterDisplayIds), 404 LIST_ELEMENT_INFO(kWebMIdChapProcess, 4, kChapProcessIds), 405 LIST_ELEMENT_INFO(kWebMIdChapProcessCommand, 5, kChapProcessCommandIds), 406 LIST_ELEMENT_INFO(kWebMIdTags, 1, kTagsIds), 407 LIST_ELEMENT_INFO(kWebMIdTag, 2, kTagIds), 408 LIST_ELEMENT_INFO(kWebMIdTargets, 3, kTargetsIds), 409 LIST_ELEMENT_INFO(kWebMIdSimpleTag, 3, kSimpleTagIds), 410 }; 411 412 // Parses an element header id or size field. These fields are variable length 413 // encoded. The first byte indicates how many bytes the field occupies. 414 // |buf| - The buffer to parse. 415 // |size| - The number of bytes in |buf| 416 // |max_bytes| - The maximum number of bytes the field can be. ID fields 417 // set this to 4 & element size fields set this to 8. If the 418 // first byte indicates a larger field size than this it is a 419 // parser error. 420 // |mask_first_byte| - For element size fields the field length encoding bits 421 // need to be masked off. This parameter is true for 422 // element size fields and is false for ID field values. 423 // 424 // Returns: The number of bytes parsed on success. -1 on error. 425 static int ParseWebMElementHeaderField(const uint8* buf, int size, 426 int max_bytes, bool mask_first_byte, 427 int64* num) { 428 DCHECK(buf); 429 DCHECK(num); 430 431 if (size < 0) 432 return -1; 433 434 if (size == 0) 435 return 0; 436 437 int mask = 0x80; 438 uint8 ch = buf[0]; 439 int extra_bytes = -1; 440 bool all_ones = false; 441 for (int i = 0; i < max_bytes; ++i) { 442 if ((ch & mask) != 0) { 443 mask = ~mask & 0xff; 444 *num = mask_first_byte ? ch & mask : ch; 445 all_ones = (ch & mask) == mask; 446 extra_bytes = i; 447 break; 448 } 449 mask = 0x80 | mask >> 1; 450 } 451 452 if (extra_bytes == -1) 453 return -1; 454 455 // Return 0 if we need more data. 456 if ((1 + extra_bytes) > size) 457 return 0; 458 459 int bytes_used = 1; 460 461 for (int i = 0; i < extra_bytes; ++i) { 462 ch = buf[bytes_used++]; 463 all_ones &= (ch == 0xff); 464 *num = (*num << 8) | ch; 465 } 466 467 if (all_ones) 468 *num = kint64max; 469 470 return bytes_used; 471 } 472 473 int WebMParseElementHeader(const uint8* buf, int size, 474 int* id, int64* element_size) { 475 DCHECK(buf); 476 DCHECK_GE(size, 0); 477 DCHECK(id); 478 DCHECK(element_size); 479 480 if (size == 0) 481 return 0; 482 483 int64 tmp = 0; 484 int num_id_bytes = ParseWebMElementHeaderField(buf, size, 4, false, &tmp); 485 486 if (num_id_bytes <= 0) 487 return num_id_bytes; 488 489 if (tmp == kint64max) 490 tmp = kWebMReservedId; 491 492 *id = static_cast<int>(tmp); 493 494 int num_size_bytes = ParseWebMElementHeaderField(buf + num_id_bytes, 495 size - num_id_bytes, 496 8, true, &tmp); 497 498 if (num_size_bytes <= 0) 499 return num_size_bytes; 500 501 if (tmp == kint64max) 502 tmp = kWebMUnknownSize; 503 504 *element_size = tmp; 505 DVLOG(3) << "WebMParseElementHeader() : id " << std::hex << *id << std::dec 506 << " size " << *element_size; 507 return num_id_bytes + num_size_bytes; 508 } 509 510 // Finds ElementType for a specific ID. 511 static ElementType FindIdType(int id, 512 const ElementIdInfo* id_info, 513 int id_info_count) { 514 515 // Check for global element IDs that can be anywhere. 516 if (id == kWebMIdVoid || id == kWebMIdCRC32) 517 return SKIP; 518 519 for (int i = 0; i < id_info_count; ++i) { 520 if (id == id_info[i].id_) 521 return id_info[i].type_; 522 } 523 524 return UNKNOWN; 525 } 526 527 // Finds ListElementInfo for a specific ID. 528 static const ListElementInfo* FindListInfo(int id) { 529 for (size_t i = 0; i < arraysize(kListElementInfo); ++i) { 530 if (id == kListElementInfo[i].id_) 531 return &kListElementInfo[i]; 532 } 533 534 return NULL; 535 } 536 537 static int FindListLevel(int id) { 538 const ListElementInfo* list_info = FindListInfo(id); 539 if (list_info) 540 return list_info->level_; 541 542 return -1; 543 } 544 545 static int ParseUInt(const uint8* buf, int size, int id, 546 WebMParserClient* client) { 547 if ((size <= 0) || (size > 8)) 548 return -1; 549 550 // Read in the big-endian integer. 551 int64 value = 0; 552 for (int i = 0; i < size; ++i) 553 value = (value << 8) | buf[i]; 554 555 if (!client->OnUInt(id, value)) 556 return -1; 557 558 return size; 559 } 560 561 static int ParseFloat(const uint8* buf, int size, int id, 562 WebMParserClient* client) { 563 564 if ((size != 4) && (size != 8)) 565 return -1; 566 567 double value = -1; 568 569 // Read the bytes from big-endian form into a native endian integer. 570 int64 tmp = 0; 571 for (int i = 0; i < size; ++i) 572 tmp = (tmp << 8) | buf[i]; 573 574 // Use a union to convert the integer bit pattern into a floating point 575 // number. 576 if (size == 4) { 577 union { 578 int32 src; 579 float dst; 580 } tmp2; 581 tmp2.src = static_cast<int32>(tmp); 582 value = tmp2.dst; 583 } else if (size == 8) { 584 union { 585 int64 src; 586 double dst; 587 } tmp2; 588 tmp2.src = tmp; 589 value = tmp2.dst; 590 } else { 591 return -1; 592 } 593 594 if (!client->OnFloat(id, value)) 595 return -1; 596 597 return size; 598 } 599 600 static int ParseBinary(const uint8* buf, int size, int id, 601 WebMParserClient* client) { 602 return client->OnBinary(id, buf, size) ? size : -1; 603 } 604 605 static int ParseString(const uint8* buf, int size, int id, 606 WebMParserClient* client) { 607 const uint8* end = static_cast<const uint8*>(memchr(buf, '\0', size)); 608 int length = (end != NULL) ? static_cast<int>(end - buf) : size; 609 std::string str(reinterpret_cast<const char*>(buf), length); 610 return client->OnString(id, str) ? size : -1; 611 } 612 613 static int ParseNonListElement(ElementType type, int id, int64 element_size, 614 const uint8* buf, int size, 615 WebMParserClient* client) { 616 DCHECK_GE(size, element_size); 617 618 int result = -1; 619 switch(type) { 620 case LIST: 621 NOTIMPLEMENTED(); 622 result = -1; 623 break; 624 case UINT: 625 result = ParseUInt(buf, element_size, id, client); 626 break; 627 case FLOAT: 628 result = ParseFloat(buf, element_size, id, client); 629 break; 630 case BINARY: 631 result = ParseBinary(buf, element_size, id, client); 632 break; 633 case STRING: 634 result = ParseString(buf, element_size, id, client); 635 break; 636 case SKIP: 637 result = element_size; 638 break; 639 default: 640 DVLOG(1) << "Unhandled ID type " << type; 641 return -1; 642 }; 643 644 DCHECK_LE(result, size); 645 return result; 646 } 647 648 WebMParserClient::WebMParserClient() {} 649 WebMParserClient::~WebMParserClient() {} 650 651 WebMParserClient* WebMParserClient::OnListStart(int id) { 652 DVLOG(1) << "Unexpected list element start with ID " << std::hex << id; 653 return NULL; 654 } 655 656 bool WebMParserClient::OnListEnd(int id) { 657 DVLOG(1) << "Unexpected list element end with ID " << std::hex << id; 658 return false; 659 } 660 661 bool WebMParserClient::OnUInt(int id, int64 val) { 662 DVLOG(1) << "Unexpected unsigned integer element with ID " << std::hex << id; 663 return false; 664 } 665 666 bool WebMParserClient::OnFloat(int id, double val) { 667 DVLOG(1) << "Unexpected float element with ID " << std::hex << id; 668 return false; 669 } 670 671 bool WebMParserClient::OnBinary(int id, const uint8* data, int size) { 672 DVLOG(1) << "Unexpected binary element with ID " << std::hex << id; 673 return false; 674 } 675 676 bool WebMParserClient::OnString(int id, const std::string& str) { 677 DVLOG(1) << "Unexpected string element with ID " << std::hex << id; 678 return false; 679 } 680 681 WebMListParser::WebMListParser(int id, WebMParserClient* client) 682 : state_(NEED_LIST_HEADER), 683 root_id_(id), 684 root_level_(FindListLevel(id)), 685 root_client_(client) { 686 DCHECK_GE(root_level_, 0); 687 DCHECK(client); 688 } 689 690 WebMListParser::~WebMListParser() {} 691 692 void WebMListParser::Reset() { 693 ChangeState(NEED_LIST_HEADER); 694 list_state_stack_.clear(); 695 } 696 697 int WebMListParser::Parse(const uint8* buf, int size) { 698 DCHECK(buf); 699 700 if (size < 0 || state_ == PARSE_ERROR || state_ == DONE_PARSING_LIST) 701 return -1; 702 703 if (size == 0) 704 return 0; 705 706 const uint8* cur = buf; 707 int cur_size = size; 708 int bytes_parsed = 0; 709 710 while (cur_size > 0 && state_ != PARSE_ERROR && state_ != DONE_PARSING_LIST) { 711 int element_id = 0; 712 int64 element_size = 0; 713 int result = WebMParseElementHeader(cur, cur_size, &element_id, 714 &element_size); 715 716 if (result < 0) 717 return result; 718 719 if (result == 0) 720 return bytes_parsed; 721 722 switch(state_) { 723 case NEED_LIST_HEADER: { 724 if (element_id != root_id_) { 725 ChangeState(PARSE_ERROR); 726 return -1; 727 } 728 729 // Only allow Segment & Cluster to have an unknown size. 730 if (element_size == kWebMUnknownSize && 731 (element_id != kWebMIdSegment) && 732 (element_id != kWebMIdCluster)) { 733 ChangeState(PARSE_ERROR); 734 return -1; 735 } 736 737 ChangeState(INSIDE_LIST); 738 if (!OnListStart(root_id_, element_size)) 739 return -1; 740 741 break; 742 } 743 744 case INSIDE_LIST: { 745 int header_size = result; 746 const uint8* element_data = cur + header_size; 747 int element_data_size = cur_size - header_size; 748 749 if (element_size < element_data_size) 750 element_data_size = element_size; 751 752 result = ParseListElement(header_size, element_id, element_size, 753 element_data, element_data_size); 754 755 DCHECK_LE(result, header_size + element_data_size); 756 if (result < 0) { 757 ChangeState(PARSE_ERROR); 758 return -1; 759 } 760 761 if (result == 0) 762 return bytes_parsed; 763 764 break; 765 } 766 case DONE_PARSING_LIST: 767 case PARSE_ERROR: 768 // Shouldn't be able to get here. 769 NOTIMPLEMENTED(); 770 break; 771 } 772 773 cur += result; 774 cur_size -= result; 775 bytes_parsed += result; 776 } 777 778 return (state_ == PARSE_ERROR) ? -1 : bytes_parsed; 779 } 780 781 bool WebMListParser::IsParsingComplete() const { 782 return state_ == DONE_PARSING_LIST; 783 } 784 785 void WebMListParser::ChangeState(State new_state) { 786 state_ = new_state; 787 } 788 789 int WebMListParser::ParseListElement(int header_size, 790 int id, int64 element_size, 791 const uint8* data, int size) { 792 DCHECK_GT(list_state_stack_.size(), 0u); 793 794 ListState& list_state = list_state_stack_.back(); 795 DCHECK(list_state.element_info_); 796 797 const ListElementInfo* element_info = list_state.element_info_; 798 ElementType id_type = 799 FindIdType(id, element_info->id_info_, element_info->id_info_count_); 800 801 // Unexpected ID. 802 if (id_type == UNKNOWN) { 803 if (list_state.size_ != kWebMUnknownSize || 804 !IsSiblingOrAncestor(list_state.id_, id)) { 805 DVLOG(1) << "No ElementType info for ID 0x" << std::hex << id; 806 return -1; 807 } 808 809 // We've reached the end of a list of unknown size. Update the size now that 810 // we know it and dispatch the end of list calls. 811 list_state.size_ = list_state.bytes_parsed_; 812 813 if (!OnListEnd()) 814 return -1; 815 816 // Check to see if all open lists have ended. 817 if (list_state_stack_.size() == 0) 818 return 0; 819 820 list_state = list_state_stack_.back(); 821 } 822 823 // Make sure the whole element can fit inside the current list. 824 int64 total_element_size = header_size + element_size; 825 if (list_state.size_ != kWebMUnknownSize && 826 list_state.size_ < list_state.bytes_parsed_ + total_element_size) { 827 return -1; 828 } 829 830 if (id_type == LIST) { 831 list_state.bytes_parsed_ += header_size; 832 833 if (!OnListStart(id, element_size)) 834 return -1; 835 return header_size; 836 } 837 838 // Make sure we have the entire element before trying to parse a non-list 839 // element. 840 if (size < element_size) 841 return 0; 842 843 int bytes_parsed = ParseNonListElement(id_type, id, element_size, 844 data, size, list_state.client_); 845 DCHECK_LE(bytes_parsed, size); 846 847 // Return if an error occurred or we need more data. 848 // Note: bytes_parsed is 0 for a successful parse of a size 0 element. We 849 // need to check the element_size to disambiguate the "need more data" case 850 // from a successful parse. 851 if (bytes_parsed < 0 || (bytes_parsed == 0 && element_size != 0)) 852 return bytes_parsed; 853 854 int result = header_size + bytes_parsed; 855 list_state.bytes_parsed_ += result; 856 857 // See if we have reached the end of the current list. 858 if (list_state.bytes_parsed_ == list_state.size_) { 859 if (!OnListEnd()) 860 return -1; 861 } 862 863 return result; 864 } 865 866 bool WebMListParser::OnListStart(int id, int64 size) { 867 const ListElementInfo* element_info = FindListInfo(id); 868 if (!element_info) 869 return false; 870 871 int current_level = root_level_ + list_state_stack_.size() - 1; 872 if (current_level + 1 != element_info->level_) 873 return false; 874 875 WebMParserClient* current_list_client = NULL; 876 if (!list_state_stack_.empty()) { 877 // Make sure the new list doesn't go past the end of the current list. 878 ListState current_list_state = list_state_stack_.back(); 879 if (current_list_state.size_ != kWebMUnknownSize && 880 current_list_state.size_ < current_list_state.bytes_parsed_ + size) 881 return false; 882 current_list_client = current_list_state.client_; 883 } else { 884 current_list_client = root_client_; 885 } 886 887 WebMParserClient* new_list_client = current_list_client->OnListStart(id); 888 if (!new_list_client) 889 return false; 890 891 ListState new_list_state = { id, size, 0, element_info, new_list_client }; 892 list_state_stack_.push_back(new_list_state); 893 894 if (size == 0) 895 return OnListEnd(); 896 897 return true; 898 } 899 900 bool WebMListParser::OnListEnd() { 901 int lists_ended = 0; 902 for (; !list_state_stack_.empty(); ++lists_ended) { 903 const ListState& list_state = list_state_stack_.back(); 904 905 if (list_state.bytes_parsed_ != list_state.size_) 906 break; 907 908 list_state_stack_.pop_back(); 909 910 int64 bytes_parsed = list_state.bytes_parsed_; 911 WebMParserClient* client = NULL; 912 if (!list_state_stack_.empty()) { 913 // Update the bytes_parsed_ for the parent element. 914 list_state_stack_.back().bytes_parsed_ += bytes_parsed; 915 client = list_state_stack_.back().client_; 916 } else { 917 client = root_client_; 918 } 919 920 if (!client->OnListEnd(list_state.id_)) 921 return false; 922 } 923 924 DCHECK_GE(lists_ended, 1); 925 926 if (list_state_stack_.empty()) 927 ChangeState(DONE_PARSING_LIST); 928 929 return true; 930 } 931 932 bool WebMListParser::IsSiblingOrAncestor(int id_a, int id_b) const { 933 DCHECK((id_a == kWebMIdSegment) || (id_a == kWebMIdCluster)); 934 935 if (id_a == kWebMIdCluster) { 936 // kWebMIdCluster siblings. 937 for (size_t i = 0; i < arraysize(kSegmentIds); i++) { 938 if (kSegmentIds[i].id_ == id_b) 939 return true; 940 } 941 } 942 943 // kWebMIdSegment siblings. 944 return ((id_b == kWebMIdSegment) || (id_b == kWebMIdEBMLHeader)); 945 } 946 947 } // namespace media 948