1 /*
2  * jitter.h
3  *
4  * Jitter buffer support
5  *
6  * Open H323 Library
7  *
8  * Copyright (c) 1999-2001 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  * $Revision: 28053 $
30  * $Author: rjongbloed $
31  * $Date: 2012-07-18 02:50:22 -0500 (Wed, 18 Jul 2012) $
32  */
33 
34 #ifndef OPAL_RTP_JITTER_H
35 #define OPAL_RTP_JITTER_H
36 
37 #ifdef P_USE_PRAGMA
38 #pragma interface
39 #endif
40 
41 #include <opal/buildopts.h>
42 
43 #include <rtp/rtp.h>
44 
45 
46 class RTP_JitterBuffer;
47 class RTP_JitterBufferAnalyser;
48 
49 
50 ///////////////////////////////////////////////////////////////////////////////
51 /**This is an Abstract jitter buffer, which can be used simply in any
52    application. The user is required to use a descendant of this class, and
53    provide a "OnReadPacket" method, so that network packets can be placed in
54    this class instance */
55 class OpalJitterBuffer : public PSafeObject
56 {
57   PCLASSINFO(OpalJitterBuffer, PSafeObject);
58 
59   public:
60   /**@name Construction */
61   //@{
62     /**Constructor for this jitter buffer. The size of this buffer can be
63        altered later with the SetDelay method
64       */
65     OpalJitterBuffer(
66       unsigned minJitterDelay, ///<  Minimum delay in RTP timestamp units
67       unsigned maxJitterDelay, ///<  Maximum delay in RTP timestamp units
68       unsigned timeUnits = 8,  ///<  Time units, usually 8 or 16
69       PINDEX packetSize = 2048 ///<  Max RTP packet size
70     );
71 
72     /** Destructor, which closes this down and deletes the internal list of frames
73       */
74     virtual ~OpalJitterBuffer();
75   //@}
76 
77   /**@name Overrides from PObject */
78   //@{
79     /**Report the statistics for this jitter instance */
80     void PrintOn(
81       ostream & strm
82     ) const;
83   //@}
84 
85   /**@name Operations */
86   //@{
87     /**Set the maximum delay the jitter buffer will operate to.
88       */
89     void SetDelay(
90       unsigned minJitterDelay, ///<  Minimum delay in RTP timestamp units
91       unsigned maxJitterDelay, ///<  Maximum delay in RTP timestamp units
92       PINDEX packetSize = 2048 ///<  Max RTP packet size
93     );
94 
95     /**Reset jitter buffer.
96       */
97     void Reset();
98 
99     /**Write data frame from the RTP channel.
100       */
101     virtual PBoolean WriteData(
102       const RTP_DataFrame & frame,   ///< Frame to feed into jitter buffer
103       const PTimeInterval & tick = 0 ///< Real time tick for packet arrival
104     );
105 
106     /**Read a data frame from the jitter buffer.
107        This function never blocks. If no data is available, an RTP packet
108        with zero payload size is returned.
109       */
110     virtual PBoolean ReadData(
111       RTP_DataFrame & frame,  ///<  Frame to extract from jitter buffer
112       const PTimeInterval & tick = 0 ///< Real time tick for packet removal
113     );
114 
115     /**Get current delay for jitter buffer.
116       */
GetCurrentJitterDelay()117     DWORD GetCurrentJitterDelay() const { return m_currentJitterDelay; }
118 
119     /**Get minimum delay for jitter buffer.
120       */
GetMinJitterDelay()121     DWORD GetMinJitterDelay() const { return m_minJitterDelay; }
122 
123     /**Get maximum delay for jitter buffer.
124       */
GetMaxJitterDelay()125     DWORD GetMaxJitterDelay() const { return m_maxJitterDelay; }
126 
127     /**Get time units.
128       */
GetTimeUnits()129     unsigned GetTimeUnits() const { return m_timeUnits; }
130 
131     /**Get total number received packets too late to go into jitter buffer.
132       */
GetPacketsTooLate()133     DWORD GetPacketsTooLate() const { return m_packetsTooLate; }
134 
135     /**Get total number received packets that overran the jitter buffer.
136       */
GetBufferOverruns()137     DWORD GetBufferOverruns() const { return m_bufferOverruns; }
138 
139     /**Get maximum consecutive marker bits before buffer starts to ignore them.
140       */
GetMaxConsecutiveMarkerBits()141     DWORD GetMaxConsecutiveMarkerBits() const { return m_maxConsecutiveMarkerBits; }
142 
143     /**Set maximum consecutive marker bits before buffer starts to ignore them.
144       */
SetMaxConsecutiveMarkerBits(DWORD max)145     void SetMaxConsecutiveMarkerBits(DWORD max) { m_maxConsecutiveMarkerBits = max; }
146   //@}
147 
148   protected:
149     DWORD CalculateRequiredTimestamp(DWORD playOutTimestamp) const;
150     bool AdjustCurrentJitterDelay(int delta);
151 
152     unsigned m_timeUnits;
153     PINDEX   m_packetSize;
154     DWORD    m_minJitterDelay;      ///< Minimum jitter delay in timestamp units
155     DWORD    m_maxJitterDelay;      ///< Maximum jitter delay in timestamp units
156     int      m_jitterGrowTime;      ///< Amaint to increase jitter delay by when get "late" packet
157     DWORD    m_jitterShrinkPeriod;  ///< Period (in timestamp units) over which buffer is
158                                     ///< consistently filled before shrinking
159     int      m_jitterShrinkTime;    ///< Amount to shrink jitter delay by if consistently filled
160     DWORD    m_silenceShrinkPeriod; ///< Reduce jitter delay is silent for this long
161     int      m_silenceShrinkTime;   ///< Amount to shrink jitter delay by if consistently silent
162     DWORD    m_jitterDriftPeriod;
163 
164     int      m_currentJitterDelay;
165     DWORD    m_packetsTooLate;
166     DWORD    m_bufferOverruns;
167     DWORD    m_consecutiveMarkerBits;
168     DWORD    m_maxConsecutiveMarkerBits;
169     DWORD    m_consecutiveLatePackets;
170 
171     DWORD    m_averageFrameTime;
172     DWORD    m_lastTimestamp;
173     DWORD    m_lastSyncSource;
174     DWORD    m_bufferFilledTime;
175     DWORD    m_bufferLowTime;
176     DWORD    m_bufferEmptiedTime;
177     int      m_timestampDelta;
178 
179     enum {
180       e_SynchronisationStart,
181       e_SynchronisationFill,
182       e_SynchronisationShrink,
183       e_SynchronisationDone
184     } m_synchronisationState;
185 
186     typedef std::map<DWORD, RTP_DataFrame> FrameMap;
187     FrameMap m_frames;
188     PMutex   m_bufferMutex;
189 
190     RTP_JitterBufferAnalyser * m_analyser;
191 };
192 
193 
194 /**A descendant of the OpalJitterBuffer that starts a thread to read
195    from something continuously and feed it into the jitter buffer.
196   */
197 class OpalJitterBufferThread : public OpalJitterBuffer
198 {
199     PCLASSINFO(OpalJitterBufferThread, OpalJitterBuffer);
200  public:
201     OpalJitterBufferThread(
202       unsigned minJitterDelay, ///<  Minimum delay in RTP timestamp units
203       unsigned maxJitterDelay, ///<  Maximum delay in RTP timestamp units
204       unsigned timeUnits = 8,  ///<  Time units, usually 8 or 16
205       PINDEX packetSize = 2048 ///<  Max RTP packet size
206     );
207     ~OpalJitterBufferThread();
208 
209     /**Read a data frame from the jitter buffer.
210        This function never blocks. If no data is available, an RTP packet
211        with zero payload size is returned.
212 
213        Override of base class so can terminate caller when shutting down.
214       */
215     virtual PBoolean ReadData(
216       RTP_DataFrame & frame   ///<  Frame to extract from jitter buffer
217     );
218 
219     /**This class instance collects data from the outside world in this
220        method.
221 
222        @return true on successful read, false on faulty read. */
223     virtual PBoolean OnReadPacket(
224       RTP_DataFrame & frame   ///<  Frame read from the RTP session
225     ) = 0;
226 
227     void StartThread();
228 
229   protected:
230     PDECLARE_NOTIFIER(PThread, OpalJitterBufferThread, JitterThreadMain);
231 
232     /// Internal function to be called from derived class destructor
233     void WaitForThreadTermination();
234 
235     PThread * m_jitterThread;
236     bool      m_running;
237 };
238 
239 
240 /////////////////////////////////////////////////////////////////////////////
241 /**A descendant of the OpalJitterBuffer that reads RTP_DataFrame instances
242    from the RTP_Sessions
243   */
244 class RTP_JitterBuffer : public OpalJitterBufferThread
245 {
246     PCLASSINFO(RTP_JitterBuffer, OpalJitterBufferThread);
247  public:
248     RTP_JitterBuffer(
249       RTP_Session & session,   ///<  Associated RTP session tor ead data from
250       unsigned minJitterDelay, ///<  Minimum delay in RTP timestamp units
251       unsigned maxJitterDelay, ///<  Maximum delay in RTP timestamp units
252       unsigned timeUnits = 8,  ///<  Time units, usually 8 or 16
253       PINDEX packetSize = 2048 ///<  Max RTP packet size
254     );
255     ~RTP_JitterBuffer();
256 
257     /**This class instance collects data from the outside world in this
258        method.
259 
260        @return true on successful read, false on faulty read. */
261     virtual PBoolean OnReadPacket(
262       RTP_DataFrame & frame   ///<  Frame read from the RTP session
263     );
264 
265  protected:
266    /**This class extracts data from the outside world by reading from this session variable */
267    RTP_Session & m_session;
268 };
269 
270 #endif // OPAL_RTP_JITTER_H
271 
272 
273 /////////////////////////////////////////////////////////////////////////////
274