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

流媒体/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. /* 
  22.  * Notes:
  23.  *  - file formatted with tabstops == 4 spaces 
  24.  */
  25. #include <mp4creator.h>
  26. #define ADTS_HEADER_MAX_SIZE 10 /* bytes */
  27. static u_int8_t firstHeader[ADTS_HEADER_MAX_SIZE];
  28. /* 
  29.  * hdr must point to at least ADTS_HEADER_MAX_SIZE bytes of memory 
  30.  */
  31. static bool LoadNextAdtsHeader(FILE* inFile, u_int8_t* hdr)
  32. {
  33. u_int state = 0;
  34. u_int dropped = 0;
  35. u_int hdrByteSize = ADTS_HEADER_MAX_SIZE;
  36. while (1) {
  37. /* read a byte */
  38. u_int8_t b;
  39. if (fread(&b, 1, 1, inFile) == 0) {
  40. return false;
  41. }
  42. /* header is complete, return it */
  43. if (state == hdrByteSize - 1) {
  44. hdr[state] = b;
  45. if (dropped > 0) {
  46. fprintf(stderr, "Warning: dropped %u input bytesn", dropped);
  47. }
  48. return true;
  49. }
  50. /* collect requisite number of bytes, no constraints on data */
  51. if (state >= 2) {
  52. hdr[state++] = b;
  53. } else {
  54. /* have first byte, check if we have 1111X00X */
  55. if (state == 1) {
  56. if ((b & 0xF6) == 0xF0) {
  57. hdr[state] = b;
  58. state = 2;
  59. /* compute desired header size */
  60. hdrByteSize = MP4AV_AdtsGetHeaderByteSize(hdr);
  61. } else {
  62. state = 0;
  63. }
  64. }
  65. /* initial state, looking for 11111111 */
  66. if (state == 0) {
  67. if (b == 0xFF) {
  68. hdr[state] = b;
  69. state = 1;
  70. } else {
  71.  /* else drop it */ 
  72. dropped++;
  73. }
  74. }
  75. }
  76. }
  77. }
  78. /*
  79.  * Load the next frame from the file
  80.  * into the supplied buffer, which better be large enough!
  81.  *
  82.  * Note: Frames are padded to byte boundaries
  83.  */
  84. static bool LoadNextAacFrame(FILE* inFile, u_int8_t* pBuf, u_int32_t* pBufSize, bool stripAdts)
  85. {
  86. u_int16_t frameSize;
  87. u_int16_t hdrBitSize, hdrByteSize;
  88. u_int8_t hdrBuf[ADTS_HEADER_MAX_SIZE];
  89. /* get the next AAC frame header, more or less */
  90. if (!LoadNextAdtsHeader(inFile, hdrBuf)) {
  91. return false;
  92. }
  93. /* get frame size from header */
  94. frameSize = MP4AV_AdtsGetFrameSize(hdrBuf);
  95. /* get header size in bits and bytes from header */
  96. hdrBitSize = MP4AV_AdtsGetHeaderBitSize(hdrBuf);
  97. hdrByteSize = MP4AV_AdtsGetHeaderByteSize(hdrBuf);
  98. /* adjust the frame size to what remains to be read */
  99. frameSize -= hdrByteSize;
  100. if (stripAdts) {
  101. if ((hdrBitSize % 8) == 0) {
  102. /* header is byte aligned, i.e. MPEG-2 ADTS */
  103. /* read the frame data into the buffer */
  104. if (fread(pBuf, 1, frameSize, inFile) != frameSize) {
  105. return false;
  106. }
  107. (*pBufSize) = frameSize;
  108. } else {
  109. /* header is not byte aligned, i.e. MPEG-4 ADTS */
  110. int i;
  111. u_int8_t newByte;
  112. int upShift = hdrBitSize % 8;
  113. int downShift = 8 - upShift;
  114. pBuf[0] = hdrBuf[hdrBitSize / 8] << upShift;
  115. for (i = 0; i < frameSize; i++) {
  116. if (fread(&newByte, 1, 1, inFile) != 1) {
  117. return false;
  118. }
  119. pBuf[i] |= (newByte >> downShift);
  120. pBuf[i+1] = (newByte << upShift);
  121. }
  122. (*pBufSize) = frameSize + 1;
  123. }
  124. } else { /* don't strip ADTS headers */
  125. memcpy(pBuf, hdrBuf, hdrByteSize);
  126. if (fread(&pBuf[hdrByteSize], 1, frameSize, inFile) != frameSize) {
  127. return false;
  128. }
  129. }
  130. return true;
  131. }
  132. static bool GetFirstHeader(FILE* inFile)
  133. {
  134. /* read file until we find an audio frame */
  135. fpos_t curPos;
  136. /* already read first header */
  137. if (firstHeader[0] == 0xff) {
  138. return true;
  139. }
  140. /* remember where we are */
  141. fgetpos(inFile, &curPos);
  142. /* go back to start of file */
  143. rewind(inFile);
  144. if (!LoadNextAdtsHeader(inFile, firstHeader)) {
  145. return false;
  146. }
  147. /* reposition the file to where we were */
  148. fsetpos(inFile, &curPos);
  149. return true;
  150. }
  151. MP4TrackId AacCreator(MP4FileHandle mp4File, FILE* inFile)
  152. {
  153. // collect all the necessary meta information
  154. u_int32_t samplesPerSecond;
  155. u_int8_t mpegVersion;
  156. u_int8_t profile;
  157. u_int8_t channelConfig;
  158. if (!GetFirstHeader(inFile)) {
  159. fprintf(stderr,
  160. "%s: data in file doesn't appear to be valid audion",
  161.  ProgName);
  162. exit(EXIT_AAC_CREATOR);
  163. }
  164. samplesPerSecond = MP4AV_AdtsGetSamplingRate(firstHeader);
  165. mpegVersion = MP4AV_AdtsGetVersion(firstHeader);
  166. profile = MP4AV_AdtsGetProfile(firstHeader);
  167. channelConfig = MP4AV_AdtsGetChannels(firstHeader);
  168. u_int8_t audioType = MP4_INVALID_AUDIO_TYPE;
  169. switch (mpegVersion) {
  170. case 0:
  171. audioType = MP4_MPEG4_AUDIO_TYPE;
  172. break;
  173. case 1:
  174. switch (profile) {
  175. case 0:
  176. audioType = MP4_MPEG2_AAC_MAIN_AUDIO_TYPE;
  177. break;
  178. case 1:
  179. audioType = MP4_MPEG2_AAC_LC_AUDIO_TYPE;
  180. break;
  181. case 2:
  182. audioType = MP4_MPEG2_AAC_SSR_AUDIO_TYPE;
  183. break;
  184. case 3:
  185. fprintf(stderr,
  186. "%s: data in file doesn't appear to be valid audion",
  187.  ProgName);
  188. exit(EXIT_AAC_CREATOR);
  189. default:
  190. ASSERT(false);
  191. }
  192. break;
  193. default:
  194. ASSERT(false);
  195. }
  196. // add the new audio track
  197. MP4TrackId trackId = 
  198. MP4AddAudioTrack(mp4File, 
  199. samplesPerSecond, 1024, audioType);
  200. if (trackId == MP4_INVALID_TRACK_ID) {
  201. fprintf(stderr,
  202. "%s: can't create audio trackn", ProgName);
  203. exit(EXIT_AAC_CREATOR);
  204. }
  205. if (MP4GetNumberOfTracks(mp4File, MP4_AUDIO_TRACK_TYPE) == 1) {
  206. MP4SetAudioProfileLevel(mp4File, 0x0F);
  207. }
  208. u_int8_t* pConfig = NULL;
  209. u_int32_t configLength = 0;
  210. MP4AV_AacGetConfiguration(
  211. &pConfig,
  212. &configLength,
  213. profile,
  214. samplesPerSecond,
  215. channelConfig);
  216. if (!MP4SetTrackESConfiguration(mp4File, trackId, 
  217.   pConfig, configLength)) {
  218. fprintf(stderr,
  219. "%s: can't write audio configurationn", ProgName);
  220. exit(EXIT_AAC_CREATOR);
  221. }
  222. // parse the ADTS frames, and write the MP4 samples
  223. u_int8_t sampleBuffer[8 * 1024];
  224. u_int32_t sampleSize = sizeof(sampleBuffer);
  225. MP4SampleId sampleId = 1;
  226. while (LoadNextAacFrame(inFile, sampleBuffer, &sampleSize, true)) {
  227. if (!MP4WriteSample(mp4File, trackId, sampleBuffer, sampleSize)) {
  228. fprintf(stderr,
  229. "%s: can't write audio frame %un", ProgName, sampleId);
  230. exit(EXIT_AAC_CREATOR);
  231. }
  232. sampleId++;
  233. sampleSize = sizeof(sampleBuffer);
  234. }
  235. return trackId;
  236. }