diff options
Diffstat (limited to 'ac3dec/decode.c')
-rw-r--r-- | ac3dec/decode.c | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/ac3dec/decode.c b/ac3dec/decode.c new file mode 100644 index 0000000..5e7f034 --- /dev/null +++ b/ac3dec/decode.c @@ -0,0 +1,269 @@ +/* + * decode.c + * + * Copyright (C) Aaron Holtzman - May 1999 + * + * Added support for DVB-s PCI card by: + * Matjaz Thaler <matjaz.thaler@rd.iskraemeco.si> - November 2000 + * + * 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, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <sys/time.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include "ac3.h" +#include "ac3_internal.h" +#include "bitstream.h" +#include "imdct.h" +#include "exponent.h" +#include "coeff.h" +#include "bit_allocate.h" +#include "parse.h" +#include "crc.h" +#include "stats.h" +#include "rematrix.h" +#include "sanity_check.h" +#include "downmix.h" +#include "debug.h" + +#define AC3_BUFFER_SIZE (6*1024*16) + +//our global config structure +ac3_config_t ac3_config; +uint_32 error_flag = 0; + +static audblk_t audblk; +static bsi_t bsi; +static syncinfo_t syncinfo; +static uint_32 frame_count = 0; +//static uint_32 is_output_initialized = 0; + +//the floating point samples for one audblk +static stream_samples_t samples; + +//the integer samples for the entire frame (with enough space for 2 ch out) +//if this size change, be sure to change the size when muting +static sint_16 s16_samples[2 * 6 * 256]; + + +//Storage for the syncframe +#define SYNC_BUFFER_MAX_SIZE 4096 +static uint_8 sync_buffer[SYNC_BUFFER_MAX_SIZE]; +static uint_32 sync_buffer_size = 0;; + +uint_32 +decode_sync_buffer_syncframe(syncinfo_t *syncinfo, uint_8 **start,uint_8 *end) +{ + uint_8 *cur = *start; + uint_16 syncword = syncinfo->syncword; + uint_32 ret = 0; + + // + // Find an ac3 sync frame. + // +resync: + + while(syncword != 0x0b77) + { + if(cur >= end) + goto done; + syncword = (syncword << 8) + *cur++; + } + + //need the next 3 bytes to decide how big the frame is + while(sync_buffer_size < 3) + { + if(cur >= end) + goto done; + + sync_buffer[sync_buffer_size++] = *cur++; + } + + parse_syncinfo(syncinfo,sync_buffer); + stats_print_syncinfo(syncinfo); + + while(sync_buffer_size < syncinfo->frame_size * 2 - 2) + { + if(cur >= end) + goto done; + + sync_buffer[sync_buffer_size++] = *cur++; + } + + // Check the crc over the entire frame + crc_init(); + crc_process_frame(sync_buffer,syncinfo->frame_size * 2 - 2); + + if(!crc_validate()) + { + fprintf(stderr,"** CRC failed - skipping frame **\n"); + syncword = 0xffff; + sync_buffer_size = 0; + goto resync; + } + + // + //if we got to this point, we found a valid ac3 frame to decode + // + + bitstream_init(sync_buffer); + //get rid of the syncinfo struct as we already parsed it + bitstream_get(24); + + //reset the syncword for next time + syncword = 0xffff; + sync_buffer_size = 0; + ret = 1; + +done: + syncinfo->syncword = syncword; + *start = cur; + return ret; +} + +void +decode_mute(void) +{ + fprintf(stderr,"muting frame\n"); + //mute the frame + memset(s16_samples,0,sizeof(sint_16) * 256 * 2 * 6); + error_flag = 0; +} + + +void +ac3_init(ac3_config_t *config) +{ + memcpy(&ac3_config,config,sizeof(ac3_config_t)); + + imdct_init(); + sanity_check_init(&syncinfo,&bsi,&audblk); + + // ac3_output = *foo; +} + +uint_32 ac3_decode_data(uint_8 *data_start,uint_8 *data_end, int ac3reset, int *input_pointer, int *output_pointer, char *ac3_data) +{ + uint_32 i; + int datasize; + char *data; + + if(ac3reset != 0){ + syncinfo.syncword = 0xffff; + sync_buffer_size = 0; + } + + while(decode_sync_buffer_syncframe(&syncinfo,&data_start,data_end)) + { + dprintf("(decode) begin frame %d\n",frame_count++); + + if(error_flag) + { + decode_mute(); + continue; + } + + parse_bsi(&bsi); + + for(i=0; i < 6; i++) + { + //Initialize freq/time sample storage + memset(samples,0,sizeof(float) * 256 * (bsi.nfchans + bsi.lfeon)); + + // Extract most of the audblk info from the bitstream + // (minus the mantissas + parse_audblk(&bsi,&audblk); + + // Take the differential exponent data and turn it into + // absolute exponents + exponent_unpack(&bsi,&audblk); + if(error_flag) + goto error; + + // Figure out how many bits per mantissa + bit_allocate(syncinfo.fscod,&bsi,&audblk); + + // Extract the mantissas from the stream and + // generate floating point frequency coefficients + coeff_unpack(&bsi,&audblk,samples); + if(error_flag) + goto error; + + if(bsi.acmod == 0x2) + rematrix(&audblk,samples); + + // Convert the frequency samples into time samples + imdct(&bsi,&audblk,samples); + + // Downmix into the requested number of channels + // and convert floating point to sint_16 + downmix(&bsi,samples,&s16_samples[i * 2 * 256]); + + sanity_check(&syncinfo,&bsi,&audblk); + if(error_flag) + goto error; + + continue; + } + + parse_auxdata(&syncinfo); + + /* + if(!is_output_initialized) + { + ac3_output.open(16,syncinfo.sampling_rate,2); + is_output_initialized = 1; + } + */ + data = (char *)s16_samples; + datasize = 0; + while(datasize < 6144){ + if(((*input_pointer+1) % AC3_BUFFER_SIZE) != *output_pointer){ // There is room in the sync_buffer + ac3_data[*input_pointer]=data[datasize]; + datasize++; + *input_pointer = (*input_pointer+1) % AC3_BUFFER_SIZE; + } + else{ + *input_pointer = *output_pointer = 0; + break; + } + } + + + //write(1, s16_samples, 256 * 6 * 2* 2); + //ac3_output.play(s16_samples, 256 * 6 * 2); +error: + ; + //find a new frame + } + + return 0; +} |