the buf should be short generally, copy it out to continuous memory to simplify parsing.
| 573 | // the buf should be short generally, copy it out to continuous memory |
| 574 | // to simplify parsing. |
| 575 | DEFINE_SMALL_ARRAY(char, cont_buf, buf.size(), 64); |
| 576 | buf.copy_to(cont_buf, buf.size()); |
| 577 | return Create(cont_buf, buf.size()); |
| 578 | } |
| 579 | |
| 580 | butil::Status AVCDecoderConfigurationRecord::Create(const void* data, size_t len) { |
| 581 | butil::StringPiece buf((const char*)data, len); |
| 582 | if (buf.size() < 6) { |
| 583 | return butil::Status(EINVAL, "Length=%lu is not long enough", |
| 584 | (unsigned long)buf.size()); |
| 585 | } |
| 586 | // skip configurationVersion at buf[0] |
| 587 | avc_profile = (AVCProfile)buf[1]; |
| 588 | // skip profile_compatibility at buf[2] |
| 589 | avc_level = (AVCLevel)buf[3]; |
| 590 | |
| 591 | // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 |
| 592 | // 5.2.4.1 AVC decoder configuration record |
| 593 | // 5.2.4.1.2 Semantics |
| 594 | // The value of this field shall be one of 0, 1, or 3 corresponding to a |
| 595 | // length encoded with 1, 2, or 4 bytes, respectively. |
| 596 | length_size_minus1 = buf[4] & 0x03; |
| 597 | if (length_size_minus1 == 2) { |
| 598 | return butil::Status(EINVAL, "lengthSizeMinusOne should never be 2"); |
| 599 | } |
| 600 | |
| 601 | // Parsing SPS |
| 602 | const int num_sps = (int)(buf[5] & 0x1f); |
| 603 | buf.remove_prefix(6); |
| 604 | sps_list.clear(); |
| 605 | sps_list.reserve(num_sps); |
| 606 | for (int i = 0; i < num_sps; ++i) { |
| 607 | if (buf.size() < 2) { |
| 608 | return butil::Status(EINVAL, "Not enough data to decode SPS-length"); |
| 609 | } |
| 610 | const uint16_t sps_length = policy::ReadBigEndian2Bytes(buf.data()); |
| 611 | if (buf.size() < 2u + sps_length) { |
| 612 | return butil::Status(EINVAL, "Not enough data to decode SPS"); |
| 613 | } |
| 614 | if (sps_length > 0) { |
| 615 | butil::Status st = ParseSPS(buf.data() + 2, sps_length); |
| 616 | if (!st.ok()) { |
| 617 | return st; |
| 618 | } |
| 619 | sps_list.push_back(buf.substr(2, sps_length).as_string()); |
| 620 | } |
| 621 | buf.remove_prefix(2 + sps_length); |
| 622 | } |
| 623 | // Parsing PPS |
| 624 | pps_list.clear(); |
| 625 | if (buf.empty()) { |
| 626 | return butil::Status(EINVAL, "Not enough data to decode PPS"); |
| 627 | } |
| 628 | const int num_pps = (int)buf[0]; |
| 629 | buf.remove_prefix(1); |
| 630 | for (int i = 0; i < num_pps; ++i) { |
| 631 | if (buf.size() < 2) { |
| 632 | return butil::Status(EINVAL, "Not enough data to decode PPS-length"); |
no test coverage detected