| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/formats/webm/webm_parser.h" | 5 #include "media/formats/webm/webm_parser.h" |
| 6 | 6 |
| 7 // This file contains code to parse WebM file elements. It was created | 7 // This file contains code to parse WebM file elements. It was created |
| 8 // from information in the Matroska spec. | 8 // from information in the Matroska spec. |
| 9 // http://www.matroska.org/technical/specs/index.html | 9 // http://www.matroska.org/technical/specs/index.html |
| 10 // This file contains code for encrypted WebM. Current WebM | 10 // This file contains code for encrypted WebM. Current WebM |
| 11 // encrypted request for comments specification is here | 11 // encrypted request for comments specification is here |
| 12 // http://wiki.webmproject.org/encryption/webm-encryption-rfc | 12 // http://wiki.webmproject.org/encryption/webm-encryption-rfc |
| 13 | 13 |
| 14 #include <iomanip> | 14 #include <iomanip> |
| 15 #include <limits> |
| 15 | 16 |
| 16 #include "base/logging.h" | 17 #include "base/logging.h" |
| 17 #include "base/numerics/safe_conversions.h" | 18 #include "base/numerics/safe_conversions.h" |
| 18 #include "media/formats/webm/webm_constants.h" | 19 #include "media/formats/webm/webm_constants.h" |
| 19 | 20 |
| 20 namespace media { | 21 namespace media { |
| 21 | 22 |
| 22 enum ElementType { | 23 enum ElementType { |
| 23 UNKNOWN, | 24 UNKNOWN, |
| 24 LIST, // Referred to as Master Element in the Matroska spec. | 25 LIST, // Referred to as Master Element in the Matroska spec. |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 // |size| - The number of bytes in |buf| | 417 // |size| - The number of bytes in |buf| |
| 417 // |max_bytes| - The maximum number of bytes the field can be. ID fields | 418 // |max_bytes| - The maximum number of bytes the field can be. ID fields |
| 418 // set this to 4 & element size fields set this to 8. If the | 419 // set this to 4 & element size fields set this to 8. If the |
| 419 // first byte indicates a larger field size than this it is a | 420 // first byte indicates a larger field size than this it is a |
| 420 // parser error. | 421 // parser error. |
| 421 // |mask_first_byte| - For element size fields the field length encoding bits | 422 // |mask_first_byte| - For element size fields the field length encoding bits |
| 422 // need to be masked off. This parameter is true for | 423 // need to be masked off. This parameter is true for |
| 423 // element size fields and is false for ID field values. | 424 // element size fields and is false for ID field values. |
| 424 // | 425 // |
| 425 // Returns: The number of bytes parsed on success. -1 on error. | 426 // Returns: The number of bytes parsed on success. -1 on error. |
| 426 static int ParseWebMElementHeaderField(const uint8* buf, int size, | 427 static int ParseWebMElementHeaderField(const uint8_t* buf, |
| 427 int max_bytes, bool mask_first_byte, | 428 int size, |
| 428 int64* num) { | 429 int max_bytes, |
| 430 bool mask_first_byte, |
| 431 int64_t* num) { |
| 429 DCHECK(buf); | 432 DCHECK(buf); |
| 430 DCHECK(num); | 433 DCHECK(num); |
| 431 | 434 |
| 432 if (size < 0) | 435 if (size < 0) |
| 433 return -1; | 436 return -1; |
| 434 | 437 |
| 435 if (size == 0) | 438 if (size == 0) |
| 436 return 0; | 439 return 0; |
| 437 | 440 |
| 438 int mask = 0x80; | 441 int mask = 0x80; |
| 439 uint8 ch = buf[0]; | 442 uint8_t ch = buf[0]; |
| 440 int extra_bytes = -1; | 443 int extra_bytes = -1; |
| 441 bool all_ones = false; | 444 bool all_ones = false; |
| 442 for (int i = 0; i < max_bytes; ++i) { | 445 for (int i = 0; i < max_bytes; ++i) { |
| 443 if ((ch & mask) != 0) { | 446 if ((ch & mask) != 0) { |
| 444 mask = ~mask & 0xff; | 447 mask = ~mask & 0xff; |
| 445 *num = mask_first_byte ? ch & mask : ch; | 448 *num = mask_first_byte ? ch & mask : ch; |
| 446 all_ones = (ch & mask) == mask; | 449 all_ones = (ch & mask) == mask; |
| 447 extra_bytes = i; | 450 extra_bytes = i; |
| 448 break; | 451 break; |
| 449 } | 452 } |
| 450 mask = 0x80 | mask >> 1; | 453 mask = 0x80 | mask >> 1; |
| 451 } | 454 } |
| 452 | 455 |
| 453 if (extra_bytes == -1) | 456 if (extra_bytes == -1) |
| 454 return -1; | 457 return -1; |
| 455 | 458 |
| 456 // Return 0 if we need more data. | 459 // Return 0 if we need more data. |
| 457 if ((1 + extra_bytes) > size) | 460 if ((1 + extra_bytes) > size) |
| 458 return 0; | 461 return 0; |
| 459 | 462 |
| 460 int bytes_used = 1; | 463 int bytes_used = 1; |
| 461 | 464 |
| 462 for (int i = 0; i < extra_bytes; ++i) { | 465 for (int i = 0; i < extra_bytes; ++i) { |
| 463 ch = buf[bytes_used++]; | 466 ch = buf[bytes_used++]; |
| 464 all_ones &= (ch == 0xff); | 467 all_ones &= (ch == 0xff); |
| 465 *num = (*num << 8) | ch; | 468 *num = (*num << 8) | ch; |
| 466 } | 469 } |
| 467 | 470 |
| 468 if (all_ones) | 471 if (all_ones) |
| 469 *num = kint64max; | 472 *num = std::numeric_limits<int64_t>::max(); |
| 470 | 473 |
| 471 return bytes_used; | 474 return bytes_used; |
| 472 } | 475 } |
| 473 | 476 |
| 474 int WebMParseElementHeader(const uint8* buf, int size, | 477 int WebMParseElementHeader(const uint8_t* buf, |
| 475 int* id, int64* element_size) { | 478 int size, |
| 479 int* id, |
| 480 int64_t* element_size) { |
| 476 DCHECK(buf); | 481 DCHECK(buf); |
| 477 DCHECK_GE(size, 0); | 482 DCHECK_GE(size, 0); |
| 478 DCHECK(id); | 483 DCHECK(id); |
| 479 DCHECK(element_size); | 484 DCHECK(element_size); |
| 480 | 485 |
| 481 if (size == 0) | 486 if (size == 0) |
| 482 return 0; | 487 return 0; |
| 483 | 488 |
| 484 int64 tmp = 0; | 489 int64_t tmp = 0; |
| 485 int num_id_bytes = ParseWebMElementHeaderField(buf, size, 4, false, &tmp); | 490 int num_id_bytes = ParseWebMElementHeaderField(buf, size, 4, false, &tmp); |
| 486 | 491 |
| 487 if (num_id_bytes <= 0) | 492 if (num_id_bytes <= 0) |
| 488 return num_id_bytes; | 493 return num_id_bytes; |
| 489 | 494 |
| 490 if (tmp == kint64max) | 495 if (tmp == std::numeric_limits<int64_t>::max()) |
| 491 tmp = kWebMReservedId; | 496 tmp = kWebMReservedId; |
| 492 | 497 |
| 493 *id = static_cast<int>(tmp); | 498 *id = static_cast<int>(tmp); |
| 494 | 499 |
| 495 int num_size_bytes = ParseWebMElementHeaderField(buf + num_id_bytes, | 500 int num_size_bytes = ParseWebMElementHeaderField(buf + num_id_bytes, |
| 496 size - num_id_bytes, | 501 size - num_id_bytes, |
| 497 8, true, &tmp); | 502 8, true, &tmp); |
| 498 | 503 |
| 499 if (num_size_bytes <= 0) | 504 if (num_size_bytes <= 0) |
| 500 return num_size_bytes; | 505 return num_size_bytes; |
| 501 | 506 |
| 502 if (tmp == kint64max) | 507 if (tmp == std::numeric_limits<int64_t>::max()) |
| 503 tmp = kWebMUnknownSize; | 508 tmp = kWebMUnknownSize; |
| 504 | 509 |
| 505 *element_size = tmp; | 510 *element_size = tmp; |
| 506 DVLOG(3) << "WebMParseElementHeader() : id " << std::hex << *id << std::dec | 511 DVLOG(3) << "WebMParseElementHeader() : id " << std::hex << *id << std::dec |
| 507 << " size " << *element_size; | 512 << " size " << *element_size; |
| 508 return num_id_bytes + num_size_bytes; | 513 return num_id_bytes + num_size_bytes; |
| 509 } | 514 } |
| 510 | 515 |
| 511 // Finds ElementType for a specific ID. | 516 // Finds ElementType for a specific ID. |
| 512 static ElementType FindIdType(int id, | 517 static ElementType FindIdType(int id, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 536 } | 541 } |
| 537 | 542 |
| 538 static int FindListLevel(int id) { | 543 static int FindListLevel(int id) { |
| 539 const ListElementInfo* list_info = FindListInfo(id); | 544 const ListElementInfo* list_info = FindListInfo(id); |
| 540 if (list_info) | 545 if (list_info) |
| 541 return list_info->level_; | 546 return list_info->level_; |
| 542 | 547 |
| 543 return -1; | 548 return -1; |
| 544 } | 549 } |
| 545 | 550 |
| 546 static int ParseUInt(const uint8* buf, int size, int id, | 551 static int ParseUInt(const uint8_t* buf, |
| 552 int size, |
| 553 int id, |
| 547 WebMParserClient* client) { | 554 WebMParserClient* client) { |
| 548 if ((size <= 0) || (size > 8)) | 555 if ((size <= 0) || (size > 8)) |
| 549 return -1; | 556 return -1; |
| 550 | 557 |
| 551 // Read in the big-endian integer. | 558 // Read in the big-endian integer. |
| 552 uint64 value = 0; | 559 uint64_t value = 0; |
| 553 for (int i = 0; i < size; ++i) | 560 for (int i = 0; i < size; ++i) |
| 554 value = (value << 8) | buf[i]; | 561 value = (value << 8) | buf[i]; |
| 555 | 562 |
| 556 // We use int64 in place of uint64 everywhere for convenience. See this bug | 563 // We use int64_t in place of uint64_t everywhere for convenience. See this |
| 564 // bug |
| 557 // for more details: http://crbug.com/366750#c3 | 565 // for more details: http://crbug.com/366750#c3 |
| 558 if (!base::IsValueInRangeForNumericType<int64>(value)) | 566 if (!base::IsValueInRangeForNumericType<int64_t>(value)) |
| 559 return -1; | 567 return -1; |
| 560 | 568 |
| 561 if (!client->OnUInt(id, value)) | 569 if (!client->OnUInt(id, value)) |
| 562 return -1; | 570 return -1; |
| 563 | 571 |
| 564 return size; | 572 return size; |
| 565 } | 573 } |
| 566 | 574 |
| 567 static int ParseFloat(const uint8* buf, int size, int id, | 575 static int ParseFloat(const uint8_t* buf, |
| 576 int size, |
| 577 int id, |
| 568 WebMParserClient* client) { | 578 WebMParserClient* client) { |
| 569 | |
| 570 if ((size != 4) && (size != 8)) | 579 if ((size != 4) && (size != 8)) |
| 571 return -1; | 580 return -1; |
| 572 | 581 |
| 573 double value = -1; | 582 double value = -1; |
| 574 | 583 |
| 575 // Read the bytes from big-endian form into a native endian integer. | 584 // Read the bytes from big-endian form into a native endian integer. |
| 576 int64 tmp = 0; | 585 int64_t tmp = 0; |
| 577 for (int i = 0; i < size; ++i) | 586 for (int i = 0; i < size; ++i) |
| 578 tmp = (tmp << 8) | buf[i]; | 587 tmp = (tmp << 8) | buf[i]; |
| 579 | 588 |
| 580 // Use a union to convert the integer bit pattern into a floating point | 589 // Use a union to convert the integer bit pattern into a floating point |
| 581 // number. | 590 // number. |
| 582 if (size == 4) { | 591 if (size == 4) { |
| 583 union { | 592 union { |
| 584 int32 src; | 593 int32_t src; |
| 585 float dst; | 594 float dst; |
| 586 } tmp2; | 595 } tmp2; |
| 587 tmp2.src = static_cast<int32>(tmp); | 596 tmp2.src = static_cast<int32_t>(tmp); |
| 588 value = tmp2.dst; | 597 value = tmp2.dst; |
| 589 } else if (size == 8) { | 598 } else if (size == 8) { |
| 590 union { | 599 union { |
| 591 int64 src; | 600 int64_t src; |
| 592 double dst; | 601 double dst; |
| 593 } tmp2; | 602 } tmp2; |
| 594 tmp2.src = tmp; | 603 tmp2.src = tmp; |
| 595 value = tmp2.dst; | 604 value = tmp2.dst; |
| 596 } else { | 605 } else { |
| 597 return -1; | 606 return -1; |
| 598 } | 607 } |
| 599 | 608 |
| 600 if (!client->OnFloat(id, value)) | 609 if (!client->OnFloat(id, value)) |
| 601 return -1; | 610 return -1; |
| 602 | 611 |
| 603 return size; | 612 return size; |
| 604 } | 613 } |
| 605 | 614 |
| 606 static int ParseBinary(const uint8* buf, int size, int id, | 615 static int ParseBinary(const uint8_t* buf, |
| 616 int size, |
| 617 int id, |
| 607 WebMParserClient* client) { | 618 WebMParserClient* client) { |
| 608 return client->OnBinary(id, buf, size) ? size : -1; | 619 return client->OnBinary(id, buf, size) ? size : -1; |
| 609 } | 620 } |
| 610 | 621 |
| 611 static int ParseString(const uint8* buf, int size, int id, | 622 static int ParseString(const uint8_t* buf, |
| 623 int size, |
| 624 int id, |
| 612 WebMParserClient* client) { | 625 WebMParserClient* client) { |
| 613 const uint8* end = static_cast<const uint8*>(memchr(buf, '\0', size)); | 626 const uint8_t* end = static_cast<const uint8_t*>(memchr(buf, '\0', size)); |
| 614 int length = (end != NULL) ? static_cast<int>(end - buf) : size; | 627 int length = (end != NULL) ? static_cast<int>(end - buf) : size; |
| 615 std::string str(reinterpret_cast<const char*>(buf), length); | 628 std::string str(reinterpret_cast<const char*>(buf), length); |
| 616 return client->OnString(id, str) ? size : -1; | 629 return client->OnString(id, str) ? size : -1; |
| 617 } | 630 } |
| 618 | 631 |
| 619 static int ParseNonListElement(ElementType type, int id, int64 element_size, | 632 static int ParseNonListElement(ElementType type, |
| 620 const uint8* buf, int size, | 633 int id, |
| 634 int64_t element_size, |
| 635 const uint8_t* buf, |
| 636 int size, |
| 621 WebMParserClient* client) { | 637 WebMParserClient* client) { |
| 622 DCHECK_GE(size, element_size); | 638 DCHECK_GE(size, element_size); |
| 623 | 639 |
| 624 int result = -1; | 640 int result = -1; |
| 625 switch(type) { | 641 switch(type) { |
| 626 case LIST: | 642 case LIST: |
| 627 NOTIMPLEMENTED(); | 643 NOTIMPLEMENTED(); |
| 628 result = -1; | 644 result = -1; |
| 629 break; | 645 break; |
| 630 case UINT: | 646 case UINT: |
| (...skipping 26 matching lines...) Expand all Loading... |
| 657 WebMParserClient* WebMParserClient::OnListStart(int id) { | 673 WebMParserClient* WebMParserClient::OnListStart(int id) { |
| 658 DVLOG(1) << "Unexpected list element start with ID " << std::hex << id; | 674 DVLOG(1) << "Unexpected list element start with ID " << std::hex << id; |
| 659 return NULL; | 675 return NULL; |
| 660 } | 676 } |
| 661 | 677 |
| 662 bool WebMParserClient::OnListEnd(int id) { | 678 bool WebMParserClient::OnListEnd(int id) { |
| 663 DVLOG(1) << "Unexpected list element end with ID " << std::hex << id; | 679 DVLOG(1) << "Unexpected list element end with ID " << std::hex << id; |
| 664 return false; | 680 return false; |
| 665 } | 681 } |
| 666 | 682 |
| 667 bool WebMParserClient::OnUInt(int id, int64 val) { | 683 bool WebMParserClient::OnUInt(int id, int64_t val) { |
| 668 DVLOG(1) << "Unexpected unsigned integer element with ID " << std::hex << id; | 684 DVLOG(1) << "Unexpected unsigned integer element with ID " << std::hex << id; |
| 669 return false; | 685 return false; |
| 670 } | 686 } |
| 671 | 687 |
| 672 bool WebMParserClient::OnFloat(int id, double val) { | 688 bool WebMParserClient::OnFloat(int id, double val) { |
| 673 DVLOG(1) << "Unexpected float element with ID " << std::hex << id; | 689 DVLOG(1) << "Unexpected float element with ID " << std::hex << id; |
| 674 return false; | 690 return false; |
| 675 } | 691 } |
| 676 | 692 |
| 677 bool WebMParserClient::OnBinary(int id, const uint8* data, int size) { | 693 bool WebMParserClient::OnBinary(int id, const uint8_t* data, int size) { |
| 678 DVLOG(1) << "Unexpected binary element with ID " << std::hex << id; | 694 DVLOG(1) << "Unexpected binary element with ID " << std::hex << id; |
| 679 return false; | 695 return false; |
| 680 } | 696 } |
| 681 | 697 |
| 682 bool WebMParserClient::OnString(int id, const std::string& str) { | 698 bool WebMParserClient::OnString(int id, const std::string& str) { |
| 683 DVLOG(1) << "Unexpected string element with ID " << std::hex << id; | 699 DVLOG(1) << "Unexpected string element with ID " << std::hex << id; |
| 684 return false; | 700 return false; |
| 685 } | 701 } |
| 686 | 702 |
| 687 WebMListParser::WebMListParser(int id, WebMParserClient* client) | 703 WebMListParser::WebMListParser(int id, WebMParserClient* client) |
| 688 : state_(NEED_LIST_HEADER), | 704 : state_(NEED_LIST_HEADER), |
| 689 root_id_(id), | 705 root_id_(id), |
| 690 root_level_(FindListLevel(id)), | 706 root_level_(FindListLevel(id)), |
| 691 root_client_(client) { | 707 root_client_(client) { |
| 692 DCHECK_GE(root_level_, 0); | 708 DCHECK_GE(root_level_, 0); |
| 693 DCHECK(client); | 709 DCHECK(client); |
| 694 } | 710 } |
| 695 | 711 |
| 696 WebMListParser::~WebMListParser() {} | 712 WebMListParser::~WebMListParser() {} |
| 697 | 713 |
| 698 void WebMListParser::Reset() { | 714 void WebMListParser::Reset() { |
| 699 ChangeState(NEED_LIST_HEADER); | 715 ChangeState(NEED_LIST_HEADER); |
| 700 list_state_stack_.clear(); | 716 list_state_stack_.clear(); |
| 701 } | 717 } |
| 702 | 718 |
| 703 int WebMListParser::Parse(const uint8* buf, int size) { | 719 int WebMListParser::Parse(const uint8_t* buf, int size) { |
| 704 DCHECK(buf); | 720 DCHECK(buf); |
| 705 | 721 |
| 706 if (size < 0 || state_ == PARSE_ERROR || state_ == DONE_PARSING_LIST) | 722 if (size < 0 || state_ == PARSE_ERROR || state_ == DONE_PARSING_LIST) |
| 707 return -1; | 723 return -1; |
| 708 | 724 |
| 709 if (size == 0) | 725 if (size == 0) |
| 710 return 0; | 726 return 0; |
| 711 | 727 |
| 712 const uint8* cur = buf; | 728 const uint8_t* cur = buf; |
| 713 int cur_size = size; | 729 int cur_size = size; |
| 714 int bytes_parsed = 0; | 730 int bytes_parsed = 0; |
| 715 | 731 |
| 716 while (cur_size > 0 && state_ != PARSE_ERROR && state_ != DONE_PARSING_LIST) { | 732 while (cur_size > 0 && state_ != PARSE_ERROR && state_ != DONE_PARSING_LIST) { |
| 717 int element_id = 0; | 733 int element_id = 0; |
| 718 int64 element_size = 0; | 734 int64_t element_size = 0; |
| 719 int result = WebMParseElementHeader(cur, cur_size, &element_id, | 735 int result = WebMParseElementHeader(cur, cur_size, &element_id, |
| 720 &element_size); | 736 &element_size); |
| 721 | 737 |
| 722 if (result < 0) | 738 if (result < 0) |
| 723 return result; | 739 return result; |
| 724 | 740 |
| 725 if (result == 0) | 741 if (result == 0) |
| 726 return bytes_parsed; | 742 return bytes_parsed; |
| 727 | 743 |
| 728 switch(state_) { | 744 switch(state_) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 742 | 758 |
| 743 ChangeState(INSIDE_LIST); | 759 ChangeState(INSIDE_LIST); |
| 744 if (!OnListStart(root_id_, element_size)) | 760 if (!OnListStart(root_id_, element_size)) |
| 745 return -1; | 761 return -1; |
| 746 | 762 |
| 747 break; | 763 break; |
| 748 } | 764 } |
| 749 | 765 |
| 750 case INSIDE_LIST: { | 766 case INSIDE_LIST: { |
| 751 int header_size = result; | 767 int header_size = result; |
| 752 const uint8* element_data = cur + header_size; | 768 const uint8_t* element_data = cur + header_size; |
| 753 int element_data_size = cur_size - header_size; | 769 int element_data_size = cur_size - header_size; |
| 754 | 770 |
| 755 if (element_size < element_data_size) | 771 if (element_size < element_data_size) |
| 756 element_data_size = element_size; | 772 element_data_size = element_size; |
| 757 | 773 |
| 758 result = ParseListElement(header_size, element_id, element_size, | 774 result = ParseListElement(header_size, element_id, element_size, |
| 759 element_data, element_data_size); | 775 element_data, element_data_size); |
| 760 | 776 |
| 761 DCHECK_LE(result, header_size + element_data_size); | 777 DCHECK_LE(result, header_size + element_data_size); |
| 762 if (result < 0) { | 778 if (result < 0) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 786 | 802 |
| 787 bool WebMListParser::IsParsingComplete() const { | 803 bool WebMListParser::IsParsingComplete() const { |
| 788 return state_ == DONE_PARSING_LIST; | 804 return state_ == DONE_PARSING_LIST; |
| 789 } | 805 } |
| 790 | 806 |
| 791 void WebMListParser::ChangeState(State new_state) { | 807 void WebMListParser::ChangeState(State new_state) { |
| 792 state_ = new_state; | 808 state_ = new_state; |
| 793 } | 809 } |
| 794 | 810 |
| 795 int WebMListParser::ParseListElement(int header_size, | 811 int WebMListParser::ParseListElement(int header_size, |
| 796 int id, int64 element_size, | 812 int id, |
| 797 const uint8* data, int size) { | 813 int64_t element_size, |
| 814 const uint8_t* data, |
| 815 int size) { |
| 798 DCHECK_GT(list_state_stack_.size(), 0u); | 816 DCHECK_GT(list_state_stack_.size(), 0u); |
| 799 | 817 |
| 800 ListState& list_state = list_state_stack_.back(); | 818 ListState& list_state = list_state_stack_.back(); |
| 801 DCHECK(list_state.element_info_); | 819 DCHECK(list_state.element_info_); |
| 802 | 820 |
| 803 const ListElementInfo* element_info = list_state.element_info_; | 821 const ListElementInfo* element_info = list_state.element_info_; |
| 804 ElementType id_type = | 822 ElementType id_type = |
| 805 FindIdType(id, element_info->id_info_, element_info->id_info_count_); | 823 FindIdType(id, element_info->id_info_, element_info->id_info_count_); |
| 806 | 824 |
| 807 // Unexpected ID. | 825 // Unexpected ID. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 820 return -1; | 838 return -1; |
| 821 | 839 |
| 822 // Check to see if all open lists have ended. | 840 // Check to see if all open lists have ended. |
| 823 if (list_state_stack_.size() == 0) | 841 if (list_state_stack_.size() == 0) |
| 824 return 0; | 842 return 0; |
| 825 | 843 |
| 826 list_state = list_state_stack_.back(); | 844 list_state = list_state_stack_.back(); |
| 827 } | 845 } |
| 828 | 846 |
| 829 // Make sure the whole element can fit inside the current list. | 847 // Make sure the whole element can fit inside the current list. |
| 830 int64 total_element_size = header_size + element_size; | 848 int64_t total_element_size = header_size + element_size; |
| 831 if (list_state.size_ != kWebMUnknownSize && | 849 if (list_state.size_ != kWebMUnknownSize && |
| 832 list_state.size_ < list_state.bytes_parsed_ + total_element_size) { | 850 list_state.size_ < list_state.bytes_parsed_ + total_element_size) { |
| 833 return -1; | 851 return -1; |
| 834 } | 852 } |
| 835 | 853 |
| 836 if (id_type == LIST) { | 854 if (id_type == LIST) { |
| 837 list_state.bytes_parsed_ += header_size; | 855 list_state.bytes_parsed_ += header_size; |
| 838 | 856 |
| 839 if (!OnListStart(id, element_size)) | 857 if (!OnListStart(id, element_size)) |
| 840 return -1; | 858 return -1; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 862 | 880 |
| 863 // See if we have reached the end of the current list. | 881 // See if we have reached the end of the current list. |
| 864 if (list_state.bytes_parsed_ == list_state.size_) { | 882 if (list_state.bytes_parsed_ == list_state.size_) { |
| 865 if (!OnListEnd()) | 883 if (!OnListEnd()) |
| 866 return -1; | 884 return -1; |
| 867 } | 885 } |
| 868 | 886 |
| 869 return result; | 887 return result; |
| 870 } | 888 } |
| 871 | 889 |
| 872 bool WebMListParser::OnListStart(int id, int64 size) { | 890 bool WebMListParser::OnListStart(int id, int64_t size) { |
| 873 const ListElementInfo* element_info = FindListInfo(id); | 891 const ListElementInfo* element_info = FindListInfo(id); |
| 874 if (!element_info) | 892 if (!element_info) |
| 875 return false; | 893 return false; |
| 876 | 894 |
| 877 int current_level = root_level_ + list_state_stack_.size() - 1; | 895 int current_level = root_level_ + list_state_stack_.size() - 1; |
| 878 if (current_level + 1 != element_info->level_) | 896 if (current_level + 1 != element_info->level_) |
| 879 return false; | 897 return false; |
| 880 | 898 |
| 881 WebMParserClient* current_list_client = NULL; | 899 WebMParserClient* current_list_client = NULL; |
| 882 if (!list_state_stack_.empty()) { | 900 if (!list_state_stack_.empty()) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 900 if (size == 0) | 918 if (size == 0) |
| 901 return OnListEnd(); | 919 return OnListEnd(); |
| 902 | 920 |
| 903 return true; | 921 return true; |
| 904 } | 922 } |
| 905 | 923 |
| 906 bool WebMListParser::OnListEnd() { | 924 bool WebMListParser::OnListEnd() { |
| 907 int lists_ended = 0; | 925 int lists_ended = 0; |
| 908 for (; !list_state_stack_.empty(); ++lists_ended) { | 926 for (; !list_state_stack_.empty(); ++lists_ended) { |
| 909 const ListState& list_state = list_state_stack_.back(); | 927 const ListState& list_state = list_state_stack_.back(); |
| 910 int64 bytes_parsed = list_state.bytes_parsed_; | 928 int64_t bytes_parsed = list_state.bytes_parsed_; |
| 911 int id = list_state.id_; | 929 int id = list_state.id_; |
| 912 | 930 |
| 913 if (bytes_parsed != list_state.size_) | 931 if (bytes_parsed != list_state.size_) |
| 914 break; | 932 break; |
| 915 | 933 |
| 916 list_state_stack_.pop_back(); | 934 list_state_stack_.pop_back(); |
| 917 | 935 |
| 918 WebMParserClient* client = NULL; | 936 WebMParserClient* client = NULL; |
| 919 if (!list_state_stack_.empty()) { | 937 if (!list_state_stack_.empty()) { |
| 920 // Update the bytes_parsed_ for the parent element. | 938 // Update the bytes_parsed_ for the parent element. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 945 if (kSegmentIds[i].id_ == id_b) | 963 if (kSegmentIds[i].id_ == id_b) |
| 946 return true; | 964 return true; |
| 947 } | 965 } |
| 948 } | 966 } |
| 949 | 967 |
| 950 // kWebMIdSegment siblings. | 968 // kWebMIdSegment siblings. |
| 951 return ((id_b == kWebMIdSegment) || (id_b == kWebMIdEBMLHeader)); | 969 return ((id_b == kWebMIdSegment) || (id_b == kWebMIdEBMLHeader)); |
| 952 } | 970 } |
| 953 | 971 |
| 954 } // namespace media | 972 } // namespace media |
| OLD | NEW |