00001 #ifndef RTP_H_
00002 #define RTP_H_
00003
00004 #include <qsocketdevice.h>
00005 #include <qsqldatabase.h>
00006 #include <qregexp.h>
00007 #include <qtimer.h>
00008 #include <qptrlist.h>
00009 #include <qthread.h>
00010 #include <qdatetime.h>
00011
00012 #ifdef WIN32
00013 #include <windows.h>
00014 #include <io.h>
00015 #include <sstream>
00016 #include <mmsystem.h>
00017 #endif
00018
00019 #include <dtmffilter.h>
00020 #include <audiodrv.h>
00021
00022
00023 #define IP_MAX_MTU 1500 // Max size of rxed RTP packet
00024 #define IP_MTU 1290 // Max size of txed RTP packet. Standard MTU is 1500, leave some room for IPSec etc
00025 #define TX_USER_STREAM_SIZE 4096
00026 #define MINBYTESIZE 80
00027 #define RTP_HEADER_SIZE 12
00028 #define UDP_HEADER_SIZE 28
00029 #define MESSAGE_SIZE 80 // bytes to send per 10ms
00030 #define ULAW_BYTES_PER_MS 8 // bytes to send per 1ms
00031
00032 #define RTP_STATS_INTERVAL 1 // Seconds between sending statistics
00033
00034 class rtp;
00035
00036 class RtpEvent : public QCustomEvent
00037 {
00038 public:
00039 enum Type { RxVideoFrame = (QEvent::User + 300), RtpDebugEv, RtpStatisticsEv, RtpRtcpStatsEv };
00040
00041 RtpEvent(Type t, QString s="") : QCustomEvent(t) { text=s; }
00042 RtpEvent(Type t, rtp *r, QTime tm, int ms, int s1, int s2, int s3, int s4, int s5, int s6,
00043 int s7, int s8, int s9, int s10, int s11, int s12, int s13, int s14, int s15, int s16)
00044 : QCustomEvent(t)
00045 { rtpThread=r; timestamp=tm; msPeriod = ms; pkIn=s1; pkOut=s2; pkMiss=s3; pkLate=s4;
00046 pkInDisc=s5; pkOutDrop=s6;
00047 byteIn=s7; byteOut=s8; bytePlayed=s9; framesIn=s10; framesOut=s11; framesInDisc=s12;
00048 framesOutDisc=s13; minPlayout=s14; avgPlayout=s15; maxPlayout=s16; }
00049 RtpEvent(Type t, rtp *r, QTime tm, int ms, int s1, int s2) : QCustomEvent(t)
00050 { rtpThread=r; timestamp=tm; msPeriod = ms; rtcpFractionLoss=s1; rtcpTotalLoss=s2;}
00051 ~RtpEvent() { }
00052 QString msg() { return text;}
00053 rtp *owner() { return rtpThread; }
00054 int getPkIn() { return pkIn; }
00055 int getPkMissed() { return pkMiss; }
00056 int getPkLate() { return pkLate; }
00057 int getPkOut() { return pkOut; }
00058 int getPkInDisc() { return pkInDisc; }
00059 int getPkOutDrop() { return pkOutDrop; }
00060 int getBytesIn() { return byteIn; }
00061 int getBytesOut() { return byteOut; }
00062 int getFramesIn() { return framesIn; }
00063 int getFramesOut() { return framesOut; }
00064 int getFramesInDiscarded() { return framesInDisc; }
00065 int getFramesOutDiscarded() { return framesOutDisc; }
00066 int getPeriod() { return msPeriod; }
00067 int getRtcpFractionLoss() { return rtcpFractionLoss; }
00068 int getRtcpTotalLoss() { return rtcpTotalLoss; }
00069 int getMinPlayout() { return minPlayout; }
00070 int getAvgPlayout() { return avgPlayout; }
00071 int getMaxPlayout() { return maxPlayout; }
00072
00073 private:
00074 QString text;
00075
00076 rtp *rtpThread;
00077 QTime timestamp;
00078 int msPeriod;
00079 int pkIn;
00080 int pkOut;
00081 int pkOutDrop;
00082 int pkMiss;
00083 int pkLate;
00084 int pkInDisc;
00085 int framesIn;
00086 int framesOut;
00087 int framesInDisc;
00088 int framesOutDisc;
00089 int byteIn;
00090 int byteOut;
00091 int bytePlayed;
00092 int rtcpFractionLoss;
00093 int rtcpTotalLoss;
00094 int minPlayout;
00095 int avgPlayout;
00096 int maxPlayout;
00097 };
00098
00099
00100
00101 typedef struct RTPPACKET
00102 {
00103 int len;
00104 uchar RtpVPXCC;
00105 uchar RtpMPT;
00106 ushort RtpSequenceNumber;
00107 ulong RtpTimeStamp;
00108 ulong RtpSourceID;
00109 uchar RtpData[IP_MAX_MTU-RTP_HEADER_SIZE-UDP_HEADER_SIZE];
00110 } RTPPACKET;
00111
00112 #define RTCP_PERIOD 10 // Seconds
00113 #define MAX_RTCP_SR_BLOCKS 1
00114
00115 typedef struct RTCP_SR_BLOCK
00116 {
00117 ulong Ssrc;
00118 uchar fractionLost;
00119 uchar totPacketLostMsb;
00120 ushort totPacketLostLsw;
00121 ulong extHighestSeqNumRx;
00122 ulong arrivalJitter;
00123 ulong lastSR;
00124 ulong delayLastSR;
00125 } RTCP_SR_BLOCK;
00126
00127 typedef struct RTCP_SR
00128 {
00129 ulong RtcpSsrc;
00130 ulong RtcpNtpTimestampMsw;
00131 ulong RtcpNtpTimestampLsw;
00132 ulong RtcpTimestamp;
00133 ulong RtcpSendPkCount;
00134 ulong RtcpSendOctetCount;
00135 RTCP_SR_BLOCK srBlock[MAX_RTCP_SR_BLOCKS];
00136 } RTCP_SR;
00137
00138 typedef struct RTCPPACKET
00139 {
00140 uchar RtcpVPRC;
00141 uchar RtcpPT;
00142 ushort RtcpLen;
00143 union
00144 {
00145 RTCP_SR sr;
00146 } d;
00147 char padding[1500];
00148 } RTCPPACKET;
00149
00150 typedef struct
00151 {
00152 uchar dtmfDigit;
00153 uchar dtmfERVolume;
00154 short dtmfDuration;
00155 } DTMF_RFC2833;
00156
00157 typedef struct
00158 {
00159 ulong h263hdr;
00160 } H263_RFC2190_HDR;
00161
00162
00163 #define RTCP_SENDER_REPORT 200
00164 #define RTCP_RECEIVER_REPORT 201
00165 #define RTCP_SOURCES_DESCR 202
00166 #define RTCP_GOODBYE 203
00167 #define RTCP_APP_DEFINED 204
00168
00169 #define H263HDR(s) ((s)<<13)
00170 #define H263HDR_GETSZ(h) (((h)>>13) & 0x7)
00171 #define H263HDR_GETSBIT(h) (((h)>>3) & 0x7)
00172 #define H263HDR_GETEBIT(h) ((h) & 0x7)
00173
00174 #define H263_SRC_SQCIF 1
00175 #define H263_SRC_QCIF 2
00176 #define H263_SRC_CIF 3
00177 #define H263_SRC_4CIF 4
00178 #define H263_SRC_16CIF 5
00179
00180
00181 #define MAX_VIDEO_LEN 256000
00182 typedef struct VIDEOBUFFER
00183 {
00184 int len;
00185 int w,h;
00186 uchar video[MAX_VIDEO_LEN];
00187 } VIDEOBUFFER;
00188
00189
00190 #define RTP_PAYLOAD_G711U 0x00
00191 #define RTP_PAYLOAD_G711A 0x08
00192 #define RTP_PAYLOAD_COMF_NOISE 0x0D
00193 #define RTP_PAYLOAD_G729 0x12
00194 #define RTP_PAYLOAD_GSM 0x03
00195 #define RTP_PAYLOAD_MARKER_BIT 0x80
00196 #define PAYLOAD(r) (((r)->RtpMPT) & (~RTP_PAYLOAD_MARKER_BIT))
00197 #define RTP_DTMF_EBIT 0x80
00198 #define RTP_DTMF_VOLUMEMASK 0x3F
00199 #define JITTERQ_SIZE 512
00200 #define PKLATE(c,r) (((r)<(c)) && (((c)-(r))<32000)) // check if rxed seq-number is less than current but handle wrap
00201 #define H263SPACE (IP_MTU-RTP_HEADER_SIZE-UDP_HEADER_SIZE-sizeof(H263_RFC2190_HDR))
00202
00203 #define DTMF_STAR 10
00204 #define DTMF_HASH 11
00205 #define DTMF2CHAR(d) ((d)>DTMF_HASH ? '?' : ((d)==DTMF_STAR ? '*' : ((d) == DTMF_HASH ? '#' : ((d)+'0'))))
00206 #define CHAR2DTMF(c) ((c)=='#' ? DTMF_HASH : ((c)=='*' ? DTMF_STAR : ((c)-'0')))
00207
00208
00209
00210 class codec
00211 {
00212 public:
00213 codec();
00214 virtual ~codec();
00215 virtual int Decode(uchar *In, short *out, int Len, short &maxPower);
00216 virtual int Encode(short *In, uchar *out, int Samples, short &maxPower, int gain);
00217 virtual int Silence(uchar *out, int ms);
00218 virtual QString WhoAreYou();
00219 virtual int bandwidth() { return 0; };
00220 private:
00221 };
00222
00223 #define JB_REASON_OK 0 // Buffer which matches seq-number returned
00224 #define JB_REASON_EMPTY 1 // No buffers queued
00225 #define JB_REASON_MISSING 2 // Buffers exist, but none which match your seq-num
00226 #define JB_REASON_SEQERR 3 // Buffers exist, but their seq-numbers are nowhere near yours
00227 #define JB_REASON_DTMF 4 // Buffer which matches seq-number contained DTMF
00228 #define JB_REASON_DUPLICATE 5 // Got the same sequence number twice
00229
00230 class Jitter : public QPtrList<RTPPACKET>
00231 {
00232 public:
00233 Jitter();
00234 ~Jitter();
00235 RTPPACKET *GetJBuffer();
00236 void FreeJBuffer(RTPPACKET *Buf);
00237 void InsertDTMF(RTPPACKET *Buffer);
00238 void InsertJBuffer(RTPPACKET *Buffer);
00239 RTPPACKET *DequeueJBuffer(ushort seqNum, int &reason);
00240 int DumpAllJBuffers(bool StopAtMarkerBit);
00241 virtual int compareItems(QPtrCollection::Item s1, QPtrCollection::Item s2);
00242 int AnyData() { return count(); };
00243 bool isPacketQueued(ushort Seq);
00244 int countPacketsInFrontOf(ushort Seq);
00245 int GotAllBufsInFrame(ushort seq, int offset);
00246 void CountMissingPackets(ushort seq, ushort &cntValid, ushort &cntMissing);
00247 void Debug();
00248
00249
00250 private:
00251 QPtrList<RTPPACKET> FreeJitterQ;
00252 };
00253
00254
00255 class TxShaper
00256 {
00257 public:
00258 TxShaper(int bw, int period, int granularity);
00259 ~TxShaper();
00260 bool OkToSend();
00261 void Send(int Bytes);
00262 void setMaxBandwidth(int bytesPerSec) {maxBandwidth = bytesPerSec; }
00263
00264 private:
00265 void flushHistory();
00266 int historySize;
00267 int *txHistory;
00268 int txGranularity;
00269 int txWindowTotal;
00270 int maxBandwidth;
00271 int itTail;
00272 int itHead;
00273 QTime timestamp;
00274 int timeLastFlush;
00275 int timeLastSend;
00276 };
00277
00278
00279 enum rtpTxMode { RTP_TX_AUDIO_FROM_BUFFER=1, RTP_TX_AUDIO_FROM_MICROPHONE=2, RTP_TX_AUDIO_SILENCE=3, RTP_TX_VIDEO=4 };
00280 enum rtpRxMode { RTP_RX_AUDIO_TO_BUFFER=1, RTP_RX_AUDIO_TO_SPEAKER=2, RTP_RX_AUDIO_DISCARD=3, RTP_RX_VIDEO=4 };
00281
00282 class rtpListener : public QThread
00283 {
00284 public:
00285 rtpListener(QSocketDevice *s, QWaitCondition *w) { sock=s; cond=w; killThread=false; start(); }
00286 ~rtpListener() { killThread=true; wait(); }
00287 virtual void run() { while (!killThread) { if (sock->waitForMore(2000) > 0) cond->wakeAll(); }}
00288
00289 private:
00290 QSocketDevice *sock;
00291 QWaitCondition *cond;
00292 bool killThread;
00293 };
00294
00295
00296
00297 class rtp : public QThread
00298 {
00299
00300 public:
00301 rtp(QWidget *callingApp, int localPort, QString remoteIP, int remotePort, int mediaPay, int playout, int dtmfPay, QString micDev, QString spkDev, rtpTxMode txm=RTP_TX_AUDIO_FROM_MICROPHONE, rtpRxMode rxm=RTP_RX_AUDIO_TO_SPEAKER);
00302 ~rtp();
00303 virtual void run();
00304
00305 void Transmit(short *pcmBuffer, int Samples);
00306 void Transmit(int ms);
00307 void Record(short *pcmBuffer, int Samples);
00308 void StopTransmitRecord() { rtpMutex.lock(); txMode=RTP_TX_AUDIO_SILENCE; rxMode=RTP_RX_AUDIO_DISCARD; if (txBuffer) delete txBuffer; txBuffer=0; recBuffer=0; recBufferMaxLen=0; rtpMutex.unlock(); };
00309 bool Finished() { rtpMutex.lock(); bool b = ((txBuffer == 0) && (recBuffer == 0)); rtpMutex.unlock(); return b;};
00310 int GetRecordSamples() { rtpMutex.lock(); int s = recBufferLen; rtpMutex.unlock(); return s;};
00311 bool checkDtmf() { rtpMutex.lock(); bool b=(dtmfIn[0] != 0); rtpMutex.unlock(); return b; }
00312 QString getDtmf() { rtpMutex.lock(); QString s = dtmfIn; dtmfIn = ""; rtpMutex.unlock(); return s; }
00313 void sendDtmf(char d) { rtpMutex.lock(); dtmfOut.append(d); rtpMutex.unlock(); }
00314 bool toggleMute() { micMuted = !micMuted; return micMuted; }
00315 void getPower(short &m, short &s) { m = micPower; s = spkPower; micPower = 0; spkPower = 0; }
00316 bool queueVideo(VIDEOBUFFER *v) { bool res=false; rtpMutex.lock(); if (videoToTx==0) {videoToTx=v; if (eventCond) eventCond->wakeAll(); res=true; } else framesOutDiscarded++; rtpMutex.unlock(); return res; }
00317 bool readyForVideo() { bool res=true; rtpMutex.lock(); if (pTxShaper) res = pTxShaper->OkToSend(); rtpMutex.unlock(); return res; }
00318 VIDEOBUFFER *getRxedVideo() { rtpMutex.lock(); VIDEOBUFFER *b=rxedVideoFrames.take(0); rtpMutex.unlock(); return b; }
00319 VIDEOBUFFER *getVideoBuffer(int len=0);
00320 void freeVideoBuffer(VIDEOBUFFER *Buf);
00321 void PlayToneToSpeaker(short *tone, int Samples);
00322 void setMaxBandwidth(int kbps) { rtpMutex.lock(); if (pTxShaper) pTxShaper->setMaxBandwidth(kbps*1000/8); rtpMutex.unlock(); }
00323 int getCodecBandwidth() { int res=0; rtpMutex.lock(); if (Codec) res = Codec->bandwidth(); rtpMutex.unlock(); return res; }
00324 void changePlayoutDelay(int ms) { rtpMutex.lock(); adjustPlayoutDelay = ms; rtpMutex.unlock(); }
00325
00326 private:
00327 void rtpThreadWorker();
00328 void rtpAudioThreadWorker();
00329 void rtpVideoThreadWorker();
00330 void rtpInitialise();
00331 void OpenSocket();
00332 void CloseSocket();
00333 void StreamInVideo();
00334 int appendVideoPacket(VIDEOBUFFER *picture, int curLen, RTPPACKET *JBuf, int mLen);
00335 void StreamInAudio();
00336 void PlayOutAudio();
00337 bool isSpeakerHungry();
00338 void recordInPacket(short *data, int dataBytes);
00339 void HandleRxDTMF(RTPPACKET *RTPpacket);
00340 void SendWaitingDtmf();
00341 void StreamOut(void* pData, int nLen);
00342 void StreamOut(RTPPACKET &RTPpacket);
00343 void fillPacketwithSilence(RTPPACKET &RTPpacket);
00344 bool fillPacketfromMic(RTPPACKET &RTPpacket);
00345 void fillPacketfromBuffer(RTPPACKET &RTPpacket);
00346 void initVideoBuffers(int Num);
00347 void destroyVideoBuffers();
00348 void transmitQueuedVideo();
00349 void AddToneToAudio(short *buffer, int Samples);
00350 void Debug(QString dbg);
00351 void CheckSendStatistics();
00352 void SendRtcpStatistics();
00353 void RtcpSendReceive(bool forceSend=false);
00354 void sendRtcpSenderReport(uint txPkCnt, uint txOctetCnt, long rxSsrc, uint rxPkCnt, uint rxPkLost, ushort highestRxSeq);
00355 void parseRtcpMessage(RTCPPACKET *rtcpPacket, int len);
00356 int GetAdjustPlayout();
00357 int measurePlayoutDelay(int seqNum);
00358 bool CheckAnyAudioQueued(int i);
00359
00360
00361 AudioDriver *audio;
00362 DtmfFilter *DTMFFilter;
00363
00364 QObject *eventWindow;
00365 QMutex rtpMutex;
00366 QSocketDevice *rtpSocket;
00367 QSocketDevice *rtcpSocket;
00368 QWaitCondition *eventCond;
00369 QTime timeNextRtcpTx;
00370 codec *Codec;
00371 Jitter *pJitter;
00372 TxShaper *pTxShaper;
00373 int rxMsPacketSize;
00374 int txMsPacketSize;
00375 int rxPCMSamplesPerPacket;
00376 int txPCMSamplesPerPacket;
00377 ushort rxSeqNum;
00378 bool rxFirstFrame;
00379 ushort txSequenceNumber;
00380 ulong txTimeStamp;
00381 uchar rtpMPT;
00382 uchar rtpMarker;
00383 ulong peerSsrc;
00384 QHostAddress yourIP;
00385 int myPort, yourPort, myRtcpPort, yourRtcpPort;
00386 rtpTxMode txMode;
00387 rtpRxMode rxMode;
00388 bool oobError;
00389 bool killRtpThread;
00390 short *txBuffer;
00391 int txBufferLen, txBufferPtr;
00392 ulong lastDtmfTimestamp;
00393 QString dtmfIn;
00394 QString dtmfOut;
00395 short *recBuffer;
00396 int recBufferLen, recBufferMaxLen;
00397 int audioPayload;
00398 int dtmfPayload;
00399 bool micMuted;
00400 int adjustPlayoutDelay;
00401
00402 short *ToneToSpk;
00403 int ToneToSpkSamples;
00404 int ToneToSpkPlayed;
00405
00406
00407 int videoPayload;
00408 QPtrList<VIDEOBUFFER> FreeVideoBufferQ;
00409 QPtrList<VIDEOBUFFER> rxedVideoFrames;
00410 VIDEOBUFFER *videoToTx;
00411 int videoFrameFirstSeqNum;
00412
00413
00414 QTime timeNextStatistics;
00415 QTime timeLastStatistics;
00416 QTime timeLastRtcpStatistics;
00417 int pkIn;
00418 int pkOut;
00419 int pkMissed;
00420 int pkLate;
00421 int pkOutDrop;
00422 int pkInDisc;
00423 int bytesIn;
00424 int bytesOut;
00425 int bytesToSpeaker;
00426 int framesIn;
00427 int framesOut;
00428 int framesInDiscarded;
00429 int framesOutDiscarded;
00430 short micPower;
00431 short spkPower;
00432 uint prevRxPkLost;
00433 uint prevRxPkCnt;
00434 int rtcpFractionLoss;
00435 int rtcpTotalLoss;
00436
00437 int minPlayout;
00438 int maxPlayout;
00439 int totPlayout;
00440 int cntPlayout;
00441 int avgPlayout;
00442 int nominalPlayout;
00443 };
00444
00445
00446
00447
00448 #endif