rtphint.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:12k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is MPEG4IP.
  13.  * 
  14.  * The Initial Developer of the Original Code is Cisco Systems Inc.
  15.  * Portions created by Cisco Systems Inc. are
  16.  * Copyright (C) Cisco Systems Inc. 2000, 2001.  All Rights Reserved.
  17.  * 
  18.  * Contributor(s): 
  19.  * Dave Mackie dmackie@cisco.com
  20.  */
  21. #include "quicktime.h"
  22. quicktime_rtp_sample_t* quicktime_get_hint_sample(u_char* hintBuf)
  23. {
  24. return (quicktime_rtp_sample_t*)hintBuf;
  25. }
  26. quicktime_rtp_packet_entry_t* quicktime_get_hint_last_packet_entry(
  27. u_char* hintBuf)
  28. {
  29. quicktime_rtp_sample_t* sample = quicktime_get_hint_sample(hintBuf);
  30. u_int16_t numPacketEntries = ntohs(sample->entryCount);
  31. u_char* bufPtr = hintBuf + sizeof(quicktime_rtp_sample_t);
  32. int i;
  33. if (numPacketEntries == 0) {
  34. return NULL;
  35. }
  36. for (i = 0; i < numPacketEntries - 1; i++) {
  37. bufPtr += quicktime_get_packet_size(bufPtr);
  38. }
  39. return (quicktime_rtp_packet_entry_t*)bufPtr;
  40. }
  41. void quicktime_init_hint_sample(u_char* hintBuf, u_int* pHintBufSize)
  42. {
  43. quicktime_rtp_sample_t* sample = quicktime_get_hint_sample(hintBuf);
  44. sample->entryCount = htons(0);
  45. sample->reserved = htons(0);
  46. (*pHintBufSize) = sizeof(quicktime_rtp_sample_t);
  47. }
  48. void quicktime_add_hint_packet(u_char* hintBuf, u_int* pHintBufSize, 
  49. u_int payloadNumber, u_int rtpSeqNum)
  50. {
  51. quicktime_rtp_sample_t* sample = quicktime_get_hint_sample(hintBuf);
  52. quicktime_rtp_packet_entry_t* packetEntry = 
  53. (quicktime_rtp_packet_entry_t*)(hintBuf + (*pHintBufSize));
  54. sample->entryCount = htons(ntohs(sample->entryCount) + 1);
  55. packetEntry->relativeXmitTime = htonl(0);
  56. packetEntry->headerInfo = htons(payloadNumber);
  57. packetEntry->seqNum = htons(rtpSeqNum);
  58. packetEntry->flags = htons(0);
  59. packetEntry->numDataEntries = htons(0);
  60. (*pHintBufSize) += sizeof(quicktime_rtp_packet_entry_t);
  61. }
  62. void quicktime_set_rtp_hint_timestamp_offset(u_char* hintBuf, 
  63. u_int* pHintBufSize, int offset)
  64. {
  65. quicktime_rtp_packet_entry_t* packetEntry = 
  66. quicktime_get_hint_last_packet_entry(hintBuf);
  67. u_int32_t* pTlvTableSize = (u_int32_t*)
  68. ((u_char*)packetEntry + sizeof(quicktime_rtp_packet_entry_t));
  69. quicktime_rtp_tlv_entry_t* tlvEntry = (quicktime_rtp_tlv_entry_t*)
  70. ((u_char*)pTlvTableSize + sizeof(u_int32_t));
  71. /* nothing to do */
  72. if (offset == 0) {
  73. return;
  74. }
  75. if (ntohs(packetEntry->numDataEntries)) {
  76. #ifdef DEBUG
  77. printf("OOPS, have already added data to this hint packetn");
  78. #endif
  79. return;
  80. }
  81. packetEntry->flags |= htons(1 << 2);  /* signal presence of TLV */
  82. *pTlvTableSize = htonl(16);
  83. /* the TLV entry */
  84. tlvEntry->size = htonl(12);
  85. memcpy(tlvEntry->id, "rtpo", sizeof(tlvEntry->id));
  86. *((int32_t*)&tlvEntry->data) = htonl(offset);
  87. (*pHintBufSize) += 16;
  88. }
  89. void quicktime_add_hint_immed_data(u_char* hintBuf, u_int* pHintBufSize, 
  90. u_char* data, u_int length)
  91. {
  92. quicktime_rtp_packet_entry_t* packetEntry = 
  93. quicktime_get_hint_last_packet_entry(hintBuf);
  94. quicktime_rtp_immed_data_entry_t* dataEntry = 
  95. (quicktime_rtp_immed_data_entry_t*)(hintBuf + (*pHintBufSize));
  96. dataEntry->source = 1;
  97. dataEntry->length = MIN(length, sizeof(dataEntry->data));
  98. memcpy(dataEntry->data, data, dataEntry->length);
  99. packetEntry->numDataEntries = htons(ntohs(packetEntry->numDataEntries) + 1);
  100. (*pHintBufSize) += sizeof(quicktime_rtp_immed_data_entry_t);
  101. }
  102. void quicktime_add_hint_sample_data(u_char* hintBuf, u_int* pHintBufSize, 
  103. u_int fromSampleNum, u_int offset, u_int length)
  104. {
  105. quicktime_rtp_packet_entry_t* packetEntry = 
  106. quicktime_get_hint_last_packet_entry(hintBuf);
  107. quicktime_rtp_sample_data_entry_t* dataEntry = 
  108. (quicktime_rtp_sample_data_entry_t*)(hintBuf + (*pHintBufSize));
  109. dataEntry->source = 2;
  110. dataEntry->trackId = 0;
  111. dataEntry->length = htons(length);
  112. dataEntry->fromSampleNum = htonl(fromSampleNum);
  113. dataEntry->offset = htonl(offset);
  114. dataEntry->bytesPerCompressionBlock = htons(0);
  115. dataEntry->samplesPerCompressionBlock = htons(0);
  116. packetEntry->numDataEntries = htons(ntohs(packetEntry->numDataEntries) + 1);
  117. (*pHintBufSize) += sizeof(quicktime_rtp_sample_data_entry_t);
  118. }
  119. void quicktime_set_hint_Mbit(u_char* hintBuf)
  120. {
  121. quicktime_rtp_packet_entry_t* packetEntry = 
  122. quicktime_get_hint_last_packet_entry(hintBuf);
  123. packetEntry->headerInfo |= htons(1 << 7);
  124. }
  125. void quicktime_set_hint_Bframe(u_char* hintBuf)
  126. {
  127. quicktime_rtp_packet_entry_t* packetEntry = 
  128. quicktime_get_hint_last_packet_entry(hintBuf);
  129. packetEntry->flags |= htons(1 << 1); 
  130. }
  131. void quicktime_set_hint_repeat(u_char* hintBuf)
  132. {
  133. quicktime_rtp_packet_entry_t* packetEntry = 
  134. quicktime_get_hint_last_packet_entry(hintBuf);
  135. packetEntry->flags |= htons(1 << 0);
  136. }
  137. void quicktime_set_hint_repeat_offset(u_char* hintBuf, u_int32_t offset)
  138. {
  139. quicktime_rtp_packet_entry_t* packetEntry = 
  140. quicktime_get_hint_last_packet_entry(hintBuf);
  141. packetEntry->relativeXmitTime = offset;
  142. }
  143. int quicktime_dump_hint_sample(u_char* hintBuf)
  144. {
  145. quicktime_rtp_sample_t* sample = quicktime_get_hint_sample(hintBuf);
  146. int i, numPacketEntries;
  147. u_char* bufPtr;
  148. fprintf(stdout, " entryCount %un", ntohs(sample->entryCount));
  149. fprintf(stdout, " reserved %un", ntohs(sample->reserved));
  150. /* entryCount of quicktime_rtp_packet_entry_t follow */
  151. numPacketEntries = ntohs(sample->entryCount);
  152. bufPtr = hintBuf + sizeof(quicktime_rtp_sample_t);
  153. for (i = 0; i < numPacketEntries; i++) {
  154. fprintf(stdout, " packet %un", i + 1);
  155. bufPtr += quicktime_dump_hint_packet(bufPtr);
  156. }
  157. /* return number of bytes dumped */
  158. return (bufPtr - hintBuf);
  159. }
  160. int quicktime_dump_hint_packet(u_char* hintBuf)
  161. {
  162. quicktime_rtp_packet_entry_t* packetEntry = 
  163. (quicktime_rtp_packet_entry_t*)hintBuf;
  164. u_char* bufPtr;
  165. int i;
  166. fprintf(stdout, "  relativeXmitTime %lun", ntohl(packetEntry->relativeXmitTime));
  167. fprintf(stdout, "  headerInfo %xn", packetEntry->headerInfo);
  168. fprintf(stdout, "  seqNum %un", ntohs(packetEntry->seqNum));
  169. fprintf(stdout, "  flags %xn", ntohs(packetEntry->flags));
  170. fprintf(stdout, "  numDataEntries %un", ntohs(packetEntry->numDataEntries));
  171. bufPtr = hintBuf + sizeof(quicktime_rtp_packet_entry_t);
  172. /* if X bit is set in flags, TLV entries exist */
  173. if (packetEntry->flags & htons(1 << 2)) {
  174. u_char* tlvTableStart = bufPtr;
  175. u_int32_t tlvTableSize = ntohl(*(u_int32_t*)bufPtr);
  176. bufPtr += sizeof(u_int32_t);
  177. fprintf(stdout, "  tlvTableSize %un", tlvTableSize);
  178. i = 1;
  179. do {
  180. fprintf(stdout, "  tlvEntry %un", i);
  181. bufPtr += quicktime_dump_hint_tlv(bufPtr);
  182. i++;
  183. } while (bufPtr < tlvTableStart + tlvTableSize);
  184. }
  185. /* numDataEntries of qt_rtp_data_entry follow */
  186. for (i = 0; i < ntohs(packetEntry->numDataEntries); i++) {
  187. fprintf(stdout, "  dataEntry %un", i + 1);
  188. bufPtr += quicktime_dump_hint_data(bufPtr);
  189. }
  190. /* return number of bytes dumped */
  191. return (bufPtr - hintBuf);
  192. }
  193. int quicktime_dump_hint_tlv(u_char* hintBuf)
  194. {
  195. quicktime_rtp_tlv_entry_t* tlvEntry = 
  196. (quicktime_rtp_tlv_entry_t*)hintBuf;
  197. fprintf(stdout, "   id %.4sn", tlvEntry->id);
  198. if (!memcmp(tlvEntry->id, "rtpo", 4)) {
  199. fprintf(stdout, "   offset %dn", ntohl(*(u_int32_t*)&tlvEntry->data));
  200. }
  201. return ntohl(tlvEntry->size);
  202. }
  203. int quicktime_dump_hint_data(u_char* hintBuf)
  204. {
  205. quicktime_rtp_data_entry_t* dataEntry = 
  206. (quicktime_rtp_data_entry_t*)hintBuf;
  207. fprintf(stdout, "   source %un", dataEntry->null.source);
  208. if (dataEntry->null.source == 1) {
  209. u_int i;
  210. fprintf(stdout, "   length %un", dataEntry->immed.length);
  211. fprintf(stdout, "   data ");
  212. for (i = 0; i < MIN(dataEntry->immed.length, sizeof(dataEntry->immed.data)); i++) {
  213. fprintf(stdout, "%x ", dataEntry->immed.data[i]);
  214. }
  215. fprintf(stdout, "n");
  216. } else if (dataEntry->null.source == 2) {
  217. fprintf(stdout, "   trackId %un", dataEntry->sample.trackId);
  218. fprintf(stdout, "   length %un", ntohs(dataEntry->sample.length));
  219. fprintf(stdout, "   fromSampleNum %un", ntohl(dataEntry->sample.fromSampleNum));
  220. fprintf(stdout, "   offset %un", ntohl(dataEntry->sample.offset));
  221. fprintf(stdout, "   bytesPerCompressionBlock %un", ntohs(dataEntry->sample.bytesPerCompressionBlock));
  222. fprintf(stdout, "   samplesPerCompressionBlock %un", ntohs(dataEntry->sample.samplesPerCompressionBlock));
  223. /* return number of bytes dumped */
  224. return sizeof(quicktime_rtp_data_entry_t); 
  225. }
  226. int quicktime_get_hint_size(u_char* hintBuf)
  227. {
  228. quicktime_rtp_sample_t* sample = quicktime_get_hint_sample(hintBuf);
  229. u_int16_t numPacketEntries = ntohs(sample->entryCount);
  230. u_char* bufPtr = hintBuf + sizeof(quicktime_rtp_sample_t);
  231. int i;
  232. for (i = 0; i < numPacketEntries; i++) {
  233. bufPtr += quicktime_get_packet_size(bufPtr);
  234. }
  235. return (bufPtr - hintBuf);
  236. }
  237. int quicktime_get_packet_entry_size(u_char* hintBuf)
  238. {
  239. quicktime_rtp_packet_entry_t* packetEntry = 
  240. (quicktime_rtp_packet_entry_t*)hintBuf;
  241. u_char* bufPtr = hintBuf + sizeof(quicktime_rtp_packet_entry_t);
  242. if (packetEntry->flags & htons(1 << 2)) {
  243. u_int32_t tlvTableSize = ntohl(*(u_int32_t*)bufPtr);
  244. bufPtr += tlvTableSize;
  245. }
  246. return (bufPtr - hintBuf);
  247. }
  248. int quicktime_get_packet_size(u_char* hintBuf)
  249. {
  250. quicktime_rtp_packet_entry_t* packetEntry = 
  251. (quicktime_rtp_packet_entry_t*)hintBuf;
  252. u_int numDataEntries = ntohs(packetEntry->numDataEntries);
  253. return quicktime_get_packet_entry_size(hintBuf) 
  254. + (numDataEntries * sizeof(quicktime_rtp_data_entry_t));
  255. }
  256. int quicktime_get_hint_info(u_char* hintBuf, u_int hintBufSize, quicktime_hint_info_t* pHintInfo)
  257. {
  258. quicktime_rtp_sample_t* sample = quicktime_get_hint_sample(hintBuf);
  259. u_int16_t numPacketEntries = ntohs(sample->entryCount);
  260. u_char* bufPtr = hintBuf + sizeof(quicktime_rtp_sample_t);
  261. int i, j;
  262. memset(pHintInfo, 0, sizeof(quicktime_hint_info_t));
  263. pHintInfo->nump = numPacketEntries;
  264. for (i = 0; i < numPacketEntries; i++) {
  265. quicktime_rtp_packet_entry_t* packetEntry = 
  266. (quicktime_rtp_packet_entry_t*)bufPtr;
  267. u_int numDataEntries = ntohs(packetEntry->numDataEntries);
  268. u_int32_t rtpPacketLength = 0;
  269. pHintInfo->tmin = MIN(pHintInfo->tmin,
  270. (int32_t)ntohl(packetEntry->relativeXmitTime));
  271. pHintInfo->tmax = MAX(pHintInfo->tmax,
  272. (int32_t)ntohl(packetEntry->relativeXmitTime));
  273. bufPtr += quicktime_get_packet_entry_size(bufPtr);
  274. for (j = 0; j < numDataEntries; j++) {
  275. quicktime_rtp_data_entry_t* dataEntry =
  276. (quicktime_rtp_data_entry_t*)bufPtr; 
  277. u_int16_t dataLength = 0;
  278. if (dataEntry->null.source == 1) {
  279. /* immediate data */
  280. dataLength = dataEntry->immed.length;
  281. pHintInfo->dimm += dataLength;
  282. } else if (dataEntry->null.source == 2) {
  283. /* sample data */
  284. dataLength = ntohs(dataEntry->sample.length);
  285. pHintInfo->dmed += dataLength;
  286. }
  287. rtpPacketLength += dataLength;
  288. bufPtr += sizeof(quicktime_rtp_data_entry_t);
  289. }
  290. pHintInfo->trpy += RTP_HEADER_STD_SIZE + rtpPacketLength;
  291. pHintInfo->tpyl += rtpPacketLength;
  292. if (ntohs(packetEntry->flags) & 0x80) {
  293. /* repeated data */
  294. pHintInfo->drep += rtpPacketLength;
  295. }
  296. pHintInfo->pmax = MAX(pHintInfo->pmax, 
  297. RTP_HEADER_STD_SIZE + rtpPacketLength);
  298. }
  299. }