summaryrefslogtreecommitdiff
path: root/ac3dec/decode.c
diff options
context:
space:
mode:
Diffstat (limited to 'ac3dec/decode.c')
-rw-r--r--ac3dec/decode.c269
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;
+}