151 lines
3.8 KiB
C++
151 lines
3.8 KiB
C++
#include "rtp-packet.h"
|
|
#include "rtp-util.h"
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
|
|
// RFC3550 RTP: A Transport Protocol for Real-Time Applications
|
|
// 5.1 RTP Fixed Header Fields (p12)
|
|
/*
|
|
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=2|P|X| CC |M| PT | sequence number |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| timestamp |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| synchronization source (SSRC) identifier |
|
|
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
|
| contributing source (CSRC) identifiers |
|
|
| .... |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
*/
|
|
|
|
int rtp_packet_deserialize(struct rtp_packet_t *pkt, const void* data, int bytes)
|
|
{
|
|
uint32_t i, v;
|
|
int hdrlen;
|
|
const uint8_t *ptr;
|
|
|
|
if (bytes < RTP_FIXED_HEADER) // RFC3550 5.1 RTP Fixed Header Fields(p12)
|
|
return -1;
|
|
ptr = (const unsigned char *)data;
|
|
memset(pkt, 0, sizeof(struct rtp_packet_t));
|
|
|
|
// pkt header
|
|
v = nbo_r32(ptr);
|
|
pkt->rtp.v = RTP_V(v);
|
|
pkt->rtp.p = RTP_P(v);
|
|
pkt->rtp.x = RTP_X(v);
|
|
pkt->rtp.cc = RTP_CC(v);
|
|
pkt->rtp.m = RTP_M(v);
|
|
pkt->rtp.pt = RTP_PT(v);
|
|
pkt->rtp.seq = RTP_SEQ(v);
|
|
pkt->rtp.timestamp = nbo_r32(ptr + 4);
|
|
pkt->rtp.ssrc = nbo_r32(ptr + 8);
|
|
assert(RTP_VERSION == pkt->rtp.v);
|
|
|
|
hdrlen = RTP_FIXED_HEADER + pkt->rtp.cc * 4;
|
|
if (RTP_VERSION != pkt->rtp.v || bytes < hdrlen + (pkt->rtp.x ? 4 : 0) + (pkt->rtp.p ? 1 : 0))
|
|
return -1;
|
|
|
|
// pkt contributing source
|
|
for (i = 0; i < pkt->rtp.cc; i++)
|
|
{
|
|
pkt->csrc[i] = nbo_r32(ptr + 12 + i * 4);
|
|
}
|
|
|
|
assert(bytes >= hdrlen);
|
|
pkt->payload = (uint8_t*)ptr + hdrlen;
|
|
pkt->payloadlen = bytes - hdrlen;
|
|
|
|
// pkt header extension
|
|
if (1 == pkt->rtp.x)
|
|
{
|
|
const uint8_t *rtpext = ptr + hdrlen;
|
|
assert(pkt->payloadlen >= 4);
|
|
pkt->extension = rtpext + 4;
|
|
pkt->extprofile = nbo_r16(rtpext);
|
|
pkt->extlen = nbo_r16(rtpext + 2) * 4;
|
|
if (pkt->extlen + 4 > pkt->payloadlen)
|
|
{
|
|
assert(0);
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
pkt->payload = rtpext + pkt->extlen + 4;
|
|
pkt->payloadlen -= pkt->extlen + 4;
|
|
}
|
|
}
|
|
|
|
// padding
|
|
if (1 == pkt->rtp.p)
|
|
{
|
|
uint8_t padding = ptr[bytes - 1];
|
|
if (pkt->payloadlen < padding)
|
|
{
|
|
assert(0);
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
pkt->payloadlen -= padding;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int rtp_packet_serialize_header(const struct rtp_packet_t *pkt, void* data, int bytes)
|
|
{
|
|
int hdrlen;
|
|
uint32_t i;
|
|
uint8_t* ptr;
|
|
|
|
if (RTP_VERSION != pkt->rtp.v || 0 != (pkt->extlen % 4))
|
|
{
|
|
assert(0); // RTP version field must equal 2 (p66)
|
|
return -1;
|
|
}
|
|
|
|
// RFC3550 5.1 RTP Fixed Header Fields(p12)
|
|
hdrlen = RTP_FIXED_HEADER + pkt->rtp.cc * 4 + (pkt->rtp.x ? 4 : 0);
|
|
if (bytes < hdrlen + pkt->extlen)
|
|
return -1;
|
|
|
|
ptr = (uint8_t *)data;
|
|
nbo_write_rtp_header(ptr, &pkt->rtp);
|
|
ptr += RTP_FIXED_HEADER;
|
|
|
|
// pkt contributing source
|
|
for (i = 0; i < pkt->rtp.cc; i++, ptr += 4)
|
|
{
|
|
nbo_w32(ptr, pkt->csrc[i]);
|
|
}
|
|
|
|
// pkt header extension
|
|
if (1 == pkt->rtp.x)
|
|
{
|
|
// 5.3.1 RTP Header Extension
|
|
assert(0 == (pkt->extlen % 4));
|
|
nbo_w16(ptr, pkt->extprofile);
|
|
nbo_w16(ptr + 2, pkt->extlen / 4);
|
|
memcpy(ptr + 4, pkt->extension, pkt->extlen);
|
|
ptr += pkt->extlen + 4;
|
|
}
|
|
|
|
return hdrlen + pkt->extlen;
|
|
}
|
|
|
|
int rtp_packet_serialize(const struct rtp_packet_t *pkt, void* data, int bytes)
|
|
{
|
|
int hdrlen;
|
|
|
|
hdrlen = rtp_packet_serialize_header(pkt, data, bytes);
|
|
if (hdrlen < RTP_FIXED_HEADER || hdrlen + pkt->payloadlen > bytes)
|
|
return -1;
|
|
|
|
memcpy(((uint8_t*)data) + hdrlen, pkt->payload, pkt->payloadlen);
|
|
return hdrlen + pkt->payloadlen;
|
|
}
|