packetq.cpp
Upload User: dangjiwu
Upload Date: 2013-07-19
Package Size: 42019k
Code Size: 13k
Category:

Symbian

Development Platform:

Visual C++

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