avi.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 <mp4creator.h>
  26. #include <avilib.h>
  27. static MP4TrackId VideoCreator(MP4FileHandle mp4File, avi_t* aviFile)
  28. {
  29. char* videoType = AVI_video_compressor(aviFile);
  30. if (strcasecmp(videoType, "divx")
  31.   && strcasecmp(videoType, "dx50")
  32.   && strcasecmp(videoType, "xvid")) {
  33. fprintf(stderr,
  34. "%s: video compressor %s not recognizedn",
  35.  ProgName, videoType);
  36. exit(EXIT_AVI_CREATOR);
  37. }
  38. double frameRate = AVI_video_frame_rate(aviFile);
  39. if (frameRate == 0) {
  40. fprintf(stderr,
  41. "%s: no video frame rate in avi filen", ProgName);
  42. exit(EXIT_AVI_CREATOR);
  43. }
  44. #ifdef _WIN32
  45. MP4Duration mp4FrameDuration;
  46. mp4FrameDuration = 
  47. (MP4Duration)((double)Mp4TimeScale / frameRate);
  48. #else
  49. MP4Duration mp4FrameDuration = 
  50. (MP4Duration)(Mp4TimeScale / frameRate);
  51. #endif
  52. MP4TrackId trackId = MP4AddVideoTrack(mp4File,
  53. Mp4TimeScale, mp4FrameDuration, 
  54. AVI_video_width(aviFile), AVI_video_height(aviFile), 
  55. MP4_MPEG4_VIDEO_TYPE);
  56. if (trackId == MP4_INVALID_TRACK_ID) {
  57. fprintf(stderr,
  58. "%s: can't create video trackn", ProgName);
  59. exit(EXIT_AVI_CREATOR);
  60. }
  61. int32_t i;
  62. int32_t numFrames = AVI_video_frames(aviFile);
  63. int32_t frameSize;
  64. int32_t maxFrameSize = 0;
  65. // determine maximum video frame size
  66. AVI_seek_start(aviFile);
  67. for (i = 0; i < numFrames; i++) {
  68. frameSize = AVI_frame_size(aviFile, i);
  69. if (frameSize > maxFrameSize) {
  70. maxFrameSize = frameSize;
  71. }
  72. }
  73. // allocate a large enough frame buffer
  74. u_int8_t* pFrameBuffer = (u_int8_t*)malloc(maxFrameSize);
  75. if (pFrameBuffer == NULL) {
  76. fprintf(stderr,
  77. "%s: can't allocate memoryn", ProgName);
  78. exit(EXIT_AVI_CREATOR);
  79. }
  80. AVI_seek_start(aviFile);
  81. // read first frame, should contain VO/VOL and I-VOP
  82. frameSize = AVI_read_frame(aviFile, (char*)pFrameBuffer);
  83. if (frameSize < 0) {
  84. fprintf(stderr,
  85. "%s: can't read video frame 1: %sn",
  86. ProgName, AVI_strerror());
  87. exit(EXIT_AVI_CREATOR);
  88. }
  89. // find VOP start code in first sample
  90. static u_int8_t vopStartCode[4] = { 
  91. 0x00, 0x00, 0x01, MP4AV_MPEG4_VOP_START 
  92. };
  93. for (i = 0; i < frameSize - 4; i++) {
  94. if (!memcmp(&pFrameBuffer[i], vopStartCode, 4)) {
  95. // everything before the VOP
  96. // should be configuration info
  97. MP4SetTrackESConfiguration(mp4File, trackId,
  98. pFrameBuffer, i);
  99. }
  100. }
  101. if (MP4GetNumberOfTracks(mp4File, MP4_VIDEO_TRACK_TYPE) == 1) {
  102. MP4SetVideoProfileLevel(mp4File, 0x01);
  103. }
  104. // write out the first frame, including the initial configuration info
  105. MP4WriteSample(mp4File, trackId, 
  106. pFrameBuffer, frameSize, mp4FrameDuration, 0, true);
  107. // process the rest of the frames
  108. for (i = 1; i < numFrames; i++) {
  109. // read the frame from the AVI file
  110. frameSize = AVI_read_frame(aviFile, (char*)pFrameBuffer);
  111. if (frameSize < 0) {
  112. fprintf(stderr,
  113. "%s: can't read video frame %i: %sn",
  114. ProgName, i + 1, AVI_strerror());
  115. exit(EXIT_AVI_CREATOR);
  116. }
  117. // we mark random access points in MP4 files
  118. bool isIFrame = 
  119. (MP4AV_Mpeg4GetVopType(pFrameBuffer, frameSize) == 'I');
  120. // write the frame to the MP4 file
  121. MP4WriteSample(mp4File, trackId, 
  122. pFrameBuffer, frameSize, mp4FrameDuration, 0, isIFrame);
  123. }
  124. return trackId;
  125. }
  126. static inline u_int32_t BytesToInt32(u_int8_t* pBytes) 
  127. {
  128. return (pBytes[0] << 24) | (pBytes[1] << 16) 
  129. | (pBytes[2] << 8) | pBytes[3];
  130. }
  131. static MP4TrackId AudioCreator(MP4FileHandle mp4File, avi_t* aviFile)
  132. {
  133. int32_t audioType = AVI_audio_format(aviFile);
  134. // Check for MP3 audio type
  135. if (audioType != 0x55) {
  136. fprintf(stderr,
  137. "%s: audio compressor 0x%x not recognizedn",
  138.  ProgName, audioType);
  139. exit(EXIT_AVI_CREATOR);
  140. }
  141. u_int8_t temp[4];
  142. u_int32_t mp3header;
  143. AVI_seek_start(aviFile);
  144. if (AVI_read_audio(aviFile, (char*)&temp, 4) != 4) {
  145. fprintf(stderr,
  146. "%s: can't read audio frame 0: %sn",
  147. ProgName, AVI_strerror());
  148. exit(EXIT_AVI_CREATOR);
  149. }
  150. mp3header = BytesToInt32(temp);
  151. // check mp3header sanity
  152. if ((mp3header & 0xFFE00000) != 0xFFE00000) {
  153. fprintf(stderr,
  154. "%s: data in file doesn't appear to be valid mp3 audion",
  155. ProgName);
  156. exit(EXIT_AVI_CREATOR);
  157. }
  158. u_int16_t samplesPerSecond = 
  159. MP4AV_Mp3GetHdrSamplingRate(mp3header);
  160. u_int16_t samplesPerFrame = 
  161. MP4AV_Mp3GetHdrSamplingWindow(mp3header);
  162. u_int8_t mp4AudioType = 
  163. MP4AV_Mp3ToMp4AudioType(MP4AV_Mp3GetHdrVersion(mp3header));
  164. if (audioType == MP4_INVALID_AUDIO_TYPE
  165.   || samplesPerSecond == 0) {
  166. fprintf(stderr,
  167. "%s: data in file doesn't appear to be valid mp3 audion",
  168.  ProgName);
  169. exit(EXIT_AVI_CREATOR);
  170. }
  171. MP4TrackId trackId = MP4AddAudioTrack(mp4File, 
  172. samplesPerSecond, samplesPerFrame, mp4AudioType);
  173. if (trackId == MP4_INVALID_TRACK_ID) {
  174. fprintf(stderr,
  175. "%s: can't create audio trackn", ProgName);
  176. exit(EXIT_AVI_CREATOR);
  177. }
  178. if (MP4GetNumberOfTracks(mp4File, MP4_AUDIO_TRACK_TYPE) == 1) {
  179. MP4SetAudioProfileLevel(mp4File, 0xFE);
  180. }
  181. int32_t i;
  182. int32_t aviFrameSize;
  183. int32_t maxAviFrameSize = 0;
  184. // determine maximum avi audio chunk size
  185. // should be at least as large as maximum mp3 frame size
  186. AVI_seek_start(aviFile);
  187. i = 0;
  188. while (AVI_set_audio_frame(aviFile, i, (long*)&aviFrameSize) == 0) {
  189. if (aviFrameSize > maxAviFrameSize) {
  190. maxAviFrameSize = aviFrameSize;
  191. }
  192. i++;
  193. }
  194. // allocate a large enough frame buffer
  195. u_int8_t* pFrameBuffer = (u_int8_t*)malloc(maxAviFrameSize);
  196. if (pFrameBuffer == NULL) {
  197. fprintf(stderr,
  198. "%s: can't allocate memoryn", ProgName);
  199. exit(EXIT_AVI_CREATOR);
  200. }
  201. AVI_seek_start(aviFile);
  202. u_int32_t mp3FrameNumber = 1;
  203. while (true) {
  204. if (AVI_read_audio(aviFile, (char*)pFrameBuffer, 4) != 4) {
  205. // EOF presumably
  206. break;
  207. }
  208. mp3header = BytesToInt32(&pFrameBuffer[0]);
  209. u_int16_t mp3FrameSize = MP4AV_Mp3GetFrameSize(mp3header);
  210. if (AVI_read_audio(aviFile, (char*)&pFrameBuffer[4], mp3FrameSize - 4)
  211.   != mp3FrameSize - 4) {
  212. fprintf(stderr,
  213. "%s: can't read audio frame %u: %sn",
  214. ProgName, mp3FrameNumber, AVI_strerror());
  215. exit(EXIT_AVI_CREATOR);
  216. }
  217. if (!MP4WriteSample(mp4File, trackId, 
  218.   &pFrameBuffer[0], mp3FrameSize)) {
  219. fprintf(stderr,
  220. "%s: can't write audio frame %un", ProgName, mp3FrameNumber);
  221. exit(EXIT_AVI_CREATOR);
  222. }
  223. mp3FrameNumber++;
  224. }
  225. return trackId;
  226. }
  227. MP4TrackId* AviCreator(MP4FileHandle mp4File, const char* aviFileName)
  228. {
  229. static MP4TrackId trackIds[3];
  230. u_int8_t numTracks = 0;
  231. avi_t* aviFile = AVI_open_input_file(aviFileName, true);
  232. if (aviFile == NULL) {
  233. fprintf(stderr,
  234. "%s: can't open %s: %sn",
  235. ProgName, aviFileName, AVI_strerror());
  236. exit(EXIT_AVI_CREATOR);
  237. }
  238. if (AVI_video_frames(aviFile) > 0) {
  239. trackIds[numTracks++] = VideoCreator(mp4File, aviFile);
  240. }
  241. if (AVI_audio_bytes(aviFile) > 0) {
  242. trackIds[numTracks++] = AudioCreator(mp4File, aviFile);
  243. }
  244. trackIds[numTracks] = MP4_INVALID_TRACK_ID;
  245. AVI_close(aviFile);
  246. return trackIds;
  247. }