Create Project for repo.or.cz
[vp.git] / src / jitter / JitterBuffer.cpp
blob90b837d5eefc5d18bb8566684624bcf8fb5a97ad
1 /*******************************************************************************
2 * File Name : JitterBuffer.cpp
3 *
4 * Author : Henry He
5 * Created Time : 2009-10-14 10:13:41
6 * Description :
7 ******************************************************************************/
10 /*******************************************************************************
11 * Desc : Includes Files
12 ******************************************************************************/
14 #include "JitterBuffer.h"
17 /*******************************************************************************
18 * Desc : Macro Definations
19 ******************************************************************************/
21 //#define M_ZHRHIGHTIMESTAMP m_zhrHighTimestamp//( HLH_RoundU32(*(volatile UINT32*)(m_zhrHighTimestamp.m_unVal)) )
23 #define M_ZHRHIGHTIMESTAMP ( HLH_RoundU32(m_zhrHighTimestamp.GetUINT32()) )
24 #define M_ZHRRECVTIMESTAMP ( HLH_RoundU32(m_zhrRecvTimestamp.GetUINT32()) )
27 /*******************************************************************************
28 * Desc : Type Definations
29 ******************************************************************************/
32 /*******************************************************************************
33 * Desc : Global Variables
34 ******************************************************************************/
37 /*******************************************************************************
38 * Desc : File Variables
39 ******************************************************************************/
45 /******************************************************************************
46 * Desc : Constructor / Deconstructor
47 ******************************************************************************/
53 /******************************************************************************
54 * Func : JitterBuffer::JitterBuffer
55 * Desc : Constructor
56 * Args : NONE
57 * Outs : NONE
58 ******************************************************************************/
59 JitterBuffer::JitterBuffer ()
62 // Init mutexs and conditions
63 m_zhmMutex.Init ();
64 m_zhcPkgListCond.Init ();
66 // Notify that this instance not created
67 m_bCreated = false;
72 /******************************************************************************
73 * Func : JitterBuffer::~JitterBuffer
74 * Desc : Deconstructor of JitterBuffer
75 * Args : NONE
76 * Outs : NONE
77 ******************************************************************************/
78 JitterBuffer::~JitterBuffer ()
80 Destroy ();
87 /******************************************************************************
88 * Desc : Operations
89 ******************************************************************************/
96 /******************************************************************************
97 * Func : JitterBuffer::Create
98 * Desc : Create this instance
99 * Args : unTimestampFirst First timestamp will be received
100 * zhtPerTimestamp Time interval between timestamp
101 * zhtJitterTime Jitter time before ignore old packages
102 * Outs : If success, return 0. otherwise return error code
103 ******************************************************************************/
104 int JitterBuffer::Create (
105 UINT32 unPerTimestamp,
106 UINT32 unJitterTimestamp,
107 OnJitterBufferGetFunc zojOnJitterBufferGet,
108 void * pvOnJitterBufferGetParam
111 ASSERT (unPerTimestamp < unJitterTimestamp);
113 // Lock this instance
114 m_zhmMutex.Lock ();
116 if (m_bCreated) {
117 // Unlock this instance
118 m_zhmMutex.Unlock ();
120 HLH_DEBUG ( HLH_DEBUG_JITTER, ("already created") );
121 return JITTER_BUFFER_ERR_ALREADY_CREATED;
125 // Init package list
126 m_slpPkgList.clear ();
128 // Init timestamp
129 m_unJitterTimestamp = unJitterTimestamp;
130 m_unPerTimestamp = unPerTimestamp;
132 #if 0
133 m_zhrRecvTimestamp = unTimestampFirst;
134 m_zhrHighTimestamp = unTimestampFirst + unJitterTimestamp/2;
135 #else
136 m_bPut = false;
137 #endif
140 // Create Thread
141 m_zojOnJitterBufferGet = zojOnJitterBufferGet;
142 m_pvOnJitterBufferGetParam = pvOnJitterBufferGetParam;
144 if (zojOnJitterBufferGet != NULL) {
145 HLH_DEBUG ( HLH_DEBUG_JITTER, ("start get thread") );
146 m_zhtGetThread.Start (GetThreadFunc, this);
150 // Notify that this instance is created
151 m_bCreated = true;
153 // Unlock this instance
154 m_zhmMutex.Unlock ();
156 return 0;
163 /******************************************************************************
164 * Func : JitterBuffer::Destroy
165 * Desc : Destroy this Jitter Buffer, and stop thread started
166 * Args : NONE
167 * Outs : NONE
168 ******************************************************************************/
169 void JitterBuffer::Destroy ()
171 std::list<JPackage>::iterator slpIt;
172 JReleaseFunc zjrRelease;
175 // Stop get thread if started
176 m_zhtGetThread.Stop ();
178 // Lock this instance
179 m_zhmMutex.Lock ();
181 if (!m_bCreated) {
182 // Unlock this instance
183 m_zhmMutex.Unlock ();
185 HLH_DEBUG ( HLH_DEBUG_JITTER, ("not created") );
186 return;
190 // Clear Pkg List
191 for ( slpIt = m_slpPkgList.begin(); slpIt != m_slpPkgList.end(); slpIt ++ ) {
192 zjrRelease = slpIt->m_zjrRelease;
194 if (zjrRelease != NULL) {
195 zjrRelease (slpIt->m_pvData);
199 m_slpPkgList.clear ();
201 // Notify that this instance not created
202 m_bCreated = false;
204 // Unlock this instance
205 m_zhmMutex.Unlock ();
210 /******************************************************************************
211 * Func : JitterBuffer::IsCreated
212 * Desc : Whether this instance created
213 * Args : NONE
214 * Outs : If created return 0, otherwise return error code.
215 ******************************************************************************/
216 bool JitterBuffer::IsCreated ()
218 bool bCreated;
220 m_zhmMutex.Lock ();
221 bCreated = m_bCreated;
222 m_zhmMutex.Unlock ();
224 return bCreated;
231 /******************************************************************************
232 * Func : JitterBuffer::PutPkg
233 * Desc : Put one package into this JitterBuffer
234 * Args : zhrTimestamp timestamp of package
235 * pvData pointer of package
236 * zjrRelease release function for pvData
237 * (can be NULL if no release need)
238 * Outs : If success return 0, otherwise return error code
239 ******************************************************************************/
240 int JitterBuffer::PutPkg ( HLH_RoundU32 zhrTimestamp,
241 void *pvData, JReleaseFunc zjrRelease )
244 std::list<JPackage>::iterator slpIt;
245 JPackage zjpPkgNew;
246 HLH_RoundU32 zhrTimestamp2Recv;
247 bool bSignal = false;
249 // Lock this instance
250 m_zhmMutex.Lock ();
252 if (!m_bCreated) {
253 // Unlock this instance
254 m_zhmMutex.Unlock ();
255 HLH_DEBUG ( HLH_DEBUG_JITTER, ("not created") );
256 return JITTER_BUFFER_ERR_NOT_CREATED;
259 // Initialize timestamp range to receive
260 if (!m_bPut) {
261 m_bPut = true;
262 m_zhrRecvTimestamp = (UINT32)zhrTimestamp - m_unJitterTimestamp/2;
263 m_zhrHighTimestamp = zhrTimestamp;
264 HLH_DEBUG ( HLH_DEBUG_JITTER,
265 ( "Init m_zhrRecvTimestamp = %u, m_zhrHighTimestamp = %u",
266 (UINT32)m_zhrRecvTimestamp, (UINT32)m_zhrHighTimestamp ) );
269 HLH_DEBUG ( HLH_DEBUG_JITTER, ("put pkg %u", (UINT32)zhrTimestamp) );
270 // Check if zhrTimestamp is old
271 if (zhrTimestamp < m_zhrRecvTimestamp) {
272 HLH_DEBUG ( HLH_DEBUG_JITTER, ("XXX: ignore old package") );
273 // Just ignore this old package
274 goto failed;
277 // Search for the position to insert
278 for ( slpIt = m_slpPkgList.begin (); slpIt != m_slpPkgList.end (); slpIt ++ ) {
279 if (zhrTimestamp <= slpIt->m_zhrTimestamp) {
280 break;
284 // Get the position now
285 // Insert the package into list
287 if (slpIt != m_slpPkgList.end () && zhrTimestamp == slpIt->m_zhrTimestamp) {
288 // XXX: should not happed after all, just ignore this here
289 HLH_DEBUG ( HLH_DEBUG_JITTER, ("XXX %u already received", (UINT32)zhrTimestamp) );
290 goto failed;
291 } else {
292 zjpPkgNew.m_zhrTimestamp = zhrTimestamp;
293 zjpPkgNew.m_pvData = pvData;
294 zjpPkgNew.m_zjrRelease = zjrRelease;
296 m_slpPkgList.insert (slpIt, zjpPkgNew);
300 // Goto the receive pointer
301 for ( slpIt = m_slpPkgList.begin ();
302 slpIt != m_slpPkgList.end () && slpIt->m_zhrTimestamp < m_zhrRecvTimestamp;
303 slpIt ++) {
307 // Update \c m_zhrRecvTimestamp and \c m_zhtRecvTime if need
308 for ( zhrTimestamp2Recv = m_zhrRecvTimestamp;
309 slpIt != m_slpPkgList.end () && zhrTimestamp2Recv == slpIt->m_zhrTimestamp;
310 slpIt ++, zhrTimestamp2Recv += m_unPerTimestamp ) {
314 if (slpIt == m_slpPkgList.end() || zhrTimestamp2Recv != m_zhrRecvTimestamp) {
315 // At least one oldest package received
316 m_zhrRecvTimestamp = zhrTimestamp2Recv;
318 // Signal GetPkg ()
319 HLH_DEBUG ( HLH_DEBUG_JITTER, ("package ready before %d", (UINT32)zhrTimestamp2Recv) );
320 bSignal = true;
323 if (zhrTimestamp > m_zhrHighTimestamp) {
324 m_zhrHighTimestamp = zhrTimestamp;
325 bSignal = true;
328 if (bSignal) {
329 HLH_DEBUG ( HLH_DEBUG_JITTER, ("put signal") );
330 m_zhcPkgListCond.Signal ();
333 // Unlock this instance
334 m_zhmMutex.Unlock ();
336 return 0;
338 failed:
339 // Unlock this instance
340 m_zhmMutex.Unlock ();
342 return JITTER_BUFFER_ERR_FAILED;
346 /******************************************************************************
347 * Func : JitterBuffer::GetPkg
348 * Desc : Get one package from this JitterBuffer
349 * Args : zhtWait Time to wait before success
350 * Outs : If success, return one package,
351 * otherwise return package with null content.
352 ******************************************************************************/
353 JPackage JitterBuffer::GetPkg (HLH_Time &zhtWaitTime)
355 int nRetVal;
356 JPackage zjpPkg;
357 HLH_RoundU32 zhrHighTimestamp;
359 std::list<JPackage>::iterator slpIt;
362 // Lock this instance
363 m_zhmMutex.Lock ();
365 if (!m_bCreated) {
366 HLH_DEBUG ( HLH_DEBUG_JITTER, ("not created") );
367 goto failed;
371 // If package not empty
372 if ( !m_slpPkgList.empty () ) {
374 zjpPkg = m_slpPkgList.front ();
376 zhrHighTimestamp = M_ZHRHIGHTIMESTAMP;
378 // Check if receive timestamp out of date
379 if (M_ZHRRECVTIMESTAMP < zhrHighTimestamp - (HLH_RoundU32)m_unJitterTimestamp) {
380 // Reset receive timestamp
381 HLH_DEBUG ( HLH_DEBUG_TEST|HLH_DEBUG_JITTER,
382 ("reset jitter from %u to %u", (UINT32)M_ZHRRECVTIMESTAMP, (UINT32)zhrHighTimestamp - m_unJitterTimestamp/2) );
383 m_zhrRecvTimestamp = (UINT32)zhrHighTimestamp - m_unJitterTimestamp/2;
386 // Check if already anti jitter
387 if (zjpPkg.m_zhrTimestamp < M_ZHRRECVTIMESTAMP) {
388 m_slpPkgList.pop_front ();
389 HLH_DEBUG ( HLH_DEBUG_TEST|HLH_DEBUG_JITTER, ("get pkg %u", (UINT32)zjpPkg.m_zhrTimestamp) );
390 goto finished;
393 // Wait for receive
394 goto wait_recv;
396 } else {
398 zhrHighTimestamp = M_ZHRHIGHTIMESTAMP;
400 // Check if receive timestamp out of date
401 if (M_ZHRRECVTIMESTAMP < zhrHighTimestamp - (HLH_RoundU32)m_unJitterTimestamp) {
402 // Reset receive timestamp
403 HLH_DEBUG ( HLH_DEBUG_TEST|HLH_DEBUG_JITTER,
404 ("reset jitter from %u to %u", (UINT32)M_ZHRRECVTIMESTAMP, (UINT32)zhrHighTimestamp - m_unJitterTimestamp/2) );
405 m_zhrRecvTimestamp = (UINT32)zhrHighTimestamp - m_unJitterTimestamp/2;
408 wait_recv:
410 // Wait for packages
411 nRetVal = m_zhcPkgListCond.TimeWait (m_zhmMutex, zhtWaitTime);
412 if (nRetVal < 0) {
413 HLH_DEBUG ( HLH_DEBUG_JITTER|HLH_DEBUG_MAIN, ("timeout") );
414 goto failed;
417 // Check if package availble
418 if ( !m_slpPkgList.empty () ) {
419 zjpPkg = m_slpPkgList.front ();
421 zhrHighTimestamp = M_ZHRHIGHTIMESTAMP;
423 // Check if receive timestamp out of date
424 if (M_ZHRRECVTIMESTAMP < zhrHighTimestamp - (HLH_RoundU32)m_unJitterTimestamp) {
425 // Reset receive timestamp
426 HLH_DEBUG ( HLH_DEBUG_TEST|HLH_DEBUG_JITTER,
427 ("reset jitter from %u to %u", (UINT32)M_ZHRRECVTIMESTAMP, (UINT32)zhrHighTimestamp - m_unJitterTimestamp/2) );
428 m_zhrRecvTimestamp = (UINT32)zhrHighTimestamp - m_unJitterTimestamp/2;
431 // Check if already anti jitter
432 if (zjpPkg.m_zhrTimestamp < M_ZHRRECVTIMESTAMP) {
433 m_slpPkgList.pop_front ();
434 HLH_DEBUG ( HLH_DEBUG_TEST|HLH_DEBUG_JITTER, ("get pkg %u", (UINT32)zjpPkg.m_zhrTimestamp) );
435 goto finished;
439 goto failed;
442 finished:
443 // Unlock this instance
444 m_zhmMutex.Unlock ();
446 return zjpPkg;
448 failed:
449 // Unlock this instance
450 m_zhmMutex.Unlock ();
452 memset ( &zjpPkg, 0, sizeof(JPackage) );
453 return zjpPkg;
459 /******************************************************************************
460 * Func : JitterBuffer::__GetThreadFunc
461 * Desc : Thread function to call OnJitterBufferGet ()
462 * when JitterBuffer ready.
463 * Args : zhtGetThread Thread to call this function
464 * Outs : NONE
465 ******************************************************************************/
466 void JitterBuffer::__GetThreadFunc (HLH_Thread & zhtGetThread)
468 JPackage zjpPkg;
469 HLH_Time zhtTime;
471 zhtGetThread.ThreadStarted ();
473 // Check if this instance created
475 // Lock this instance
476 m_zhmMutex.Lock ();
478 if (!m_bCreated) {
479 // Unlock this instance
480 m_zhmMutex.Unlock ();
481 return;
484 // Unlock this instance
485 m_zhmMutex.Unlock ();
488 do {
490 // Wait for package
491 zhtTime.SetTime (JITTER_BUFFER_TIMEOUT_GET_PKG_SECONDS, 0);
492 zjpPkg = GetPkg (zhtTime);
494 // Check if JitterBuffer ready
495 if (zjpPkg.m_pvData != NULL) {
496 HLH_DEBUG ( HLH_DEBUG_JITTER,
497 ("get pkg %u", (UINT32)zjpPkg.m_zhrTimestamp) );
498 m_zojOnJitterBufferGet (m_pvOnJitterBufferGetParam, zjpPkg);
500 // Check if need to release zjpPkg.m_pvData
501 if (zjpPkg.m_zjrRelease != NULL) {
502 zjpPkg.m_zjrRelease (zjpPkg.m_pvData);
506 // Exit this thread if stop request
507 if ( zhtGetThread.IsStopping () ) {
508 HLH_DEBUG ( HLH_DEBUG_JITTER|HLH_DEBUG_TEST, ("stop on request") );
509 break;
512 } while (1);
516 /******************************************************************************
517 * Func : JitterBuffer::GetThreadFunc
518 * Desc : Wrapper of JitterBuffer::__GetThreadFunc to called by thread
519 * Args : zhtGetThread Thread to call this function
520 * pvThis pointer to this instance
521 * Outs : Alway return (void*) 0.
522 ******************************************************************************/
523 void * JitterBuffer::GetThreadFunc (HLH_Thread & zhtGetThread, void *pvThis)
525 ASSERT (pvThis != NULL);
526 ( (JitterBuffer *) pvThis )->__GetThreadFunc (zhtGetThread);
528 return ( (void*) 0 );