#ifndef MS_RTC_RTCP_RECEIVER_REPORT_HPP
#define MS_RTC_RTCP_RECEIVER_REPORT_HPP
#include "common.hpp"
#include "RTC/RTCP/Packet.hpp"
#include "Utils.hpp"
#include <vector>
namespace RTC
{
namespace RTCP
{
class ReceiverReport
{
public:
struct Header
{
uint32_t ssrc;
uint32_t fractionLost : 8;
uint32_t totalLost : 24;
uint32_t lastSeq;
uint32_t jitter;
uint32_t lsr;
uint32_t dlsr;
};
public:
static const size_t HeaderSize{ 24 };
static ReceiverReport* Parse(const uint8_t* data, size_t len);
public:
ReceiverReport()
{
this->header = reinterpret_cast<Header*>(this->raw);
}
explicit ReceiverReport(Header* header) : header(header)
{
}
explicit ReceiverReport(ReceiverReport* report) : header(report->header)
{
}
void Dump(int indentation = 0) const;
size_t Serialize(uint8_t* buffer);
size_t GetSize() const
{
return HeaderSize;
}
uint32_t GetSsrc() const
{
return ntohl(this->header->ssrc);
}
void SetSsrc(uint32_t ssrc)
{
this->header->ssrc = htonl(ssrc);
}
uint8_t GetFractionLost() const
{
return Utils::Byte::Get1Byte(reinterpret_cast<uint8_t*>(this->header), 4);
}
void SetFractionLost(uint8_t fractionLost)
{
Utils::Byte::Set1Byte(reinterpret_cast<uint8_t*>(this->header), 4, fractionLost);
}
int32_t GetTotalLost() const
{
return Utils::Byte::Get3BytesSigned(reinterpret_cast<uint8_t*>(this->header), 5);
}
void SetTotalLost(int32_t totalLost)
{
Utils::Byte::Set3BytesSigned(reinterpret_cast<uint8_t*>(this->header), 5, totalLost);
}
uint32_t GetLastSeq() const
{
return ntohl(this->header->lastSeq);
}
void SetLastSeq(uint32_t lastSeq)
{
this->header->lastSeq = htonl(lastSeq);
}
uint32_t GetJitter() const
{
return ntohl(this->header->jitter);
}
void SetJitter(float jitter)
{
this->header->jitter = htonl(static_cast<uint32_t>(jitter));
}
uint32_t GetLastSenderReport() const
{
return ntohl(this->header->lsr);
}
void SetLastSenderReport(uint32_t lsr)
{
this->header->lsr = htonl(lsr);
}
uint32_t GetDelaySinceLastSenderReport() const
{
return ntohl(this->header->dlsr);
}
void SetDelaySinceLastSenderReport(uint32_t dlsr)
{
this->header->dlsr = htonl(dlsr);
}
private:
Header* header{ nullptr };
uint8_t raw[HeaderSize]{ 0u };
};
class ReceiverReportPacket : public Packet
{
public:
static size_t maxReportsPerPacket;
using Iterator = std::vector<ReceiverReport*>::iterator;
public:
static ReceiverReportPacket* Parse(const uint8_t* data, size_t len, size_t offset = 0);
public:
ReceiverReportPacket() : Packet(Type::RR)
{
}
explicit ReceiverReportPacket(CommonHeader* commonHeader) : Packet(commonHeader)
{
}
~ReceiverReportPacket() override
{
for (auto* report : this->reports)
{
delete report;
}
}
uint32_t GetSsrc() const
{
return this->ssrc;
}
void SetSsrc(uint32_t ssrc)
{
this->ssrc = ssrc;
}
void AddReport(ReceiverReport* report)
{
this->reports.push_back(report);
}
void RemoveReport(ReceiverReport* report)
{
auto it = std::find(this->reports.begin(), this->reports.end(), report);
if (it != this->reports.end())
{
this->reports.erase(it);
}
}
Iterator Begin()
{
return this->reports.begin();
}
Iterator End()
{
return this->reports.end();
}
public:
void Dump(int indentation = 0) const override;
size_t Serialize(uint8_t* buffer) override;
Type GetType() const override
{
return Type::RR;
}
size_t GetCount() const override
{
return this->reports.size();
}
size_t GetSize() const override
{
size_t size = (Packet::CommonHeaderSize + 4u ) *
((this->GetCount() / maxReportsPerPacket) + 1);
size += ReceiverReport::HeaderSize * this->GetCount();
return size;
}
private:
uint32_t ssrc{ 0u };
std::vector<ReceiverReport*> reports;
};
} }
#endif