text: #ifndef MS_RTC_RTCP_FEEDBACK_RTP_TRANSPORT_HPP
  #define MS_RTC_RTCP_FEEDBACK_RTP_TRANSPORT_HPP
  
  #include "common.hpp"
  #include "RTC/RTCP/FeedbackRtp.hpp"
  #include <vector>
  
  /* RTP Extensions for Transport-wide Congestion Control
   * draft-holmer-rmcat-transport-wide-cc-extensions-01
  
     0               1               2               3
     0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |V=2|P|  FMT=15 |    PT=205     |           length              |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                     SSRC of packet sender                     |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                      SSRC of media source                     |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |      base sequence number     |      packet status count      |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                 reference time                | fb pkt. count |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |          packet chunk         |         packet chunk          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    .                                                               .
    .                                                               .
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |         packet chunk          |  recv delta   |  recv delta   |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    .                                                               .
    .                                                               .
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |           recv delta          |  recv delta   | zero padding  |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   */
  
  namespace RTC
  {
  	namespace RTCP
  	{
  		class FeedbackRtpTransportPacket : public FeedbackRtpPacket
  		{
  		public:
  			struct PacketResult
  			{
  				PacketResult(uint16_t sequenceNumber, bool received)
  				  : sequenceNumber(sequenceNumber), received(received)
  				{
  				}
  
  				uint16_t sequenceNumber;   // Wide sequence number.
  				int16_t delta{ 0 };        // Delta.
  				bool received{ false };    // Packet received or not.
  				int64_t receivedAtMs{ 0 }; // Received time (ms) in remote timestamp reference.
  			};
  
  		public:
  			enum class AddPacketResult
  			{
  				SUCCESS           = 0,
  				MAX_SIZE_EXCEEDED = 1,
  				FATAL
  			};
  
  		private:
  			enum Status : uint8_t
  			{
  				NotReceived = 0,
  				SmallDelta,
  				LargeDelta,
  				Reserved,
  				None
  			};
  
  		private:
  			struct Context
  			{
  				bool allSameStatus{ true };
  				Status currentStatus{ Status::None };
  				std::vector<Status> statuses;
  			};
  
  		private:
  			class Chunk
  			{
  			public:
  				static Chunk* Parse(const uint8_t* data, size_t len, uint16_t count);
  
  			public:
  				Chunk()          = default;
  				virtual ~Chunk() = default;
  
  				virtual bool AddDeltas(
  				  const uint8_t* data, size_t len, std::vector<int16_t>& deltas, size_t& offset) = 0;
  				virtual void Dump() const                                                        = 0;
  				virtual uint16_t GetCount() const                                                = 0;
  				virtual uint16_t GetReceivedStatusCount() const                                  = 0;
  				virtual void FillResults(
  				  std::vector<struct PacketResult>& packetResults, uint16_t& currentSequenceNumber) const = 0;
  				virtual size_t Serialize(uint8_t* buffer) = 0;
  			};
  
  		private:
  			class RunLengthChunk : public Chunk
  			{
  			public:
  				RunLengthChunk(Status status, uint16_t count) : status(status), count(count)
  				{
  				}
  				explicit RunLengthChunk(uint16_t buffer);
  
  			public:
  				bool AddDeltas(
  				  const uint8_t* data, size_t len, std::vector<int16_t>& deltas, size_t& offset) override;
  				Status GetStatus() const
  				{
  					return this->status;
  				}
  				void Dump() const override;
  				uint16_t GetCount() const override
  				{
  					return this->count;
  				}
  				uint16_t GetReceivedStatusCount() const override;
  				void FillResults(
  				  std::vector<struct PacketResult>& packetResults,
  				  uint16_t& currentSequenceNumber) const override;
  				size_t Serialize(uint8_t* buffer) override;
  
  			private:
  				Status status{ Status::None };
  				uint16_t count{ 0u };
  			};
  
  		private:
  			class OneBitVectorChunk : public Chunk
  			{
  			public:
  				explicit OneBitVectorChunk(const std::vector<Status>& statuses) : statuses(statuses)
  				{
  				}
  				OneBitVectorChunk(uint16_t buffer, uint16_t count);
  
  			public:
  				bool AddDeltas(
  				  const uint8_t* data, size_t len, std::vector<int16_t>& deltas, size_t& offset) override;
  				void Dump() const override;
  				uint16_t GetCount() const override
  				{
  					return this->statuses.size();
  				}
  				uint16_t GetReceivedStatusCount() const override;
  				void FillResults(
  				  std::vector<struct PacketResult>& packetResults,
  				  uint16_t& currentSequenceNumber) const override;
  				size_t Serialize(uint8_t* buffer) override;
  
  			private:
  				std::vector<Status> statuses;
  			};
  
  		private:
  			class TwoBitVectorChunk : public Chunk
  			{
  			public:
  				explicit TwoBitVectorChunk(const std::vector<Status>& statuses) : statuses(statuses)
  				{
  				}
  				TwoBitVectorChunk(uint16_t buffer, uint16_t count);
  
  			public:
  				bool AddDeltas(
  				  const uint8_t* data, size_t len, std::vector<int16_t>& deltas, size_t& offset) override;
  				void Dump() const override;
  				uint16_t GetCount() const override
  				{
  					return this->statuses.size();
  				}
  				uint16_t GetReceivedStatusCount() const override;
  				void FillResults(
  				  std::vector<struct PacketResult>& packetResults,
  				  uint16_t& currentSequenceNumber) const override;
  				size_t Serialize(uint8_t* buffer) override;
  
  			private:
  				std::vector<Status> statuses;
  			};
  
  		public:
  			static size_t fixedHeaderSize;
  			static uint16_t maxMissingPackets;
  			static uint16_t maxPacketStatusCount;
  			static int16_t maxPacketDelta;
  
  		public:
  			static FeedbackRtpTransportPacket* Parse(const uint8_t* data, size_t len);
  
  		private:
  			static absl::flat_hash_map<Status, std::string> status2String;
  
  		public:
  			FeedbackRtpTransportPacket(uint32_t senderSsrc, uint32_t mediaSsrc)
  			  : FeedbackRtpPacket(RTC::RTCP::FeedbackRtp::MessageType::TCC, senderSsrc, mediaSsrc)
  			{
  			}
  			FeedbackRtpTransportPacket(CommonHeader* commonHeader, size_t availableLen);
  			~FeedbackRtpTransportPacket();
  
  		public:
  			AddPacketResult AddPacket(uint16_t sequenceNumber, uint64_t timestamp, size_t maxRtcpPacketLen);
  			void Finish(); // Just for locally generated packets.
  			bool IsFull()
  			{
  				// NOTE: Since AddPendingChunks() is called at the end, we cannot track
  				// the exact ongoing value of packetStatusCount. Hence, let's reserve 7
  				// packets just in case.
  				return this->packetStatusCount >= FeedbackRtpTransportPacket::maxPacketStatusCount - 7;
  			}
  			bool IsSerializable() const
  			{
  				return this->deltas.size() > 0;
  			}
  			bool IsCorrect() const // Just for locally generated packets.
  			{
  				return this->isCorrect;
  			}
  			uint16_t GetBaseSequenceNumber() const
  			{
  				return this->baseSequenceNumber;
  			}
  			uint16_t GetPacketStatusCount() const
  			{
  				return this->packetStatusCount;
  			}
  			int32_t GetReferenceTime() const
  			{
  				return this->referenceTime;
  			}
  			int64_t GetReferenceTimestamp() const // Reference time in ms.
  			{
  				return static_cast<int64_t>(this->referenceTime) * 64;
  			}
  			uint8_t GetFeedbackPacketCount() const
  			{
  				return this->feedbackPacketCount;
  			}
  			void SetFeedbackPacketCount(uint8_t count)
  			{
  				this->feedbackPacketCount = count;
  			}
  			uint16_t GetLatestSequenceNumber() const // Just for locally generated packets.
  			{
  				return this->latestSequenceNumber;
  			}
  			uint64_t GetLatestTimestamp() const // Just for locally generated packets.
  			{
  				return this->latestTimestamp;
  			}
  			std::vector<struct PacketResult> GetPacketResults() const;
  			uint8_t GetPacketFractionLost() const;
  
  			/* Pure virtual methods inherited from Packet. */
  		public:
  			void Dump() const override;
  			size_t Serialize(uint8_t* buffer) override;
  			size_t GetSize() const override
  			{
  				if (this->size)
  					return this->size;
  
  				// Fixed packet size.
  				size_t size = FeedbackRtpPacket::GetSize();
  
  				size += FeedbackRtpTransportPacket::fixedHeaderSize;
  				size += this->deltasAndChunksSize;
  
  				// 32 bits padding.
  				size += (-size) & 3;
  
  				return size;
  			}
  
  		private:
  			void FillChunk(uint16_t previousSequenceNumber, uint16_t sequenceNumber, int16_t delta);
  			void CreateRunLengthChunk(Status status, uint16_t count);
  			void CreateOneBitVectorChunk(std::vector<Status>& statuses);
  			void CreateTwoBitVectorChunk(std::vector<Status>& statuses);
  			void AddPendingChunks();
  
  		private:
  			uint16_t baseSequenceNumber{ 0u };
  			int32_t referenceTime{ 0 };
  			uint16_t latestSequenceNumber{ 0u }; // Just for locally generated packets.
  			uint64_t latestTimestamp{ 0u };      // Just for locally generated packets.
  			uint16_t packetStatusCount{ 0u };
  			uint8_t feedbackPacketCount{ 0u };
  			std::vector<Chunk*> chunks;
  			std::vector<int16_t> deltas;
  			Context context; // Just for locally generated packets.
  			size_t deltasAndChunksSize{ 0u };
  			size_t size{ 0 };
  			bool isCorrect{ true };
  		};
  	} // namespace RTCP
  } // namespace RTC
  
  #endif
  