#include <nic.h>
#include <utility/random.h>
#include <udp.h>
#include <tcp.h>
__BEGIN_SYS
class RTP : public Protocol_Common {
public:
enum PType {
PCMU = 0, _1016 = 1, G721 = 2, GSM = 3,
G723 = 4, DVI4_8 = 5, DVI4_16 = 6, LPC = 7,
PCMA = 8, G722 = 9, L16_Stereo = 10, L16_Mono = 11,
QCELP = 12, CN = 13, MPA = 14, G728 = 15,
DVI4_11 = 16, DVI4_22 = 17, G729 = 18, CellB = 25,
JPEG = 26, NV = 28, H261 = 31, MPV = 32,
MP2T = 33, H263 = 34
};
class Header {
static const u8 VERSION_NUMBER = 2;
static const u8 CSRC_COUNT = 0;
public:
Header(u8 marker, PType payload_type, u32 timestamp, u32 ssrc_id) {
set_marker(marker);
set_payload_type(payload_type);
set_timestamp(timestamp);
set_contrib_count(CSRC_COUNT);
set_version_number(VERSION_NUMBER);
set_ssrc_id(ssrc_id);
}
u16 sequence_number() const { return _sequence_number; }
u32 timestamp() const { return _timestamp; }
u32 ssrc_id() const { return _ssrc_id; }
u8 payload_type() const { return _payload_type & 0x7f; }
u8 marker() const { return _marker >> 7; }
u8 contrib_sources_count() const { return _contrib_sources_count & 0x0f; }
u8 extensions() const { return (_extensions >> 4) & 0x1; }
u8 version_number() const { return _version_number >> 6; }
void set_version_number(u8 version_number) {
u8 vnumber = 0x03 & version_number;
u8 aux = _version_number & 0x3f;
_version_number = vnumber | aux;
}
void set_sequence_number(u16 seq) {
_sequence_number = CPU::htons(seq);
}
void set_timestamp(u32 timestamp) {
_timestamp = CPU::htonl(timestamp);
}
void set_ssrc_id(u32 ssrc_id) {
_ssrc_id = CPU::htonl(ssrc_id);
}
void set_marker(u8 marker) { u8 m = marker << 7;
u8 aux = _marker & 0x7f;
_marker = m | aux;
}
void set_payload_type(PType payload_type) { u8 ptype = 0x7f & ( (u8) payload_type);
u8 aux = _payload_type & 0x80;
_payload_type = ptype | aux;
}
void set_contrib_count(u8 contrib_count) {
u8 cc = 0x0f & contrib_count;
u8 aux = _contrib_sources_count & 0xf0;
_contrib_sources_count = cc | aux;
}
const int size() const { return sizeof(Header); }
friend Debug & operator << (Debug & db, const Header & h);
private:
u8 _contrib_sources_count:4;
u8 _extensions:1;
u8 _padding:1;
u8 _version_number:2;
u8 _payload_type:7;
u8 _marker:1;
u16 _sequence_number;
u32 _timestamp;
u32 _ssrc_id;};
class PDU {
public:
static const int TCP_PAYLOAD_SIZE = 512;
static const int PDU_DATA_SIZE = TCP_PAYLOAD_SIZE - sizeof(Header);
PDU(Header head, const char data[]) : _header(head) {
memcpy(_data, data, PDU_DATA_SIZE);
}
const char * data() const {return _data;}
private:
Header _header;
char _data[ PDU_DATA_SIZE ];
};
RTP(UDP::Address remote);
static int get_ssrc_id();
static int listen(RTP * self, UDP::Address rtp_local, UDP::Address rtcp_local);
int send(u32 timestamp, PType payload_type, u8 marker, char *payload,int payload_len);
char * receive();
private:
UDP::Address _rtp_remote;
UDP::Address _rtcp_remote;
TCP::Socket *_local_rtp;
TCP::Socket *_local_rtcp;
TCP::Socket *_remote_rtp;
TCP::Socket *_remote_rtcp;
u32 _ssrc_id;
u16 _sequence_number;
};
__END_SYS