mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
270 lines
5.9 KiB
C
270 lines
5.9 KiB
C
|
/*
|
||
|
* 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;
|
||
|
}
|