| // Copyright (c) 2016 The WebM project authors. All Rights Reserved. |
| // |
| // Use of this source code is governed by a BSD-style license |
| // that can be found in the LICENSE file in the root of the source |
| // tree. An additional intellectual property rights grant can be found |
| // in the file PATENTS. All contributing project authors may |
| // be found in the AUTHORS file in the root of the source tree. |
| #include "src/id_parser.h" |
| |
| #include <cassert> |
| #include <cstdint> |
| |
| #include "src/bit_utils.h" |
| #include "src/parser_utils.h" |
| #include "webm/id.h" |
| #include "webm/reader.h" |
| #include "webm/status.h" |
| |
| namespace webm { |
| |
| Status IdParser::Feed(Callback* callback, Reader* reader, |
| std::uint64_t* num_bytes_read) { |
| assert(callback != nullptr); |
| assert(reader != nullptr); |
| assert(num_bytes_read != nullptr); |
| assert(num_bytes_remaining_ != 0); |
| |
| *num_bytes_read = 0; |
| |
| // Spec references: |
| // http://matroska.org/technical/specs/index.html#EBML_ex |
| // https://github.com/Matroska-Org/ebml-specification/blob/master/specification.markdown#variable-size-integer |
| // https://github.com/Matroska-Org/ebml-specification/blob/master/specification.markdown#element-id |
| |
| // IDs are encoded like so (big-endian): |
| // 0b1xxx xxxx |
| // 0b01xx xxxx xxxx xxxx |
| // 0b001x xxxx xxxx xxxx xxxx xxxx |
| // 0b0001 xxxx xxxx xxxx xxxx xxxx xxxx xxxx |
| |
| if (num_bytes_remaining_ == -1) { |
| std::uint8_t first_byte; |
| const Status status = ReadByte(reader, &first_byte); |
| if (!status.completed_ok()) { |
| return status; |
| } |
| ++*num_bytes_read; |
| |
| // The marker bit is the first 1-bit. It indicates the length of the ID. |
| // If there is no marker bit in the first half-octet, this isn't a valid |
| // ID, since IDs can't be more than 4 octets in MKV/WebM. |
| if (!(first_byte & 0xf0)) { |
| return Status(Status::kInvalidElementId); |
| } |
| |
| num_bytes_remaining_ = CountLeadingZeros(first_byte); |
| |
| id_ = static_cast<Id>(first_byte); |
| } |
| |
| std::uint64_t local_num_bytes_read; |
| const Status status = AccumulateIntegerBytes(num_bytes_remaining_, reader, |
| &id_, &local_num_bytes_read); |
| *num_bytes_read += local_num_bytes_read; |
| num_bytes_remaining_ -= static_cast<int>(local_num_bytes_read); |
| |
| return status; |
| } |
| |
| Id IdParser::id() const { |
| assert(num_bytes_remaining_ == 0); |
| return id_; |
| } |
| |
| } // namespace webm |