From 82cc56749b49a1bbacaff903d96aaf08b802c5ee Mon Sep 17 00:00:00 2001 From: lodoyun Date: Tue, 4 Mar 2014 11:49:43 +0100 Subject: [PATCH 1/4] Added packetqueue to handle rtp packets --- erizo/src/erizo/media/rtp/RtpHeader.h | 2 + erizo/src/erizo/media/rtp/RtpPacketQueue.cpp | 171 +++++++++++++++++++ erizo/src/erizo/media/rtp/RtpPacketQueue.h | 99 +++++++++++ 3 files changed, 272 insertions(+) create mode 100644 erizo/src/erizo/media/rtp/RtpPacketQueue.cpp create mode 100644 erizo/src/erizo/media/rtp/RtpPacketQueue.h diff --git a/erizo/src/erizo/media/rtp/RtpHeader.h b/erizo/src/erizo/media/rtp/RtpHeader.h index 00a8f7d83e..f995961409 100644 --- a/erizo/src/erizo/media/rtp/RtpHeader.h +++ b/erizo/src/erizo/media/rtp/RtpHeader.h @@ -8,6 +8,8 @@ #ifndef RTPHEADER_H_ #define RTPHEADER_H_ +#include + class RTPHeader { public: // constants diff --git a/erizo/src/erizo/media/rtp/RtpPacketQueue.cpp b/erizo/src/erizo/media/rtp/RtpPacketQueue.cpp new file mode 100644 index 0000000000..440c523f82 --- /dev/null +++ b/erizo/src/erizo/media/rtp/RtpPacketQueue.cpp @@ -0,0 +1,171 @@ +#include "RtpPacketQueue.h" +#include "RtpHeader.h" + +#include + +namespace erizo{ + + // ----------------------------------------------------------------------------- + // RtpPacketQueue::RtpPacketQueue + // + // ----------------------------------------------------------------------------- + // + RtpPacketQueue::RtpPacketQueue() + : lastNseq(0), lastTs(0) + { + } + + + // ----------------------------------------------------------------------------- + // RtpPacketQueue::~RtpPacketQueue + // + // ----------------------------------------------------------------------------- + // + RtpPacketQueue::~RtpPacketQueue(void) + { + cleanQueue(); + } + + // ----------------------------------------------------------------------------- + // RtpPacketQueue::packetReceived + // + // ----------------------------------------------------------------------------- + // + void RtpPacketQueue::packetReceived(const unsigned char *data, int length) + { + //channel->packetReceived2(data, length); + //return; + + const RTPHeader *header = reinterpret_cast(data); + uint16_t nseq = header->getSeqNumber(); + uint32_t ts = header->getTimestamp(); + + long long int ltsdiff = (long long int)ts - (long long int)lastTs; + int tsdiff = (int)ltsdiff; + int nseqdiff = nseq - lastNseq; + /* + // nseq sequence cicle test + if ( abs(nseqdiff) > ( USHRT_MAX - MAX_DIFF ) ) + { + NOTIFY("Vuelta del NSeq ns=%d last=%d\n", nseq, lastNseq); + if (nseqdiff > 0) + nseqdiff-= (USHRT_MAX + 1); + else + nseqdiff+= (USHRT_MAX + 1); + } + */ + if (abs(tsdiff) > MAX_DIFF_TS || abs(nseqdiff) > MAX_DIFF ) + { + // new flow, process and clean queue + //channel->packetReceived2(data, length); + lastNseq = nseq; + lastTs = ts; + cleanQueue(); + } + else if (nseqdiff > 1) + { + // Jump in nseq, enqueue + enqueuePacket(data, length, nseq); + checkQueue(); + } + else if (nseqdiff == 1) + { + // next packet, process + // channel->packetReceived2(data, length); + lastNseq = nseq; + lastTs = ts; + checkQueue(); + } + else if (nseqdiff < 0) + { + // old packet, discard? + // stats? + } + else if (nseqdiff == 0) + { + //duplicate packet, process (for stats)? + } + } + + // ----------------------------------------------------------------------------- + // RtpPacketQueue::enqueuePacket + // + // ----------------------------------------------------------------------------- + // + void + RtpPacketQueue::enqueuePacket(const unsigned char *data, int length, uint16_t nseq) + { + unsigned char *buf = new unsigned char[length]; + memcpy(buf, data, length); + queue.insert(PACKETQUEUE::value_type(nseq, buf)); + lqueue.insert(LENGTHQ::value_type(nseq, length)); + } + + // ----------------------------------------------------------------------------- + // RtpPacketQueue::checkQueue + // + // ----------------------------------------------------------------------------- + // + void + RtpPacketQueue::checkQueue(void) + { + // Max size reached, send first + if (queue.size() >= MAX_SIZE) + { + sendFirst(); + } + // recorrer la cola para ver si hay paquetes que pueden ser enviados + while (queue.size() > 0) + { + if (queue.begin()->first == lastNseq + 1) + { + sendFirst(); + } + else + { + break; + } + } + } + + // ----------------------------------------------------------------------------- + // RtpPacketQueue::cleanQueue + // + // ----------------------------------------------------------------------------- + // + void + RtpPacketQueue::cleanQueue(void) + { + // vaciar el mapa + while (queue.size() > 0) + { + unsigned char *data = queue.begin()->second; + queue.erase(queue.begin()); + delete[] data; + } + lqueue.clear(); + } + + // ----------------------------------------------------------------------------- + // RtpPacketQueue::sendFirst + // + // ----------------------------------------------------------------------------- + // + void + RtpPacketQueue::sendFirst(void) + { + unsigned char *data = queue.begin()->second; + int length = lqueue.begin()->second; + + const RTPHeader *header = reinterpret_cast(data); + lastNseq = queue.begin()->first; + lastTs = header->getTimestamp(); + + //channel->packetReceived2(data, length); + queue.erase(queue.begin()); + lqueue.erase(lqueue.begin()); + + delete []data; + } + +} /* namespace erizo */ diff --git a/erizo/src/erizo/media/rtp/RtpPacketQueue.h b/erizo/src/erizo/media/rtp/RtpPacketQueue.h new file mode 100644 index 0000000000..6ed887a6ea --- /dev/null +++ b/erizo/src/erizo/media/rtp/RtpPacketQueue.h @@ -0,0 +1,99 @@ +#ifndef __RTPPACKETQUEUE_H__ +#define __RTPPACKETQUEUE_H__ + +#include +#include "logger.h" + +namespace erizo{ + + typedef std::map< int, unsigned char *> PACKETQUEUE; + typedef std::map< int, int > LENGTHQ; + + /** + * Esta clase se encarga de cuando llega un paquete pasarselo al playchannel si es el siguiente en el flujo o + * encolarlo si no. Los paquetes se mantienen en la cola hasta que llegan los paquetes desordenados o + * hasta que ha pasado el tiempo máximo en cola. + */ + class RtpPacketQueue + { + public: + + /** + * Constructor de la clase. + */ + RtpPacketQueue(); + + /** + * Destructor virtual + */ + virtual ~RtpPacketQueue(void); + + /** + * Método para procesar paquetes recibidos. + */ + void packetReceived(const unsigned char *data, int length); + + private: + + /** + * Guarda un paquete en la cola de paquetes + */ + void enqueuePacket(const unsigned char *data, int length, uint16_t nseq); + + /** + * Comprueba si hay que enviar alguno de los paquetes de la cola + */ + void checkQueue(void); + + /** + * Borra la cola + */ + void cleanQueue(void); + + /** + * Envia el primer paque de la cola + */ + void sendFirst(void); + + /** + * Numero maximo de diferencia entre un paquete y otro. + * Un numero mayor indicaria reseteo del numero de secuencia. + **/ + static const int MAX_DIFF = 25; + + /** + * Numero maximo de diferencia en TS entre un paquete y otro. + * Un numero mayor indicaria reseteo del numero del TS. + */ + static const int MAX_DIFF_TS = 5000; + + /** + * Tamaño de la cola de paquetes + */ + static const int MAX_SIZE = 10; + + /** + * cola de paquets + */ + PACKETQUEUE queue; + + /** + * cola con las longitudes de los paquetes + */ + LENGTHQ lqueue; + + /** + * Ultimo número de secuencia enviado hacia el playchannel + */ + uint16_t lastNseq; + + /** + * Timestamp del ultimo paquete recibido. + */ + uint32_t lastTs; + + }; +} /* namespace erizo */ + +#endif /* RTPPACKETQUEUE*/ + From 1ea178b774734943e1e77b199782b96974e616b3 Mon Sep 17 00:00:00 2001 From: lodoyun Date: Thu, 6 Mar 2014 11:23:38 +0100 Subject: [PATCH 2/4] Modified RtpPacketQueue to work with ExternalOutput, added logging --- erizo/src/erizo/media/ExternalOutput.cpp | 27 ++++++---- erizo/src/erizo/media/ExternalOutput.h | 3 ++ erizo/src/erizo/media/rtp/RtpPacketQueue.cpp | 51 ++++++++++++------- erizo/src/erizo/media/rtp/RtpPacketQueue.h | 24 ++++----- .../erizoController/log4cxx.properties | 3 +- 5 files changed, 68 insertions(+), 40 deletions(-) diff --git a/erizo/src/erizo/media/ExternalOutput.cpp b/erizo/src/erizo/media/ExternalOutput.cpp index 8110716f19..da3af5ee50 100644 --- a/erizo/src/erizo/media/ExternalOutput.cpp +++ b/erizo/src/erizo/media/ExternalOutput.cpp @@ -319,16 +319,11 @@ namespace erizo { return; } boost::mutex::scoped_lock lock(queueMutex_); - - if (packetQueue_.size()>1000){ - return; + if (type == VIDEO_PACKET){ + videoQueue_.packetReceived(buffer, length); + }else{ + audioQueue_.packetReceived(buffer, length); } - dataPacket p; - memset(p.data, 0,length); - memcpy(p.data, buffer, length); - p.type = type; - p.length = length; - packetQueue_.push(p); cond_.notify_one(); } @@ -365,7 +360,7 @@ namespace erizo { while (sending_ == true) { boost::unique_lock lock(queueMutex_); - while (packetQueue_.size() == 0) { + while ((!audioQueue_.getSize())&&(!videoQueue_.getSize())) { cond_.wait(lock); if (sending_ == false) { lock.unlock(); @@ -373,11 +368,23 @@ namespace erizo { } } + dataPacket *audioP = audioQueue_.getFirst(); + dataPacket *videoP = videoQueue_.getFirst(); + if (videoP){ + this->writeVideoData(videoP->data, videoP->length); + } + if (audioP){ + this->writeAudioData(audioP->data, audioP->length); + } + + /* if (packetQueue_.front().type == VIDEO_PACKET) { this->writeVideoData(packetQueue_.front().data, packetQueue_.front().length); } else { this->writeAudioData(packetQueue_.front().data, packetQueue_.front().length); } +*/ + packetQueue_.pop(); lock.unlock(); } diff --git a/erizo/src/erizo/media/ExternalOutput.h b/erizo/src/erizo/media/ExternalOutput.h index 56a0b25e25..6a4f60f8aa 100644 --- a/erizo/src/erizo/media/ExternalOutput.h +++ b/erizo/src/erizo/media/ExternalOutput.h @@ -5,6 +5,7 @@ #include #include #include "../MediaDefinitions.h" +#include "rtp/RtpPacketQueue.h" #include "codecs/VideoCodec.h" #include "codecs/AudioCodec.h" #include "MediaProcessor.h" @@ -32,8 +33,10 @@ namespace erizo{ private: OutputProcessor* op_; + RtpPacketQueue audioQueue_, videoQueue_; unsigned char* decodedBuffer_; char* sendVideoBuffer_; + std::string url; volatile bool sending_; diff --git a/erizo/src/erizo/media/rtp/RtpPacketQueue.cpp b/erizo/src/erizo/media/rtp/RtpPacketQueue.cpp index 440c523f82..11d38a8c91 100644 --- a/erizo/src/erizo/media/rtp/RtpPacketQueue.cpp +++ b/erizo/src/erizo/media/rtp/RtpPacketQueue.cpp @@ -1,10 +1,17 @@ +#include +#include + + +#include "../../MediaDefinitions.h" +#include "../../logger.h" #include "RtpPacketQueue.h" #include "RtpHeader.h" -#include namespace erizo{ + DEFINE_LOGGER(RtpPacketQueue, "RtpPacketQueue"); + // ----------------------------------------------------------------------------- // RtpPacketQueue::RtpPacketQueue // @@ -31,7 +38,7 @@ namespace erizo{ // // ----------------------------------------------------------------------------- // - void RtpPacketQueue::packetReceived(const unsigned char *data, int length) + void RtpPacketQueue::packetReceived(const char *data, int length) { //channel->packetReceived2(data, length); //return; @@ -66,7 +73,7 @@ namespace erizo{ { // Jump in nseq, enqueue enqueuePacket(data, length, nseq); - checkQueue(); +// checkQueue(); } else if (nseqdiff == 1) { @@ -74,7 +81,7 @@ namespace erizo{ // channel->packetReceived2(data, length); lastNseq = nseq; lastTs = ts; - checkQueue(); +// checkQueue(); } else if (nseqdiff < 0) { @@ -93,12 +100,19 @@ namespace erizo{ // ----------------------------------------------------------------------------- // void - RtpPacketQueue::enqueuePacket(const unsigned char *data, int length, uint16_t nseq) + RtpPacketQueue::enqueuePacket(const char *data, int length, uint16_t nseq) { + boost::shared_ptr packet(new dataPacket()); + memcpy(packet->data, data, length); + packet->length = length; + /* unsigned char *buf = new unsigned char[length]; memcpy(buf, data, length); queue.insert(PACKETQUEUE::value_type(nseq, buf)); lqueue.insert(LENGTHQ::value_type(nseq, length)); + */ + queue.insert(PACKETQUEUE::value_type(nseq,packet.get())); + } // ----------------------------------------------------------------------------- @@ -106,20 +120,21 @@ namespace erizo{ // // ----------------------------------------------------------------------------- // + void RtpPacketQueue::checkQueue(void) { // Max size reached, send first if (queue.size() >= MAX_SIZE) { - sendFirst(); + //sendFirst(); } // recorrer la cola para ver si hay paquetes que pueden ser enviados while (queue.size() > 0) { if (queue.begin()->first == lastNseq + 1) { - sendFirst(); + //sendFirst(); } else { @@ -139,11 +154,8 @@ namespace erizo{ // vaciar el mapa while (queue.size() > 0) { - unsigned char *data = queue.begin()->second; queue.erase(queue.begin()); - delete[] data; } - lqueue.clear(); } // ----------------------------------------------------------------------------- @@ -151,21 +163,26 @@ namespace erizo{ // // ----------------------------------------------------------------------------- // - void - RtpPacketQueue::sendFirst(void) + dataPacket *RtpPacketQueue::getFirst(void) { - unsigned char *data = queue.begin()->second; - int length = lqueue.begin()->second; + dataPacket *packet = queue.begin()->second; + if (packet == NULL){ + return packet; + } - const RTPHeader *header = reinterpret_cast(data); + const RTPHeader *header = reinterpret_cast(packet->data); lastNseq = queue.begin()->first; lastTs = header->getTimestamp(); //channel->packetReceived2(data, length); queue.erase(queue.begin()); - lqueue.erase(lqueue.begin()); + return packet; - delete []data; } + int RtpPacketQueue::getSize(){ + return queue.size(); + } + + } /* namespace erizo */ diff --git a/erizo/src/erizo/media/rtp/RtpPacketQueue.h b/erizo/src/erizo/media/rtp/RtpPacketQueue.h index 6ed887a6ea..314ae951b5 100644 --- a/erizo/src/erizo/media/rtp/RtpPacketQueue.h +++ b/erizo/src/erizo/media/rtp/RtpPacketQueue.h @@ -6,8 +6,9 @@ namespace erizo{ - typedef std::map< int, unsigned char *> PACKETQUEUE; - typedef std::map< int, int > LENGTHQ; + class dataPacket; + + typedef std::map< int, dataPacket* > PACKETQUEUE; /** * Esta clase se encarga de cuando llega un paquete pasarselo al playchannel si es el siguiente en el flujo o @@ -16,6 +17,7 @@ namespace erizo{ */ class RtpPacketQueue { + DECLARE_LOGGER(); public: /** @@ -31,14 +33,20 @@ namespace erizo{ /** * Método para procesar paquetes recibidos. */ - void packetReceived(const unsigned char *data, int length); + void packetReceived(const char *data, int length); + /** + * Envia el primer paque de la cola + */ + dataPacket* getFirst(void); + + int getSize(); private: /** * Guarda un paquete en la cola de paquetes */ - void enqueuePacket(const unsigned char *data, int length, uint16_t nseq); + void enqueuePacket(const char *data, int length, uint16_t nseq); /** * Comprueba si hay que enviar alguno de los paquetes de la cola @@ -50,10 +58,6 @@ namespace erizo{ */ void cleanQueue(void); - /** - * Envia el primer paque de la cola - */ - void sendFirst(void); /** * Numero maximo de diferencia entre un paquete y otro. @@ -77,10 +81,6 @@ namespace erizo{ */ PACKETQUEUE queue; - /** - * cola con las longitudes de los paquetes - */ - LENGTHQ lqueue; /** * Ultimo número de secuencia enviado hacia el playchannel diff --git a/erizo_controller/erizoController/log4cxx.properties b/erizo_controller/erizoController/log4cxx.properties index 87a38d836d..440089bf35 100644 --- a/erizo_controller/erizoController/log4cxx.properties +++ b/erizo_controller/erizoController/log4cxx.properties @@ -31,6 +31,7 @@ log4j.logger.media.ExternalOutput=DEBUG log4j.logger.media.rtp.RtpVP8Fragmenter=DEBUG log4j.logger.media.rtp.RtpParser=DEBUG +log4j.logger.media.rtp.RtpPacketQueue=DEBUG log4j.logger.media.mixers.VideoUtils=DEBUG log4j.logger.media.mixers.VideoMixer=DEBUG @@ -38,4 +39,4 @@ log4j.logger.media.mixers.VideoMixer=DEBUG log4j.logger.media.codecs.VideoEncoder=DEBUG log4j.logger.media.codecs.VideoDecoder=DEBUG log4j.logger.media.codecs.AudioEncoder=DEBUG -log4j.logger.media.codecs.AudioDecoder=DEBUG \ No newline at end of file +log4j.logger.media.codecs.AudioDecoder=DEBUG From 7b57bf95d0032d3d74cac1f0bd39532dee72ed3d Mon Sep 17 00:00:00 2001 From: lodoyun Date: Thu, 6 Mar 2014 13:07:34 +0100 Subject: [PATCH 3/4] switched paquetqueue to shared_ptr --- erizo/src/erizo/media/ExternalOutput.cpp | 16 ++++++------ erizo/src/erizo/media/rtp/RtpPacketQueue.cpp | 26 +++++++++---------- erizo/src/erizo/media/rtp/RtpPacketQueue.h | 8 +++--- .../erizoController/log4cxx.properties | 2 +- 4 files changed, 27 insertions(+), 25 deletions(-) diff --git a/erizo/src/erizo/media/ExternalOutput.cpp b/erizo/src/erizo/media/ExternalOutput.cpp index da3af5ee50..79dc00bc78 100644 --- a/erizo/src/erizo/media/ExternalOutput.cpp +++ b/erizo/src/erizo/media/ExternalOutput.cpp @@ -367,16 +367,17 @@ namespace erizo { return; } } - - dataPacket *audioP = audioQueue_.getFirst(); - dataPacket *videoP = videoQueue_.getFirst(); - if (videoP){ - this->writeVideoData(videoP->data, videoP->length); - } - if (audioP){ + if (audioQueue_.getSize()){ + ELOG_DEBUG("Getting Audio packet"); + boost::shared_ptr audioP = audioQueue_.getFirst(); this->writeAudioData(audioP->data, audioP->length); } + if (videoQueue_.getSize()) { + ELOG_DEBUG("Getting Video packet"); + boost::shared_ptr videoP = videoQueue_.getFirst(); + this->writeVideoData(videoP->data, videoP->length); + } /* if (packetQueue_.front().type == VIDEO_PACKET) { this->writeVideoData(packetQueue_.front().data, packetQueue_.front().length); @@ -385,7 +386,6 @@ namespace erizo { } */ - packetQueue_.pop(); lock.unlock(); } } diff --git a/erizo/src/erizo/media/rtp/RtpPacketQueue.cpp b/erizo/src/erizo/media/rtp/RtpPacketQueue.cpp index 11d38a8c91..7c88840c3b 100644 --- a/erizo/src/erizo/media/rtp/RtpPacketQueue.cpp +++ b/erizo/src/erizo/media/rtp/RtpPacketQueue.cpp @@ -1,9 +1,7 @@ #include -#include #include "../../MediaDefinitions.h" -#include "../../logger.h" #include "RtpPacketQueue.h" #include "RtpHeader.h" @@ -65,6 +63,7 @@ namespace erizo{ { // new flow, process and clean queue //channel->packetReceived2(data, length); + ELOG_DEBUG("Max diff reached, cleaning queue"); lastNseq = nseq; lastTs = ts; cleanQueue(); @@ -72,6 +71,7 @@ namespace erizo{ else if (nseqdiff > 1) { // Jump in nseq, enqueue + ELOG_DEBUG("Jump in nseq"); enqueuePacket(data, length, nseq); // checkQueue(); } @@ -81,15 +81,18 @@ namespace erizo{ // channel->packetReceived2(data, length); lastNseq = nseq; lastTs = ts; + enqueuePacket(data, length, nseq); // checkQueue(); } else if (nseqdiff < 0) { + ELOG_DEBUG("Old Packet Received"); // old packet, discard? // stats? } else if (nseqdiff == 0) { + ELOG_DEBUG("Duplicate Packet received"); //duplicate packet, process (for stats)? } } @@ -111,7 +114,7 @@ namespace erizo{ queue.insert(PACKETQUEUE::value_type(nseq, buf)); lqueue.insert(LENGTHQ::value_type(nseq, length)); */ - queue.insert(PACKETQUEUE::value_type(nseq,packet.get())); + queue.insert(PACKETQUEUE::value_type(nseq,packet)); } @@ -151,6 +154,7 @@ namespace erizo{ void RtpPacketQueue::cleanQueue(void) { + ELOG_DEBUG("Cleaning queue"); // vaciar el mapa while (queue.size() > 0) { @@ -163,26 +167,22 @@ namespace erizo{ // // ----------------------------------------------------------------------------- // - dataPacket *RtpPacketQueue::getFirst(void) + boost::shared_ptr RtpPacketQueue::getFirst(void) { - dataPacket *packet = queue.begin()->second; - if (packet == NULL){ +// dataPacket *packet = queue.begin()->second; + boost::shared_ptr packet = queue.begin()->second; + if (packet.get() == NULL){ return packet; } - const RTPHeader *header = reinterpret_cast(packet->data); lastNseq = queue.begin()->first; lastTs = header->getTimestamp(); - - //channel->packetReceived2(data, length); queue.erase(queue.begin()); return packet; - } int RtpPacketQueue::getSize(){ - return queue.size(); + uint16_t size = queue.size(); + return size; } - - } /* namespace erizo */ diff --git a/erizo/src/erizo/media/rtp/RtpPacketQueue.h b/erizo/src/erizo/media/rtp/RtpPacketQueue.h index 314ae951b5..8c7aabbd92 100644 --- a/erizo/src/erizo/media/rtp/RtpPacketQueue.h +++ b/erizo/src/erizo/media/rtp/RtpPacketQueue.h @@ -2,13 +2,15 @@ #define __RTPPACKETQUEUE_H__ #include +#include + #include "logger.h" namespace erizo{ class dataPacket; - typedef std::map< int, dataPacket* > PACKETQUEUE; + typedef std::map< int, boost::shared_ptr> PACKETQUEUE; /** * Esta clase se encarga de cuando llega un paquete pasarselo al playchannel si es el siguiente en el flujo o @@ -37,7 +39,7 @@ namespace erizo{ /** * Envia el primer paque de la cola */ - dataPacket* getFirst(void); + boost::shared_ptr getFirst(void); int getSize(); @@ -74,7 +76,7 @@ namespace erizo{ /** * Tamaño de la cola de paquetes */ - static const int MAX_SIZE = 10; + static const unsigned int MAX_SIZE = 10; /** * cola de paquets diff --git a/erizo_controller/erizoController/log4cxx.properties b/erizo_controller/erizoController/log4cxx.properties index 440089bf35..5ef52b97cf 100644 --- a/erizo_controller/erizoController/log4cxx.properties +++ b/erizo_controller/erizoController/log4cxx.properties @@ -31,7 +31,7 @@ log4j.logger.media.ExternalOutput=DEBUG log4j.logger.media.rtp.RtpVP8Fragmenter=DEBUG log4j.logger.media.rtp.RtpParser=DEBUG -log4j.logger.media.rtp.RtpPacketQueue=DEBUG +log4j.logger.media.rtp.RtpPacketQueue=INFO log4j.logger.media.mixers.VideoUtils=DEBUG log4j.logger.media.mixers.VideoMixer=DEBUG From c9455010f2d519a6ab62ce7ead663291a279a0b7 Mon Sep 17 00:00:00 2001 From: lodoyun Date: Thu, 6 Mar 2014 16:33:14 +0100 Subject: [PATCH 4/4] Added isRtcp method and fixed ExternalOutput to ignore RTCP --- erizo/src/erizo/SdesTransport.cpp | 5 +- erizo/src/erizo/WebRtcConnection.cpp | 6 +- erizo/src/erizo/media/ExternalOutput.cpp | 18 +- erizo/src/erizo/media/ExternalOutput.h | 2 - erizo/src/erizo/media/rtp/RtpPacketQueue.cpp | 158 ++----- erizo/src/erizo/media/rtp/RtpPacketQueue.h | 95 +--- erizo/src/erizo/rtputils.h | 445 ++++++++++--------- 7 files changed, 303 insertions(+), 426 deletions(-) diff --git a/erizo/src/erizo/SdesTransport.cpp b/erizo/src/erizo/SdesTransport.cpp index 93b6d9b584..369c12ce01 100644 --- a/erizo/src/erizo/SdesTransport.cpp +++ b/erizo/src/erizo/SdesTransport.cpp @@ -69,10 +69,7 @@ void SdesTransport::onNiceData(unsigned int component_id, char* data, int len, N } rtcpheader *chead = reinterpret_cast (unprotectBuf_); - if (chead->packettype == RTCP_Sender_PT || - chead->packettype == RTCP_Receiver_PT || - chead->packettype == RTCP_PS_Feedback_PT|| - chead->packettype == RTCP_RTP_Feedback_PT){ + if (chead->isRtcp()){ if(srtp->unprotectRtcp(unprotectBuf_, &length)<0) return; } else { diff --git a/erizo/src/erizo/WebRtcConnection.cpp b/erizo/src/erizo/WebRtcConnection.cpp index 29d55f0ba2..00079047a6 100644 --- a/erizo/src/erizo/WebRtcConnection.cpp +++ b/erizo/src/erizo/WebRtcConnection.cpp @@ -194,7 +194,7 @@ namespace erizo { int WebRtcConnection::deliverFeedback(char* buf, int len){ // Check where to send the feedback - rtcpheader *chead = (rtcpheader*) buf; + rtcpheader *chead = reinterpret_cast (buf); ELOG_DEBUG("received Feedback type %u ssrc %u, sourcessrc %u", chead->packettype, ntohl(chead->ssrc), ntohl(chead->ssrcsource)); if (ntohl(chead->ssrcsource) == this->getAudioSourceSSRC()) { writeSsrc(buf,len,this->getAudioSinkSSRC()); @@ -216,10 +216,10 @@ namespace erizo { } void WebRtcConnection::writeSsrc(char* buf, int len, unsigned int ssrc) { - rtpheader *head = (rtpheader*) buf; + rtpheader *head = reinterpret_cast (buf); rtcpheader *chead = reinterpret_cast (buf); //if it is RTCP we check it it is a compound packet - if (chead->packettype == RTCP_Sender_PT || chead->packettype == RTCP_Receiver_PT || chead->packettype == RTCP_PS_Feedback_PT || chead->packettype == RTCP_RTP_Feedback_PT) { + if (chead->isRtcp()) { processRtcpHeaders(buf,len,ssrc); } else { head->ssrc=htonl(ssrc); diff --git a/erizo/src/erizo/media/ExternalOutput.cpp b/erizo/src/erizo/media/ExternalOutput.cpp index 79dc00bc78..7e708e0d2c 100644 --- a/erizo/src/erizo/media/ExternalOutput.cpp +++ b/erizo/src/erizo/media/ExternalOutput.cpp @@ -246,11 +246,19 @@ namespace erizo { } int ExternalOutput::deliverAudioData(char* buf, int len) { + rtcpheader *head = reinterpret_cast(buf); + if (head->isRtcp()){ + return 0; + } this->queueData(buf,len,AUDIO_PACKET); return 0; } int ExternalOutput::deliverVideoData(char* buf, int len) { + rtcpheader *head = reinterpret_cast(buf); + if (head->isRtcp()){ + return 0; + } this->queueData(buf,len,VIDEO_PACKET); return 0; } @@ -320,9 +328,9 @@ namespace erizo { } boost::mutex::scoped_lock lock(queueMutex_); if (type == VIDEO_PACKET){ - videoQueue_.packetReceived(buffer, length); + videoQueue_.pushPacket(buffer, length); }else{ - audioQueue_.packetReceived(buffer, length); + audioQueue_.pushPacket(buffer, length); } cond_.notify_one(); @@ -368,13 +376,11 @@ namespace erizo { } } if (audioQueue_.getSize()){ - ELOG_DEBUG("Getting Audio packet"); - boost::shared_ptr audioP = audioQueue_.getFirst(); + boost::shared_ptr audioP = audioQueue_.popPacket(); this->writeAudioData(audioP->data, audioP->length); } if (videoQueue_.getSize()) { - ELOG_DEBUG("Getting Video packet"); - boost::shared_ptr videoP = videoQueue_.getFirst(); + boost::shared_ptr videoP = videoQueue_.popPacket(); this->writeVideoData(videoP->data, videoP->length); } diff --git a/erizo/src/erizo/media/ExternalOutput.h b/erizo/src/erizo/media/ExternalOutput.h index 6a4f60f8aa..8df70752b8 100644 --- a/erizo/src/erizo/media/ExternalOutput.h +++ b/erizo/src/erizo/media/ExternalOutput.h @@ -3,7 +3,6 @@ #include #include -#include #include "../MediaDefinitions.h" #include "rtp/RtpPacketQueue.h" #include "codecs/VideoCodec.h" @@ -43,7 +42,6 @@ namespace erizo{ boost::mutex queueMutex_; boost::thread thread_; boost::condition_variable cond_; - std::queue packetQueue_; AVStream *video_st, *audio_st; AudioEncoder* audioCoder_; diff --git a/erizo/src/erizo/media/rtp/RtpPacketQueue.cpp b/erizo/src/erizo/media/rtp/RtpPacketQueue.cpp index 7c88840c3b..5b704e73d2 100644 --- a/erizo/src/erizo/media/rtp/RtpPacketQueue.cpp +++ b/erizo/src/erizo/media/rtp/RtpPacketQueue.cpp @@ -1,71 +1,53 @@ #include - -#include "../../MediaDefinitions.h" #include "RtpPacketQueue.h" +#include "../../MediaDefinitions.h" #include "RtpHeader.h" namespace erizo{ DEFINE_LOGGER(RtpPacketQueue, "RtpPacketQueue"); - - // ----------------------------------------------------------------------------- - // RtpPacketQueue::RtpPacketQueue - // - // ----------------------------------------------------------------------------- - // + RtpPacketQueue::RtpPacketQueue() - : lastNseq(0), lastTs(0) + : lastNseq_(0), lastTs_(0) { } - - // ----------------------------------------------------------------------------- - // RtpPacketQueue::~RtpPacketQueue - // - // ----------------------------------------------------------------------------- - // RtpPacketQueue::~RtpPacketQueue(void) { cleanQueue(); } - // ----------------------------------------------------------------------------- - // RtpPacketQueue::packetReceived - // - // ----------------------------------------------------------------------------- - // - void RtpPacketQueue::packetReceived(const char *data, int length) + void RtpPacketQueue::pushPacket(const char *data, int length) { - //channel->packetReceived2(data, length); - //return; const RTPHeader *header = reinterpret_cast(data); uint16_t nseq = header->getSeqNumber(); uint32_t ts = header->getTimestamp(); - long long int ltsdiff = (long long int)ts - (long long int)lastTs; + long long int ltsdiff = (long long int)ts - (long long int)lastTs_; int tsdiff = (int)ltsdiff; - int nseqdiff = nseq - lastNseq; + int nseqdiff = nseq - lastNseq_; /* // nseq sequence cicle test if ( abs(nseqdiff) > ( USHRT_MAX - MAX_DIFF ) ) { - NOTIFY("Vuelta del NSeq ns=%d last=%d\n", nseq, lastNseq); + NOTIFY("Vuelta del NSeq ns=%d last=%d\n", nseq, lastNseq_); if (nseqdiff > 0) nseqdiff-= (USHRT_MAX + 1); else nseqdiff+= (USHRT_MAX + 1); } */ + if (abs(tsdiff) > MAX_DIFF_TS || abs(nseqdiff) > MAX_DIFF ) { // new flow, process and clean queue - //channel->packetReceived2(data, length); - ELOG_DEBUG("Max diff reached, cleaning queue"); - lastNseq = nseq; - lastTs = ts; + ELOG_DEBUG("Max diff reached, new Flow? nsqediff %d , tsdiff %d", nseqdiff, tsdiff); + ELOG_DEBUG("PT %d", header->getPayloadType()); + lastNseq_ = nseq; + lastTs_ = ts; cleanQueue(); } else if (nseqdiff > 1) @@ -73,16 +55,13 @@ namespace erizo{ // Jump in nseq, enqueue ELOG_DEBUG("Jump in nseq"); enqueuePacket(data, length, nseq); -// checkQueue(); } else if (nseqdiff == 1) { // next packet, process - // channel->packetReceived2(data, length); - lastNseq = nseq; - lastTs = ts; + lastNseq_ = nseq; + lastTs_ = ts; enqueuePacket(data, length, nseq); -// checkQueue(); } else if (nseqdiff < 0) { @@ -97,92 +76,39 @@ namespace erizo{ } } - // ----------------------------------------------------------------------------- - // RtpPacketQueue::enqueuePacket - // - // ----------------------------------------------------------------------------- - // - void - RtpPacketQueue::enqueuePacket(const char *data, int length, uint16_t nseq) - { - boost::shared_ptr packet(new dataPacket()); - memcpy(packet->data, data, length); - packet->length = length; - /* - unsigned char *buf = new unsigned char[length]; - memcpy(buf, data, length); - queue.insert(PACKETQUEUE::value_type(nseq, buf)); - lqueue.insert(LENGTHQ::value_type(nseq, length)); - */ - queue.insert(PACKETQUEUE::value_type(nseq,packet)); - + void RtpPacketQueue::enqueuePacket(const char *data, int length, uint16_t nseq) + { + if (queue_.size() > MAX_SIZE) { // if queue is growing too much, we start again + cleanQueue(); } - // ----------------------------------------------------------------------------- - // RtpPacketQueue::checkQueue - // - // ----------------------------------------------------------------------------- - // - - void - RtpPacketQueue::checkQueue(void) - { - // Max size reached, send first - if (queue.size() >= MAX_SIZE) - { - //sendFirst(); - } - // recorrer la cola para ver si hay paquetes que pueden ser enviados - while (queue.size() > 0) - { - if (queue.begin()->first == lastNseq + 1) - { - //sendFirst(); - } - else - { - break; - } - } - } + boost::shared_ptr packet(new dataPacket()); + memcpy(packet->data, data, length); + packet->length = length; + queue_.insert(std::map< int, boost::shared_ptr>::value_type(nseq,packet)); - // ----------------------------------------------------------------------------- - // RtpPacketQueue::cleanQueue - // - // ----------------------------------------------------------------------------- - // - void - RtpPacketQueue::cleanQueue(void) - { - ELOG_DEBUG("Cleaning queue"); - // vaciar el mapa - while (queue.size() > 0) - { - queue.erase(queue.begin()); - } - } + } - // ----------------------------------------------------------------------------- - // RtpPacketQueue::sendFirst - // - // ----------------------------------------------------------------------------- - // - boost::shared_ptr RtpPacketQueue::getFirst(void) - { -// dataPacket *packet = queue.begin()->second; - boost::shared_ptr packet = queue.begin()->second; - if (packet.get() == NULL){ - return packet; - } - const RTPHeader *header = reinterpret_cast(packet->data); - lastNseq = queue.begin()->first; - lastTs = header->getTimestamp(); - queue.erase(queue.begin()); + void RtpPacketQueue::cleanQueue() + { + queue_.clear(); + } + + boost::shared_ptr RtpPacketQueue::popPacket() + { + boost::shared_ptr packet = queue_.begin()->second; + if (packet.get() == NULL){ return packet; } + const RTPHeader *header = reinterpret_cast(packet->data); + lastNseq_ = queue_.begin()->first; + lastTs_ = header->getTimestamp(); + queue_.erase(queue_.begin()); + return packet; + } - int RtpPacketQueue::getSize(){ - uint16_t size = queue.size(); - return size; - } + int RtpPacketQueue::getSize(){ + uint16_t size = queue_.size(); + return size; + } } /* namespace erizo */ diff --git a/erizo/src/erizo/media/rtp/RtpPacketQueue.h b/erizo/src/erizo/media/rtp/RtpPacketQueue.h index 8c7aabbd92..a61754504f 100644 --- a/erizo/src/erizo/media/rtp/RtpPacketQueue.h +++ b/erizo/src/erizo/media/rtp/RtpPacketQueue.h @@ -7,92 +7,31 @@ #include "logger.h" namespace erizo{ - + //forward declaration class dataPacket; - - typedef std::map< int, boost::shared_ptr> PACKETQUEUE; - - /** - * Esta clase se encarga de cuando llega un paquete pasarselo al playchannel si es el siguiente en el flujo o - * encolarlo si no. Los paquetes se mantienen en la cola hasta que llegan los paquetes desordenados o - * hasta que ha pasado el tiempo máximo en cola. - */ + class RtpPacketQueue { DECLARE_LOGGER(); - public: - - /** - * Constructor de la clase. - */ - RtpPacketQueue(); - /** - * Destructor virtual - */ - virtual ~RtpPacketQueue(void); - - /** - * Método para procesar paquetes recibidos. - */ - void packetReceived(const char *data, int length); - /** - * Envia el primer paque de la cola - */ - boost::shared_ptr getFirst(void); + public: + RtpPacketQueue(); + virtual ~RtpPacketQueue(void); - int getSize(); + void pushPacket(const char *data, int length); + boost::shared_ptr popPacket(); + int getSize(); private: - - /** - * Guarda un paquete en la cola de paquetes - */ - void enqueuePacket(const char *data, int length, uint16_t nseq); - - /** - * Comprueba si hay que enviar alguno de los paquetes de la cola - */ - void checkQueue(void); - - /** - * Borra la cola - */ - void cleanQueue(void); - - - /** - * Numero maximo de diferencia entre un paquete y otro. - * Un numero mayor indicaria reseteo del numero de secuencia. - **/ - static const int MAX_DIFF = 25; - - /** - * Numero maximo de diferencia en TS entre un paquete y otro. - * Un numero mayor indicaria reseteo del numero del TS. - */ - static const int MAX_DIFF_TS = 5000; - - /** - * Tamaño de la cola de paquetes - */ - static const unsigned int MAX_SIZE = 10; - - /** - * cola de paquets - */ - PACKETQUEUE queue; - - - /** - * Ultimo número de secuencia enviado hacia el playchannel - */ - uint16_t lastNseq; - - /** - * Timestamp del ultimo paquete recibido. - */ - uint32_t lastTs; + static const int MAX_DIFF = 50; + static const int MAX_DIFF_TS = 50000; + static const unsigned int MAX_SIZE = 10; + std::map< int, boost::shared_ptr> queue_; + uint16_t lastNseq_; + uint32_t lastTs_; + + void enqueuePacket(const char *data, int length, uint16_t nseq); + void cleanQueue(void); }; } /* namespace erizo */ diff --git a/erizo/src/erizo/rtputils.h b/erizo/src/erizo/rtputils.h index 16de762834..a59a33e1dc 100644 --- a/erizo/src/erizo/rtputils.h +++ b/erizo/src/erizo/rtputils.h @@ -7,132 +7,153 @@ #include -// 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 | -// | .... | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +namespace erizo{ + // Payload types +#define RTCP_Sender_PT 200 // RTCP Sender Report +#define RTCP_Receiver_PT 201 // RTCP Receiver Report +#define RTCP_RTP_Feedback_PT 205 // RTCP Transport Layer Feedback Packet +#define RTCP_PS_Feedback_PT 206 // RTCP Payload Specific Feedback Packet + +#define VP8_90000_PT 100 // VP8 Video Codec +#define RED_90000_PT 116 // REDundancy (RFC 2198) +#define ULP_90000_PT 117 // ULP/FEC +#define ISAC_16000_PT 103 // ISAC Audio Codec +#define ISAC_32000_PT 104 // ISAC Audio Codec +#define PCMU_8000_PT 0 // PCMU Audio Codec +#define OPUS_48000_PT 111 // Opus Audio Codec +#define PCMA_8000_PT 8 // PCMA Audio Codec +#define CN_8000_PT 13 // CN Audio Codec +#define CN_16000_PT 105 // CN Audio Codec +#define CN_32000_PT 106 // CN Audio Codec +#define CN_48000_PT 107 // CN Audio Codec +#define TEL_8000_PT 126 // Tel Audio Events -// The first twelve octets are present in every RTP packet, while the -// list of CSRC identifiers is present only when inserted by a mixer. -// The fields have the following meaning: + // 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 | + // | .... | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// version (V): 2 bits -// This field identifies the version of RTP. The version defined by -// this specification is two (2). (The value 1 is used by the first -// draft version of RTP and the value 0 is used by the protocol -// initially implemented in the "vat" audio tool.) + // The first twelve octets are present in every RTP packet, while the + // list of CSRC identifiers is present only when inserted by a mixer. + // The fields have the following meaning: -// padding (P): 1 bit -// If the padding bit is set, the packet contains one or more -// additional padding octets at the end which are not part of the -// payload. The last octet of the padding contains a count of how -// many padding octets should be ignored. Padding may be needed by -// some encryption algorithms with fixed block sizes or for -// carrying several RTP packets in a lower-layer protocol data -// unit. + // version (V): 2 bits + // This field identifies the version of RTP. The version defined by + // this specification is two (2). (The value 1 is used by the first + // draft version of RTP and the value 0 is used by the protocol + // initially implemented in the "vat" audio tool.) -// extension (X): 1 bit -// If the extension bit is set, the fixed header is followed by -// exactly one header extension, with a format defined in Section -// 5.3.1. + // padding (P): 1 bit + // If the padding bit is set, the packet contains one or more + // additional padding octets at the end which are not part of the + // payload. The last octet of the padding contains a count of how + // many padding octets should be ignored. Padding may be needed by + // some encryption algorithms with fixed block sizes or for + // carrying several RTP packets in a lower-layer protocol data + // unit. -// CSRC count (CC): 4 bits -// The CSRC count contains the number of CSRC identifiers that -// follow the fixed header. + // extension (X): 1 bit + // If the extension bit is set, the fixed header is followed by + // exactly one header extension, with a format defined in Section + // 5.3.1. -// marker (M): 1 bit -// The interpretation of the marker is defined by a profile. It is -// intended to allow significant events such as frame boundaries to -// be marked in the packet stream. A profile may define additional -// marker bits or specify that there is no marker bit by changing -// the number of bits in the payload type field (see Section 5.3). + // CSRC count (CC): 4 bits + // The CSRC count contains the number of CSRC identifiers that + // follow the fixed header. -// payload type (PT): 7 bits -// This field identifies the format of the RTP payload and -// determines its interpretation by the application. A profile -// specifies a default static mapping of payload type codes to -// payload formats. Additional payload type codes may be defined -// dynamically through non-RTP means (see Section 3). An initial -// set of default mappings for audio and video is specified in the -// companion profile Internet-Draft draft-ietf-avt-profile, and -// may be extended in future editions of the Assigned Numbers RFC -// [6]. An RTP sender emits a single RTP payload type at any given -// time; this field is not intended for multiplexing separate media -// streams (see Section 5.2). + // marker (M): 1 bit + // The interpretation of the marker is defined by a profile. It is + // intended to allow significant events such as frame boundaries to + // be marked in the packet stream. A profile may define additional + // marker bits or specify that there is no marker bit by changing + // the number of bits in the payload type field (see Section 5.3). -// sequence number: 16 bits -// The sequence number increments by one for each RTP data packet -// sent, and may be used by the receiver to detect packet loss and -// to restore packet sequence. The initial value of the sequence -// number is random (unpredictable) to make known-plaintext attacks -// on encryption more difficult, even if the source itself does not -// encrypt, because the packets may flow through a translator that -// does. Techniques for choosing unpredictable numbers are -// discussed in [7]. + // payload type (PT): 7 bits + // This field identifies the format of the RTP payload and + // determines its interpretation by the application. A profile + // specifies a default static mapping of payload type codes to + // payload formats. Additional payload type codes may be defined + // dynamically through non-RTP means (see Section 3). An initial + // set of default mappings for audio and video is specified in the + // companion profile Internet-Draft draft-ietf-avt-profile, and + // may be extended in future editions of the Assigned Numbers RFC + // [6]. An RTP sender emits a single RTP payload type at any given + // time; this field is not intended for multiplexing separate media + // streams (see Section 5.2). -// timestamp: 32 bits -// The timestamp reflects the sampling instant of the first octet -// in the RTP data packet. The sampling instant must be derived -// from a clock that increments monotonically and linearly in time -// to allow synchronization and jitter calculations (see Section -// 6.3.1). The resolution of the clock must be sufficient for the -// desired synchronization accuracy and for measuring packet -// arrival jitter (one tick per video frame is typically not -// sufficient). The clock frequency is dependent on the format of -// data carried as payload and is specified statically in the -// profile or payload format specification that defines the format, -// or may be specified dynamically for payload formats defined -// through non-RTP means. If RTP packets are generated -// periodically, the nominal sampling instant as determined from -// the sampling clock is to be used, not a reading of the system -// clock. As an example, for fixed-rate audio the timestamp clock -// would likely increment by one for each sampling period. If an -// audio application reads blocks covering 160 sampling periods -// from the input device, the timestamp would be increased by 160 -// for each such block, regardless of whether the block is -// transmitted in a packet or dropped as silent. + // sequence number: 16 bits + // The sequence number increments by one for each RTP data packet + // sent, and may be used by the receiver to detect packet loss and + // to restore packet sequence. The initial value of the sequence + // number is random (unpredictable) to make known-plaintext attacks + // on encryption more difficult, even if the source itself does not + // encrypt, because the packets may flow through a translator that + // does. Techniques for choosing unpredictable numbers are + // discussed in [7]. -// The initial value of the timestamp is random, as for the sequence -// number. Several consecutive RTP packets may have equal timestamps if -// they are (logically) generated at once, e.g., belong to the same -// video frame. Consecutive RTP packets may contain timestamps that are -// not monotonic if the data is not transmitted in the order it was -// sampled, as in the case of MPEG interpolated video frames. (The -// sequence numbers of the packets as transmitted will still be -// monotonic.) + // timestamp: 32 bits + // The timestamp reflects the sampling instant of the first octet + // in the RTP data packet. The sampling instant must be derived + // from a clock that increments monotonically and linearly in time + // to allow synchronization and jitter calculations (see Section + // 6.3.1). The resolution of the clock must be sufficient for the + // desired synchronization accuracy and for measuring packet + // arrival jitter (one tick per video frame is typically not + // sufficient). The clock frequency is dependent on the format of + // data carried as payload and is specified statically in the + // profile or payload format specification that defines the format, + // or may be specified dynamically for payload formats defined + // through non-RTP means. If RTP packets are generated + // periodically, the nominal sampling instant as determined from + // the sampling clock is to be used, not a reading of the system + // clock. As an example, for fixed-rate audio the timestamp clock + // would likely increment by one for each sampling period. If an + // audio application reads blocks covering 160 sampling periods + // from the input device, the timestamp would be increased by 160 + // for each such block, regardless of whether the block is + // transmitted in a packet or dropped as silent. -// SSRC: 32 bits -// The SSRC field identifies the synchronization source. This -// identifier is chosen randomly, with the intent that no two -// synchronization sources within the same RTP session will have -// the same SSRC identifier. An example algorithm for generating a -// random identifier is presented in Appendix A.6. Although the -// probability of multiple sources choosing the same identifier is -// low, all RTP implementations must be prepared to detect and -// resolve collisions. Section 8 describes the probability of -// collision along with a mechanism for resolving collisions and -// detecting RTP-level forwarding loops based on the uniqueness of -// the SSRC identifier. If a source changes its source transport -// address, it must also choose a new SSRC identifier to avoid -// being interpreted as a looped source. + // The initial value of the timestamp is random, as for the sequence + // number. Several consecutive RTP packets may have equal timestamps if + // they are (logically) generated at once, e.g., belong to the same + // video frame. Consecutive RTP packets may contain timestamps that are + // not monotonic if the data is not transmitted in the order it was + // sampled, as in the case of MPEG interpolated video frames. (The + // sequence numbers of the packets as transmitted will still be + // monotonic.) -// 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 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | defined by profile | length | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | header extension | -// | .... | + // SSRC: 32 bits + // The SSRC field identifies the synchronization source. This + // identifier is chosen randomly, with the intent that no two + // synchronization sources within the same RTP session will have + // the same SSRC identifier. An example algorithm for generating a + // random identifier is presented in Appendix A.6. Although the + // probability of multiple sources choosing the same identifier is + // low, all RTP implementations must be prepared to detect and + // resolve collisions. Section 8 describes the probability of + // collision along with a mechanism for resolving collisions and + // detecting RTP-level forwarding loops based on the uniqueness of + // the SSRC identifier. If a source changes its source transport + // address, it must also choose a new SSRC identifier to avoid + // being interpreted as a looped source. -typedef struct { + // 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 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | defined by profile | length | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | header extension | + // | .... | + + typedef struct { uint32_t cc :4; uint32_t extension :1; uint32_t padding :1; @@ -144,35 +165,35 @@ typedef struct { uint32_t ssrc; uint32_t extensionpayload:16; uint32_t extensionlength:16; -} rtpheader; + } rtpheader; -// 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| RC | PT=RR=201 | length | header -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | SSRC of packet sender | -// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -// | SSRC_1 (SSRC of first source) | report -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block -// | fraction lost | cumulative number of packets lost | 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | extended highest sequence number received | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | interarrival jitter | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | last SR (LSR) | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | delay since last SR (DLSR) | -// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -// | SSRC_2 (SSRC of second source) | report -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block -// : ... : 2 -// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -// | profile-specific extensions | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // 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| RC | PT=RR=201 | length | header + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | SSRC of packet sender | + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // | SSRC_1 (SSRC of first source) | report + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block + // | fraction lost | cumulative number of packets lost | 1 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | extended highest sequence number received | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | interarrival jitter | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | last SR (LSR) | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | delay since last SR (DLSR) | + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // | SSRC_2 (SSRC of second source) | report + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block + // : ... : 2 + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // | profile-specific extensions | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -typedef struct { + typedef struct { uint32_t blockcount :5; uint32_t padding :1; uint32_t version :2; @@ -181,36 +202,45 @@ typedef struct { uint32_t ssrc; uint32_t ssrcsource; uint32_t fractionlost:8; -} rtcpheader; + bool isRtcp(){ + if (packettype == RTCP_Sender_PT || + packettype == RTCP_Receiver_PT || + packettype == RTCP_PS_Feedback_PT|| + packettype == RTCP_RTP_Feedback_PT){ + return true; + } + return false; + } + } rtcpheader; -// 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| FMT | PT | length | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | SSRC of packet sender | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | SSRC of media source | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// : Feedback Control Information (FCI) : -// : : + // 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| FMT | PT | length | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | SSRC of packet sender | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | SSRC of media source | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // : Feedback Control Information (FCI) : + // : : -// The Feedback Control Information (FCI) for the Full Intra Request -// consists of one or more FCI entries, the content of which is depicted -// in Figure 4. The length of the FIR feedback message MUST be set to -// 2+2*N, where N is the number of FCI entries. -// -// 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 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | SSRC | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | Seq nr. | Reserved | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // The Feedback Control Information (FCI) for the Full Intra Request + // consists of one or more FCI entries, the content of which is depicted + // in Figure 4. The length of the FIR feedback message MUST be set to + // 2+2*N, where N is the number of FCI entries. + // + // 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 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | SSRC | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | Seq nr. | Reserved | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -typedef struct { + typedef struct { uint32_t fmt :5; uint32_t padding :1; uint32_t version :2; @@ -219,66 +249,47 @@ typedef struct { uint32_t ssrc; uint32_t ssrcofmediasource; uint32_t ssrc_fir; -} firheader; + } firheader; -// 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 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |F| block PT | timestamp offset | block length | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// -// -// RFC 2198 RTP Payload for Redundant Audio Data September 1997 -// -// The bits in the header are specified as follows: -// -// F: 1 bit First bit in header indicates whether another header block -// follows. If 1 further header blocks follow, if 0 this is the -// last header block. -// If 0 there is only 1 byte RED header -// -// block PT: 7 bits RTP payload type for this block. -// -// timestamp offset: 14 bits Unsigned offset of timestamp of this block -// relative to timestamp given in RTP header. The use of an unsigned -// offset implies that redundant data must be sent after the primary -// data, and is hence a time to be subtracted from the current -// timestamp to determine the timestamp of the data for which this -// block is the redundancy. -// -// block length: 10 bits Length in bytes of the corresponding data -// block excluding header. -struct redheader { + // 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 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // |F| block PT | timestamp offset | block length | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // + // + // RFC 2198 RTP Payload for Redundant Audio Data September 1997 + // + // The bits in the header are specified as follows: + // + // F: 1 bit First bit in header indicates whether another header block + // follows. If 1 further header blocks follow, if 0 this is the + // last header block. + // If 0 there is only 1 byte RED header + // + // block PT: 7 bits RTP payload type for this block. + // + // timestamp offset: 14 bits Unsigned offset of timestamp of this block + // relative to timestamp given in RTP header. The use of an unsigned + // offset implies that redundant data must be sent after the primary + // data, and is hence a time to be subtracted from the current + // timestamp to determine the timestamp of the data for which this + // block is the redundancy. + // + // block length: 10 bits Length in bytes of the corresponding data + // block excluding header. + struct redheader { uint32_t payloadtype :7; uint32_t follow :1; uint32_t tsLength :24; uint32_t getTS() { - return (ntohl(tsLength) & 0xfffc00) >> 10; + return (ntohl(tsLength) & 0xfffc00) >> 10; } uint32_t getLength() { - return (ntohl(tsLength) & 0x3ff); + return (ntohl(tsLength) & 0x3ff); } -}; - -// Payload types -#define RTCP_Sender_PT 200 // RTCP Sender Report -#define RTCP_Receiver_PT 201 // RTCP Receiver Report -#define RTCP_RTP_Feedback_PT 205 // RTCP Transport Layer Feedback Packet -#define RTCP_PS_Feedback_PT 206 // RTCP Payload Specific Feedback Packet - -#define VP8_90000_PT 100 // VP8 Video Codec -#define RED_90000_PT 116 // REDundancy (RFC 2198) -#define ULP_90000_PT 117 // ULP/FEC -#define ISAC_16000_PT 103 // ISAC Audio Codec -#define ISAC_32000_PT 104 // ISAC Audio Codec -#define PCMU_8000_PT 0 // PCMU Audio Codec -#define OPUS_48000_PT 111 // Opus Audio Codec -#define PCMA_8000_PT 8 // PCMA Audio Codec -#define CN_8000_PT 13 // CN Audio Codec -#define CN_16000_PT 105 // CN Audio Codec -#define CN_32000_PT 106 // CN Audio Codec -#define CN_48000_PT 107 // CN Audio Codec -#define TEL_8000_PT 126 // Tel Audio Events + }; +} /*namespace erizo*/ #endif /* RTPUTILS_H */