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

流媒体/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. static bool LoadNextMp3Header(FILE* inFile, u_int32_t* pHdr, bool allowLayer4)
  27. {
  28. u_int8_t state = 0;
  29. u_int32_t dropped = 0;
  30. u_int8_t bytes[4];
  31. while (true) {
  32. /* read a byte */
  33. u_int8_t b;
  34. if (fread(&b, 1, 1, inFile) == 0) {
  35. return false;
  36. }
  37. if (state == 3) {
  38. bytes[state] = b;
  39. (*pHdr) = (bytes[0] << 24) | (bytes[1] << 16) 
  40. | (bytes[2] << 8) | bytes[3];
  41. if (dropped > 0) {
  42. fprintf(stderr, "Warning dropped %u input bytesn", dropped);
  43. }
  44. return true;
  45. }
  46. if (state == 2) {
  47. if ((b & 0xF0) == 0 || (b & 0xF0) == 0xF0 || (b & 0x0C) == 0x0C) {
  48. if (bytes[1] == 0xFF) {
  49. state = 1; 
  50. } else {
  51. state = 0; 
  52. }
  53. } else {
  54. bytes[state] = b;
  55. state = 3;
  56. }
  57. }
  58. if (state == 1) {
  59. if ((b & 0xE0) == 0xE0 && (b & 0x18) != 0x08 && 
  60.   ((b & 0x06) != 0 || allowLayer4)) {
  61. bytes[state] = b;
  62. state = 2;
  63. } else {
  64. state = 0;
  65. }
  66. }
  67. if (state == 0) {
  68. if (b == 0xFF) {
  69. bytes[state] = b;
  70. state = 1;
  71. } else {
  72. if (dropped == 0 && 
  73.   ((b & 0xE0) == 0xE0 && 
  74.   (b & 0x18) != 0x08 && 
  75.      ((b & 0x06) != 0 || allowLayer4))) {
  76. /*
  77.  * HACK have seen files where previous frame 
  78.  * was marked as padded, but the byte was never added
  79.  * which results in the next frame's leading 0XFF being
  80.  * eaten. We attempt to repair that situation here.
  81.  */
  82. bytes[0] = 0xFF;
  83. bytes[1] = b;
  84. state = 2;
  85. } else {
  86. /* else drop it */ 
  87. dropped++;
  88. }
  89. }
  90. }
  91. }
  92. }
  93. /*
  94.  * Load the next frame from the file
  95.  * into the supplied buffer, which better be large enough!
  96.  *
  97.  * Note: Frames are padded to byte boundaries
  98.  */
  99. static bool LoadNextMp3Frame(FILE* inFile, u_int8_t* pBuf, u_int32_t* pBufSize)
  100. {
  101. u_int32_t header;
  102. u_int16_t frameSize;
  103. /* get the next MP3 frame header */
  104. if (!LoadNextMp3Header(inFile, &header, false)) {
  105. return false;
  106. }
  107. /* get frame size from header */
  108. frameSize = MP4AV_Mp3GetFrameSize(header);
  109. // guard against buffer overflow
  110. if (frameSize > (*pBufSize)) {
  111. return false;
  112. }
  113. /* put the header in the buffer */
  114. pBuf[0] = (header >> 24) & 0xFF;
  115. pBuf[1] = (header >> 16) & 0xFF;
  116. pBuf[2] = (header >> 8) & 0xFF;
  117. pBuf[3] = header & 0xFF;
  118. /* read the frame data into the buffer */
  119. if (fread(&pBuf[4], 1, frameSize - 4, inFile) != (size_t)(frameSize - 4)) {
  120. return false;
  121. }
  122. (*pBufSize) = frameSize;
  123. return true;
  124. }
  125. static bool GetMp3SamplingParams(FILE* inFile, 
  126. u_int16_t* pSamplingRate, u_int16_t* pSamplingWindow, u_int8_t* pVersion)
  127. {
  128. /* read file until we find an audio frame */
  129. fpos_t curPos;
  130. u_int32_t header;
  131. /* remember where we are */
  132. fgetpos(inFile, &curPos);
  133. /* get the next MP3 frame header */
  134. if (!LoadNextMp3Header(inFile, &header, false)) {
  135. return false;
  136. }
  137. (*pSamplingRate) = MP4AV_Mp3GetHdrSamplingRate(header);
  138. (*pSamplingWindow) = MP4AV_Mp3GetHdrSamplingWindow(header);
  139. (*pVersion) = MP4AV_Mp3GetHdrVersion(header);
  140. /* rewind the file to where we were */
  141. fsetpos(inFile, &curPos);
  142. return true;
  143. }
  144. /*
  145.  * Get MPEG layer from MP3 header
  146.  * if it's really MP3, it should be layer 3, value 01
  147.  * if it's really ADTS, it should be layer 4, value 00
  148.  */
  149. static bool GetMpegLayer(FILE* inFile, u_int8_t* pLayer)
  150. {
  151. /* read file until we find an audio frame */
  152. fpos_t curPos;
  153. u_int32_t header;
  154. /* remember where we are */
  155. fgetpos(inFile, &curPos);
  156. /* get the next MP3 frame header */
  157. if (!LoadNextMp3Header(inFile, &header, true)) {
  158. return false;
  159. }
  160. (*pLayer) = MP4AV_Mp3GetHdrLayer(header);
  161. /* rewind the file to where we were */
  162. fsetpos(inFile, &curPos);
  163. return true;
  164. }
  165. MP4TrackId Mp3Creator(MP4FileHandle mp4File, FILE* inFile)
  166. {
  167. u_int8_t mpegLayer;
  168. if (!GetMpegLayer(inFile, &mpegLayer)) {
  169. fprintf(stderr,
  170. "%s: data in file doesn't appear to be MPEG audion", ProgName);
  171. exit(EXIT_MP3_CREATOR);
  172. }
  173. if (mpegLayer == 0) {
  174. fprintf(stderr,
  175. "%s: data in file appears to be AAC audio, use .aac extensionn",
  176.  ProgName);
  177. exit(EXIT_MP3_CREATOR);
  178. }
  179. u_int16_t samplesPerSecond;
  180. u_int16_t samplesPerFrame;
  181. u_int8_t mpegVersion;
  182. if (!GetMp3SamplingParams(inFile, 
  183.   &samplesPerSecond, &samplesPerFrame, &mpegVersion)) {
  184. fprintf(stderr,
  185. "%s: data in file doesn't appear to be valid audion",
  186.  ProgName);
  187. exit(EXIT_MP3_CREATOR);
  188. }
  189. u_int8_t audioType = MP4AV_Mp3ToMp4AudioType(mpegVersion);
  190. if (audioType == MP4_INVALID_AUDIO_TYPE
  191.   || samplesPerSecond == 0) {
  192. fprintf(stderr,
  193. "%s: data in file doesn't appear to be valid audion",
  194.  ProgName);
  195. exit(EXIT_MP3_CREATOR);
  196. }
  197. MP4TrackId trackId = 
  198. MP4AddAudioTrack(mp4File, 
  199. samplesPerSecond, samplesPerFrame, audioType);
  200. if (trackId == MP4_INVALID_TRACK_ID) {
  201. fprintf(stderr,
  202. "%s: can't create audio trackn", ProgName);
  203. exit(EXIT_MP3_CREATOR);
  204. }
  205. if (MP4GetNumberOfTracks(mp4File, MP4_AUDIO_TRACK_TYPE) == 1) {
  206. MP4SetAudioProfileLevel(mp4File, 0xFE);
  207. }
  208. u_int8_t sampleBuffer[8 * 1024];
  209. u_int32_t sampleSize = sizeof(sampleBuffer);
  210. MP4SampleId sampleId = 1;
  211. while (LoadNextMp3Frame(inFile, sampleBuffer, &sampleSize)) {
  212. if (!MP4WriteSample(mp4File, trackId, sampleBuffer, sampleSize)) {
  213. fprintf(stderr,
  214. "%s: can't write audio frame %un", ProgName, sampleId);
  215. exit(EXIT_MP3_CREATOR);
  216. }
  217. sampleId++;
  218. sampleSize = sizeof(sampleBuffer);
  219. }
  220. return trackId;
  221. }