/*
 * We referenced this code from WEBRTC NATIVE CODE.
 */

#pragma once

#include "base/common_types.h"
#include "red_rtp_packet.h"

/*
* RTP + RED + FEC
    0                   1                    2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3  4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | V |P|X|  CC   |M| RED PT(96)  |         SN                    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         timestamp                             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         SSRC                                  |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -----------> RTP Header
   |0| FEC PT(97)  |E|L|P|X|  CC   |M| PT recovery |   SN base     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -----------> 1 Octet for RED
   |   SN base     |               TS recovery                     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  TS recovery  |        length recovery        |   Protection  |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Length      |             mask              |  mask cont.   |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                mask cont(only when L=1)       |               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+               +
   +                        FEC Payload                            +
   +                                               +---------------+
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/

/*
 *	The current version of OME protects all contiguous media packets with one FEC packet,
 *  and one media packet only protects with one FEC packet.
 *  Fec packets is generated by a frame.
 *  Current version generates only one fec packet, near future we will apply bursty mask model.
 *  The session determines whether the FEC PACKET is sent according to the network status (using RTCP RR).
 */

class UlpfecGenerator
{
public:
	UlpfecGenerator();
	~UlpfecGenerator();

	void SetHighRateProtection(bool high_level);
	// Because RTP is already being sent out, we execute ulpfec using the newly created red packet.
	// I used this technique to reduce the copying and improve performance.
	bool AddRtpPacketAndGenerateFec(std::shared_ptr<RedRtpPacket> packet);
	bool IsAvailableFecPackets() const;
	bool NextPacket(RtpPacket *packet);

private:
	bool Encode();
	void XorFecPacket(uint8_t *fec_packet, size_t fec_header_len, RedRtpPacket *packet);
	void FinalizeFecHeader(uint8_t *fec_packet, const size_t fec_payload_len, const uint8_t *mask, const size_t mask_len);

	std::queue<std::shared_ptr<ov::Data>>	    _generated_fec_packets;
	std::vector<std::shared_ptr<RedRtpPacket>>	_media_packets;
	bool                                        _high_level;
};