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

流媒体/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 <math.h>
  22. #include <mpeg4ip.h>
  23. #include <mpeg4ip_getopt.h>
  24. #include <avilib.h>
  25. /* globals */
  26. char* progName;
  27. /*
  28.  * avi2raw
  29.  * required arg1 should be the input AVI file
  30.  * required arg2 should be the output RAW file
  31.  */ 
  32. int main(int argc, char** argv)
  33. {
  34. /* configurable variables from command line */
  35. bool extractVideo = TRUE; /* FALSE implies extract audio */
  36. u_int32_t start = 0; /* secs, start offset */
  37. u_int32_t duration = 0; /* secs, 0 implies entire file */
  38. bool quiet = FALSE;
  39. /* internal variables */
  40. char* aviFileName = NULL;
  41. char* rawFileName = NULL;
  42. avi_t* aviFile = NULL;
  43. FILE* rawFile = NULL;
  44. u_int32_t numBytes;
  45. /* begin process command line */
  46. progName = argv[0];
  47. while (1) {
  48. int c = -1;
  49. int option_index = 0;
  50. static struct option long_options[] = {
  51. { "audio", 0, 0, 'a' },
  52. { "length", 1, 0, 'l' },
  53. { "quiet", 0, 0, 'q' },
  54. { "start", 1, 0, 's' },
  55. { "video", 0, 0, 'v' },
  56. { "version", 0, 0, 'V'},
  57. { "help", 0, 0, 'h'},
  58. { NULL, 0, 0, 0 }
  59. };
  60. c = getopt_long_only(argc, argv, "al:qs:vVh",
  61. long_options, &option_index);
  62. if (c == -1)
  63. break;
  64. switch (c) {
  65. case 'h':
  66.   fprintf(stderr, "%s - %s version %sn", progName,
  67.   PACKAGE, VERSION);
  68.   fprintf(stderr, "options:n");
  69.   fprintf(stderr, " --audio - extract audio trackn");
  70.   fprintf(stderr, " --length <length> - extract <length> secsn");
  71.   fprintf(stderr, " --quiet - quiet moden");
  72.   fprintf(stderr, " --start <time> - extract from <start> timen");
  73.   fprintf(stderr, " --video - extract video trackn");
  74.   return 0;
  75. case 'a': {
  76. extractVideo = FALSE;
  77. break;
  78. }
  79. case 'l': {
  80. /* --length=<secs> */
  81. u_int i;
  82. if (sscanf(optarg, "%u", &i) < 1) {
  83. fprintf(stderr, 
  84. "%s: bad length specified: %sn",
  85.  progName, optarg);
  86. } else {
  87. duration = i;
  88. }
  89. break;
  90. }
  91. case 'q': {
  92. quiet = TRUE;
  93. break;
  94. }
  95. case 's': {
  96. /* --start=<secs> */
  97. u_int i;
  98. if (sscanf(optarg, "%u", &i) < 1) {
  99. fprintf(stderr, 
  100. "%s: bad start specified: %sn",
  101.  progName, optarg);
  102. } else {
  103. start = i;
  104. }
  105. break;
  106. }
  107. case 'v': {
  108. extractVideo = TRUE;
  109. break;
  110. }
  111. case '?':
  112. break;
  113. case 'V':
  114.   fprintf(stderr, "%s - %s version %sn", progName,
  115.   PACKAGE, VERSION);
  116.   return(0);
  117. default:
  118. fprintf(stderr, "%s: unknown option specified, ignoring: %cn", 
  119. progName, c);
  120. }
  121. }
  122. /* check that we have at least two non-option arguments */
  123. if ((argc - optind) < 2) {
  124. fprintf(stderr, 
  125. "usage: %s <avi-file> <raw-file>n",
  126. progName);
  127. exit(1);
  128. }
  129. /* point to the specified file names */
  130. aviFileName = argv[optind++];
  131. rawFileName = argv[optind++];
  132. /* warn about extraneous non-option arguments */
  133. if (optind < argc) {
  134. fprintf(stderr, "%s: unknown options specified, ignoring: ");
  135. while (optind < argc) {
  136. fprintf(stderr, "%s ", argv[optind++]);
  137. }
  138. fprintf(stderr, "n");
  139. }
  140. /* end processing of command line */
  141. /* open the AVI file */
  142. aviFile = AVI_open_input_file(aviFileName, TRUE);
  143. if (aviFile == NULL) {
  144. fprintf(stderr, 
  145. "%s: error %s: %sn",
  146. progName, aviFileName, AVI_strerror());
  147. exit(4);
  148. }
  149. if (!quiet) {
  150.   fprintf(stderr, "%s - %s version %sn",
  151.   progName, PACKAGE, VERSION);
  152. }
  153. /* open the RAW file */
  154. rawFile = fopen(rawFileName, "wb");
  155. if (rawFile == NULL) {
  156. fprintf(stderr,
  157. "%s: error opening %s: %sn",
  158. progName, rawFileName, strerror(errno));
  159. exit(5);
  160. }
  161. if (extractVideo) {
  162. double videoFrameRate = AVI_video_frame_rate(aviFile);
  163. u_int32_t numVideoFrames = AVI_video_frames(aviFile);
  164. u_int32_t fileDuration = ceil(numVideoFrames / videoFrameRate);
  165. u_int32_t numDesiredVideoFrames;
  166. u_int32_t videoFramesRead = 0;
  167. u_int32_t emptyFramesRead = 0;
  168. /* get a buffer large enough to handle a frame of raw SDTV */
  169. u_char* buf = (u_char*)malloc(768 * 576 * 4);
  170. if (duration) {
  171. numDesiredVideoFrames = duration * videoFrameRate;
  172. } else {
  173. numDesiredVideoFrames = numVideoFrames;
  174. }
  175. if (buf == NULL) {
  176. fprintf(stderr,
  177. "%s: error allocating memory: %sn",
  178. progName, strerror(errno));
  179. exit(6);
  180. }
  181. /* check that start offset is valid */
  182. if (start > fileDuration) {
  183. fprintf(stderr,
  184. "%s: specified start is past the end of the filen",
  185. progName);
  186. exit(7);
  187. }
  188. if (AVI_seek_start(aviFile)) {
  189. fprintf(stderr,
  190. "%s: bad seek: %sn",
  191. progName, AVI_strerror());
  192. exit(8);
  193. }
  194. if (AVI_set_video_position(aviFile, (long) ROUND(start * videoFrameRate), NULL)) {
  195. fprintf(stderr,
  196. "%s: bad seek: %sn",
  197. progName, AVI_strerror());
  198. exit(9);
  199. }
  200. while (TRUE) {
  201. numBytes = AVI_read_frame(aviFile, buf);
  202. /* read error */
  203. if (numBytes < 0) {
  204. break;
  205. }
  206. /*
  207.  * note some capture programs 
  208.  * insert a zero length frame occasionally
  209.  * hence numBytes == 0, but we're not a EOF
  210.  */
  211. if (numBytes) {
  212. if (fwrite(buf, 1, numBytes, rawFile) != numBytes) {
  213. fprintf(stderr,
  214. "%s: error writing %s: %sn",
  215. progName, rawFileName, strerror(errno));
  216. break;
  217. }
  218. } else {
  219. emptyFramesRead++;
  220. }
  221. videoFramesRead++;
  222. if (videoFramesRead >= numDesiredVideoFrames) {
  223. break;
  224. }
  225. }
  226. if (numBytes < 0) {
  227. printf("%s: error reading %s, frame %d, %sn",
  228. progName, aviFileName, videoFramesRead + 1, AVI_strerror());
  229. }
  230. if (videoFramesRead < numDesiredVideoFrames) {
  231. fprintf(stderr,
  232. "%s: warning: could only extract %u seconds of video (%u of %u frames)n",
  233. progName, ceil(videoFramesRead / videoFrameRate),
  234. videoFramesRead, numDesiredVideoFrames);
  235. }
  236. if (emptyFramesRead) {
  237. fprintf(stderr,
  238. "%s: warning: %u zero length frames ignoredn",
  239. progName, emptyFramesRead);
  240. }
  241. if (!quiet) {
  242. printf("%u video frames writtenn", 
  243. videoFramesRead - emptyFramesRead);
  244. }
  245. /* cleanup */
  246. free(buf);
  247. } else {
  248. /* extract audio */
  249.   u_int32_t audioBytesRead = 0;
  250.   u_char *buf = (u_char*) malloc(8*1024);
  251.   u_int32_t numDesiredAudioBytes = AVI_audio_bytes(aviFile);
  252.   u_int32_t audioBytesPerSec = 0;
  253.   if (start != 0) {
  254. u_int32_t numAudioBytes = numDesiredAudioBytes;
  255. u_int32_t fileDuration;
  256. audioBytesPerSec = AVI_audio_rate(aviFile) * 
  257.   ((AVI_audio_bits(aviFile) + 7) / 8) * AVI_audio_channels(aviFile);
  258. fileDuration = ceil(numAudioBytes / audioBytesPerSec);
  259. numDesiredAudioBytes = duration * audioBytesPerSec;
  260. /* check that start offset is valid */
  261. if (start > fileDuration) {
  262. fprintf(stderr,
  263. "%s: specified start is past the end of the filen",
  264. progName);
  265. exit(7);
  266. }
  267. if (AVI_seek_start(aviFile)) {
  268. fprintf(stderr,
  269. "%s: bad seek: %sn",
  270. progName, AVI_strerror());
  271. exit(8);
  272. }
  273. if (AVI_set_audio_position(aviFile, start * audioBytesPerSec)) {
  274. fprintf(stderr,
  275. "%s: bad seek: %sn",
  276. progName, AVI_strerror());
  277. exit(9);
  278. }
  279.   } else {
  280. if (AVI_seek_start(aviFile)) {
  281. fprintf(stderr,
  282. "%s: bad seek: %sn",
  283. progName, AVI_strerror());
  284. exit(8);
  285. }
  286. if (AVI_set_audio_position(aviFile, 0)) {
  287. fprintf(stderr,
  288. "%s: bad seek: %sn",
  289. progName, AVI_strerror());
  290. exit(9);
  291. }
  292.   }
  293. while ((numBytes = AVI_read_audio(aviFile, buf, sizeof(buf))) > 0) {
  294. if (fwrite(buf, 1, numBytes, rawFile) != numBytes) {
  295. fprintf(stderr,
  296. "%s: error writing %s: %sn",
  297. progName, rawFileName, strerror(errno));
  298. break;
  299. }
  300. audioBytesRead += numBytes;
  301. if (numDesiredAudioBytes 
  302.   && audioBytesRead >= numDesiredAudioBytes) {
  303. break;
  304. }
  305. }
  306. if (duration && audioBytesRead < numDesiredAudioBytes) {
  307. fprintf(stderr,
  308. "%s: warning: could only extract %u seconds of audion",
  309. progName, audioBytesPerSec == 0 ? audioBytesRead : audioBytesRead / audioBytesPerSec);
  310. }
  311. if (!quiet && AVI_audio_bits(aviFile) != 0) {
  312. printf("%u audio samples writtenn", 
  313. audioBytesRead / ((AVI_audio_bits(aviFile) + 7) / 8)); 
  314. }
  315. }
  316. /* cleanup */
  317. AVI_close(aviFile);
  318. fclose(rawFile);
  319. return(0);
  320. }