1 /*******************************************************************************
2 * File Name : JitterBuffer.cpp
5 * Created Time : 2009-10-14 10:13:41
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
58 ******************************************************************************/
59 JitterBuffer::JitterBuffer ()
62 // Init mutexs and conditions
64 m_zhcPkgListCond
.Init ();
66 // Notify that this instance not created
72 /******************************************************************************
73 * Func : JitterBuffer::~JitterBuffer
74 * Desc : Deconstructor of JitterBuffer
77 ******************************************************************************/
78 JitterBuffer::~JitterBuffer ()
87 /******************************************************************************
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
117 // Unlock this instance
118 m_zhmMutex
.Unlock ();
120 HLH_DEBUG ( HLH_DEBUG_JITTER
, ("already created") );
121 return JITTER_BUFFER_ERR_ALREADY_CREATED
;
126 m_slpPkgList
.clear ();
129 m_unJitterTimestamp
= unJitterTimestamp
;
130 m_unPerTimestamp
= unPerTimestamp
;
133 m_zhrRecvTimestamp
= unTimestampFirst
;
134 m_zhrHighTimestamp
= unTimestampFirst
+ unJitterTimestamp
/2;
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
153 // Unlock this instance
154 m_zhmMutex
.Unlock ();
163 /******************************************************************************
164 * Func : JitterBuffer::Destroy
165 * Desc : Destroy this Jitter Buffer, and stop thread started
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
182 // Unlock this instance
183 m_zhmMutex
.Unlock ();
185 HLH_DEBUG ( HLH_DEBUG_JITTER
, ("not created") );
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
204 // Unlock this instance
205 m_zhmMutex
.Unlock ();
210 /******************************************************************************
211 * Func : JitterBuffer::IsCreated
212 * Desc : Whether this instance created
214 * Outs : If created return 0, otherwise return error code.
215 ******************************************************************************/
216 bool JitterBuffer::IsCreated ()
221 bCreated
= m_bCreated
;
222 m_zhmMutex
.Unlock ();
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
;
246 HLH_RoundU32 zhrTimestamp2Recv
;
247 bool bSignal
= false;
249 // Lock this instance
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
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
277 // Search for the position to insert
278 for ( slpIt
= m_slpPkgList
.begin (); slpIt
!= m_slpPkgList
.end (); slpIt
++ ) {
279 if (zhrTimestamp
<= slpIt
->m_zhrTimestamp
) {
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
) );
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
;
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
;
319 HLH_DEBUG ( HLH_DEBUG_JITTER
, ("package ready before %d", (UINT32
)zhrTimestamp2Recv
) );
323 if (zhrTimestamp
> m_zhrHighTimestamp
) {
324 m_zhrHighTimestamp
= zhrTimestamp
;
329 HLH_DEBUG ( HLH_DEBUG_JITTER
, ("put signal") );
330 m_zhcPkgListCond
.Signal ();
333 // Unlock this instance
334 m_zhmMutex
.Unlock ();
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
)
357 HLH_RoundU32 zhrHighTimestamp
;
359 std::list
<JPackage
>::iterator slpIt
;
362 // Lock this instance
366 HLH_DEBUG ( HLH_DEBUG_JITTER
, ("not created") );
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
) );
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;
411 nRetVal
= m_zhcPkgListCond
.TimeWait (m_zhmMutex
, zhtWaitTime
);
413 HLH_DEBUG ( HLH_DEBUG_JITTER
|HLH_DEBUG_MAIN
, ("timeout") );
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
) );
443 // Unlock this instance
444 m_zhmMutex
.Unlock ();
449 // Unlock this instance
450 m_zhmMutex
.Unlock ();
452 memset ( &zjpPkg
, 0, sizeof(JPackage
) );
459 /******************************************************************************
460 * Func : JitterBuffer::__GetThreadFunc
461 * Desc : Thread function to call OnJitterBufferGet ()
462 * when JitterBuffer ready.
463 * Args : zhtGetThread Thread to call this function
465 ******************************************************************************/
466 void JitterBuffer::__GetThreadFunc (HLH_Thread
& zhtGetThread
)
471 zhtGetThread
.ThreadStarted ();
473 // Check if this instance created
475 // Lock this instance
479 // Unlock this instance
480 m_zhmMutex
.Unlock ();
484 // Unlock this instance
485 m_zhmMutex
.Unlock ();
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") );
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 );