stream-deploy/ZLM/3rdpart/media-server/librtsp/source/client/rtp-over-rtsp.c

141 lines
3.1 KiB
C++

#include "rtp-over-rtsp.h"
#include "rtp-header.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define VMIN(x, y) ((x) < (y) ? (x) : (y))
enum rtp_over_tcp_state_t
{
rtp_start = 0,
rtp_channel,
rtp_length_1,
rtp_length_2,
rtp_data,
};
static int rtp_alloc(struct rtp_over_rtsp_t *rtp)
{
void* p;
if (rtp->capacity < rtp->length)
{
p = realloc(rtp->data, rtp->length);
if (!p)
return -1;
rtp->data = (uint8_t*)p;
rtp->capacity = rtp->length;
}
return 0;
}
#if defined(RTP_OVER_RTSP_TRY_TO_FIND_NEXT_PACKET)
// skip missing data, find next start
static const uint8_t* rtp_over_rtsp_try_to_find_next_packet(struct rtp_over_rtsp_t* rtp, const uint8_t* data, const uint8_t* end)
{
const uint8_t* p;
p = (const uint8_t*)memchr(data, '$', end - data);
if (!p)
return end; // not found
rtp->check = 1;
return p;
}
#endif
// 10.12 Embedded (Interleaved) Binary Data
// Stream data such as RTP packets is encapsulated by an ASCII dollar sign(24 hexadecimal),
// followed by a one-byte channel identifier,
// followed by the length of the encapsulated binary data as a binary two-byte integer in network byte order.
const uint8_t* rtp_over_rtsp(struct rtp_over_rtsp_t *rtp, const uint8_t* data, const uint8_t* end)
{
int n;
for (n = 0; data < end; data++)
{
switch (rtp->state)
{
case rtp_start:
if (*data != '$') {
#if defined(RTP_OVER_RTSP_TRY_TO_FIND_NEXT_PACKET)
return rtp_over_rtsp_try_to_find_next_packet(rtp, data, end);
#else
return end;
#endif
}
rtp->bytes = 0;
rtp->state = rtp_channel;
break;
case rtp_channel:
// The channel identifier is defined in the Transport header with
// the interleaved parameter(Section 12.39).
rtp->channel = *data;
rtp->state = rtp_length_1;
break;
case rtp_length_1:
rtp->length = *data << 8;
rtp->state = rtp_length_2;
break;
case rtp_length_2:
rtp->length |= *data;
rtp->state = rtp_data;
break;
case rtp_data:
if (0 == rtp->bytes && 0 != rtp_alloc(rtp))
return end;
n = (int)(end - data);
n = VMIN(rtp->length - rtp->bytes, n);
memcpy(rtp->data + rtp->bytes, data, n);
rtp->bytes += (uint16_t)n;
#if defined(RTP_OVER_RTSP_TRY_TO_FIND_NEXT_PACKET)
if (rtp->bytes >= 12)
{
uint32_t ssrc;
ssrc = *(uint32_t*)(rtp->data + 8);
if (rtp->check)
{
if (rtp->channel >= sizeof(rtp->ssrc) / sizeof(rtp->ssrc[0])
|| ssrc != rtp->ssrc[rtp->channel]
|| RTP_VERSION != (*rtp->data >> 6))
{
rtp->state = rtp_start;
return rtp_over_rtsp_try_to_find_next_packet(rtp, data, end);
}
rtp->check = 0;
}
else if(rtp->channel < sizeof(rtp->ssrc) / sizeof(rtp->ssrc[0]) && 0 == rtp->ssrc[rtp->channel])
{
assert(RTP_VERSION == (*rtp->data >> 6));
//assert(0 == rtp->ssrc[rtp->channel] || ssrc == rtp->ssrc[rtp->channel]);
rtp->ssrc[rtp->channel] = ssrc;
}
}
#endif
data += n;
if (rtp->bytes == rtp->length)
{
rtp->state = rtp_start;
if(rtp->onrtp)
rtp->onrtp(rtp->param, rtp->channel, rtp->data, rtp->length);
return data;
}
break;
default:
assert(0);
return end;
}
}
return data;
}