/* * Copyright (c) 2021, Hunter Salyer * Copyright (c) 2022-2026, Gregory Bertilson * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include "Streamer.h" namespace Media::Matroska { Streamer::Streamer(NonnullRefPtr const& stream_cursor) : m_stream_cursor(stream_cursor) { } Streamer::~Streamer() = default; DecoderErrorOr Streamer::read_string() { auto string_length = TRY(read_variable_size_integer()); auto string_data = TRY(read_raw_octets(string_length)); auto const* string_data_raw = reinterpret_cast(string_data.data()); auto string_value = String::from_utf8(ReadonlyBytes(string_data.data(), strnlen(string_data_raw, string_length))); if (string_value.is_error()) return DecoderError::format(DecoderErrorCategory::Invalid, "String is not valid UTF-8"); return string_value.release_value(); } DecoderErrorOr Streamer::read_octet() { u8 result; Bytes bytes { &result, 1 }; auto bytes_read = TRY(m_stream_cursor->read_into(bytes)); if (bytes_read != 1) return DecoderError::corrupted("Failed to read octet"sv); return bytes[0]; } DecoderErrorOr Streamer::read_i16() { return (TRY(read_octet()) << 8) | TRY(read_octet()); } DecoderErrorOr Streamer::read_element_id() { auto length_byte = TRY(read_octet()); auto length = count_leading_zeroes_safe(length_byte) + 1; if (length > 4) return DecoderError::corrupted("Element ID must be 4 bytes or less"sv); u32 result = length_byte; auto bytes_left = length; while (--bytes_left > 0) { result <<= 8; result |= TRY(read_octet()); } return result; } DecoderErrorOr> Streamer::read_element_size() { auto length_byte = TRY(read_octet()); auto length = count_leading_zeroes_safe(length_byte) + 1; if (length > 8) return DecoderError::corrupted("Element Data Size 8 bytes or less"sv); size_t result = length_byte; auto bytes_left = length; while (--bytes_left > 0) { result <<= 8; result |= TRY(read_octet()); } auto mask = 0xFFFFFFFFFFFFFFFF >> (64 - (7 * length)); result &= mask; if (result == mask) return OptionalNone(); return result; } DecoderErrorOr Streamer::read_variable_size_integer() { auto length_byte = TRY(read_octet()); auto length = count_leading_zeroes_safe(length_byte) + 1; if (length > 8) return DecoderError::corrupted("VINT is too large"sv); auto bytes_left = length; auto result = length_byte & (0xFF >> length); while (--bytes_left > 0) { result <<= 8; result |= TRY(read_octet()); } return result; } DecoderErrorOr Streamer::read_variable_size_signed_integer() { auto length_byte = TRY(read_octet()); auto length = count_leading_zeroes_safe(length_byte) + 1; if (length > 8) return DecoderError::corrupted("VINT is too large"sv); auto bytes_left = length; i64 result = length_byte & (0xFF >> length); while (--bytes_left > 0) { result <<= 8; result |= TRY(read_octet()); } result -= AK::exp2((length * 7) - 1) - 1; return result; } DecoderErrorOr Streamer::read_raw_octets(size_t num_octets) { auto result = MUST(ByteBuffer::create_uninitialized(num_octets)); auto bytes = result.bytes(); TRY(m_stream_cursor->read_into(bytes)); return result; } DecoderErrorOr Streamer::read_u64() { auto integer_length = TRY(read_variable_size_integer()); if (integer_length == 0) return 0; if (integer_length > 8) return DecoderError::corrupted("Integer Element is too large"sv); u64 result = 0; for (size_t i = 0; i < integer_length; i++) { result <<= 8; result |= TRY(read_octet()); } return result; } DecoderErrorOr Streamer::read_i64() { auto integer_length = TRY(read_variable_size_integer()); if (integer_length == 0) return 0; if (integer_length > 8) return DecoderError::corrupted("Signed Integer Element is too large"sv); i64 result = 0; for (size_t i = 0; i < integer_length; i++) { result <<= 8; result |= TRY(read_octet()); } auto shift = 64 - (static_cast(integer_length) * 8); result <<= shift; result >>= shift; return result; } DecoderErrorOr Streamer::read_float() { auto length = TRY(read_variable_size_integer()); if (length == 0) return 0; if (length != 4u && length != 8u) return DecoderError::format(DecoderErrorCategory::Invalid, "Float size must be 4 or 8 bytes"); union { u64 value; float float_value; double double_value; } read_data; read_data.value = 0; for (size_t i = 0; i < length; i++) { read_data.value = (read_data.value << 8u) + TRY(read_octet()); } if (length == 4u) return read_data.float_value; return read_data.double_value; } DecoderErrorOr Streamer::read_unknown_element() { auto element_length = TRY(read_variable_size_integer()); dbgln_if(MATROSKA_TRACE_DEBUG, "Skipping unknown element of size {}.", element_length); TRY(m_stream_cursor->seek(element_length, AK::SeekMode::FromCurrentPosition)); return {}; } size_t Streamer::position() const { return m_stream_cursor->position(); } DecoderErrorOr Streamer::seek_to_position(size_t position) { return m_stream_cursor->seek(position, AK::SeekMode::SetPosition); } }