mirror of
				https://github.com/kunkundi/crossdesk.git
				synced 2025-10-26 20:25:34 +08:00 
			
		
		
		
	Add parser for OBU packets
This commit is contained in:
		| @@ -20,6 +20,8 @@ extern "C" { | |||||||
| }; | }; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #include "obu_parser.h" | ||||||
|  |  | ||||||
| #define SAVE_NV12_STREAM 0 | #define SAVE_NV12_STREAM 0 | ||||||
| #define SAVE_H264_STREAM 1 | #define SAVE_H264_STREAM 1 | ||||||
|  |  | ||||||
| @@ -340,6 +342,13 @@ int AomAv1Encoder::Encode( | |||||||
|       SET_ENCODER_PARAM_OR_RETURN_ERROR(AOME_GET_LAST_QUANTIZER, &qp); |       SET_ENCODER_PARAM_OR_RETURN_ERROR(AOME_GET_LAST_QUANTIZER, &qp); | ||||||
|       LOG_INFO("Encoded frame qp = {}", qp); |       LOG_INFO("Encoded frame qp = {}", qp); | ||||||
|  |  | ||||||
|  |       std::vector<Obu> obus = ParseObus(encoded_frame_, encoded_frame_size_); | ||||||
|  |       // LOG_ERROR("Obu size = [{}]", obus.size()); | ||||||
|  |       // for (int i = 0; i < obus.size(); i++) { | ||||||
|  |       //   LOG_ERROR("Obu size = {} [{} {}]", i, obus[i].size_, | ||||||
|  |       //             obus[i].payload_size_); | ||||||
|  |       // } | ||||||
|  |  | ||||||
|       // int consumed_size = 0; |       // int consumed_size = 0; | ||||||
|       // int offset = 0; |       // int offset = 0; | ||||||
|       // int unit = 0; |       // int unit = 0; | ||||||
|   | |||||||
							
								
								
									
										59
									
								
								src/media/video/encode/aom/byte_buffer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/media/video/encode/aom/byte_buffer.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | |||||||
|  | #include "byte_buffer.h" | ||||||
|  |  | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | ByteBufferReader::ByteBufferReader(const char* bytes, size_t len) { | ||||||
|  |   Construct(bytes, len); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ByteBufferReader::Construct(const char* bytes, size_t len) { | ||||||
|  |   bytes_ = bytes; | ||||||
|  |   size_ = len; | ||||||
|  |   start_ = 0; | ||||||
|  |   end_ = len; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool ByteBufferReader::ReadBytes(char* val, size_t len) { | ||||||
|  |   if (len > Length()) { | ||||||
|  |     return false; | ||||||
|  |   } else { | ||||||
|  |     memcpy(val, bytes_ + start_, len); | ||||||
|  |     start_ += len; | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool ByteBufferReader::ReadUInt8(uint8_t* val) { | ||||||
|  |   if (!val) return false; | ||||||
|  |  | ||||||
|  |   return ReadBytes(reinterpret_cast<char*>(val), 1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool ByteBufferReader::ReadUVarint(uint64_t* val) { | ||||||
|  |   if (!val) { | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  |   // Integers are deserialized 7 bits at a time, with each byte having a | ||||||
|  |   // continuation byte (msb=1) if there are more bytes to be read. | ||||||
|  |   uint64_t v = 0; | ||||||
|  |   for (int i = 0; i < 64; i += 7) { | ||||||
|  |     char byte; | ||||||
|  |     if (!ReadBytes(&byte, 1)) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |     // Read the first 7 bits of the byte, then offset by bits read so far. | ||||||
|  |     v |= (static_cast<uint64_t>(byte) & 0x7F) << i; | ||||||
|  |     // True if the msb is not a continuation byte. | ||||||
|  |     if (static_cast<uint64_t>(byte) < 0x80) { | ||||||
|  |       *val = v; | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool ByteBufferReader::Consume(size_t size) { | ||||||
|  |   if (size > Length()) return false; | ||||||
|  |   start_ += size; | ||||||
|  |   return true; | ||||||
|  | } | ||||||
							
								
								
									
										40
									
								
								src/media/video/encode/aom/byte_buffer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/media/video/encode/aom/byte_buffer.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | /* | ||||||
|  |  * @Author: DI JUNKUN | ||||||
|  |  * @Date: 2024-04-22 | ||||||
|  |  * Copyright (c) 2024 by DI JUNKUN, All Rights Reserved. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef _BYTE_BUFFER_H_ | ||||||
|  | #define _BYTE_BUFFER_H_ | ||||||
|  |  | ||||||
|  | #include <stddef.h> | ||||||
|  | #include <stdint.h> | ||||||
|  |  | ||||||
|  | class ByteBufferReader { | ||||||
|  |  public: | ||||||
|  |   ByteBufferReader(const char* bytes, size_t len); | ||||||
|  |  | ||||||
|  |   ByteBufferReader(const ByteBufferReader&) = delete; | ||||||
|  |   ByteBufferReader& operator=(const ByteBufferReader&) = delete; | ||||||
|  |  | ||||||
|  |   // Returns start of unprocessed data. | ||||||
|  |   const char* Data() const { return bytes_ + start_; } | ||||||
|  |   // Returns number of unprocessed bytes. | ||||||
|  |   size_t Length() const { return end_ - start_; } | ||||||
|  |  | ||||||
|  |   bool ReadBytes(char* val, size_t len); | ||||||
|  |   bool ReadUInt8(uint8_t* val); | ||||||
|  |   bool ReadUVarint(uint64_t* val); | ||||||
|  |  | ||||||
|  |   bool Consume(size_t size); | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   void Construct(const char* bytes, size_t size); | ||||||
|  |  | ||||||
|  |   const char* bytes_; | ||||||
|  |   size_t size_; | ||||||
|  |   size_t start_; | ||||||
|  |   size_t end_; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										80
									
								
								src/media/video/encode/aom/obu.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								src/media/video/encode/aom/obu.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | |||||||
|  | #include "obu.h" | ||||||
|  |  | ||||||
|  | #include <string> | ||||||
|  |  | ||||||
|  | #include "log.h" | ||||||
|  |  | ||||||
|  | Obu::Obu() {} | ||||||
|  |  | ||||||
|  | Obu::Obu(const Obu &obu) { | ||||||
|  |   if (obu.payload_size_ > 0) { | ||||||
|  |     payload_ = (uint8_t *)malloc(obu.payload_size_); | ||||||
|  |     if (NULL == payload_) { | ||||||
|  |       LOG_ERROR("Malloc failed"); | ||||||
|  |     } else { | ||||||
|  |       memcpy(payload_, obu.payload_, obu.payload_size_); | ||||||
|  |     } | ||||||
|  |     payload_size_ = obu.payload_size_; | ||||||
|  |     header_ = obu.header_; | ||||||
|  |     extension_header_ = obu.extension_header_; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Obu::Obu(Obu &&obu) | ||||||
|  |     : payload_((uint8_t *)std::move(obu.payload_)), | ||||||
|  |       payload_size_(obu.payload_size_), | ||||||
|  |       header_(obu.header_), | ||||||
|  |       extension_header_(obu.extension_header_) { | ||||||
|  |   obu.payload_ = nullptr; | ||||||
|  |   obu.payload_size_ = 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Obu &Obu::operator=(const Obu &obu) { | ||||||
|  |   if (&obu != this) { | ||||||
|  |     payload_ = (uint8_t *)realloc(payload_, obu.payload_size_); | ||||||
|  |     memcpy(payload_, obu.payload_, obu.payload_size_); | ||||||
|  |     payload_size_ = obu.payload_size_; | ||||||
|  |     header_ = obu.header_; | ||||||
|  |     extension_header_ = obu.extension_header_; | ||||||
|  |   } | ||||||
|  |   return *this; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Obu &Obu::operator=(Obu &&obu) { | ||||||
|  |   if (&obu != this) { | ||||||
|  |     payload_ = std::move(obu.payload_); | ||||||
|  |     obu.payload_ = nullptr; | ||||||
|  |     payload_size_ = obu.payload_size_; | ||||||
|  |     obu.payload_size_ = 0; | ||||||
|  |     header_ = obu.header_; | ||||||
|  |     obu.header_ = 0; | ||||||
|  |     extension_header_ = obu.extension_header_; | ||||||
|  |     obu.extension_header_ = 0; | ||||||
|  |   } | ||||||
|  |   return *this; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Obu::~Obu() { | ||||||
|  |   if (payload_) { | ||||||
|  |     free(payload_); | ||||||
|  |     payload_ = nullptr; | ||||||
|  |   } | ||||||
|  |   payload_size_ = 0; | ||||||
|  |   header_ = 0; | ||||||
|  |   extension_header_ = 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool Obu::SetPayload(const uint8_t *payload, int size) { | ||||||
|  |   if (payload_) { | ||||||
|  |     free(payload_); | ||||||
|  |     payload_ = nullptr; | ||||||
|  |   } | ||||||
|  |   payload_ = (uint8_t *)malloc(size); | ||||||
|  |   memcpy(payload_, payload, size); | ||||||
|  |   payload_size_ = size; | ||||||
|  |  | ||||||
|  |   if (payload_) | ||||||
|  |     return true; | ||||||
|  |   else | ||||||
|  |     return false; | ||||||
|  | } | ||||||
							
								
								
									
										34
									
								
								src/media/video/encode/aom/obu.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/media/video/encode/aom/obu.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | /* | ||||||
|  |  * @Author: DI JUNKUN | ||||||
|  |  * @Date: 2024-04-22 | ||||||
|  |  * Copyright (c) 2024 by DI JUNKUN, All Rights Reserved. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef _OBU_H_ | ||||||
|  | #define _OBU_H_ | ||||||
|  |  | ||||||
|  | #include <stddef.h> | ||||||
|  | #include <stdint.h> | ||||||
|  |  | ||||||
|  | #include "aom/aom_codec.h" | ||||||
|  |  | ||||||
|  | class Obu { | ||||||
|  |  public: | ||||||
|  |   Obu(); | ||||||
|  |   Obu(const Obu &obu); | ||||||
|  |   Obu(Obu &&obu); | ||||||
|  |   Obu &operator=(const Obu &obu); | ||||||
|  |   Obu &operator=(Obu &&obu); | ||||||
|  |  | ||||||
|  |   ~Obu(); | ||||||
|  |  | ||||||
|  |   bool SetPayload(const uint8_t *payload, int size); | ||||||
|  |  | ||||||
|  |   uint8_t header_ = 0; | ||||||
|  |   uint8_t extension_header_ = 0;  // undefined if (header & kXbit) == 0 | ||||||
|  |   uint8_t *payload_ = nullptr; | ||||||
|  |   int size_ = 0;  // size of the header and payload combined. | ||||||
|  |   int payload_size_ = 0; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										112
									
								
								src/media/video/encode/aom/obu_parser.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/media/video/encode/aom/obu_parser.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,112 @@ | |||||||
|  | #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 "<Invalid OBU Type>"; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | 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<Obu> ParseObus(uint8_t* payload, int payload_size) { | ||||||
|  |   std::vector<Obu> result; | ||||||
|  |   ByteBufferReader payload_reader(reinterpret_cast<const char*>(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<const uint8_t*>(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<const uint8_t*>(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; | ||||||
|  | } | ||||||
							
								
								
									
										18
									
								
								src/media/video/encode/aom/obu_parser.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/media/video/encode/aom/obu_parser.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | /* | ||||||
|  |  * @Author: DI JUNKUN | ||||||
|  |  * @Date: 2024-04-22 | ||||||
|  |  * Copyright (c) 2024 by DI JUNKUN, All Rights Reserved. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef _OBU_PARSER_H_ | ||||||
|  | #define _OBU_PARSER_H_ | ||||||
|  |  | ||||||
|  | #include <stddef.h> | ||||||
|  | #include <stdint.h> | ||||||
|  |  | ||||||
|  | #include <vector> | ||||||
|  |  | ||||||
|  | #include "obu.h" | ||||||
|  |  | ||||||
|  | std::vector<Obu> ParseObus(uint8_t* payload, int payload_size); | ||||||
|  | #endif | ||||||
| @@ -64,7 +64,7 @@ int PeerConnection::Init(PeerConnectionParams params, | |||||||
|            hardware_acceleration_ ? "ON" : "OFF"); |            hardware_acceleration_ ? "ON" : "OFF"); | ||||||
|  |  | ||||||
|   av1_encoding_ = cfg_av1_encoding_ == "true" ? true : false; |   av1_encoding_ = cfg_av1_encoding_ == "true" ? true : false; | ||||||
|   LOG_INFO("av1 encoding [{}]", hardware_acceleration_ ? "ON" : "OFF"); |   LOG_INFO("av1 encoding [{}]", av1_encoding_ ? "ON" : "OFF"); | ||||||
|  |  | ||||||
|   on_receive_video_buffer_ = params.on_receive_video_buffer; |   on_receive_video_buffer_ = params.on_receive_video_buffer; | ||||||
|   on_receive_audio_buffer_ = params.on_receive_audio_buffer; |   on_receive_audio_buffer_ = params.on_receive_audio_buffer; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user