rfcisma.cpp
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:8k
源码类别:

流媒体/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-2002.  All Rights Reserved.
  17.  * 
  18.  * Contributor(s): 
  19.  * Dave Mackie dmackie@cisco.com
  20.  */
  21. /* 
  22.  * Notes:
  23.  *  - file formatted with tabstops == 4 spaces 
  24.  */
  25. #include <mp4av_common.h>
  26. bool MP4AV_RfcIsmaConcatenator(
  27. MP4FileHandle mp4File, 
  28. MP4TrackId mediaTrackId, 
  29. MP4TrackId hintTrackId,
  30. u_int8_t samplesThisHint, 
  31. MP4SampleId* pSampleIds, 
  32. MP4Duration hintDuration,
  33. u_int16_t maxPayloadSize)
  34. {
  35. // handle degenerate case
  36. if (samplesThisHint == 0) {
  37. return true;
  38. }
  39. u_int8_t auPayloadHdrSize;
  40. // LATER would be more efficient if this were a parameter
  41. u_int8_t mpeg4AudioType =
  42. MP4GetTrackAudioMpeg4Type(mp4File, mediaTrackId);
  43. if (mpeg4AudioType == MP4_MPEG4_CELP_AUDIO_TYPE) {
  44. auPayloadHdrSize = 1;
  45. } else {
  46. auPayloadHdrSize = 2;
  47. }
  48. // construct the new hint
  49. MP4AddRtpHint(mp4File, hintTrackId);
  50. MP4AddRtpPacket(mp4File, hintTrackId, true);
  51. u_int8_t payloadHeader[2];
  52. u_int16_t numHdrBits = samplesThisHint * auPayloadHdrSize * 8;
  53. payloadHeader[0] = numHdrBits >> 8;
  54. payloadHeader[1] = numHdrBits & 0xFF;
  55. MP4AddRtpImmediateData(mp4File, hintTrackId,
  56. (u_int8_t*)&payloadHeader, sizeof(payloadHeader));
  57. u_int8_t i;
  58. // first the headers
  59. for (i = 0; i < samplesThisHint; i++) {
  60. MP4SampleId sampleId = pSampleIds[i];
  61. u_int32_t sampleSize = 
  62. MP4GetSampleSize(mp4File, mediaTrackId, sampleId);
  63. if (auPayloadHdrSize == 1) {
  64. // AU payload header is 6 bits of size
  65. // follow by 2 bits of the difference between sampleId's - 1
  66. payloadHeader[0] = sampleSize << 2;
  67. } else { // auPayloadHdrSize == 2
  68. // AU payload header is 13 bits of size
  69. // follow by 3 bits of the difference between sampleId's - 1
  70. payloadHeader[0] = sampleSize >> 5;
  71. payloadHeader[1] = (sampleSize & 0x1F) << 3;
  72. }
  73. if (i > 0) {
  74. payloadHeader[auPayloadHdrSize - 1] 
  75. |= ((sampleId - pSampleIds[i-1]) - 1); 
  76. }
  77. MP4AddRtpImmediateData(mp4File, hintTrackId,
  78. (u_int8_t*)&payloadHeader, auPayloadHdrSize);
  79. }
  80. // then the samples
  81. for (i = 0; i < samplesThisHint; i++) {
  82. MP4SampleId sampleId = pSampleIds[i];
  83. u_int32_t sampleSize = 
  84. MP4GetSampleSize(mp4File, mediaTrackId, sampleId);
  85. MP4AddRtpSampleData(mp4File, hintTrackId, sampleId, 0, sampleSize);
  86. }
  87. // write the hint
  88. MP4WriteRtpHint(mp4File, hintTrackId, hintDuration);
  89. return true;
  90. }
  91. bool MP4AV_RfcIsmaFragmenter(
  92. MP4FileHandle mp4File, 
  93. MP4TrackId mediaTrackId, 
  94. MP4TrackId hintTrackId,
  95. MP4SampleId sampleId, 
  96. u_int32_t sampleSize, 
  97. MP4Duration sampleDuration,
  98. u_int16_t maxPayloadSize)
  99. {
  100. MP4AddRtpHint(mp4File, hintTrackId);
  101. MP4AddRtpPacket(mp4File, hintTrackId, false);
  102. // Note: CELP is never fragmented
  103. // so we assume the two byte AAC-hbr payload header
  104. u_int8_t payloadHeader[4];
  105. payloadHeader[0] = 0;
  106. payloadHeader[1] = 16;
  107. payloadHeader[2] = sampleSize >> 5;
  108. payloadHeader[3] = (sampleSize & 0x1F) << 3;
  109. MP4AddRtpImmediateData(mp4File, hintTrackId,
  110. (u_int8_t*)&payloadHeader, sizeof(payloadHeader));
  111. u_int16_t sampleOffset = 0;
  112. u_int16_t fragLength = maxPayloadSize - 4;
  113. do {
  114. MP4AddRtpSampleData(mp4File, hintTrackId,
  115. sampleId, sampleOffset, fragLength);
  116. sampleOffset += fragLength;
  117. if (sampleSize - sampleOffset > maxPayloadSize) {
  118. fragLength = maxPayloadSize; 
  119. MP4AddRtpPacket(mp4File, hintTrackId, false);
  120. } else {
  121. fragLength = sampleSize - sampleOffset; 
  122. if (fragLength) {
  123. MP4AddRtpPacket(mp4File, hintTrackId, true);
  124. }
  125. }
  126. } while (sampleOffset < sampleSize);
  127. MP4WriteRtpHint(mp4File, hintTrackId, sampleDuration);
  128. return true;
  129. }
  130. extern "C" bool MP4AV_RfcIsmaHinter(
  131. MP4FileHandle mp4File, 
  132. MP4TrackId mediaTrackId, 
  133. bool interleave,
  134. u_int16_t maxPayloadSize)
  135. {
  136. // gather information, and check for validity
  137. MP4TrackId hintTrackId =
  138. MP4AddHintTrack(mp4File, mediaTrackId);
  139. if (hintTrackId == MP4_INVALID_TRACK_ID) {
  140. return false;
  141. }
  142. u_int32_t numSamples =
  143. MP4GetTrackNumberOfSamples(mp4File, mediaTrackId);
  144. if (numSamples == 0) {
  145. return false;
  146. }
  147. u_int32_t timeScale =
  148. MP4GetTrackTimeScale(mp4File, hintTrackId);
  149. if (timeScale == 0) {
  150. return false;
  151. }
  152. MP4Duration sampleDuration = 
  153. MP4GetSampleDuration(mp4File, mediaTrackId, 1);
  154. if (sampleDuration == MP4_INVALID_DURATION) {
  155. return false;
  156. }
  157. u_int8_t audioType =
  158. MP4GetTrackAudioType(mp4File, mediaTrackId);
  159. if (audioType != MP4_MPEG4_AUDIO_TYPE
  160.   && !MP4_IS_AAC_AUDIO_TYPE(audioType)) {
  161. return false;
  162. }
  163. u_int8_t mpeg4AudioType =
  164. MP4GetTrackAudioMpeg4Type(mp4File, mediaTrackId);
  165. if (audioType == MP4_MPEG4_AUDIO_TYPE) {
  166. // check that track contains either MPEG-4 AAC or CELP
  167. if (!MP4_IS_MPEG4_AAC_AUDIO_TYPE(mpeg4AudioType) 
  168.   && mpeg4AudioType != MP4_MPEG4_CELP_AUDIO_TYPE) {
  169. return false;
  170. }
  171. }
  172. /* get the ES configuration */
  173. u_int8_t* pConfig = NULL;
  174. u_int32_t configSize;
  175. MP4GetTrackESConfiguration(mp4File, mediaTrackId, &pConfig, &configSize);
  176. if (!pConfig) {
  177. return false;
  178. }
  179. /* convert ES Config into ASCII form */
  180. char* sConfig = 
  181. MP4BinaryToBase16(pConfig, configSize);
  182. free(pConfig);
  183. if (!sConfig) {
  184. return false;
  185. }
  186. /* create the appropriate SDP attribute */
  187. char* sdpBuf = 
  188. (char*)malloc(strlen(sConfig) + 256);
  189. if (!sdpBuf) {
  190. free(sConfig);
  191. return false;
  192. }
  193. // now add the hint track
  194. u_int8_t payloadNumber = 0;
  195. MP4SetHintTrackRtpPayload(mp4File, hintTrackId, 
  196. "mpeg4-generic", &payloadNumber, 0);
  197. MP4Duration maxLatency;
  198. if (mpeg4AudioType == MP4_MPEG4_CELP_AUDIO_TYPE) {
  199. sprintf(sdpBuf,
  200. "a=fmtp:%u "
  201. "streamtype=5; profile-level-id=15; mode=CELP-vbr; config=%s; "
  202. "SizeLength=6; IndexLength=2; IndexDeltaLength=2; Profile=0;"
  203. "1512",
  204. payloadNumber,
  205. sConfig); 
  206. // 200 ms max latency for ISMA profile 1
  207. maxLatency = timeScale / 5;
  208. } else { // AAC
  209. sprintf(sdpBuf,
  210. "a=fmtp:%u "
  211. "streamtype=5; profile-level-id=15; mode=AAC-hbr; config=%s; "
  212. "SizeLength=13; IndexLength=3; IndexDeltaLength=3; Profile=1;"
  213. "1512",
  214. payloadNumber,
  215. sConfig); 
  216. // 500 ms max latency for ISMA profile 1
  217. maxLatency = timeScale / 2;
  218. }
  219. /* add this to the track's sdp */
  220. MP4AppendHintTrackSdp(mp4File, hintTrackId, sdpBuf);
  221. free(sConfig);
  222. free(sdpBuf);
  223. u_int32_t samplesPerPacket = 0;
  224.  
  225. if (interleave) {
  226. u_int32_t maxSampleSize =
  227. MP4GetTrackMaxSampleSize(mp4File, mediaTrackId);
  228. // compute how many maximum size samples would fit in a packet
  229. samplesPerPacket = 
  230. (maxPayloadSize - 2) / (maxSampleSize + 2);
  231. // can't interleave if this number is 0 or 1
  232. if (samplesPerPacket < 2) {
  233. interleave = false;
  234. }
  235. }
  236. if (interleave) {
  237. u_int32_t samplesPerGroup = maxLatency / sampleDuration;
  238. MP4AV_AudioInterleaveHinter(
  239. mp4File, 
  240. mediaTrackId, 
  241. hintTrackId,
  242. sampleDuration, 
  243. samplesPerGroup / samplesPerPacket, // stride
  244. samplesPerPacket, // bundle
  245. maxPayloadSize,
  246. MP4AV_RfcIsmaConcatenator);
  247. } else {
  248. MP4AV_AudioConsecutiveHinter(
  249. mp4File, 
  250. mediaTrackId, 
  251. hintTrackId,
  252. sampleDuration, 
  253. 2, // perPacketHeaderSize
  254. 2, // perSampleHeaderSize
  255. maxLatency / sampleDuration, // maxSamplesPerPacket
  256. maxPayloadSize,
  257. MP4GetSampleSize,
  258. MP4AV_RfcIsmaConcatenator,
  259. MP4AV_RfcIsmaFragmenter);
  260. }
  261. return true;
  262. }