extract_ac3.c
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:5k
源码类别:

DVD

开发平台:

Unix_Linux

  1. /*
  2.  *  extract_ac3.c
  3.  *
  4.  *  Copyright (C) Aaron Holtzman <aholtzma@ess.engr.uvic.ca> - June 1999
  5.  *
  6.  *  Extracts an AC-3 audio stream from an MPEG-2 system stream
  7.  *  and writes it to stdout
  8.  *
  9.  *  Ideas and bitstream syntax info borrowed from code written 
  10.  *  by Nathan Laredo <laredo@gnu.org>
  11.  *
  12.  *  Multiple track support by Yuqing Deng <deng@tinker.chem.brown.edu>
  13.  * 
  14.  *
  15.  *  This file is part of ac3dec, a free Dolby AC-3 stream decoder.
  16.  *
  17.  *  ac3dec is free software; you can redistribute it and/or modify
  18.  *  it under the terms of the GNU General Public License as published by
  19.  *  the Free Software Foundation; either version 2, or (at your option)
  20.  *  any later version.
  21.  *   
  22.  *  ac3dec is distributed in the hope that it will be useful,
  23.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  24.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  25.  *  GNU General Public License for more details.
  26.  *   
  27.  *  You should have received a copy of the GNU General Public License
  28.  *  along with GNU Make; see the file COPYING.  If not, write to
  29.  *  the Free Software Foundation, 
  30.  *
  31.  */
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <stdarg.h>
  35. #include <unistd.h>
  36. #include <string.h>
  37. #include <fcntl.h>
  38. #include <errno.h>
  39. #include <sys/stat.h>
  40. #include <sys/mman.h>
  41. static unsigned char *mpeg_data = 0;
  42. static unsigned char *mpeg_data_end = 0;
  43. static unsigned char *cur_pos;
  44. //Audio track to play
  45. static unsigned char track_code = 0x80;
  46. static unsigned char track_table[8] = 
  47. 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87 
  48. };
  49. int map_file(char file_name[])
  50. {
  51. struct stat st;
  52. int f;
  53. int mpeg_data_size;
  54. if ((f = open(file_name, O_RDONLY)) < 0) 
  55. {
  56. fprintf(stderr,"File not foundn");
  57. exit(1);
  58. }
  59. if (fstat(f, &st) < 0) 
  60. {
  61. fprintf(stderr,"File not foundn");
  62. exit(1);
  63. }
  64. mpeg_data_size = st.st_size - 4;
  65. if ((mpeg_data = mmap(0, mpeg_data_size, PROT_READ, MAP_SHARED, f, 0)) == MAP_FAILED) 
  66. {
  67. fprintf(stderr,"%s : mmap failedn",strerror(errno));
  68. exit(1);
  69. }
  70. cur_pos = mpeg_data;
  71. mpeg_data_end = mpeg_data + mpeg_data_size;
  72. return f;
  73. }
  74. inline void increment_position(long x)
  75. {
  76. cur_pos += x;
  77. if(cur_pos >= mpeg_data_end)
  78. {
  79. fprintf(stderr, "Error: unexpected end of streamn");
  80. exit(1);
  81. }
  82. }
  83. inline int next_24_bits(long x)
  84. {
  85. if (cur_pos[0] != ((x >> 16) & 0xff))
  86. return 0;
  87. if (cur_pos[1] != ((x >>  8) & 0xff))
  88. return 0;
  89. if (cur_pos[2] != ((x      ) & 0xff))
  90. return 0;
  91. return 1;
  92. }
  93. inline int next_32_bits(long x)
  94. {
  95. if (cur_pos[0] != ((x >> 24) & 0xff))
  96. return 0;
  97. if (cur_pos[1] != ((x >> 16) & 0xff))
  98. return 0;
  99. if (cur_pos[2] != ((x >>  8) & 0xff))
  100. return 0;
  101. if (cur_pos[3] != ((x      ) & 0xff))
  102. return 0;
  103. return 1;
  104. }
  105. void parse_pes(void)
  106. {
  107. unsigned long data_length;
  108. unsigned long header_length;
  109. //The header length is the PES_header_data_length byte plus 6 for the packet
  110. //start code and packet size, 3 for the PES_header_data_length and two
  111. //misc bytes, and finally 4 bytes for the mystery AC3 packet tag 
  112. header_length = cur_pos[8] + 6 + 3 + 4 ;
  113. data_length =(cur_pos[4]<<8) + cur_pos[5];
  114. //If we have AC-3 audio then output it
  115. if(cur_pos[3] == 0xbd)
  116. {
  117. #if 0
  118. //Debugging printfs
  119. fprintf(stderr,"start of pes curpos[] = %02x%02x%02x%02xn",
  120. cur_pos[0],cur_pos[1],cur_pos[2],cur_pos[3]);
  121. fprintf(stderr,"header_length = %d data_length = %xn",
  122. header_length, data_length);
  123. fprintf(stderr,"extra crap 0x%02x%02x%02x%02x data size 0x%0lxn",cur_pos[header_length-4],
  124. cur_pos[header_length-3],cur_pos[header_length-2],cur_pos[header_length-1],data_length);
  125. #endif
  126. //Only extract the track we want
  127. if((cur_pos[header_length-4] == track_code )) 
  128. fwrite(&cur_pos[header_length],1,data_length - (header_length - 6),stdout);
  129. }
  130. //The packet size is data_length plus 6 bytes to account for the
  131. //packet start code and the data_length itself.
  132. increment_position(data_length + 6);
  133. }
  134. void parse_pack(void)
  135. {
  136. unsigned long skip_length;
  137. // Deal with the pack header 
  138. // The first 13 bytes are junk. The fourteenth byte 
  139. // contains the number of stuff bytes 
  140. skip_length = cur_pos[13] & 0x7;
  141. increment_position(14 + skip_length);
  142. // Deal with the system header if it exists 
  143. if(next_32_bits(0x000001bb))
  144. {
  145. // Bytes 5 and 6 contain the length of the header minus 6 
  146. skip_length = (cur_pos[4] << 8) +  cur_pos[5];
  147. increment_position(6 + skip_length);
  148. }
  149. while(next_24_bits(0x000001) && !next_32_bits(0x000001ba))
  150. {
  151. parse_pes();
  152. }
  153. }
  154. int main(int argc, char *argv[])
  155. {
  156. int f;
  157. int track = 0;
  158. if (argc < 2) {
  159. fprintf(stderr, "usage: %s mpeg_stream [track number]n", argv[0]);
  160. exit(1);
  161. }
  162. if (argc == 3) 
  163. {
  164. track = strtol(argv[2], NULL, 0);
  165. fprintf(stderr,"Extracting track %dn",track);
  166. }
  167. if (track < 0 || track > 7) 
  168. {
  169. fprintf(stderr, "Invalid track number: %dn", track);
  170. exit(1);
  171. }
  172. track_code = track_table[track];
  173. f = map_file(argv[1]);
  174. if(!next_32_bits(0x000001ba))
  175. {
  176. fprintf(stderr, "Non-program streams not handled - exitingnn");
  177. exit(1);
  178. }
  179. do
  180. {
  181. parse_pack();
  182. while(next_32_bits(0x000001ba));
  183. fprintf(stderr,"curpos[] = %x%x%x%xn",cur_pos[0],cur_pos[1],cur_pos[2],cur_pos[3]);
  184. if(!next_32_bits(0x000001b9))
  185. {
  186. fprintf(stderr, "Error: expected end of stream coden");
  187. exit(1);
  188. }
  189. close(f);
  190. return 0;
  191. }