#include "obu_parser.h" #include "byte_buffer.h" #include "log.h" constexpr int kAggregationHeaderSize = 1; // when there are 3 or less OBU (fragments) in a packet, size of the last one // can be omited. constexpr int kMaxNumObusToOmitSize = 3; constexpr uint8_t kObuSizePresentBit = 0b0'0000'010; constexpr int kObuTypeSequenceHeader = 1; constexpr int kObuTypeTemporalDelimiter = 2; constexpr int kObuTypeTileList = 8; constexpr int kObuTypePadding = 15; const char* ObuTypeToString(OBU_TYPE type) { switch (type) { case OBU_SEQUENCE_HEADER: return "OBU_SEQUENCE_HEADER"; case OBU_TEMPORAL_DELIMITER: return "OBU_TEMPORAL_DELIMITER"; case OBU_FRAME_HEADER: return "OBU_FRAME_HEADER"; case OBU_REDUNDANT_FRAME_HEADER: return "OBU_REDUNDANT_FRAME_HEADER"; case OBU_FRAME: return "OBU_FRAME"; case OBU_TILE_GROUP: return "OBU_TILE_GROUP"; case OBU_METADATA: return "OBU_METADATA"; case OBU_TILE_LIST: return "OBU_TILE_LIST"; case OBU_PADDING: return "OBU_PADDING"; default: break; } return ""; } bool ObuHasExtension(uint8_t obu_header) { return obu_header & 0b0'0000'100; } bool ObuHasSize(uint8_t obu_header) { return obu_header & kObuSizePresentBit; } int ObuType(uint8_t obu_header) { return (obu_header & 0b0'1111'000) >> 3; } std::vector ParseObus(uint8_t* payload, int payload_size) { std::vector result; ByteBufferReader payload_reader(reinterpret_cast(payload), payload_size); while (payload_reader.Length() > 0) { Obu obu; payload_reader.ReadUInt8(&obu.header_); LOG_ERROR("Get obu type = [{}]", ObuTypeToString((OBU_TYPE)ObuType(obu.header_))) obu.size_ = 1; if (ObuHasExtension(obu.header_)) { if (payload_reader.Length() == 0) { LOG_ERROR( "Malformed AV1 input: expected extension_header, no more bytes in " "the buffer. Offset: {}", (payload_size - payload_reader.Length())); return {}; } payload_reader.ReadUInt8(&obu.extension_header_); ++obu.size_; } if (!ObuHasSize(obu.header_)) { obu.SetPayload(reinterpret_cast(payload_reader.Data()), payload_reader.Length()); payload_reader.Consume(payload_reader.Length()); LOG_ERROR("payload_reader.Length() = {}", payload_reader.Length()); } else { uint64_t size = 0; if (!payload_reader.ReadUVarint(&size) || size > payload_reader.Length()) { LOG_ERROR( "Malformed AV1 input: declared size {} is larger than remaining " "buffer size {}", size, payload_reader.Length()); return {}; } obu.SetPayload(reinterpret_cast(payload_reader.Data()), size); payload_reader.Consume(size); LOG_ERROR("size = {}", size); } obu.size_ += obu.payload_size_; // Skip obus that shouldn't be transfered over rtp. int obu_type = ObuType(obu.header_); // if (obu_type != kObuTypeTemporalDelimiter && // // obu_type != kObuTypeTileList && // // obu_type != kObuTypePadding) { // result.push_back(obu); // } LOG_ERROR("Obu size = [{}], Obu type [{}]", obu.size_, ObuTypeToString((OBU_TYPE)ObuType(obu.header_))); if (1) { result.push_back(obu); } } LOG_ERROR("Obu size = [{}]", result.size()); for (int i = 0; i < result.size(); i++) { LOG_ERROR("[{}] Obu size = [{}], Obu type [{}]", i, result[i].payload_size_, ObuTypeToString((OBU_TYPE)ObuType(result[i].header_))); } return result; }