Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

477 lines
15 KiB

  1. /*----------------------------------------------------------------------------
  2. * File: RTP_STAT.C
  3. * Product: RTP/RTCP implementation
  4. * Description: Provides statistical calculations for RTP packets
  5. *
  6. *
  7. * INTEL Corporation Proprietary Information
  8. * This listing is supplied under the terms of a license agreement with
  9. * Intel Corporation and may not be copied nor disclosed except in
  10. * accordance with the terms of that agreement.
  11. * Copyright (c) 1995 Intel Corporation.
  12. *--------------------------------------------------------------------------*/
  13. #include "rrcm.h"
  14. #define DBG_JITTER_ENABLE 0
  15. /*---------------------------------------------------------------------------
  16. / Global Variables
  17. /--------------------------------------------------------------------------*/
  18. /*---------------------------------------------------------------------------
  19. / External Variables
  20. /--------------------------------------------------------------------------*/
  21. extern PRTP_CONTEXT pRTPContext;
  22. extern RRCM_WS RRCMws;
  23. #ifdef _DEBUG
  24. extern char debug_string[];
  25. #endif
  26. /*----------------------------------------------------------------------------
  27. * Function : calculateJitter
  28. * Description: Determines jitter between current and last received packet.
  29. *
  30. * Input : pRTPHeader : -> to the RTP header
  31. * pSSRC : -> to the session's SSRC list
  32. *
  33. * Note: Implementataion adapted from IETF RFC1889
  34. *
  35. * Return: RRCM_NoError = OK.
  36. * Otherwise(!=0) = Error.
  37. ---------------------------------------------------------------------------*/
  38. DWORD calculateJitter (RTP_HDR_T *pRTPHeader,
  39. PSSRC_ENTRY pSSRC)
  40. {
  41. DWORD dwStatus = RRCM_NoError;
  42. DWORD streamClk;
  43. DWORD dwTmp;
  44. int dwPropagationTime; // packet's transmit time
  45. int dwIASourceTime; // Packet's timestamp for IA
  46. int delta; // of 2 consec. packets
  47. IN_OUT_STR ("RTP : Enter calculateJitter()\n");
  48. // Convert the RTP timestamp to host order
  49. RRCMws.ntohl (pSSRC->RTPsd, pRTPHeader->ts, (PDWORD)&dwIASourceTime);
  50. // lock access
  51. EnterCriticalSection (&pSSRC->critSect);
  52. // Take the difference, after having adjusted the clock to the payload
  53. // type frequency
  54. streamClk =
  55. ((PSSRC_ENTRY)pSSRC->pRTCPses->XmtSSRCList.prev)->dwStreamClock;
  56. if (streamClk)
  57. {
  58. dwTmp = streamClk / 1000;
  59. // update the time to be in unit of the source clock
  60. dwPropagationTime = (timeGetTime() * dwTmp) - dwIASourceTime;
  61. }
  62. else
  63. dwPropagationTime = timeGetTime() - dwIASourceTime;
  64. // initialize for the first valid packet, otherwise jitter will be off
  65. if (pSSRC->rcvInfo.dwPropagationTime == 0)
  66. {
  67. pSSRC->rcvInfo.dwPropagationTime = dwPropagationTime;
  68. LeaveCriticalSection (&pSSRC->critSect);
  69. IN_OUT_STR ("RTP : Exit calculateJitter()\n");
  70. return (dwStatus);
  71. }
  72. #if DBG_JITTER_ENABLE
  73. wsprintf(debug_string, "RTP : Time: %ld - Src Timestamp: %ld",
  74. timeGetTime(),
  75. dwIASourceTime);
  76. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  77. wsprintf(debug_string, "RTP : Propagation (Src unit): %ld",
  78. dwPropagationTime);
  79. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  80. wsprintf(debug_string, "RTP : Previous Propagation (Src unit): %ld",
  81. pSSRC->rcvInfo.dwPropagationTime);
  82. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  83. #endif
  84. // Determine the difference in the transit times and save the latest
  85. delta = dwPropagationTime - pSSRC->rcvInfo.dwPropagationTime;
  86. if (delta < 0)
  87. delta = -delta;
  88. // check for a wrap-around, which is always possible, and avoid sending
  89. // the jitter through the roof - It will take a long time thereafter to
  90. // go back down to a reasonable level
  91. // Check against arbitrary large number
  92. if (delta > 20000)
  93. {
  94. pSSRC->rcvInfo.dwPropagationTime = dwPropagationTime;
  95. LeaveCriticalSection (&pSSRC->critSect);
  96. IN_OUT_STR ("RTP : Exit calculateJitter()\n");
  97. return (dwStatus);
  98. }
  99. #if DBG_JITTER_ENABLE
  100. wsprintf(debug_string, "RTP : Delta (Src unit): %ld", delta);
  101. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  102. #endif
  103. pSSRC->rcvInfo.dwPropagationTime = dwPropagationTime;
  104. #ifdef ENABLE_FLOATING_POINT
  105. // This is the RFC way to do it
  106. pSSRC->rcvInfo.interJitter +=
  107. ((1./16.) * ((double)delta - pSSRC->rcvInfo.interJitter));
  108. #else
  109. // and this is when we need to remove floating point operation
  110. pSSRC->rcvInfo.interJitter +=
  111. (delta - (((long)pSSRC->rcvInfo.interJitter + 8) >> 4));
  112. #endif
  113. LeaveCriticalSection (&pSSRC->critSect);
  114. #if DBG_JITTER_ENABLE
  115. if (streamClk)
  116. {
  117. wsprintf(debug_string, "RTP : iJitter: %ld - iJitter (msec): %ld",
  118. pSSRC->rcvInfo.interJitter,
  119. (pSSRC->rcvInfo.interJitter / (streamClk / 1000)));
  120. }
  121. else
  122. {
  123. wsprintf(debug_string, "RTP : iJitter: %ld - Delta: %ld",
  124. pSSRC->rcvInfo.interJitter,
  125. delta);
  126. }
  127. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  128. wsprintf(debug_string, "RTP : Next RTCP RR iJitter: %ld",
  129. (pSSRC->rcvInfo.interJitter >> 4));
  130. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  131. #endif
  132. IN_OUT_STR ("RTP : Exit calculateJitter()\n");
  133. return (dwStatus);
  134. }
  135. /*----------------------------------------------------------------------------
  136. * Function : initRTPStats
  137. * Description: initializes statistics table for newly recieved SSRC
  138. *
  139. * Input : RTPSequence : Sequence number received in the packet.
  140. * NB: Must be in LittleEndian(IA) format
  141. * pSSRC : -> to SSRC table entry for this terminal
  142. *
  143. * Note: Implementataion adapted from draftspec 08, Appendix A.1
  144. *
  145. * Return: None.
  146. ---------------------------------------------------------------------------*/
  147. void initRTPStats (WORD RTPSequence,
  148. PSSRC_ENTRY pSSRC)
  149. {
  150. IN_OUT_STR ("RTP : Enter initRTPStats()\n");
  151. pSSRC->rcvInfo.dwNumPcktRcvd = 0;
  152. pSSRC->rcvInfo.dwPrvNumPcktRcvd = 0;
  153. pSSRC->rcvInfo.dwExpectedPrior = 0;
  154. pSSRC->rcvInfo.dwNumBytesRcvd = 0;
  155. pSSRC->rcvInfo.dwBadSeqNum = RTP_SEQ_MOD + 1; // Out of range
  156. pSSRC->rcvInfo.XtendedSeqNum.seq_union.RTPSequence.wSequenceNum =
  157. RTPSequence;
  158. pSSRC->rcvInfo.XtendedSeqNum.seq_union.RTPSequence.wCycle = 0;
  159. #if 0
  160. // as per the RFC, but always 1 packet off by doing this ???
  161. pSSRC->rcvInfo.dwBaseRcvSeqNum = RTPSequence - 1;
  162. #else
  163. pSSRC->rcvInfo.dwBaseRcvSeqNum = RTPSequence;
  164. #endif
  165. IN_OUT_STR ("RTP : Exit initRTPStats()\n");
  166. }
  167. /*----------------------------------------------------------------------------
  168. * Function : sequenceCheck
  169. * Description: Determines whether received packet sequence number is in a
  170. * valid range to include for statistical tracking purposes.
  171. *
  172. * Input : RTPSequence : Sequence number received in the packet.
  173. * NB: Must be in LittleEndian(IA) format
  174. * pSSRC : -> to SSRC table entry for this terminal
  175. *
  176. * Note: Implementataion adapted from draftspec 08, Appendix A.1
  177. *
  178. * Return: TRUE = OK.
  179. * FALSE = Stale or invalid data.
  180. ---------------------------------------------------------------------------*/
  181. #if 1
  182. BOOL sequenceCheck (WORD RTPSequence,
  183. PSSRC_ENTRY pSSRC)
  184. {
  185. WORD delta = RTPSequence -
  186. pSSRC->rcvInfo.XtendedSeqNum.seq_union.RTPSequence.wSequenceNum;
  187. IN_OUT_STR ("RTP : Enter sequenceCheck()\n");
  188. // Have we received enough consecutive sequence numbered pckts in order
  189. // to valide ?
  190. if (pSSRC->rcvInfo.dwProbation)
  191. {
  192. // Is the sequence received the expected one ?
  193. if (RTPSequence ==
  194. (pSSRC->rcvInfo.XtendedSeqNum.seq_union.RTPSequence.wSequenceNum + 1))
  195. {
  196. // Decrement the number of consecutive packets we need before we
  197. // consider statistics to be valid
  198. pSSRC->rcvInfo.dwProbation--;
  199. pSSRC->rcvInfo.XtendedSeqNum.seq_union.RTPSequence.wSequenceNum =
  200. RTPSequence;
  201. if (pSSRC->rcvInfo.dwProbation == 0)
  202. {
  203. initRTPStats(RTPSequence, pSSRC);
  204. IN_OUT_STR ("RTP : Exit sequenceCheck()\n");
  205. return TRUE;
  206. }
  207. }
  208. else
  209. {
  210. pSSRC->rcvInfo.dwProbation = MIN_SEQUENTIAL - 1;
  211. pSSRC->rcvInfo.XtendedSeqNum.seq_union.RTPSequence.wSequenceNum =
  212. RTPSequence;
  213. }
  214. IN_OUT_STR ("RTP : Exit sequenceCheck()\n");
  215. return FALSE;
  216. }
  217. else if (delta < MAX_DROPOUT)
  218. {
  219. // In order with permissible gap
  220. if (RTPSequence < pSSRC->rcvInfo.XtendedSeqNum.seq_union.RTPSequence.wSequenceNum)
  221. // sequence number wrapped - count another 64K cycle
  222. pSSRC->rcvInfo.XtendedSeqNum.seq_union.RTPSequence.wCycle += 1;
  223. pSSRC->rcvInfo.XtendedSeqNum.seq_union.RTPSequence.wSequenceNum = RTPSequence;
  224. }
  225. else if (delta <= RTP_SEQ_MOD - MAX_MISORDER)
  226. {
  227. // the sequence number made a very large jump
  228. if (RTPSequence == pSSRC->rcvInfo.dwBadSeqNum)
  229. // two sequential packet. Assume the other side restarted w/o telling
  230. // us, so just re-sync, i.e., pretend this was the first packet
  231. initRTPStats(RTPSequence, pSSRC);
  232. else
  233. {
  234. pSSRC->rcvInfo.dwBadSeqNum = (RTPSequence + 1) & (RTP_SEQ_MOD - 1);
  235. IN_OUT_STR ("RTP : Exit sequenceCheck()\n");
  236. return FALSE;
  237. }
  238. }
  239. else
  240. {
  241. // duplicate or reordered packet
  242. }
  243. IN_OUT_STR ("RTP : Exit sequenceCheck()\n");
  244. return (TRUE);
  245. }
  246. #else
  247. //BOOL sequenceCheck (WORD RTPSequence,
  248. // PSSRC_ENTRY lpSSRCList)
  249. //{
  250. // BOOL bStatus;
  251. // WORD delta;
  252. //
  253. //#ifdef IN_OUT_CHK
  254. // OutputDebugString ("\nEnter sequenceCheck()");
  255. //#endif
  256. //
  257. // // Have we received a couple of consecutive sequence numbered packets for
  258. // // validation?
  259. // if (lpSSRCList->probation) {
  260. //
  261. // // Default status is don't include since the source hasn't been validated yet
  262. // bStatus = FALSE;
  263. //
  264. // // Is the sequence received the expected one?
  265. // if (RTPSequence == (lpSSRCList->XtendedSeqNum.seq_union.RTPSequence.wSequenceNum + 1)) {
  266. // // Decrement the number of consecutive packets we need before we
  267. // // consider statistics to be valid
  268. // lpSSRCList->probation--;
  269. // lpSSRCList->XtendedSeqNum.seq_union.RTPSequence.wSequenceNum = RTPSequence;
  270. // if (lpSSRCList->probation == 0) {
  271. // initRTPStats(RTPSequence, lpSSRCList);
  272. // bStatus = TRUE;
  273. // }
  274. // }
  275. // else {
  276. // lpSSRCList->probation = MIN_SEQUENTIAL - 1;
  277. // lpSSRCList->XtendedSeqNum.seq_union.RTPSequence.wSequenceNum = RTPSequence;
  278. // }
  279. // }
  280. // else {
  281. // // Default status is include since the source has been validated
  282. // bStatus = TRUE;
  283. //
  284. // // First consider the case where delta is positive (or a duplicate packet)
  285. // if (RTPSequence >= lpSSRCList->XtendedSeqNum.seq_union.RTPSequence.wSequenceNum) {
  286. //
  287. // delta = RTPSequence - lpSSRCList->XtendedSeqNum.seq_union.RTPSequence.wSequenceNum;
  288. //
  289. // if (delta < MAX_DROPOUT) {
  290. // // packets may be missing, but not too many so as to be deemed restarted
  291. // lpSSRCList->XtendedSeqNum.seq_union.RTPSequence.wSequenceNum = RTPSequence;
  292. // }
  293. // else if (delta > (RTP_SEQ_MOD - MAX_MISORDER)) {
  294. // // There has been a recent wraparound, and this is just a recent old packet
  295. // // Nothing to do but include for statistical processing
  296. // }
  297. // else {
  298. // // there was a very large jump in sequence numbers
  299. // if (RTPSequence == lpSSRCList->badSeqNum ) {
  300. // // Two sequential packets after what was thought was a bad packet or
  301. // // (assume a very large jump and proceed as if the sender restarted
  302. // // without telling us) or a new terminal is in the session.
  303. // initRTPStats(RTPSequence, lpSSRCList);
  304. // }
  305. // else {
  306. // lpSSRCList->badSeqNum = (RTPSequence + 1) & (RTP_SEQ_MOD - 1);
  307. // bStatus = FALSE;
  308. // }
  309. // }
  310. // }
  311. // else {
  312. // // sequence number is less than the last we received. Could be either
  313. // // a recent late packet, a very late packet, a wraparound or a restartup
  314. // // of a new session for an SSRC from which we hadn't received a BYE
  315. //
  316. // delta = lpSSRCList->XtendedSeqNum.seq_union.RTPSequence.wSequenceNum - RTPSequence;
  317. //
  318. // if (delta < MAX_MISORDER) {
  319. // // Packet arrived a little bit late, it's still OK
  320. // // do nothing here, will be counted in stat routines
  321. // }
  322. // else if (delta > (RTP_SEQ_MOD - MAX_DROPOUT)) {
  323. // // wrap around, adjust cycle number and sequence number
  324. // lpSSRCList->XtendedSeqNum.seq_union.RTPSequence.cycle++;
  325. // lpSSRCList->XtendedSeqNum.seq_union.RTPSequence.wSequenceNum = RTPSequence;
  326. // }
  327. // else {
  328. // // there was a very large jump in sequence numbers
  329. // if (RTPSequence == lpSSRCList->badSeqNum) {
  330. // // Two sequential packets after what was thought was a bad packet.
  331. // // Assume a very large jump and proceed as if the sender restarted
  332. // // without telling us
  333. // initRTPStats(RTPSequence, lpSSRCList);
  334. // }
  335. // else {
  336. // lpSSRCList->badSeqNum = (RTPSequence + 1) & (RTP_SEQ_MOD - 1);
  337. // bStatus = FALSE;
  338. // }
  339. // }
  340. // }
  341. // }
  342. //
  343. //#ifdef IN_OUT_CHK
  344. // OutputDebugString ("\nExit sequenceCheck()");
  345. //#endif
  346. //
  347. // return (bStatus);
  348. //}
  349. #endif
  350. /*----------------------------------------------------------------------------
  351. * Function : updateRTPStats
  352. * Description: Updates statistics for RTP packets received from net
  353. *
  354. * Input : pRTPHeader : -> to packet's RTP header field
  355. * pSSRC : -> to remote source's statistics table
  356. * cbTransferred : Number of bytes transferred
  357. *
  358. *
  359. * Return: RRCM_NoError = OK.
  360. * Otherwise(!=0) = Initialization Error.
  361. ---------------------------------------------------------------------------*/
  362. DWORD updateRTPStats (RTP_HDR_T *pRTPHeader,
  363. PSSRC_ENTRY pSSRC,
  364. DWORD cbTransferred)
  365. {
  366. WORD RTPSequenceNum;
  367. IN_OUT_STR ("RTP : Enter updateRTPStats()\n");
  368. // Update statistics only if the data looks good. Check the sequence number
  369. // to ensure it is within an appropriate range. First, we must convert the
  370. // sequence number to IA (little Endian) format
  371. RRCMws.ntohs (pSSRC->RTPsd, pRTPHeader->seq,
  372. (unsigned short *)&RTPSequenceNum);
  373. if (sequenceCheck (RTPSequenceNum, pSSRC))
  374. {
  375. // lock access to data
  376. EnterCriticalSection (&pSSRC->critSect);
  377. // update number of packet received
  378. pSSRC->rcvInfo.dwNumPcktRcvd++;
  379. // Number octets received (exclusive of header) depends on whether
  380. // a mixer (CSRC != 0) was involved
  381. if (pRTPHeader->cc == 0)
  382. {
  383. pSSRC->rcvInfo.dwNumBytesRcvd +=
  384. (cbTransferred - (sizeof(RTP_HDR_T) - sizeof(pRTPHeader->csrc[0])));
  385. }
  386. else
  387. {
  388. pSSRC->rcvInfo.dwNumBytesRcvd +=
  389. (cbTransferred - sizeof(RTP_HDR_T) +
  390. ((pRTPHeader->cc - 1) * sizeof(pRTPHeader->csrc[0])));
  391. }
  392. // Packet received sequentially in order (difference
  393. // of 1, or -1 if wraparound) save new current
  394. // sequence number
  395. RRCMws.ntohs (pSSRC->RTPsd, pRTPHeader->seq,
  396. (unsigned short *)&pSSRC->xmtInfo.dwCurXmtSeqNum);
  397. // Calculate JITTER
  398. calculateJitter (pRTPHeader, pSSRC);
  399. // unlock access to data
  400. LeaveCriticalSection (&pSSRC->critSect);
  401. }
  402. IN_OUT_STR ("RTP : Exit updateRTPStats()\n");
  403. return (RRCM_NoError);
  404. }
  405. // [EOF]