OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / lib / libopenh323 / include / rtp.h
1 /*
2  * rtp.h
3  *
4  * RTP protocol handler
5  *
6  * Open H323 Library
7  *
8  * Copyright (c) 1998-2000 Equivalence Pty. Ltd.
9  *
10  * The contents of this file are subject to the Mozilla Public License
11  * Version 1.0 (the "License"); you may not use this file except in
12  * compliance with the License. You may obtain a copy of the License at
13  * http://www.mozilla.org/MPL/
14  *
15  * Software distributed under the License is distributed on an "AS IS"
16  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17  * the License for the specific language governing rights and limitations
18  * under the License.
19  *
20  * The Original Code is Open H323 Library.
21  *
22  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
23  *
24  * Portions of this code were written with the assisance of funding from
25  * Vovida Networks, Inc. http://www.vovida.com.
26  *
27  * Contributor(s): ______________________________________.
28  *
29  * $Log: rtp.h,v $
30  * Revision 1.60  2006/01/26 03:35:03  shorne
31  * Added more NAT traversal support
32  *
33  * Revision 1.59  2006/01/18 07:46:08  csoutheren
34  * Initial version of RTP aggregation (disabled by default)
35  *
36  * Revision 1.58  2005/11/30 13:05:01  csoutheren
37  * Changed tags for Doxygen
38  *
39  * Revision 1.57  2005/11/21 21:06:23  shorne
40  * Added GQoS switches
41  *
42  * Revision 1.56  2005/08/27 02:06:00  csoutheren
43  * Keep track of time first RTP packet is received
44  *
45  * Revision 1.55  2005/01/03 14:03:20  csoutheren
46  * Added new configure options and ability to disable/enable modules
47  *
48  * Revision 1.54  2005/01/03 06:25:52  csoutheren
49  * Added extensive support for disabling code modules at compile time
50  *
51  * Revision 1.53  2004/04/22 12:38:02  rjongbloed
52  * Removed the RTP QoS class if there is no QoS support in build,
53  *   thanks Nick Hoath, ISDN Communications Ltd.
54  *
55  * Revision 1.52  2004/04/07 05:31:42  csoutheren
56  * Added ability to receive calls from endpoints behind NAT firewalls
57  *
58  * Revision 1.51  2003/10/27 06:03:39  csoutheren
59  * Added support for QoS
60  *   Thanks to Henry Harrison of AliceStreet
61  *
62  * Revision 1.50  2003/10/09 09:47:45  csoutheren
63  * Fixed problem with re-opening RTP half-channels under unusual
64  * circumstances. Thanks to Damien Sandras
65  *
66  * Revision 1.49  2003/05/14 13:46:39  rjongbloed
67  * Removed hack of using special payload type for H.263 for a method which
68  *   would be less prone to failure in the future.
69  *
70  * Revision 1.48  2003/05/02 04:57:43  robertj
71  * Added header extension support to RTP data frame class.
72  *
73  * Revision 1.47  2003/05/02 04:21:53  craigs
74  * Added hacked OpalH263 codec
75  *
76  * Revision 1.46  2003/02/07 00:30:41  robertj
77  * Changes for bizarre usage of RTP code outside of scope of H.323 specs.
78  *
79  * Revision 1.45  2003/02/05 06:32:08  robertj
80  * Fixed non-stun symmetric NAT support recently broken.
81  *
82  * Revision 1.44  2003/02/04 07:06:41  robertj
83  * Added STUN support.
84  *
85  * Revision 1.43  2002/11/19 01:48:15  robertj
86  * Allowed get/set of canonical anme and tool name.
87  *
88  * Revision 1.42  2002/11/12 22:10:48  robertj
89  * Updated documentation.
90  *
91  * Revision 1.41  2002/10/31 00:33:29  robertj
92  * Enhanced jitter buffer system so operates dynamically between minimum and
93  *   maximum values. Altered API to assure app writers note the change!
94  *
95  * Revision 1.40  2002/09/26 04:01:58  robertj
96  * Fixed calculation of fraction of packets lost in RR, thanks Awais Ali
97  *
98  * Revision 1.39  2002/09/16 01:14:15  robertj
99  * Added #define so can select if #pragma interface/implementation is used on
100  *   platform basis (eg MacOS) rather than compiler, thanks Robert Monaghan.
101  *
102  * Revision 1.38  2002/09/03 05:47:02  robertj
103  * Normalised the multi-include header prevention ifdef/define symbol.
104  * Added copy constructor/operator for session manager.
105  *
106  * Revision 1.37  2002/08/05 10:03:47  robertj
107  * Cosmetic changes to normalise the usage of pragma interface/implementation.
108  *
109  * Revision 1.36  2002/05/28 02:37:37  robertj
110  * Fixed reading data out of RTCP compound statements.
111  *
112  * Revision 1.35  2002/05/02 05:58:24  robertj
113  * Changed the mechanism for sending RTCP reports so that they will continue
114  *   to be sent regardless of if there is any actual data traffic.
115  * Added support for compound RTCP statements for sender and receiver reports.
116  *
117  * Revision 1.34  2002/02/09 02:33:37  robertj
118  * Improved payload type docuemntation and added Cisco CN.
119  *
120  * Revision 1.33  2002/01/22 07:08:26  robertj
121  * Added IllegalPayloadType enum as need marker for none set
122  *   and MaxPayloadType is a legal value.
123  *
124  * Revision 1.32  2001/11/09 05:39:54  craigs
125  * Added initial T.38 support thanks to Adam Lazur
126  *
127  * Revision 1.31  2001/09/11 00:21:21  robertj
128  * Fixed missing stack sizes in endpoint for cleaner thread and jitter thread.
129  *
130  * Revision 1.30  2001/07/06 06:32:22  robertj
131  * Added flag and checks for RTP data having specific SSRC.
132  * Changed transmitter IP address check so is based on first received
133  *    PDU instead of expecting it to come from the host we are sending to.
134  *
135  * Revision 1.29  2001/06/04 11:37:48  robertj
136  * Added thread safe enumeration functions of RTP sessions.
137  * Added member access functions to UDP based RTP sessions.
138  *
139  * Revision 1.28  2001/04/24 06:15:50  robertj
140  * Added work around for strange Cisco bug which suddenly starts sending
141  *   RTP packets beginning at a difference sequence number base.
142  *
143  * Revision 1.27  2001/04/02 23:58:23  robertj
144  * Added jitter calculation to RTP session.
145  * Added trace of statistics.
146  *
147  * Revision 1.26  2001/02/09 05:16:24  robertj
148  * Added #pragma interface for GNU C++.
149  *
150  * Revision 1.25  2000/12/18 08:58:30  craigs
151  * Added ability set ports
152  *
153  * Revision 1.24  2000/09/25 01:44:31  robertj
154  * Fixed possible race condition on shutdown of RTP session with jitter buffer.
155  *
156  * Revision 1.23  2000/09/21 02:06:06  craigs
157  * Added handling for endpoints that return conformant, but useless, RTP address
158  * and port numbers
159  *
160  * Revision 1.22  2000/05/23 12:57:28  robertj
161  * Added ability to change IP Type Of Service code from applications.
162  *
163  * Revision 1.21  2000/05/18 11:53:34  robertj
164  * Changes to support doc++ documentation generation.
165  *
166  * Revision 1.20  2000/05/04 11:49:21  robertj
167  * Added Packets Too Late statistics, requiring major rearrangement of jitter buffer code.
168  *
169  * Revision 1.19  2000/05/02 04:32:25  robertj
170  * Fixed copyright notice comment.
171  *
172  * Revision 1.18  2000/05/01 01:01:24  robertj
173  * Added flag for what to do with out of orer packets (use if jitter, don't if not).
174  *
175  * Revision 1.17  2000/04/30 03:55:18  robertj
176  * Improved the RTCP messages, epecially reports
177  *
178  * Revision 1.16  2000/04/10 17:39:21  robertj
179  * Fixed debug output of RTP payload types to allow for unknown numbers.
180  *
181  * Revision 1.15  2000/04/05 03:17:31  robertj
182  * Added more RTP statistics gathering and H.245 round trip delay calculation.
183  *
184  * Revision 1.14  2000/03/23 02:55:18  robertj
185  * Added sending of SDES control packets.
186  *
187  * Revision 1.13  2000/03/20 20:54:04  robertj
188  * Fixed problem with being able to reopen for reading an RTP_Session (Cisco compatibilty)
189  *
190  * Revision 1.12  2000/02/29 13:00:13  robertj
191  * Added extra statistic display for RTP packets out of order.
192  *
193  * Revision 1.11  1999/12/30 09:14:31  robertj
194  * Changed payload type functions to use enum.
195  *
196  * Revision 1.10  1999/12/23 23:02:35  robertj
197  * File reorganision for separating RTP from H.323 and creation of LID for VPB support.
198  *
199  * Revision 1.9  1999/11/20 05:35:57  robertj
200  * Fixed possibly I/O block in RTP read loops.
201  *
202  * Revision 1.8  1999/11/19 09:17:15  robertj
203  * Fixed problems with aycnhronous shut down of logical channels.
204  *
205  * Revision 1.7  1999/11/14 11:41:18  robertj
206  * Added access functions to RTP statistics.
207  *
208  * Revision 1.6  1999/09/08 04:05:48  robertj
209  * Added support for video capabilities & codec, still needs the actual codec itself!
210  *
211  * Revision 1.5  1999/08/31 12:34:18  robertj
212  * Added gatekeeper support.
213  *
214  * Revision 1.4  1999/07/13 09:53:24  robertj
215  * Fixed some problems with jitter buffer and added more debugging.
216  *
217  * Revision 1.3  1999/07/09 06:09:49  robertj
218  * Major implementation. An ENORMOUS amount of stuff added everywhere.
219  *
220  * Revision 1.2  1999/06/22 13:49:40  robertj
221  * Added GSM support and further RTP protocol enhancements.
222  *
223  * Revision 1.1  1999/06/14 06:12:25  robertj
224  * Changes for using RTP sessions correctly in H323 Logical Channel context
225  *
226  */
227
228 #ifndef __OPAL_RTP_H
229 #define __OPAL_RTP_H
230
231 #ifdef P_USE_PRAGMA
232 #pragma interface
233 #endif
234
235 #include <openh323buildopts.h>
236 #include <ptlib/sockets.h>
237
238 class RTP_JitterBuffer;
239 class PHandleAggregator;
240
241 #ifdef P_STUN
242 class PNatMethod;
243 #endif
244
245 ///////////////////////////////////////////////////////////////////////////////
246 // 
247 // class to hold the QoS definitions for an RTP channel
248
249 #if P_HAS_QOS
250
251 class RTP_QOS : public PObject
252 {
253   PCLASSINFO(RTP_QOS,PObject);
254   public:
255     PQoS dataQoS;
256     PQoS ctrlQoS;
257 };
258
259 #else
260
261 class RTP_QOS;
262
263 #endif
264
265 ///////////////////////////////////////////////////////////////////////////////
266 // Real Time Protocol - IETF RFC1889 and RFC1890
267
268 /**An RTP data frame encapsulation.
269   */
270 class RTP_DataFrame : public PBYTEArray
271 {
272   PCLASSINFO(RTP_DataFrame, PBYTEArray);
273
274   public:
275     RTP_DataFrame(PINDEX payloadSize = 2048);
276
277     enum {
278       ProtocolVersion = 2,
279       MinHeaderSize = 12
280     };
281
282     enum PayloadTypes {
283       PCMU,         // G.711 u-Law
284       FS1016,       // Federal Standard 1016 CELP
285       G721,         // ADPCM - Subsumed by G.726
286       G726 = G721,
287       GSM,          // GSM 06.10
288       G7231,        // G.723.1 at 6.3kbps or 5.3 kbps
289       DVI4_8k,      // DVI4 at 8kHz sample rate
290       DVI4_16k,     // DVI4 at 16kHz sample rate
291       LPC,          // LPC-10 Linear Predictive CELP
292       PCMA,         // G.711 A-Law
293       G722,         // G.722
294       L16_Stereo,   // 16 bit linear PCM
295       L16_Mono,     // 16 bit linear PCM
296       G723,         // G.723
297       CN,           // Confort Noise
298       MPA,          // MPEG1 or MPEG2 audio
299       G728,         // G.728 16kbps CELP
300       DVI4_11k,     // DVI4 at 11kHz sample rate
301       DVI4_22k,     // DVI4 at 22kHz sample rate
302       G729,         // G.729 8kbps
303       Cisco_CN,     // Cisco systems comfort noise (unofficial)
304
305       CelB = 25,    // Sun Systems Cell-B video
306       JPEG,         // Motion JPEG
307       H261 = 31,    // H.261
308       MPV,          // MPEG1 or MPEG2 video
309       MP2T,         // MPEG2 transport system
310       H263,         // H.263
311
312       LastKnownPayloadType,
313
314       DynamicBase = 96,
315       MaxPayloadType = 127,
316       IllegalPayloadType
317     };
318
319     unsigned GetVersion() const { return (theArray[0]>>6)&3; }
320
321     BOOL GetExtension() const   { return (theArray[0]&0x10) != 0; }
322     void SetExtension(BOOL ext);
323
324     BOOL GetMarker() const { return (theArray[1]&0x80) != 0; }
325     void SetMarker(BOOL m);
326
327     PayloadTypes GetPayloadType() const { return (PayloadTypes)(theArray[1]&0x7f); }
328     void         SetPayloadType(PayloadTypes t);
329
330     WORD GetSequenceNumber() const { return *(PUInt16b *)&theArray[2]; }
331     void SetSequenceNumber(WORD n) { *(PUInt16b *)&theArray[2] = n; }
332
333     DWORD GetTimestamp() const  { return *(PUInt32b *)&theArray[4]; }
334     void  SetTimestamp(DWORD t) { *(PUInt32b *)&theArray[4] = t; }
335
336     DWORD GetSyncSource() const  { return *(PUInt32b *)&theArray[8]; }
337     void  SetSyncSource(DWORD s) { *(PUInt32b *)&theArray[8] = s; }
338
339     PINDEX GetContribSrcCount() const { return theArray[0]&0xf; }
340     DWORD  GetContribSource(PINDEX idx) const;
341     void   SetContribSource(PINDEX idx, DWORD src);
342
343     PINDEX GetHeaderSize() const;
344
345     int GetExtensionType() const; // -1 is no extension
346     void   SetExtensionType(int type);
347     PINDEX GetExtensionSize() const;
348     BOOL   SetExtensionSize(PINDEX sz);
349     BYTE * GetExtensionPtr() const;
350
351     PINDEX GetPayloadSize() const { return payloadSize; }
352     BOOL   SetPayloadSize(PINDEX sz);
353     BYTE * GetPayloadPtr()     const { return (BYTE *)(theArray+GetHeaderSize()); }
354
355   protected:
356     PINDEX payloadSize;
357
358 #if PTRACING
359     friend ostream & operator<<(ostream & o, PayloadTypes t);
360 #endif
361 };
362
363 PLIST(RTP_DataFrameList, RTP_DataFrame);
364
365
366 /**An RTP control frame encapsulation.
367   */
368 class RTP_ControlFrame : public PBYTEArray
369 {
370   PCLASSINFO(RTP_ControlFrame, PBYTEArray);
371
372   public:
373     RTP_ControlFrame(PINDEX compoundSize = 2048);
374
375     unsigned GetVersion() const { return (BYTE)theArray[compoundOffset]>>6; }
376
377     unsigned GetCount() const { return (BYTE)theArray[compoundOffset]&0x1f; }
378     void     SetCount(unsigned count);
379
380     enum PayloadTypes {
381       e_SenderReport = 200,
382       e_ReceiverReport,
383       e_SourceDescription,
384       e_Goodbye,
385       e_ApplDefined
386     };
387
388     unsigned GetPayloadType() const { return (BYTE)theArray[compoundOffset+1]; }
389     void     SetPayloadType(unsigned t);
390
391     PINDEX GetPayloadSize() const { return 4*(*(PUInt16b *)&theArray[compoundOffset+2]); }
392     void   SetPayloadSize(PINDEX sz);
393
394     BYTE * GetPayloadPtr() const { return (BYTE *)(theArray+compoundOffset+4); }
395
396     BOOL ReadNextCompound();
397     BOOL WriteNextCompound();
398
399     PINDEX GetCompoundSize() const { return compoundSize; }
400
401 #pragma pack(1)
402     struct ReceiverReport {
403       PUInt32b ssrc;      /* data source being reported */
404       BYTE fraction;      /* fraction lost since last SR/RR */
405       BYTE lost[3];       /* cumulative number of packets lost (signed!) */
406       PUInt32b last_seq;  /* extended last sequence number received */
407       PUInt32b jitter;    /* interarrival jitter */
408       PUInt32b lsr;       /* last SR packet from this source */
409       PUInt32b dlsr;      /* delay since last SR packet */
410
411       unsigned GetLostPackets() const { return (lost[0]<<16U)+(lost[1]<<8U)+lost[2]; }
412       void SetLostPackets(unsigned lost);
413     };
414
415     struct SenderReport {
416       PUInt32b ssrc;      /* source this RTCP packet refers to */
417       PUInt32b ntp_sec;   /* NTP timestamp */
418       PUInt32b ntp_frac;
419       PUInt32b rtp_ts;    /* RTP timestamp */
420       PUInt32b psent;     /* packets sent */
421       PUInt32b osent;     /* octets sent */ 
422     };
423
424     enum DescriptionTypes {
425       e_END,
426       e_CNAME,
427       e_NAME,
428       e_EMAIL,
429       e_PHONE,
430       e_LOC,
431       e_TOOL,
432       e_NOTE,
433       e_PRIV,
434       NumDescriptionTypes
435     };
436
437     struct SourceDescription {
438       PUInt32b src;       /* first SSRC/CSRC */
439       struct Item {
440         BYTE type;        /* type of SDES item (enum DescriptionTypes) */
441         BYTE length;      /* length of SDES item (in octets) */
442         char data[1];     /* text, not zero-terminated */
443
444         const Item * GetNextItem() const { return (const Item *)((char *)this + length + 2); }
445         Item * GetNextItem() { return (Item *)((char *)this + length + 2); }
446       } item[1];          /* list of SDES items */
447     };
448
449     SourceDescription & AddSourceDescription(
450       DWORD src   ///<  SSRC/CSRC identifier
451     );
452
453     SourceDescription::Item & AddSourceDescriptionItem(
454       SourceDescription & sdes, ///<  SDES record to add item to
455       unsigned type,            ///<  Description type
456       const PString & data      ///<  Data for description
457     );
458 #pragma pack()
459
460   protected:
461     PINDEX compoundOffset;
462     PINDEX compoundSize;
463 };
464
465
466 class RTP_Session;
467
468 /**This class is the base for user data that may be attached to the RTP_session
469    allowing callbacks for statistics and progress monitoring to be passed to an
470    arbitrary object that an RTP consumer may require.
471   */
472 class RTP_UserData : public PObject
473 {
474   PCLASSINFO(RTP_UserData, PObject);
475
476   public:
477     /**Callback from the RTP session for transmit statistics monitoring.
478        This is called every RTP_Session::txStatisticsInterval packets on the
479        transmitter indicating that the statistics have been updated.
480
481        The default behaviour does nothing.
482       */
483     virtual void OnTxStatistics(
484       const RTP_Session & session   ///<  Session with statistics
485     ) const;
486
487     /**Callback from the RTP session for receive statistics monitoring.
488        This is called every RTP_Session::receiverReportInterval packets on the
489        receiver indicating that the statistics have been updated.
490
491        The default behaviour does nothing.
492       */
493     virtual void OnRxStatistics(
494       const RTP_Session & session   ///<  Session with statistics
495     ) const;
496 };
497
498
499 /**This class is for encpsulating the IETF Real Time Protocol interface.
500  */
501 class RTP_Session : public PObject
502 {
503   PCLASSINFO(RTP_Session, PObject);
504
505   public:
506     enum {
507       DefaultAudioSessionID = 1,
508       DefaultVideoSessionID = 2,
509       DefaultFaxSessionID = 3
510     };
511
512   /**@name Construction */
513   //@{
514     /**Create a new RTP session.
515      */
516     RTP_Session(
517 #ifdef H323_RTP_AGGREGATE
518       PHandleAggregator * aggregator, ///<  RTP aggregator
519 #endif
520       unsigned id,                    ///<  Session ID for RTP channel
521       RTP_UserData * userData = NULL  ///<  Optional data for session.
522     );
523
524     /**Delete a session.
525        This deletes the userData field.
526      */
527     ~RTP_Session();
528   //@}
529
530   /**@name Operations */
531   //@{
532     /**Sets the size of the jitter buffer to be used by this RTP session.
533        A session default to not having any jitter buffer enabled for reading
534        and the ReadBufferedData() function simply calls ReadData(). Once a
535        jitter buffer has been created it cannot be removed, though its size
536        may be adjusted.
537        
538        If the jitterDelay paramter is zero, it destroys the jitter buffer
539        attached to this RTP session.
540       */
541     void SetJitterBufferSize(
542       unsigned minJitterDelay, ///<  Minimum jitter buffer delay in RTP timestamp units
543       unsigned maxJitterDelay, ///<  Maximum jitter buffer delay in RTP timestamp units
544       PINDEX stackSize = 30000 ///<  Stack size for jitter thread
545     );
546
547     /**Get current size of the jitter buffer.
548        This returns the currently used jitter buffer delay in RTP timestamp
549        units. It will be some value between the minimum and maximum set in
550        the SetJitterBufferSize() function.
551       */
552     unsigned GetJitterBufferSize() const;
553
554     /**Modifies the QOS specifications for this RTP session*/
555     virtual BOOL ModifyQOS(RTP_QOS * )
556     { return FALSE; }
557
558     /**Read a data frame from the RTP channel.
559        This function will conditionally read data from eth jitter buffer or
560        directly if there is no jitter buffer enabled. An application should
561        generally use this in preference to directly calling ReadData().
562       */
563     BOOL ReadBufferedData(
564       DWORD timestamp,        ///<  Timestamp to read from buffer.
565       RTP_DataFrame & frame   ///<  Frame read from the RTP session
566     );
567
568     /**Read a data frame from the RTP channel.
569        Any control frames received are dispatched to callbacks and are not
570        returned by this function. It will block until a data frame is
571        available or an error occurs.
572       */
573     virtual BOOL ReadData(
574       RTP_DataFrame & frame,   ///<  Frame read from the RTP session
575       BOOL loop                ///<  If TRUE, loop as long as data is available, if FALSE, only process once
576     ) = 0;
577
578     /**Write a data frame from the RTP channel.
579       */
580     virtual BOOL WriteData(
581       RTP_DataFrame & frame   ///<  Frame to write to the RTP session
582     ) = 0;
583
584     /**Write a control frame from the RTP channel.
585       */
586     virtual BOOL WriteControl(
587       RTP_ControlFrame & frame    ///<  Frame to write to the RTP session
588     ) = 0;
589
590     /**Write the RTCP reports.
591       */
592     virtual BOOL SendReport();
593
594     /**Close down the RTP session.
595       */
596     virtual void Close(
597       BOOL reading    ///<  Closing the read side of the session
598     ) = 0;
599
600     /**Get the local host name as used in SDES packes.
601       */
602     virtual PString GetLocalHostName() = 0;
603   //@}
604
605   /**@name Call back functions */
606   //@{
607     enum SendReceiveStatus {
608       e_ProcessPacket,
609       e_IgnorePacket,
610       e_AbortTransport
611     };
612     virtual SendReceiveStatus OnSendData(RTP_DataFrame & frame);
613     virtual SendReceiveStatus OnReceiveData(const RTP_DataFrame & frame);
614     virtual SendReceiveStatus OnReceiveControl(RTP_ControlFrame & frame);
615
616     class ReceiverReport : public PObject  {
617         PCLASSINFO(ReceiverReport, PObject);
618       public:
619         void PrintOn(ostream &) const;
620
621         DWORD sourceIdentifier;
622         DWORD fractionLost;         /* fraction lost since last SR/RR */
623         DWORD totalLost;            /* cumulative number of packets lost (signed!) */
624         DWORD lastSequenceNumber;   /* extended last sequence number received */
625         DWORD jitter;               /* interarrival jitter */
626         PTimeInterval lastTimestamp;/* last SR packet from this source */
627         PTimeInterval delay;        /* delay since last SR packet */
628     };
629     PARRAY(ReceiverReportArray, ReceiverReport);
630
631     class SenderReport : public PObject  {
632         PCLASSINFO(SenderReport, PObject);
633       public:
634         void PrintOn(ostream &) const;
635
636         DWORD sourceIdentifier;
637         PTime realTimestamp;
638         DWORD rtpTimestamp;
639         DWORD packetsSent;
640         DWORD octetsSent;
641     };
642     virtual void OnRxSenderReport(const SenderReport & sender,
643                                   const ReceiverReportArray & reports);
644     virtual void OnRxReceiverReport(DWORD src,
645                                     const ReceiverReportArray & reports);
646
647     class SourceDescription : public PObject  {
648         PCLASSINFO(SourceDescription, PObject);
649       public:
650         SourceDescription(DWORD src) { sourceIdentifier = src; }
651         void PrintOn(ostream &) const;
652
653         DWORD            sourceIdentifier;
654         POrdinalToString items;
655     };
656     PARRAY(SourceDescriptionArray, SourceDescription);
657     virtual void OnRxSourceDescription(const SourceDescriptionArray & descriptions);
658
659     virtual void OnRxGoodbye(const PDWORDArray & sources,
660                              const PString & reason);
661
662     virtual void OnRxApplDefined(const PString & type, unsigned subtype, DWORD src,
663                                  const BYTE * data, PINDEX size);
664   //@}
665
666   /**@name Member variable access */
667   //@{
668     /**Get the ID for the RTP session.
669       */
670     unsigned GetSessionID() const { return sessionID; }
671
672     /**Get the canonical name for the RTP session.
673       */
674     PString GetCanonicalName() const;
675
676     /**Set the canonical name for the RTP session.
677       */
678     void SetCanonicalName(const PString & name);
679
680     /**Get the tool name for the RTP session.
681       */
682     PString GetToolName() const;
683
684     /**Set the tool name for the RTP session.
685       */
686     void SetToolName(const PString & name);
687
688     /**Get the user data for the session.
689       */
690     RTP_UserData * GetUserData() const { return userData; }
691
692     /**Set the user data for the session.
693       */
694     void SetUserData(
695       RTP_UserData * data   ///<  New user data to be used
696     );
697
698     /**Get the source output identifier.
699       */
700     DWORD GetSyncSourceOut() const { return syncSourceOut; }
701
702     /**Increment reference count for RTP session.
703       */
704     void IncrementReference() { referenceCount++; }
705
706     /**Decrement reference count for RTP session.
707       */
708     BOOL DecrementReference() { return --referenceCount == 0; }
709
710     /**Indicate if will ignore all but first received SSRC value.
711       */
712     BOOL WillIgnoreOtherSources() const { return ignoreOtherSources; }
713
714     /**Indicate if will ignore all but first received SSRC value.
715       */
716     void SetIgnoreOtherSources(
717       BOOL ignore   ///<  Flag for ignore other SSRC values
718     ) { ignoreOtherSources = ignore; }
719
720     /**Indicate if will ignore out of order packets.
721       */
722     BOOL WillIgnoreOutOfOrderPackets() const { return ignoreOutOfOrderPackets; }
723
724     /**Indicate if will ignore out of order packets.
725       */
726     void SetIgnoreOutOfOrderPackets(
727       BOOL ignore   ///<  Flag for ignore out of order packets
728     ) { ignoreOutOfOrderPackets = ignore; }
729
730     /**Get the time interval for sending RTCP reports in the session.
731       */
732     const PTimeInterval & GetReportTimeInterval() { return reportTimeInterval; }
733
734     /**Set the time interval for sending RTCP reports in the session.
735       */
736     void SetReportTimeInterval(
737       const PTimeInterval & interval ///<  New time interval for reports.
738     )  { reportTimeInterval = interval; }
739
740     /**Get the current report timer
741      */
742     PTimeInterval GetReportTimer()
743     { return reportTimer; }
744
745     /**Get the interval for transmitter statistics in the session.
746       */
747     unsigned GetTxStatisticsInterval() { return txStatisticsInterval; }
748
749     /**Set the interval for transmitter statistics in the session.
750       */
751     void SetTxStatisticsInterval(
752       unsigned packets   ///<  Number of packets between callbacks
753     );
754
755     /**Get the interval for receiver statistics in the session.
756       */
757     unsigned GetRxStatisticsInterval() { return rxStatisticsInterval; }
758
759     /**Set the interval for receiver statistics in the session.
760       */
761     void SetRxStatisticsInterval(
762       unsigned packets   ///<  Number of packets between callbacks
763     );
764
765     /**Get total number of packets sent in session.
766       */
767     DWORD GetPacketsSent() const { return packetsSent; }
768
769     /**Get total number of octets sent in session.
770       */
771     DWORD GetOctetsSent() const { return octetsSent; }
772
773     /**Get total number of packets received in session.
774       */
775     DWORD GetPacketsReceived() const { return packetsReceived; }
776
777     /**Get total number of octets received in session.
778       */
779     DWORD GetOctetsReceived() const { return octetsReceived; }
780
781     /**Get total number received packets lost in session.
782       */
783     DWORD GetPacketsLost() const { return packetsLost; }
784
785     /**Get total number of packets received out of order in session.
786       */
787     DWORD GetPacketsOutOfOrder() const { return packetsOutOfOrder; }
788
789     /**Get total number received packets too late to go into jitter buffer.
790       */
791     DWORD GetPacketsTooLate() const;
792
793     /**Get average time between sent packets.
794        This is averaged over the last txStatisticsInterval packets and is in
795        milliseconds.
796       */
797     DWORD GetAverageSendTime() const { return averageSendTime; }
798
799     /**Get maximum time between sent packets.
800        This is over the last txStatisticsInterval packets and is in
801        milliseconds.
802       */
803     DWORD GetMaximumSendTime() const { return maximumSendTime; }
804
805     /**Get minimum time between sent packets.
806        This is over the last txStatisticsInterval packets and is in
807        milliseconds.
808       */
809     DWORD GetMinimumSendTime() const { return minimumSendTime; }
810
811     /**Get average time between received packets.
812        This is averaged over the last rxStatisticsInterval packets and is in
813        milliseconds.
814       */
815     DWORD GetAverageReceiveTime() const { return averageReceiveTime; }
816
817     /**Get maximum time between received packets.
818        This is over the last rxStatisticsInterval packets and is in
819        milliseconds.
820       */
821     DWORD GetMaximumReceiveTime() const { return maximumReceiveTime; }
822
823     /**Get minimum time between received packets.
824        This is over the last rxStatisticsInterval packets and is in
825        milliseconds.
826       */
827     DWORD GetMinimumReceiveTime() const { return minimumReceiveTime; }
828
829     /**Get averaged jitter time for received packets.
830        This is the calculated statistical variance of the interarrival
831        time of received packets in milliseconds.
832       */
833     DWORD GetAvgJitterTime() const { return jitterLevel>>7; }
834
835     /**Get averaged jitter time for received packets.
836        This is the maximum value of jitterLevel for the session.
837       */
838     DWORD GetMaxJitterTime() const { return maximumJitterLevel>>7; }
839
840     /**
841       * return the timestamp at which the first packet of RTP data was received
842       */
843     PTime GetFirstDataReceivedTime() const { return firstDataReceivedTime; }
844   //@}
845
846   /**@name Functions added to RTP aggregator */
847   //@{
848     virtual int GetDataSocketHandle() const
849     { return -1; }
850     virtual int GetControlSocketHandle() const
851     { return -1; }
852   //@}
853
854   protected:
855     void AddReceiverReport(RTP_ControlFrame::ReceiverReport & receiver);
856
857     unsigned           sessionID;
858     PString            canonicalName;
859     PString            toolName;
860     unsigned           referenceCount;
861     RTP_UserData     * userData;
862
863 #ifndef NO_H323_AUDIO_CODECS
864     RTP_JitterBuffer * jitter;
865 #endif
866
867     BOOL          ignoreOtherSources;
868     BOOL          ignoreOutOfOrderPackets;
869     DWORD         syncSourceOut;
870     DWORD         syncSourceIn;
871     PTimeInterval reportTimeInterval;
872     unsigned      txStatisticsInterval;
873     unsigned      rxStatisticsInterval;
874     WORD          lastSentSequenceNumber;
875     WORD          expectedSequenceNumber;
876     DWORD         lastSentTimestamp;
877     PTimeInterval lastSentPacketTime;
878     PTimeInterval lastReceivedPacketTime;
879     WORD          lastRRSequenceNumber;
880     PINDEX        consecutiveOutOfOrderPackets;
881
882     // Statistics
883     DWORD packetsSent;
884     DWORD octetsSent;
885     DWORD packetsReceived;
886     DWORD octetsReceived;
887     DWORD packetsLost;
888     DWORD packetsOutOfOrder;
889     DWORD averageSendTime;
890     DWORD maximumSendTime;
891     DWORD minimumSendTime;
892     DWORD averageReceiveTime;
893     DWORD maximumReceiveTime;
894     DWORD minimumReceiveTime;
895     DWORD jitterLevel;
896     DWORD maximumJitterLevel;
897
898     unsigned txStatisticsCount;
899     unsigned rxStatisticsCount;
900
901     DWORD    averageSendTimeAccum;
902     DWORD    maximumSendTimeAccum;
903     DWORD    minimumSendTimeAccum;
904     DWORD    averageReceiveTimeAccum;
905     DWORD    maximumReceiveTimeAccum;
906     DWORD    minimumReceiveTimeAccum;
907     DWORD    packetsLostSinceLastRR;
908     DWORD    lastTransitTime;
909     PTime    firstDataReceivedTime;
910
911     PMutex reportMutex;
912     PTimer reportTimer;
913
914 #ifdef H323_RTP_AGGREGATE
915     PHandleAggregator * aggregator;
916 #endif
917 };
918
919
920 /**This class is for encpsulating the IETF Real Time Protocol interface.
921  */
922 class RTP_SessionManager : public PObject
923 {
924   PCLASSINFO(RTP_SessionManager, PObject);
925
926   public:
927   /**@name Construction */
928   //@{
929     /**Construct new session manager database.
930       */
931     RTP_SessionManager();
932     RTP_SessionManager(const RTP_SessionManager & sm);
933     RTP_SessionManager & operator=(const RTP_SessionManager & sm);
934   //@}
935
936
937   /**@name Operations */
938   //@{
939     /**Use an RTP session for the specified ID.
940
941        If this function returns a non-null value, then the ReleaseSession()
942        function MUST be called or the session is never deleted for the
943        lifetime of the session manager.
944
945        If there is no session of the specified ID, then you MUST call the
946        AddSession() function with a new RTP_Session. The mutex flag is left
947        locked in this case. The AddSession() expects the mutex to be locked
948        and unlocks it automatically.
949       */
950     RTP_Session * UseSession(
951       unsigned sessionID    ///<  Session ID to use.
952     );
953
954     /**Add an RTP session for the specified ID.
955
956        This function MUST be called only after the UseSession() function has
957        returned NULL. The mutex flag is left locked in that case. This
958        function expects the mutex to be locked and unlocks it automatically.
959       */
960     void AddSession(
961       RTP_Session * session    ///<  Session to add.
962     );
963
964     /**Release the session. If the session ID is not being used any more any
965        clients via the UseSession() function, then the session is deleted.
966      */
967     void ReleaseSession(
968       unsigned sessionID    ///<  Session ID to release.
969     );
970
971     /**Get a session for the specified ID.
972        Unlike UseSession, this does not increment the usage count on the
973        session so may be used to just gain a pointer to an RTP session.
974      */
975     RTP_Session * GetSession(
976       unsigned sessionID    /// Session ID to get.
977     ) const;
978
979     /**Begin an enumeration of the RTP sessions.
980        This function acquires the mutex for the sessions database and returns
981        the first element in it.
982
983          eg:
984          RTP_Session * session;
985          for (session = rtpSessions.First(); session != NULL; session = rtpSessions.Next()) {
986            if (session->Something()) {
987              rtpSessions.Exit();
988              break;
989            }
990          }
991
992        Note that the Exit() function must be called if the enumeration is
993        stopped prior to Next() returning NULL.
994       */
995     RTP_Session * First();
996
997     /**Get the next session in the enumeration.
998        The session database remains locked until this function returns NULL.
999
1000        Note that the Exit() function must be called if the enumeration is
1001        stopped prior to Next() returning NULL.
1002       */
1003     RTP_Session * Next();
1004
1005     /**Exit the enumeration of RTP sessions.
1006        If the enumeration is desired to be exited before Next() returns NULL
1007        this this must be called to unlock the session database.
1008
1009        Note that you should NOT call Exit() if Next() HAS returned NULL, or
1010        race conditions can result.
1011       */
1012     void Exit();
1013   //@}
1014
1015
1016   protected:
1017     PDICTIONARY(SessionDict, POrdinalKey, RTP_Session);
1018     SessionDict sessions;
1019     PMutex      mutex;
1020     PINDEX      enumerationIndex;
1021 };
1022
1023
1024
1025 /**This class is for the IETF Real Time Protocol interface on UDP/IP.
1026  */
1027 class RTP_UDP : public RTP_Session
1028 {
1029   PCLASSINFO(RTP_UDP, RTP_Session);
1030
1031   public:
1032   /**@name Construction */
1033   //@{
1034     /**Create a new RTP channel.
1035      */
1036     RTP_UDP(
1037 #ifdef H323_RTP_AGGREGATE
1038       PHandleAggregator * aggregator, ///< RTP aggregator
1039 #endif
1040       unsigned id,                    ///<  Session ID for RTP channel
1041       BOOL remoteIsNat = FALSE        ///<  If TRUE, we have hints the remote endpoint is behind a NAT
1042     );
1043
1044     /// Destroy the RTP
1045     ~RTP_UDP();
1046   //@}
1047
1048   /**@name Overrides from class RTP_Session */
1049   //@{
1050     /**Read a data frame from the RTP channel.
1051        Any control frames received are dispatched to callbacks and are not
1052        returned by this function. It will block until a data frame is
1053        available or an error occurs.
1054       */
1055     virtual BOOL ReadData(RTP_DataFrame & frame, BOOL loop);
1056
1057     /**Write a data frame from the RTP channel.
1058       */
1059     virtual BOOL WriteData(RTP_DataFrame & frame);
1060
1061     /**Write a control frame from the RTP channel.
1062       */
1063     virtual BOOL WriteControl(RTP_ControlFrame & frame);
1064
1065     /**Close down the RTP session.
1066       */
1067     virtual void Close(
1068       BOOL reading    ///<  Closing the read side of the session
1069     );
1070
1071     /**Get the session description name.
1072       */
1073     virtual PString GetLocalHostName();
1074   //@}
1075
1076   /**@name QoS Settings */
1077   //@{
1078     /**Change the QoS settings
1079       */
1080     virtual BOOL ModifyQOS(RTP_QOS * rtpqos);
1081
1082     /** Enable QOS on Call Basis
1083       */
1084      virtual void EnableGQoS();
1085
1086 #if P_HAS_QOS
1087      /** Get the QOS settings
1088        */
1089       PQoS & GetQOS();
1090 #endif
1091   //@}
1092
1093   /**@name New functions for class */
1094   //@{
1095     /**Open the UDP ports for the RTP session.
1096       */
1097     BOOL Open(
1098       PIPSocket::Address localAddress,  ///<  Local interface to bind to
1099       WORD portBase,                    ///<  Base of ports to search
1100       WORD portMax,                     ///<  end of ports to search (inclusive)
1101       BYTE ipTypeOfService,             ///<  Type of Service byte
1102 #ifdef P_STUN
1103      PNatMethod * meth = NULL,          ///* Nat Method to use to create sockets (or NULL if no Method)
1104 #else
1105       void * = NULL,                    ///<  STUN server to use createing sockets (or NULL if no STUN)
1106 #endif
1107       RTP_QOS * rtpqos = NULL           ///<  QOS spec (or NULL if no QoS)
1108     );
1109   //@}
1110
1111    /**Reopens an existing session in the given direction.
1112       */
1113     void Reopen(BOOL isReading);
1114   //@}
1115
1116   /**@name Member variable access */
1117   //@{
1118     /**Get local address of session.
1119       */
1120     PIPSocket::Address GetLocalAddress() const { return localAddress; }
1121
1122     /**Set local address of session.
1123       */
1124     void SetLocalAddress(
1125       const PIPSocket::Address & addr
1126     ) { localAddress = addr; }
1127
1128     /**Get remote address of session.
1129       */
1130     PIPSocket::Address GetRemoteAddress() const { return remoteAddress; }
1131
1132     /**Get local data port of session.
1133       */
1134     WORD GetLocalDataPort() const { return localDataPort; }
1135
1136     /**Get local control port of session.
1137       */
1138     WORD GetLocalControlPort() const { return localControlPort; }
1139
1140     /**Get remote data port of session.
1141       */
1142     WORD GetRemoteDataPort() const { return remoteDataPort; }
1143
1144     /**Get remote control port of session.
1145       */
1146     WORD GetRemoteControlPort() const { return remoteControlPort; }
1147
1148     /**Get data UDP socket of session.
1149       */
1150     PUDPSocket & GetDataSocket() { return *dataSocket; }
1151
1152     /**Get control UDP socket of session.
1153       */
1154     PUDPSocket & GetControlSocket() { return *controlSocket; }
1155
1156     /**Set the remote address and port information for session.
1157       */
1158     BOOL SetRemoteSocketInfo(
1159       PIPSocket::Address address,   ///<  Address of remote
1160       WORD port,                    ///<  Port on remote
1161       BOOL isDataPort               ///<  Flag for data or control channel
1162     );
1163
1164     /**Apply QOS - requires address to connect the socket on Windows platforms
1165      */
1166     void ApplyQOS(
1167       const PIPSocket::Address & addr
1168     );
1169   //@}
1170
1171     int GetDataSocketHandle() const
1172     { return dataSocket != NULL ? dataSocket->GetHandle() : -1; }
1173
1174     int GetControlSocketHandle() const
1175     { return controlSocket != NULL ? controlSocket->GetHandle() : -1; }
1176
1177   protected:
1178     SendReceiveStatus ReadDataPDU(RTP_DataFrame & frame);
1179     SendReceiveStatus ReadControlPDU();
1180     SendReceiveStatus ReadDataOrControlPDU(
1181       PUDPSocket & socket,
1182       PBYTEArray & frame,
1183       BOOL fromDataChannel
1184     );
1185
1186     PIPSocket::Address localAddress;
1187     WORD               localDataPort;
1188     WORD               localControlPort;
1189
1190     PIPSocket::Address remoteAddress;
1191     WORD               remoteDataPort;
1192     WORD               remoteControlPort;
1193
1194     PIPSocket::Address remoteTransmitAddress;
1195
1196     BOOL shutdownRead;
1197     BOOL shutdownWrite;
1198
1199     PUDPSocket * dataSocket;
1200     PUDPSocket * controlSocket;
1201
1202     BOOL appliedQOS;
1203     BOOL enableGQOS;
1204
1205     BOOL remoteIsNAT;
1206 };
1207
1208
1209 #endif // __OPAL_RTP_H
1210
1211
1212 /////////////////////////////////////////////////////////////////////////////