vdr-plugin-satip/rtp.c

115 lines
3.3 KiB
C

/*
* rtp.c: SAT>IP plugin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
*/
#include "common.h"
#include "rtp.h"
cSatipRtp::cSatipRtp(cSatipDeviceIf &deviceP, unsigned int bufferLenP)
: deviceM(&deviceP),
bufferLenM(bufferLenP),
bufferM(MALLOC(unsigned char, bufferLenM)),
lastErrorReportM(0),
packetErrorsM(0),
sequenceNumberM(-1)
{
if (bufferM)
memset(bufferM, 0, bufferLenM);
else
error("Cannot create RTP buffer!");
}
cSatipRtp::~cSatipRtp()
{
DELETE_POINTER(bufferM);
}
int cSatipRtp::GetFd(void)
{
return Fd();
}
void cSatipRtp::Close(void)
{
debug("cSatipRtp::%s(%d)", __FUNCTION__, GetFd());
cSatipSocket::Close();
sequenceNumberM = -1;
if (packetErrorsM) {
info("Detected %d RTP packet errors", packetErrorsM);
packetErrorsM = 0;
lastErrorReportM = time(NULL);
}
}
int cSatipRtp::GetHeaderLenght(int lengthP)
{
//debug("cSatipRtp::%s()", __FUNCTION__);
unsigned int headerlen = 0;
if (lengthP > 0) {
if (bufferM[0] == TS_SYNC_BYTE)
return headerlen;
else if (lengthP > 3) {
// http://tools.ietf.org/html/rfc3550
// http://tools.ietf.org/html/rfc2250
// Version
unsigned int v = (bufferM[0] >> 6) & 0x03;
// Extension bit
unsigned int x = (bufferM[0] >> 4) & 0x01;
// CSCR count
unsigned int cc = bufferM[0] & 0x0F;
// Payload type: MPEG2 TS = 33
//unsigned int pt = bufferAddrP[1] & 0x7F;
// Sequence number
int seq = ((bufferM[2] & 0xFF) << 8) | (bufferM[3] & 0xFF);
if ((((sequenceNumberM + 1) % 0xFFFF) == 0) && (seq == 0xFFFF))
sequenceNumberM = -1;
else if ((sequenceNumberM >= 0) && (((sequenceNumberM + 1) % 0xFFFF) != seq)) {
packetErrorsM++;
if (time(NULL) - lastErrorReportM > eReportIntervalS) {
info("Detected %d RTP packet errors", packetErrorsM);
packetErrorsM = 0;
lastErrorReportM = time(NULL);
}
sequenceNumberM = seq;
}
else
sequenceNumberM = seq;
// Header lenght
headerlen = (3 + cc) * (unsigned int)sizeof(uint32_t);
// Check if extension
if (x) {
// Extension header length
unsigned int ehl = (((bufferM[headerlen + 2] & 0xFF) << 8) | (bufferM[headerlen + 3] & 0xFF));
// Update header length
headerlen += (ehl + 1) * (unsigned int)sizeof(uint32_t);
}
// Check that rtp is version 2 and payload contains multiple of TS packet data
if ((v != 2) || (((lengthP - headerlen) % TS_SIZE) != 0) || (bufferM[headerlen] != TS_SYNC_BYTE)) {
debug("cSatipRtp::%s(%d): Received incorrect RTP packet", __FUNCTION__, lengthP);
headerlen = -1;
}
}
}
return headerlen;
}
void cSatipRtp::Action(int fdP)
{
//debug("cSatipRtp::%s(%d)", __FUNCTION__, fdP);
if (bufferM) {
int length = Read(bufferM, min(deviceM->CheckData(), bufferLenM));
if (length > 0) {
int headerlen = GetHeaderLenght(length);
if ((headerlen >= 0) && (headerlen < length))
deviceM->WriteData(bufferM + headerlen, length - headerlen);
}
}
}