packetq.cpp
Upload User: zhongxx05
Upload Date: 2007-06-06
Package Size: 33641k
Code Size: 12k
Category:

Symbian

Development Platform:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include "hxtypes.h"
  36. #include "hxcom.h"
  37. #include "hxcomm.h"
  38. #include "ihxpckts.h"
  39. #include "hxmap.h" // CHXMapLongToObj
  40. #include "netbyte.h"
  41. #include "packetq.h"
  42. #include "hxheap.h"
  43. #ifdef _DEBUG
  44. #include "hxtick.h"
  45. #undef HX_THIS_FILE
  46. static const char HX_THIS_FILE[] = __FILE__;
  47. #endif
  48. /******************************************************************
  49. *   Defines
  50. */
  51. #define MAX_GAP_SINCE_TERMINATION   3
  52. #define MAX_EXPECTED_LOSS_GAP     1000
  53. /******************************************************************
  54. *  PacketQueue
  55. *
  56. */
  57. PacketQueue::PacketQueue(const UINT32 ulWinSize,
  58.  const UINT16 unProbation,
  59.  const UINT32 ulWinTime,
  60.  const BOOL bUsesRTPPackets)
  61. : m_ulMinWindowSize(ulWinSize)
  62. , m_ulMinWindowTime(ulWinTime)
  63. , m_bUsesRTPPackets(bUsesRTPPackets)
  64. , m_unCurrent(0)
  65. , m_bInitial(TRUE)
  66. , m_bPacketReturned(FALSE)
  67. , m_unInitProbation(unProbation)
  68. , m_unProbation(unProbation)
  69. , m_ulLate(0)
  70. , m_ulLateSinceTermination(0)
  71. , m_pBuf(NULL)
  72. , m_bLastReturnedArrivalSet(FALSE)
  73. , m_pClassFactory(NULL)
  74. , m_bIsFlexTimeWindow(FALSE)
  75. {
  76.     HX_ASSERT(unProbation > 0);
  77. #ifdef _PKTQ_DEBUG
  78.     static INT32 lCount = 1;
  79.     char cFileName[30]; /* Flawfinder: ignore */
  80.     memset(cFileName, 0, 30);
  81.     wsprintf(cFileName, "c:\temp\trans%d.txt", lCount++);
  82.     m_pLogFile= fopen(cFileName, "wt"); /* Flawfinder: ignore */
  83. #endif
  84. }
  85. PacketQueue::~PacketQueue()
  86. {
  87.     ReInitVars();
  88.     HX_DELETE(m_pBuf);
  89.     HX_RELEASE(m_pClassFactory);
  90. #ifdef _PKTQ_DEBUG
  91.     fclose(m_pLogFile);
  92. #endif    
  93. }
  94. HX_RESULT
  95. PacketQueue::Init(IHXCommonClassFactory* pClassFactory)
  96. {
  97.     if (!pClassFactory)
  98.     {
  99. HX_ASSERT(!"PacketQueue::Init(hey, classfactory is NULL)");
  100. return HXR_INVALID_PARAMETER;
  101.     }
  102.     
  103.     m_pBuf = new CHXMapLongToObj();
  104.     if (!m_pBuf)
  105.     {
  106. return HXR_OUTOFMEMORY;
  107.     }
  108.     m_pClassFactory = pClassFactory;
  109.     m_pClassFactory->AddRef();
  110.     return HXR_OK;
  111. }
  112. void
  113. PacketQueue::ReInitVars()
  114. {
  115.     CArrivedPacket* pDeadPacket;
  116.     CHXMapLongToObj::Iterator i;
  117.     for (i = m_pBuf->Begin(); i != m_pBuf->End(); ++i)
  118.     {
  119. pDeadPacket = (CArrivedPacket*) (*i);
  120. delete pDeadPacket;
  121.     }
  122.     m_pBuf->RemoveAll();   
  123.     
  124.     m_bInitial = TRUE;
  125.     m_bPacketReturned = FALSE;
  126.     m_bLastReturnedArrivalSet = FALSE;
  127.     // we've already received one pkt.
  128.     m_unProbation = m_unProbation - 1;
  129.     
  130.     // the same as ones in constractor...
  131.     m_unCurrent     = 0;
  132.     m_ulLate     = 0;
  133.     m_ulLateSinceTermination = 0;
  134. }
  135. UINT16
  136. PacketQueue::GetPercentDone(void)
  137. {
  138.     HX_ASSERT(m_pBuf);
  139.     return (UINT16)((m_pBuf->GetCount() * 100) / 
  140. (m_ulMinWindowSize ? m_ulMinWindowSize : 1));
  141. }
  142. HX_RESULT
  143. PacketQueue::AddPacket(UINT16 unSeq, 
  144.        IHXPacket* pPacket, 
  145.        ULONG32 ulArrivalTime)
  146. {
  147.     // RTP sort of sanity check
  148.     // Don't add until MIN_SEQUENTIAL sequential pkts are received
  149.     if (m_unProbation)
  150.     {
  151. void* pVoid = NULL;
  152. if (m_pBuf->Lookup(unSeq - 1, (void*&) pVoid))
  153. {
  154.     HX_ASSERT(pVoid);
  155.     // in seq.
  156.     m_unProbation--;
  157. }
  158. else
  159. {
  160.     ReInitVars();
  161. }
  162.     }
  163.     if (m_bPacketReturned &&
  164. IsSeqNumGT(m_unCurrent, unSeq))
  165.     {
  166. // this packet is too late, don't add it
  167. void* pDummyVoid;
  168. if (!m_pBuf->Lookup(unSeq, pDummyVoid))
  169. {
  170.     m_ulLate++;
  171.     #ifdef _PKTQ_DEBUG
  172.     if (m_pLogFile)
  173.     {
  174.      fprintf(m_pLogFile, "LATE #%u <= #%u at %un", unSeq, m_unCurrent, HX_GET_TICKCOUNT());
  175.      fflush(m_pLogFile);
  176.     }
  177.          #endif
  178. }
  179. #ifdef _PKTQ_DEBUG
  180. else
  181. {
  182.     if (m_pLogFile)
  183.     {
  184. fprintf(m_pLogFile, "DUP #%u > #%u (%u) at %un", unSeq, m_unCurrent,
  185.     pPacket->GetTime(), HX_GET_TICKCOUNT());
  186. fflush(m_pLogFile);     
  187.     }     
  188. }
  189. #endif
  190. return HXR_OK;
  191.     }
  192.     void* pDummyVoid;
  193.     if (!m_pBuf->Lookup(unSeq, pDummyVoid))
  194.     {
  195. CArrivedPacket* pArrivedPacket = new CArrivedPacket(pPacket,
  196.     ulArrivalTime);
  197. #ifdef _PKTQ_DEBUG
  198. if (m_pLogFile)
  199. {
  200.     fprintf(m_pLogFile, "ADD #%u > #%u (%u) at %u: %un", unSeq, m_unCurrent, 
  201. pPacket->GetTime(), HX_GET_TICKCOUNT(), m_pBuf->GetCount()+1);
  202.     fflush(m_pLogFile);     
  203. }    
  204. #endif
  205. if (pArrivedPacket)
  206. {
  207.     (*m_pBuf)[unSeq] = pArrivedPacket;
  208.     if (m_bInitial)
  209.     {
  210. m_bInitial = FALSE;
  211. m_unCurrent = unSeq;
  212. m_ulLastReturnedArrivalTime = ulArrivalTime;
  213. m_unLastReturnedArrivalSeq = unSeq;
  214. m_bLastReturnedArrivalSet = TRUE;
  215.     }
  216.     else if (IsSeqNumGT(m_unCurrent, unSeq))
  217.     {
  218. m_unCurrent = unSeq;
  219.     }
  220.     return HXR_OK;
  221. }
  222.     }
  223.  #ifdef _PKTQ_DEBUG
  224.     else
  225.     {
  226. if (m_pLogFile)
  227. {
  228.     fprintf(m_pLogFile, "DUP #%u > #%u (%u) at %un", unSeq, m_unCurrent,
  229. pPacket->GetTime(), HX_GET_TICKCOUNT());
  230.     fflush(m_pLogFile);     
  231. }     
  232.     }
  233.  #endif
  234.     
  235.     return HXR_FAIL;
  236. }
  237. HX_RESULT
  238. PacketQueue::GetPacket(REF(IHXPacket*) pPacket, ULONG32 ulTimeNow)
  239. {
  240. #ifdef _PKTQ_DEBUG
  241.     if (m_pLogFile)    
  242.     {
  243. fprintf(m_pLogFile, "GetPacket(): PktCount %u, WindowSize: %u, CurrentSeq: %un", 
  244.     m_pBuf->GetCount(), m_ulMinWindowSize, m_unCurrent);
  245. fflush(m_pLogFile);
  246.     }
  247. #endif
  248.     if (!IsBufferingForSure())
  249.     {
  250. CArrivedPacket* pArrivedPacket;
  251. if (m_pBuf->Lookup(m_unCurrent, (void*&) pArrivedPacket))
  252. {
  253.     if (m_bIsFlexTimeWindow ||
  254. PacketSufficientlyAged(pArrivedPacket, ulTimeNow))
  255.     {
  256. m_pBuf->RemoveKey(m_unCurrent);
  257. m_ulLateSinceTermination = 0;
  258. m_ulLastReturnedArrivalTime = pArrivedPacket->m_ulArrivalTS;
  259. m_unLastReturnedArrivalSeq = m_unCurrent;
  260. m_bLastReturnedArrivalSet = TRUE;
  261. pPacket = pArrivedPacket->m_pPacket;
  262. pPacket->AddRef();
  263. delete pArrivedPacket;
  264. #ifdef _PKTQ_DEBUG
  265. if (m_pLogFile)
  266. {
  267.     fprintf(m_pLogFile, "tFOUND TS: %un", pPacket->GetTime());
  268.     fflush(m_pLogFile);
  269. }
  270. #endif
  271.     }
  272.     else
  273.     {
  274. return HXR_NO_DATA;
  275.     }
  276. }
  277. else
  278. {
  279.     // When we recieve RTCP_BYE, window size is set to 0.
  280.     if ((0 == m_ulMinWindowSize) &&
  281. ((m_pBuf->GetCount() == 0) ||
  282.  (m_ulLateSinceTermination > MAX_GAP_SINCE_TERMINATION)))
  283.     {
  284. // this stream is done
  285. #ifdef _PKTQ_DEBUG
  286. if (m_pLogFile)
  287. {
  288.     fprintf(m_pLogFile, "tSTREAM_DONEn");
  289.     fflush(m_pLogFile);
  290. }
  291. #endif
  292. ReInitVars();
  293. return HXR_STREAM_DONE;
  294.     }
  295.     /*
  296.      * The packet hasn't been received yet so create a new
  297.      * one and mark it as lost
  298.      */
  299. #ifdef _PKTQ_DEBUG
  300.     if (m_pLogFile)
  301.     {
  302. fprintf(m_pLogFile, "tLOSTn");
  303. fflush(m_pLogFile);
  304.     }
  305. #endif
  306.     if (PacketSufficientlyAged(NULL, ulTimeNow))
  307.     {
  308. if (0 == m_ulMinWindowSize)
  309. {
  310.     m_ulLateSinceTermination++;
  311. }
  312. if (m_bUsesRTPPackets)
  313. {
  314.     m_pClassFactory->CreateInstance(CLSID_IHXRTPPacket, (void**) &pPacket);
  315. }
  316. else
  317. {
  318.     m_pClassFactory->CreateInstance(CLSID_IHXPacket, (void**) &pPacket);
  319. }
  320.     
  321. if (pPacket)
  322. {
  323.     pPacket->SetAsLost();
  324. }
  325. else
  326. {
  327.     return HXR_OUTOFMEMORY;
  328. }
  329.     }
  330.     else
  331.     {
  332. return HXR_NO_DATA;
  333.     }
  334. }
  335. m_bPacketReturned = TRUE;
  336. m_unCurrent++;
  337.         return HXR_OK;
  338.     }
  339.     return HXR_NO_DATA;
  340. }
  341. HX_RESULT
  342. PacketQueue::GetNextTS(REF(UINT32)ulTS, ULONG32 ulTimeNow)
  343. {
  344. #ifdef _PKTQ_DEBUG
  345.     if (m_pLogFile)    
  346.     {
  347. fprintf(m_pLogFile, "GetNextTS(): PktCount %u, WindowSize: %u, CurrentSeq: %un", 
  348.     m_pBuf->GetCount(), m_ulMinWindowSize, m_unCurrent);
  349. fflush(m_pLogFile);
  350.     }
  351. #endif
  352.     if (!IsBufferingForSure())
  353.     {
  354. CArrivedPacket* pArrivedPacket;
  355. if (m_pBuf->Lookup(m_unCurrent, (void*&) pArrivedPacket))
  356. {
  357.     if (m_bIsFlexTimeWindow ||
  358. PacketSufficientlyAged(pArrivedPacket, ulTimeNow))
  359.     {
  360. ulTS = pArrivedPacket->m_pPacket->GetTime();
  361. #ifdef _PKTQ_DEBUG
  362. fprintf(m_pLogFile, "tFOUNDn");
  363. fflush(m_pLogFile);
  364. #endif
  365. return HXR_OK;
  366.     }
  367. }
  368. else
  369. {
  370.     // When we recieve RTCP_BYE, window size is set to 0.
  371.      if ((0 == m_ulMinWindowSize) &&
  372.  ((m_pBuf->GetCount() == 0) ||
  373.   (m_ulLateSinceTermination > MAX_GAP_SINCE_TERMINATION)))
  374.     {
  375. // this stream is about to end
  376. HX_ASSERT(!m_pBuf->GetCount());
  377. #ifdef _PKTQ_DEBUG
  378. if (m_pLogFile)
  379. {
  380.     fprintf(m_pLogFile, "tSTREAM_DONEn");
  381.     fflush(m_pLogFile);
  382. }
  383. #endif
  384. ReInitVars();
  385. return HXR_STREAM_DONE;
  386.     }
  387.     if (PacketSufficientlyAged(NULL, ulTimeNow))
  388.     {
  389. HX_ASSERT(m_bLastReturnedArrivalSet);
  390. ulTS = m_ulLastReturnedArrivalTime;
  391. #ifdef _PKTQ_DEBUG
  392. if (m_pLogFile)
  393. {
  394.     fprintf(m_pLogFile, "tLOSTn");
  395.     fflush(m_pLogFile);
  396. }
  397. #endif     
  398. return HXR_FAIL;
  399.     }
  400. }
  401.     }    
  402.     #ifdef _PKTQ_DEBUG
  403.     if (m_pLogFile)
  404.     {
  405. fprintf(m_pLogFile, "tBUFFERINGn");
  406. fflush(m_pLogFile);
  407.     }
  408.     #endif    
  409.     
  410.     return HXR_BUFFERING;    
  411. }
  412. BOOL PacketQueue::PacketSufficientlyAged(CArrivedPacket* pArrivedPacket,
  413.  ULONG32 ulTimeNow)
  414. {
  415.     BOOL bIsSufficientlyAged = TRUE;
  416.     if (m_ulMinWindowTime != 0)
  417.     {
  418. if (pArrivedPacket)
  419. {
  420.     if (((ULONG32) (ulTimeNow - pArrivedPacket->m_ulArrivalTS)) <
  421. m_ulMinWindowTime)
  422.     {
  423. bIsSufficientlyAged = FALSE;
  424.     }
  425. }
  426. else
  427. {
  428.     // We are answering for a lost packet
  429.     if (m_bLastReturnedArrivalSet &&
  430. (m_pBuf->GetCount() > 0))
  431.     {
  432. if (((ULONG32) (ulTimeNow - m_ulLastReturnedArrivalTime)) <
  433.     m_ulMinWindowTime)
  434. {
  435.     bIsSufficientlyAged = FALSE;
  436. }
  437.     }
  438.     else
  439.     {
  440. // Lost packet is never sufficienly aged unless
  441. // there is a non-lost packet in the buffer
  442. bIsSufficientlyAged = FALSE;
  443.     }
  444. }
  445.     }
  446.     return bIsSufficientlyAged;
  447. }
  448. ULONG32 PacketQueue::GetAge(ULONG32 ulTimeNow)
  449. {
  450.     ULONG32 ulAge = 0;
  451.     CArrivedPacket* pArrivedPacket = NULL;
  452.     if (m_pBuf->Lookup(m_unCurrent, (void*&) pArrivedPacket))
  453.     {
  454. ulAge = ((ULONG32) (ulTimeNow - pArrivedPacket->m_ulArrivalTS));
  455.     }
  456.     else if (m_bLastReturnedArrivalSet &&
  457.      (m_pBuf->GetCount() > 0))
  458.     {
  459. ulAge = ((ULONG32) (ulTimeNow - m_ulLastReturnedArrivalTime));
  460.     }
  461.     return ulAge;
  462. }