// 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 #include #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(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(local_num_bytes_read); return status; } Id IdParser::id() const { assert(num_bytes_remaining_ == 0); return id_; } } // namespace webm