00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #ifndef OPAL_RTP_JITTER_H
00035 #define OPAL_RTP_JITTER_H
00036
00037 #ifdef P_USE_PRAGMA
00038 #pragma interface
00039 #endif
00040
00041 #include <opal/buildopts.h>
00042
00043 #include <rtp/rtp.h>
00044
00045
00046 class RTP_JitterBuffer;
00047 class RTP_JitterBufferAnalyser;
00048
00049
00051
00055 class OpalJitterBuffer : public PSafeObject
00056 {
00057 PCLASSINFO(OpalJitterBuffer, PSafeObject);
00058
00059 public:
00062 OpalJitterBuffer(
00063 unsigned minJitterDelay,
00064 unsigned maxJitterDelay,
00065 unsigned timeUnits = 8,
00066 PINDEX stackSize = 30000
00067 );
00068
00070 virtual ~OpalJitterBuffer();
00071
00073 void PrintOn(ostream & strm ) const;
00074
00080 virtual PBoolean OnReadPacket (
00081 RTP_DataFrame & frame,
00082 PBoolean loop
00083 ) = 0;
00084
00085
00088 void SetDelay(
00089 unsigned minJitterDelay,
00090 unsigned maxJitterDelay
00091 );
00092
00093 void UseImmediateReduction(PBoolean state) { doJitterReductionImmediately = state; }
00094
00100 virtual PBoolean ReadData(
00101 RTP_DataFrame & frame
00102 );
00103
00106 DWORD GetJitterTime() const { return currentJitterTime; }
00107
00110 unsigned GetTimeUnits() const { return timeUnits; }
00111
00114 DWORD GetPacketsTooLate() const { return packetsTooLate; }
00115
00118 DWORD GetBufferOverruns() const { return bufferOverruns; }
00119
00122 DWORD GetMaxConsecutiveMarkerBits() const { return maxConsecutiveMarkerBits; }
00123
00126 void SetMaxConsecutiveMarkerBits(DWORD max) { maxConsecutiveMarkerBits = max; }
00127
00130 virtual void Resume();
00131
00132 PDECLARE_NOTIFIER(PThread, OpalJitterBuffer, JitterThreadMain);
00133
00134 PBoolean WaitForTermination(const PTimeInterval & t)
00135 {
00136 if (jitterThread == NULL)
00137 return PTrue;
00138 shuttingDown = true;
00139 return jitterThread->WaitForTermination(t);
00140 }
00141
00142 bool IsEmpty() { return jitterBuffer.size() == 0; }
00143
00144 protected:
00145 void Start(unsigned _minJitterTime, unsigned _maxJitterTime);
00146
00147 PINDEX bufferSize;
00148 DWORD minJitterTime;
00149 DWORD maxJitterTime;
00150 DWORD maxConsecutiveMarkerBits;
00151
00152 unsigned timeUnits;
00153 DWORD currentJitterTime;
00154 DWORD packetsTooLate;
00155 unsigned bufferOverruns;
00156 unsigned consecutiveBufferOverruns;
00157 DWORD consecutiveMarkerBits;
00158 PTimeInterval consecutiveEarlyPacketStartTime;
00159 DWORD lastWriteTimestamp;
00160 PTimeInterval lastWriteTick;
00161 DWORD jitterCalc;
00162 DWORD targetJitterTime;
00163 unsigned jitterCalcPacketCount;
00164 bool doJitterReductionImmediately;
00165
00166 class Entry : public RTP_DataFrame
00167 {
00168 public:
00169 Entry() : RTP_DataFrame(0, 512) { }
00170 PTimeInterval tick;
00171 };
00172
00173 class FrameQueue : public std::deque<Entry *>
00174 {
00175 public:
00176 void resize(size_type _Newsize)
00177 {
00178 while (size() < (size_t)_Newsize)
00179 push_back(new Entry);
00180 while (size() > (size_t)_Newsize) {
00181 delete front();
00182 pop_front();
00183 }
00184 }
00185
00186 ~FrameQueue()
00187 { resize(0); }
00188 };
00189
00190 FrameQueue freeFrames;
00191 FrameQueue jitterBuffer;
00192 inline Entry * GetNewest(bool pop) { Entry * e = jitterBuffer.back(); if (pop) jitterBuffer.pop_back(); return e; }
00193 inline Entry * GetOldest(bool pop) { Entry * e = jitterBuffer.front(); if (pop) jitterBuffer.pop_front(); return e; }
00194
00195 Entry * currentFrame;
00196
00197 PMutex bufferMutex;
00198 bool shuttingDown;
00199 bool preBuffering;
00200 bool firstReadData;
00201
00202 RTP_JitterBufferAnalyser * analyser;
00203
00204 PThread * jitterThread;
00205 PINDEX jitterStackSize;
00206
00207 PBoolean Init(Entry * & currentReadFrame, PBoolean & markerWarning);
00208 PBoolean PreRead(Entry * & currentReadFrame, PBoolean & markerWarning);
00209 PBoolean OnRead(Entry * & currentReadFrame, PBoolean & markerWarning, PBoolean loop);
00210 void DeInit(Entry * & currentReadFrame, PBoolean & markerWarning);
00211 };
00212
00214
00216 class RTP_JitterBuffer : public OpalJitterBuffer
00217 {
00218 PCLASSINFO(RTP_JitterBuffer, OpalJitterBuffer);
00219
00220 public:
00221 RTP_JitterBuffer(
00222 RTP_Session & session,
00223 unsigned minJitterDelay,
00224 unsigned maxJitterDelay,
00225 unsigned timeUnits = 8,
00226 PINDEX stackSize = 30000
00227 );
00228
00233 virtual PBoolean OnReadPacket(
00234 RTP_DataFrame & frame,
00235 PBoolean loop
00236 );
00237
00238 protected:
00240 RTP_Session & session;
00241 };
00242
00243 #endif // OPAL_RTP_JITTER_H
00244
00245