extract_ac3.c
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:5k
- /*
- * extract_ac3.c
- *
- * Copyright (C) Aaron Holtzman <aholtzma@ess.engr.uvic.ca> - June 1999
- *
- * Extracts an AC-3 audio stream from an MPEG-2 system stream
- * and writes it to stdout
- *
- * Ideas and bitstream syntax info borrowed from code written
- * by Nathan Laredo <laredo@gnu.org>
- *
- * Multiple track support by Yuqing Deng <deng@tinker.chem.brown.edu>
- *
- *
- * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
- *
- * ac3dec is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * ac3dec is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Make; see the file COPYING. If not, write to
- * the Free Software Foundation,
- *
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdarg.h>
- #include <unistd.h>
- #include <string.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <sys/stat.h>
- #include <sys/mman.h>
- static unsigned char *mpeg_data = 0;
- static unsigned char *mpeg_data_end = 0;
- static unsigned char *cur_pos;
- //Audio track to play
- static unsigned char track_code = 0x80;
- static unsigned char track_table[8] =
- {
- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87
- };
- int map_file(char file_name[])
- {
- struct stat st;
- int f;
- int mpeg_data_size;
- if ((f = open(file_name, O_RDONLY)) < 0)
- {
- fprintf(stderr,"File not foundn");
- exit(1);
- }
- if (fstat(f, &st) < 0)
- {
- fprintf(stderr,"File not foundn");
- exit(1);
- }
- mpeg_data_size = st.st_size - 4;
- if ((mpeg_data = mmap(0, mpeg_data_size, PROT_READ, MAP_SHARED, f, 0)) == MAP_FAILED)
- {
- fprintf(stderr,"%s : mmap failedn",strerror(errno));
- exit(1);
- }
- cur_pos = mpeg_data;
- mpeg_data_end = mpeg_data + mpeg_data_size;
- return f;
- }
- inline void increment_position(long x)
- {
- cur_pos += x;
- if(cur_pos >= mpeg_data_end)
- {
- fprintf(stderr, "Error: unexpected end of streamn");
- exit(1);
- }
- }
- inline int next_24_bits(long x)
- {
- if (cur_pos[0] != ((x >> 16) & 0xff))
- return 0;
- if (cur_pos[1] != ((x >> 8) & 0xff))
- return 0;
- if (cur_pos[2] != ((x ) & 0xff))
- return 0;
- return 1;
- }
- inline int next_32_bits(long x)
- {
- if (cur_pos[0] != ((x >> 24) & 0xff))
- return 0;
- if (cur_pos[1] != ((x >> 16) & 0xff))
- return 0;
- if (cur_pos[2] != ((x >> 8) & 0xff))
- return 0;
- if (cur_pos[3] != ((x ) & 0xff))
- return 0;
- return 1;
- }
- void parse_pes(void)
- {
- unsigned long data_length;
- unsigned long header_length;
- //The header length is the PES_header_data_length byte plus 6 for the packet
- //start code and packet size, 3 for the PES_header_data_length and two
- //misc bytes, and finally 4 bytes for the mystery AC3 packet tag
- header_length = cur_pos[8] + 6 + 3 + 4 ;
- data_length =(cur_pos[4]<<8) + cur_pos[5];
- //If we have AC-3 audio then output it
- if(cur_pos[3] == 0xbd)
- {
- #if 0
- //Debugging printfs
- fprintf(stderr,"start of pes curpos[] = %02x%02x%02x%02xn",
- cur_pos[0],cur_pos[1],cur_pos[2],cur_pos[3]);
- fprintf(stderr,"header_length = %d data_length = %xn",
- header_length, data_length);
- fprintf(stderr,"extra crap 0x%02x%02x%02x%02x data size 0x%0lxn",cur_pos[header_length-4],
- cur_pos[header_length-3],cur_pos[header_length-2],cur_pos[header_length-1],data_length);
- #endif
- //Only extract the track we want
- if((cur_pos[header_length-4] == track_code ))
- fwrite(&cur_pos[header_length],1,data_length - (header_length - 6),stdout);
- }
- //The packet size is data_length plus 6 bytes to account for the
- //packet start code and the data_length itself.
- increment_position(data_length + 6);
- }
- void parse_pack(void)
- {
- unsigned long skip_length;
- // Deal with the pack header
- // The first 13 bytes are junk. The fourteenth byte
- // contains the number of stuff bytes
- skip_length = cur_pos[13] & 0x7;
- increment_position(14 + skip_length);
- // Deal with the system header if it exists
- if(next_32_bits(0x000001bb))
- {
- // Bytes 5 and 6 contain the length of the header minus 6
- skip_length = (cur_pos[4] << 8) + cur_pos[5];
- increment_position(6 + skip_length);
- }
- while(next_24_bits(0x000001) && !next_32_bits(0x000001ba))
- {
- parse_pes();
- }
- }
- int main(int argc, char *argv[])
- {
- int f;
- int track = 0;
- if (argc < 2) {
- fprintf(stderr, "usage: %s mpeg_stream [track number]n", argv[0]);
- exit(1);
- }
- if (argc == 3)
- {
- track = strtol(argv[2], NULL, 0);
- fprintf(stderr,"Extracting track %dn",track);
- }
- if (track < 0 || track > 7)
- {
- fprintf(stderr, "Invalid track number: %dn", track);
- exit(1);
- }
- track_code = track_table[track];
- f = map_file(argv[1]);
- if(!next_32_bits(0x000001ba))
- {
- fprintf(stderr, "Non-program streams not handled - exitingnn");
- exit(1);
- }
- do
- {
- parse_pack();
- }
- while(next_32_bits(0x000001ba));
- fprintf(stderr,"curpos[] = %x%x%x%xn",cur_pos[0],cur_pos[1],cur_pos[2],cur_pos[3]);
- if(!next_32_bits(0x000001b9))
- {
- fprintf(stderr, "Error: expected end of stream coden");
- exit(1);
- }
- close(f);
- return 0;
- }