diff --git a/rtcp.c b/rtcp.c index 57ffc4b..2efa4e6 100644 --- a/rtcp.c +++ b/rtcp.c @@ -29,12 +29,60 @@ int cSatipRtcp::GetFd(void) return Fd(); } +int cSatipRtcp::GetApplicationOffset(int *lengthP) +{ + //debug("cSatipRtcp::%s()", __FUNCTION__); + if (!lengthP) + return -1; + int offset = 0; + int total = *lengthP; + while (total > 0) { + // Version + unsigned int v = (bufferM[offset] >> 6) & 0x03; + // Padding + //unsigned int p = (bufferM[offset] >> 5) & 0x01; + // Subtype + //unsigned int st = bufferM[offset] & 0x1F; + // Payload type + unsigned int pt = bufferM[offset + 1] & 0xFF; + // Lenght + unsigned int length = ((bufferM[offset + 2] & 0xFF) << 8) | (bufferM[offset + 3] & 0xFF); + // Convert it to bytes + length = (length + 1) * 4; + // V=2, APP = 204 + if ((v == 2) && (pt == 204)) { + // SSCR/CSCR + //unsigned int ssrc = ((bufferM[offset + 4] & 0xFF) << 24) | ((bufferM[offset + 5] & 0xFF) << 16) | + // ((bufferM[offset + 6] & 0xFF) << 8) | (bufferM[offset + 7] & 0xFF); + // Name + if ((bufferM[offset + 8] == 'S') && (bufferM[offset + 9] == 'E') && + (bufferM[offset + 10] == 'S') && (bufferM[offset + 11] == '1')) { + // Identifier + //unsigned int id = ((bufferM[offset + 12] & 0xFF) << 8) | (bufferM[offset + 13] & 0xFF); + // String length + int string_length = ((bufferM[offset + 14] & 0xFF) << 8) | (bufferM[offset + 15] & 0xFF); + if (string_length > 0) { + *lengthP = string_length; + return (offset + 16); + } + } + } + offset += length; + total -= length; + } + *lengthP = 0; + return -1; +} + void cSatipRtcp::Action(int fdP) { //debug("cSatipRtcp::%s(%d)", __FUNCTION__, fdP); if (bufferM) { - int length = ReadApplication(bufferM, bufferLenM); - if (length > 0) - tunerM->ParseReceptionParameters(bufferM, length); + int length = Read(bufferM, bufferLenM); + if (length > 0) { + int offset = GetApplicationOffset(&length); + if (offset >= 0) + tunerM->ParseReceptionParameters(bufferM + offset, length); + } } } diff --git a/rtcp.h b/rtcp.h index 4ea624d..1372244 100644 --- a/rtcp.h +++ b/rtcp.h @@ -19,6 +19,7 @@ private: cSatipTunerIf *tunerM; unsigned int bufferLenM; unsigned char *bufferM; + int GetApplicationOffset(int *lenghtP); protected: virtual int GetFd(void); diff --git a/rtp.c b/rtp.c index c756edd..44c9ad9 100644 --- a/rtp.c +++ b/rtp.c @@ -11,7 +11,10 @@ cSatipRtp::cSatipRtp(cSatipDeviceIf &deviceP, unsigned int bufferLenP) : deviceM(&deviceP), bufferLenM(bufferLenP), - bufferM(MALLOC(unsigned char, bufferLenM)) + bufferM(MALLOC(unsigned char, bufferLenM)), + lastErrorReportM(0), + packetErrorsM(0), + sequenceNumberM(-1) { if (bufferM) memset(bufferM, 0, bufferLenM); @@ -29,12 +32,83 @@ 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 = ReadVideo(bufferM, min(deviceM->CheckData(), bufferLenM)); - if (length > 0) - deviceM->WriteData(bufferM, length); + 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); + } } } diff --git a/rtp.h b/rtp.h index 0321538..b15c0a9 100644 --- a/rtp.h +++ b/rtp.h @@ -15,9 +15,16 @@ class cSatipRtp : public cSatipSocket, public cSatipPollerIf { private: + enum { + eReportIntervalS = 300 // in seconds + }; cSatipDeviceIf *deviceM; unsigned int bufferLenM; unsigned char *bufferM; + time_t lastErrorReportM; + int packetErrorsM; + int sequenceNumberM; + int GetHeaderLenght(int lengthP); protected: virtual int GetFd(void); @@ -26,6 +33,7 @@ protected: public: cSatipRtp(cSatipDeviceIf &deviceP, unsigned int bufferLenP); virtual ~cSatipRtp(); + virtual void Close(void); }; #endif /* __SATIP_RTP_H_ */ diff --git a/socket.c b/socket.c index 3ec2979..3ecde0d 100644 --- a/socket.c +++ b/socket.c @@ -20,10 +20,7 @@ cSatipSocket::cSatipSocket() : socketPortM(0), - socketDescM(-1), - lastErrorReportM(0), - packetErrorsM(0), - sequenceNumberM(-1) + socketDescM(-1) { debug("cSatipSocket::%s()", __FUNCTION__); memset(&sockAddrM, 0, sizeof(sockAddrM)); @@ -75,14 +72,8 @@ void cSatipSocket::Close(void) close(socketDescM); socketDescM = -1; socketPortM = 0; - sequenceNumberM = -1; memset(&sockAddrM, 0, sizeof(sockAddrM)); } - if (packetErrorsM) { - info("detected %d RTP packet errors", packetErrorsM); - packetErrorsM = 0; - lastErrorReportM = time(NULL); - } } bool cSatipSocket::Flush(void) @@ -141,104 +132,6 @@ int cSatipSocket::Read(unsigned char *bufferAddrP, unsigned int bufferLenP) return 0; } -int cSatipSocket::ReadVideo(unsigned char *bufferAddrP, unsigned int bufferLenP) -{ - //debug("cSatipSocket::%s()", __FUNCTION__); - int len = Read(bufferAddrP, bufferLenP); - if (len > 0) { - if (bufferAddrP[0] == TS_SYNC_BYTE) - return len; - else if (len > 3) { - // http://tools.ietf.org/html/rfc3550 - // http://tools.ietf.org/html/rfc2250 - // Version - unsigned int v = (bufferAddrP[0] >> 6) & 0x03; - // Extension bit - unsigned int x = (bufferAddrP[0] >> 4) & 0x01; - // CSCR count - unsigned int cc = bufferAddrP[0] & 0x0F; - // Payload type: MPEG2 TS = 33 - //unsigned int pt = bufferAddrP[1] & 0x7F; - // Sequence number - int seq = ((bufferAddrP[2] & 0xFF) << 8) | (bufferAddrP[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 - unsigned int headerlen = (3 + cc) * (unsigned int)sizeof(uint32_t); - // Check if extension - if (x) { - // Extension header length - unsigned int ehl = (((bufferAddrP[headerlen + 2] & 0xFF) << 8) | - (bufferAddrP[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) && (((len - headerlen) % TS_SIZE) == 0) && - (bufferAddrP[headerlen] == TS_SYNC_BYTE)) { - // Set argument point to payload in read buffer - memmove(bufferAddrP, &bufferAddrP[headerlen], (len - headerlen)); - return (len - headerlen); - } - } - } - return 0; -} - -int cSatipSocket::ReadApplication(unsigned char *bufferAddrP, unsigned int bufferLenP) -{ - //debug("cSatipSocket::%s()", __FUNCTION__); - int len = Read(bufferAddrP, bufferLenP); - int offset = 0; - while (len > 0) { - // Version - unsigned int v = (bufferAddrP[offset] >> 6) & 0x03; - // Padding - //unsigned int p = (bufferAddrP[offset] >> 5) & 0x01; - // Subtype - //unsigned int st = bufferAddrP[offset] & 0x1F; - // Payload type - unsigned int pt = bufferAddrP[offset + 1] & 0xFF; - // Lenght - unsigned int length = ((bufferAddrP[offset + 2] & 0xFF) << 8) | (bufferAddrP[offset + 3] & 0xFF); - // Convert it to bytes - length = (length + 1) * 4; - // V=2, APP = 204 - if ((v == 2) && (pt == 204)) { - // SSCR/CSCR - //unsigned int ssrc = ((bufferAddrP[offset + 4] & 0xFF) << 24) | ((bufferAddrP[offset + 5] & 0xFF) << 16) | - // ((bufferAddrP[offset + 6] & 0xFF) << 8) | (bufferAddrP[offset + 7] & 0xFF); - // Name - if ((bufferAddrP[offset + 8] == 'S') && (bufferAddrP[offset + 9] == 'E') && - (bufferAddrP[offset + 10] == 'S') && (bufferAddrP[offset + 11] == '1')) { - // Identifier - //unsigned int id = ((bufferAddrP[offset + 12] & 0xFF) << 8) | (bufferAddrP[offset + 13] & 0xFF); - // String length - int string_length = ((bufferAddrP[offset + 14] & 0xFF) << 8) | (bufferAddrP[offset + 15] & 0xFF); - if (string_length > 0) { - // Set argument point to payload in read buffer - memmove(bufferAddrP, &bufferAddrP[offset + 16], string_length); - bufferAddrP[string_length] = 0; - return string_length; - } - } - } - offset += length; - len -= length; - } - return 0; -} bool cSatipSocket::Write(const char *addrP, const unsigned char *bufferAddrP, unsigned int bufferLenP) { diff --git a/socket.h b/socket.h index aa082c7..a146551 100644 --- a/socket.h +++ b/socket.h @@ -12,28 +12,20 @@ class cSatipSocket { private: - enum { - eReportIntervalS = 300 // in seconds - }; int socketPortM; int socketDescM; struct sockaddr_in sockAddrM; - time_t lastErrorReportM; - int packetErrorsM; - int sequenceNumberM; public: cSatipSocket(); - ~cSatipSocket(); + virtual ~cSatipSocket(); bool Open(const int portP = 0); - void Close(void); + virtual void Close(void); int Fd(void) { return socketDescM; } int Port(void) { return socketPortM; } bool IsOpen(void) { return (socketDescM >= 0); } bool Flush(void); int Read(unsigned char *bufferAddrP, unsigned int bufferLenP); - int ReadVideo(unsigned char *bufferAddrP, unsigned int bufferLenP); - int ReadApplication(unsigned char *bufferAddrP, unsigned int bufferLenP); bool Write(const char *addrP, const unsigned char *bufferAddrP, unsigned int bufferLenP); };