1
0
mirror of https://github.com/VDR4Arch/vdr.git synced 2023-10-10 13:36:52 +02:00

Added support for replaying DVDs

This commit is contained in:
Klaus Schmidinger 2001-08-03 14:18:08 +02:00
parent 1962940c39
commit bff17fb1d0
51 changed files with 5962 additions and 126 deletions

View File

@ -106,3 +106,9 @@ Ulrich R
Helmut Schächner <schaechner@yahoo.com> Helmut Schächner <schaechner@yahoo.com>
for his support in keeping the Premiere World channels up to date in 'channels.conf' for his support in keeping the Premiere World channels up to date in 'channels.conf'
Andreas Schultz <aschultz@warp10.net>
for adding support for replaying DVDs
Aaron Holtzman
for writing 'ac3dec'

View File

@ -610,7 +610,10 @@ Video Disk Recorder Revision History
- Explicitly switching back to the previously active channel after ending a - Explicitly switching back to the previously active channel after ending a
replay session (to have it shown correctly in case it was in 'Transfer Mode'). replay session (to have it shown correctly in case it was in 'Transfer Mode').
2001-07-31: Version 0.86 2001-08-03: Version 0.86
- Modified the display of the channel group separators (thanks to Markus Lang - Modified the display of the channel group separators (thanks to Markus Lang
for this suggestion). for this suggestion).
- Added support for replaying DVDs (thanks to Andreas Schultz). VDR now needs
the 'libdvdread' library to be installed.

18
INSTALL
View File

@ -15,6 +15,11 @@ If you have the DVB driver source in a different location
you will have to change the definition of DVBDIR in the you will have to change the definition of DVBDIR in the
Makefile. Makefile.
VDR also needs the package 'libdvdread' in order to replay DVDs.
This package is expected to be located in the directory ../DVD (seen
from the VDR directory). Adjust the definition of DVDDIR in the
Makefile if necessary.
This program requires the card driver version 0.9.0 or higher This program requires the card driver version 0.9.0 or higher
to work properly. You need to load the dvb.o module *without* option to work properly. You need to load the dvb.o module *without* option
'outstream=0' (previous versions of VDR required this option to have 'outstream=0' (previous versions of VDR required this option to have
@ -100,6 +105,19 @@ This program must be given to VDR with the '-a' option, as in
vdr -a ac3play vdr -a ac3play
Accessing the DVD drive:
------------------------
By default VDR expects the DVD drive to be located at /dev/dvd (which
typically is a symbolic link to the actual device, for instance /dev/hdc).
You can use the '-V' option to overwrite this, as in
vdr -V /media/dvd
Note that the user id under which VDR runs needs to have write access to
the DVD device in order to replay CSS protected DVDs (which also requires
the presence of the 'libcss' library).
The video data directory: The video data directory:
------------------------- -------------------------

2
MANUAL
View File

@ -19,7 +19,7 @@ Video Disk Recorder User's Manual
Back - Menu off Main menu Main menu Discard Main menu Recordings menu Back - Menu off Main menu Main menu Discard Main menu Recordings menu
Red - Record Edit Edit - Play - Red - Record Edit Edit - Play -
Green - Language New New - Rewind Skip -60s Green - Language New New - Rewind Skip -60s
Yellow - - Delete Delete - Delete Skip +60s Yellow - Eject DVD Delete Delete - Delete Skip +60s
Blue - Resume Mark Mark - Summary Stop Blue - Resume Mark Mark - Summary Stop
0..9 Ch select - - - Numeric inp. - Editing 0..9 Ch select - - - Numeric inp. - Editing

View File

@ -4,18 +4,24 @@
# See the main source file 'vdr.c' for copyright information and # See the main source file 'vdr.c' for copyright information and
# how to reach the author. # how to reach the author.
# #
# $Id: Makefile 1.22 2001/06/02 09:15:39 kls Exp $ # $Id: Makefile 1.23 2001/08/03 13:10:52 kls Exp $
DVBDIR = ../DVB DVBDIR = ../DVB
DVDDIR = ../DVD
AC3DIR = ./ac3dec
INCLUDES = -I$(DVBDIR)/ost/include INCLUDES = -I$(DVBDIR)/ost/include -I$(DVDDIR)/libdvdread
OBJS = config.o dvbapi.o dvbosd.o eit.o font.o i18n.o interface.o menu.o osd.o\ LIBDIRS = -L$(DVDDIR)/libdvdread/dvdread/.libs
OBJS = config.o dvbapi.o dvbosd.o dvd.o eit.o font.o i18n.o interface.o menu.o osd.o\
recording.o remote.o remux.o ringbuffer.o svdrp.o thread.o tools.o vdr.o\ recording.o remote.o remux.o ringbuffer.o svdrp.o thread.o tools.o vdr.o\
videodir.o videodir.o
OSDFONT = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1 OSDFONT = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1
FIXFONT = -adobe-courier-bold-r-normal--25-*-100-100-m-*-iso8859-1 FIXFONT = -adobe-courier-bold-r-normal--25-*-100-100-m-*-iso8859-1
DEFINES += -D_LARGEFILE64_SOURCE
ifndef REMOTE ifndef REMOTE
REMOTE = KBD REMOTE = KBD
endif endif
@ -42,29 +48,30 @@ font: genfontfile fontfix.c fontosd.c
# Dependencies: # Dependencies:
config.o : config.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h remote.h svdrp.h thread.h tools.h config.o : config.c config.h dvbapi.h dvbosd.h dvd.h eit.h font.h i18n.h interface.h remote.h svdrp.h thread.h tools.h
dvbapi.o : dvbapi.c config.h dvbapi.h dvbosd.h eit.h font.h recording.h remux.h ringbuffer.h thread.h tools.h videodir.h dvbapi.o : dvbapi.c config.h dvbapi.h dvbosd.h dvd.h eit.h font.h recording.h remux.h ringbuffer.h thread.h tools.h videodir.h
dvbosd.o : dvbosd.c dvbosd.h font.h tools.h dvbosd.o : dvbosd.c dvbosd.h font.h tools.h
eit.o : eit.c config.h dvbapi.h dvbosd.h eit.h font.h thread.h tools.h videodir.h dvd.o : dvd.c dvd.h
eit.o : eit.c config.h dvbapi.h dvbosd.h dvd.h eit.h font.h thread.h tools.h videodir.h
font.o : font.c font.h fontfix.c fontosd.c tools.h font.o : font.c font.h fontfix.c fontosd.c tools.h
i18n.o : i18n.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h thread.h tools.h i18n.o : i18n.c config.h dvbapi.h dvbosd.h dvd.h eit.h font.h i18n.h thread.h tools.h
interface.o : interface.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h remote.h svdrp.h thread.h tools.h interface.o : interface.c config.h dvbapi.h dvbosd.h dvd.h eit.h font.h i18n.h interface.h remote.h svdrp.h thread.h tools.h
menu.o : menu.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h menu.h osd.h recording.h remote.h svdrp.h thread.h tools.h menu.o : menu.c config.h dvbapi.h dvbosd.h dvd.h eit.h font.h i18n.h interface.h menu.h osd.h recording.h remote.h svdrp.h thread.h tools.h
osd.o : osd.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h osd.h remote.h svdrp.h thread.h tools.h osd.o : osd.c config.h dvbapi.h dvbosd.h dvd.h eit.h font.h i18n.h interface.h osd.h remote.h svdrp.h thread.h tools.h
recording.o : recording.c config.h dvbapi.h dvbosd.h eit.h font.h interface.h recording.h remote.h svdrp.h thread.h tools.h videodir.h recording.o : recording.c config.h dvbapi.h dvbosd.h dvd.h eit.h font.h interface.h recording.h remote.h svdrp.h thread.h tools.h videodir.h
remote.o : remote.c config.h dvbapi.h dvbosd.h eit.h font.h remote.h thread.h tools.h remote.o : remote.c config.h dvbapi.h dvbosd.h dvd.h eit.h font.h remote.h thread.h tools.h
remux.o : remux.c remux.h thread.h tools.h remux.o : remux.c remux.h thread.h tools.h
ringbuffer.o: ringbuffer.c ringbuffer.h thread.h tools.h ringbuffer.o: ringbuffer.c ringbuffer.h thread.h tools.h
svdrp.o : svdrp.c config.h dvbapi.h dvbosd.h eit.h font.h interface.h remote.h svdrp.h thread.h tools.h svdrp.o : svdrp.c config.h dvbapi.h dvbosd.h dvd.h eit.h font.h interface.h remote.h svdrp.h thread.h tools.h
thread.o : thread.c thread.h tools.h thread.o : thread.c thread.h tools.h
tools.o : tools.c tools.h tools.o : tools.c tools.h
vdr.o : vdr.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h menu.h osd.h recording.h remote.h svdrp.h thread.h tools.h videodir.h vdr.o : vdr.c config.h dvbapi.h dvbosd.h dvd.h eit.h font.h i18n.h interface.h menu.h osd.h recording.h remote.h svdrp.h thread.h tools.h videodir.h
videodir.o : videodir.c tools.h videodir.h videodir.o : videodir.c tools.h videodir.h
# The main program: # The main program:
vdr: $(OBJS) vdr: $(OBJS) $(AC3DIR)/libac3.a
g++ -g -O2 $(OBJS) -lncurses -ljpeg -lpthread -o vdr g++ -g -O2 $(OBJS) -lncurses -ljpeg -lpthread $(LIBDIRS) -ldvdread $(AC3DIR)/libac3.a -o vdr
# The font files: # The font files:
@ -80,9 +87,15 @@ genfontfile.o: genfontfile.c
genfontfile: genfontfile.o genfontfile: genfontfile.o
gcc -o $@ -L/usr/X11R6/lib $< -lX11 gcc -o $@ -L/usr/X11R6/lib $< -lX11
# The ac3dec library:
$(AC3DIR)/libac3.a:
make -C $(AC3DIR) all
# Housekeeping: # Housekeeping:
clean: clean:
-rm -f $(OBJS) vdr genfontfile genfontfile.o core make -C $(AC3DIR) clean
-rm -f $(OBJS) vdr genfontfile genfontfile.o core *~
CLEAN: clean CLEAN: clean
-rm -f fontfix.c fontosd.c -rm -f fontfix.c fontosd.c

22
ac3dec/Makefile Normal file
View File

@ -0,0 +1,22 @@
#
# Makefile for 'ac3dec'
#
# $Id: Makefile 1.1 2001/08/02 13:18:08 kls Exp $
OBJS = coeff.o decode.o exponent.o rematrix.o bit_allocate.o crc.o dither.o\
imdct.o sanity_check.o bitstream.o debug.o downmix.o parse.o stats.o
DEFINES += -DDOLBY_SURROUND
all: libac3.a
libac3.a: $(OBJS)
ar -rc libac3.a $(OBJS)
# Implicit rules:
%.o: %.c
gcc -g -O2 -Wall -m486 -c $(DEFINES) $<
clean:
rm -f *~ libac3.a $(OBJS)

60
ac3dec/ac3.h Normal file
View File

@ -0,0 +1,60 @@
/*
* ac3.h
*
* Copyright (C) Aaron Holtzman - May 1999
*
* 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.
*
*
*/
#ifndef AARONS_TYPES
#define AARONS_TYPES
typedef unsigned long long uint_64;
typedef unsigned int uint_32;
typedef unsigned short uint_16;
typedef unsigned char uint_8;
typedef signed long long sint_64;
typedef signed int sint_32;
typedef signed short sint_16;
typedef signed char sint_8;
#endif
#define AC3_DOLBY_SURR_ENABLE 0x1
#define AC3_3DNOW_ENABLE 0x2
#define AC3_MMX_ENABLE 0x4
#define AC3_ALTIVEC_ENABLE 0x8
typedef struct ac3_config_s
{
//Bit flags that enable various things
uint_32 flags;
//Callback that points the decoder to new stream data
void (*fill_buffer_callback)(uint_8 **, uint_8 **);
//Number of discrete channels in final output (for downmixing)
uint_16 num_output_ch;
//Which channel of a dual mono stream to select
uint_16 dual_mono_ch_sel;
} ac3_config_t;
void ac3_init(ac3_config_t *);
uint_32 ac3_decode_data(uint_8 *data_start,uint_8 *data_end, int ac3reset, int *input_pointer, int *output_pointer, char *ac3_data);

344
ac3dec/ac3_internal.h Normal file
View File

@ -0,0 +1,344 @@
/*
* ac3_internal.h
*
* Copyright (C) Aaron Holtzman - May 1999
*
* 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.
*
*/
#ifndef __GNUC__
#define inline
#endif
/* Exponent strategy constants */
#define EXP_REUSE (0)
#define EXP_D15 (1)
#define EXP_D25 (2)
#define EXP_D45 (3)
/* Delta bit allocation constants */
#define DELTA_BIT_REUSE (0)
#define DELTA_BIT_NEW (1)
#define DELTA_BIT_NONE (2)
#define DELTA_BIT_RESERVED (3)
/* samples work structure */
typedef float stream_samples_t[6][256];
/* global config structure */
extern ac3_config_t ac3_config;
/* global error flag */
extern uint_32 error_flag;
/* Everything you wanted to know about band structure */
/*
* The entire frequency domain is represented by 256 real
* floating point fourier coefficients. Only the lower 253
* coefficients are actually utilized however. We use arrays
* of 256 to be efficient in some cases.
*
* The 5 full bandwidth channels (fbw) can have their higher
* frequencies coupled together. These coupled channels then
* share their high frequency components.
*
* This coupling band is broken up into 18 sub-bands starting
* at mantissa number 37. Each sub-band is 12 bins wide.
*
* There are 50 bit allocation sub-bands which cover the entire
* frequency range. The sub-bands are of non-uniform width, and
* approximate a 1/6 octave scale.
*/
/* The following structures are filled in by their corresponding parse_*
* functions. See http://www.atsc.org/Standards/A52/a_52.pdf for
* full details on each field. Indented fields are used to denote
* conditional fields.
*/
typedef struct syncinfo_s
{
uint_32 magic;
/* Sync word == 0x0B77 */
uint_16 syncword;
/* crc for the first 5/8 of the sync block */
/* uint_16 crc1; */
/* Stream Sampling Rate (kHz) 0 = 48, 1 = 44.1, 2 = 32, 3 = reserved */
uint_16 fscod;
/* Frame size code */
uint_16 frmsizecod;
/* Information not in the AC-3 bitstream, but derived */
/* Frame size in 16 bit words */
uint_16 frame_size;
/* Bit rate in kilobits */
uint_16 bit_rate;
/* sampling rate in hertz */
uint_32 sampling_rate;
} syncinfo_t;
typedef struct bsi_s
{
uint_32 magic;
/* Bit stream identification == 0x8 */
uint_16 bsid;
/* Bit stream mode */
uint_16 bsmod;
/* Audio coding mode */
uint_16 acmod;
/* If we're using the centre channel then */
/* centre mix level */
uint_16 cmixlev;
/* If we're using the surround channel then */
/* surround mix level */
uint_16 surmixlev;
/* If we're in 2/0 mode then */
/* Dolby surround mix level - NOT USED - */
uint_16 dsurmod;
/* Low frequency effects on */
uint_16 lfeon;
/* Dialogue Normalization level */
uint_16 dialnorm;
/* Compression exists */
uint_16 compre;
/* Compression level */
uint_16 compr;
/* Language code exists */
uint_16 langcode;
/* Language code */
uint_16 langcod;
/* Audio production info exists*/
uint_16 audprodie;
uint_16 mixlevel;
uint_16 roomtyp;
/* If we're in dual mono mode (acmod == 0) then extra stuff */
uint_16 dialnorm2;
uint_16 compr2e;
uint_16 compr2;
uint_16 langcod2e;
uint_16 langcod2;
uint_16 audprodi2e;
uint_16 mixlevel2;
uint_16 roomtyp2;
/* Copyright bit */
uint_16 copyrightb;
/* Original bit */
uint_16 origbs;
/* Timecode 1 exists */
uint_16 timecod1e;
/* Timecode 1 */
uint_16 timecod1;
/* Timecode 2 exists */
uint_16 timecod2e;
/* Timecode 2 */
uint_16 timecod2;
/* Additional bit stream info exists */
uint_16 addbsie;
/* Additional bit stream length - 1 (in bytes) */
uint_16 addbsil;
/* Additional bit stream information (max 64 bytes) */
uint_8 addbsi[64];
/* Information not in the AC-3 bitstream, but derived */
/* Number of channels (excluding LFE)
* Derived from acmod */
uint_16 nfchans;
} bsi_t;
/* more pain */
typedef struct audblk_s
{
uint_32 magic1;
/* block switch bit indexed by channel num */
uint_16 blksw[5];
/* dither enable bit indexed by channel num */
uint_16 dithflag[5];
/* dynamic range gain exists */
uint_16 dynrnge;
/* dynamic range gain */
uint_16 dynrng;
/* if acmod==0 then */
/* dynamic range 2 gain exists */
uint_16 dynrng2e;
/* dynamic range 2 gain */
uint_16 dynrng2;
/* coupling strategy exists */
uint_16 cplstre;
/* coupling in use */
uint_16 cplinu;
/* channel coupled */
uint_16 chincpl[5];
/* if acmod==2 then */
/* Phase flags in use */
uint_16 phsflginu;
/* coupling begin frequency code */
uint_16 cplbegf;
/* coupling end frequency code */
uint_16 cplendf;
/* coupling band structure bits */
uint_16 cplbndstrc[18];
/* Do coupling co-ords exist for this channel? */
uint_16 cplcoe[5];
/* Master coupling co-ordinate */
uint_16 mstrcplco[5];
/* Per coupling band coupling co-ordinates */
uint_16 cplcoexp[5][18];
uint_16 cplcomant[5][18];
/* Phase flags for dual mono */
uint_16 phsflg[18];
/* Is there a rematrixing strategy */
uint_16 rematstr;
/* Rematrixing bits */
uint_16 rematflg[4];
/* Coupling exponent strategy */
uint_16 cplexpstr;
/* Exponent strategy for full bandwidth channels */
uint_16 chexpstr[5];
/* Exponent strategy for lfe channel */
uint_16 lfeexpstr;
/* Channel bandwidth for independent channels */
uint_16 chbwcod[5];
/* The absolute coupling exponent */
uint_16 cplabsexp;
/* Coupling channel exponents (D15 mode gives 18 * 12 /3 encoded exponents */
uint_16 cplexps[18 * 12 / 3];
/* Sanity checking constant */
uint_32 magic2;
/* fbw channel exponents */
uint_16 exps[5][252 / 3];
/* channel gain range */
uint_16 gainrng[5];
/* low frequency exponents */
uint_16 lfeexps[3];
/* Bit allocation info */
uint_16 baie;
/* Slow decay code */
uint_16 sdcycod;
/* Fast decay code */
uint_16 fdcycod;
/* Slow gain code */
uint_16 sgaincod;
/* dB per bit code */
uint_16 dbpbcod;
/* masking floor code */
uint_16 floorcod;
/* SNR offset info */
uint_16 snroffste;
/* coarse SNR offset */
uint_16 csnroffst;
/* coupling fine SNR offset */
uint_16 cplfsnroffst;
/* coupling fast gain code */
uint_16 cplfgaincod;
/* fbw fine SNR offset */
uint_16 fsnroffst[5];
/* fbw fast gain code */
uint_16 fgaincod[5];
/* lfe fine SNR offset */
uint_16 lfefsnroffst;
/* lfe fast gain code */
uint_16 lfefgaincod;
/* Coupling leak info */
uint_16 cplleake;
/* coupling fast leak initialization */
uint_16 cplfleak;
/* coupling slow leak initialization */
uint_16 cplsleak;
/* delta bit allocation info */
uint_16 deltbaie;
/* coupling delta bit allocation exists */
uint_16 cpldeltbae;
/* fbw delta bit allocation exists */
uint_16 deltbae[5];
/* number of cpl delta bit segments */
uint_16 cpldeltnseg;
/* coupling delta bit allocation offset */
uint_16 cpldeltoffst[8];
/* coupling delta bit allocation length */
uint_16 cpldeltlen[8];
/* coupling delta bit allocation length */
uint_16 cpldeltba[8];
/* number of delta bit segments */
uint_16 deltnseg[5];
/* fbw delta bit allocation offset */
uint_16 deltoffst[5][8];
/* fbw delta bit allocation length */
uint_16 deltlen[5][8];
/* fbw delta bit allocation length */
uint_16 deltba[5][8];
/* skip length exists */
uint_16 skiple;
/* skip length */
uint_16 skipl;
//Removed Feb 2000 -ah
/* channel mantissas */
//uint_16 chmant[5][256];
/* coupling mantissas */
uint_16 cplmant[256];
//Removed Feb 2000 -ah
/* coupling mantissas */
//uint_16 lfemant[7];
/* -- Information not in the bitstream, but derived thereof -- */
/* Number of coupling sub-bands */
uint_16 ncplsubnd;
/* Number of combined coupling sub-bands
* Derived from ncplsubnd and cplbndstrc */
uint_16 ncplbnd;
/* Number of exponent groups by channel
* Derived from strmant, endmant */
uint_16 nchgrps[5];
/* Number of coupling exponent groups
* Derived from cplbegf, cplendf, cplexpstr */
uint_16 ncplgrps;
/* End mantissa numbers of fbw channels */
uint_16 endmant[5];
/* Start and end mantissa numbers for the coupling channel */
uint_16 cplstrtmant;
uint_16 cplendmant;
/* Decoded exponent info */
uint_16 fbw_exp[5][256];
uint_16 cpl_exp[256];
uint_16 lfe_exp[7];
/* Bit allocation pointer results */
uint_16 fbw_bap[5][256];
uint_16 cpl_bap[256];
uint_16 lfe_bap[7];
uint_32 magic3;
} audblk_t;

494
ac3dec/bit_allocate.c Normal file
View File

@ -0,0 +1,494 @@
/*
* bit_allocate.c
*
* Copyright (C) Aaron Holtzman - May 1999
*
* 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.
*
*/
#include <stdlib.h>
#include <string.h>
#include "ac3.h"
#include "ac3_internal.h"
static inline sint_16 logadd(sint_16 a,sint_16 b);
static sint_16 calc_lowcomp(sint_16 a,sint_16 b0,sint_16 b1,sint_16 bin);
static inline uint_16 min(sint_16 a,sint_16 b);
static inline uint_16 max(sint_16 a,sint_16 b);
static void ba_compute_psd(sint_16 start, sint_16 end, sint_16 exps[],
sint_16 psd[], sint_16 bndpsd[]);
static void ba_compute_excitation(sint_16 start, sint_16 end,sint_16 fgain,
sint_16 fastleak, sint_16 slowleak, sint_16 is_lfe, sint_16 bndpsd[],
sint_16 excite[]);
static void ba_compute_mask(sint_16 start, sint_16 end, uint_16 fscod,
uint_16 deltbae, uint_16 deltnseg, uint_16 deltoffst[], uint_16 deltba[],
uint_16 deltlen[], sint_16 excite[], sint_16 mask[]);
static void ba_compute_bap(sint_16 start, sint_16 end, sint_16 snroffset,
sint_16 psd[], sint_16 mask[], sint_16 bap[]);
/* Misc LUTs for bit allocation process */
static sint_16 slowdec[] = { 0x0f, 0x11, 0x13, 0x15 };
static sint_16 fastdec[] = { 0x3f, 0x53, 0x67, 0x7b };
static sint_16 slowgain[] = { 0x540, 0x4d8, 0x478, 0x410 };
static sint_16 dbpbtab[] = { 0x000, 0x700, 0x900, 0xb00 };
static uint_16 floortab[] = { 0x2f0, 0x2b0, 0x270, 0x230, 0x1f0, 0x170, 0x0f0, 0xf800 };
static sint_16 fastgain[] = { 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, 0x400 };
static sint_16 bndtab[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 31,
34, 37, 40, 43, 46, 49, 55, 61, 67, 73,
79, 85, 97, 109, 121, 133, 157, 181, 205, 229 };
static sint_16 bndsz[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 3, 3,
3, 3, 3, 3, 3, 6, 6, 6, 6, 6,
6, 12, 12, 12, 12, 24, 24, 24, 24, 24 };
static sint_16 masktab[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 28, 28, 29,
29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 32, 33, 33, 33, 34, 34,
34, 35, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 37, 37, 37,
37, 37, 37, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 40,
40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43,
43, 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44,
44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 46, 46, 46,
46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0 };
static sint_16 latab[] = { 0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003b, 0x003a, 0x0039,
0x0038, 0x0037, 0x0036, 0x0035, 0x0034, 0x0034, 0x0033, 0x0032,
0x0031, 0x0030, 0x002f, 0x002f, 0x002e, 0x002d, 0x002c, 0x002c,
0x002b, 0x002a, 0x0029, 0x0029, 0x0028, 0x0027, 0x0026, 0x0026,
0x0025, 0x0024, 0x0024, 0x0023, 0x0023, 0x0022, 0x0021, 0x0021,
0x0020, 0x0020, 0x001f, 0x001e, 0x001e, 0x001d, 0x001d, 0x001c,
0x001c, 0x001b, 0x001b, 0x001a, 0x001a, 0x0019, 0x0019, 0x0018,
0x0018, 0x0017, 0x0017, 0x0016, 0x0016, 0x0015, 0x0015, 0x0015,
0x0014, 0x0014, 0x0013, 0x0013, 0x0013, 0x0012, 0x0012, 0x0012,
0x0011, 0x0011, 0x0011, 0x0010, 0x0010, 0x0010, 0x000f, 0x000f,
0x000f, 0x000e, 0x000e, 0x000e, 0x000d, 0x000d, 0x000d, 0x000d,
0x000c, 0x000c, 0x000c, 0x000c, 0x000b, 0x000b, 0x000b, 0x000b,
0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x0009, 0x0009, 0x0009,
0x0009, 0x0009, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0006, 0x0006,
0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0005, 0x0005,
0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0004, 0x0004,
0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
0x0004, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0002,
0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
0x0002, 0x0002, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000};
static sint_16 hth[][50] = {{ 0x04d0, 0x04d0, 0x0440, 0x0400, 0x03e0, 0x03c0, 0x03b0, 0x03b0,
0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x0390, 0x0390, 0x0390,
0x0380, 0x0380, 0x0370, 0x0370, 0x0360, 0x0360, 0x0350, 0x0350,
0x0340, 0x0340, 0x0330, 0x0320, 0x0310, 0x0300, 0x02f0, 0x02f0,
0x02f0, 0x02f0, 0x0300, 0x0310, 0x0340, 0x0390, 0x03e0, 0x0420,
0x0460, 0x0490, 0x04a0, 0x0460, 0x0440, 0x0440, 0x0520, 0x0800,
0x0840, 0x0840 },
{ 0x04f0, 0x04f0, 0x0460, 0x0410, 0x03e0, 0x03d0, 0x03c0, 0x03b0,
0x03b0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x0390, 0x0390,
0x0390, 0x0380, 0x0380, 0x0380, 0x0370, 0x0370, 0x0360, 0x0360,
0x0350, 0x0350, 0x0340, 0x0340, 0x0320, 0x0310, 0x0300, 0x02f0,
0x02f0, 0x02f0, 0x02f0, 0x0300, 0x0320, 0x0350, 0x0390, 0x03e0,
0x0420, 0x0450, 0x04a0, 0x0490, 0x0460, 0x0440, 0x0480, 0x0630,
0x0840, 0x0840 },
{ 0x0580, 0x0580, 0x04b0, 0x0450, 0x0420, 0x03f0, 0x03e0, 0x03d0,
0x03c0, 0x03b0, 0x03b0, 0x03b0, 0x03a0, 0x03a0, 0x03a0, 0x03a0,
0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x0390, 0x0390, 0x0390, 0x0390,
0x0380, 0x0380, 0x0380, 0x0370, 0x0360, 0x0350, 0x0340, 0x0330,
0x0320, 0x0310, 0x0300, 0x02f0, 0x02f0, 0x02f0, 0x0300, 0x0310,
0x0330, 0x0350, 0x03c0, 0x0410, 0x0470, 0x04a0, 0x0460, 0x0440,
0x0450, 0x04e0 }};
static sint_16 baptab[] = { 0, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6,
6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10,
10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14,
14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15 };
static sint_16 sdecay;
static sint_16 fdecay;
static sint_16 sgain;
static sint_16 dbknee;
static sint_16 floor;
static sint_16 psd[256];
static sint_16 bndpsd[256];
static sint_16 excite[256];
static sint_16 mask[256];
static inline uint_16
max(sint_16 a,sint_16 b)
{
return (a > b ? a : b);
}
static inline uint_16
min(sint_16 a,sint_16 b)
{
return (a < b ? a : b);
}
static inline sint_16
logadd(sint_16 a,sint_16 b)
{
sint_16 c;
sint_16 address;
c = a - b;
address = min((abs(c) >> 1), 255);
if (c >= 0)
return(a + latab[address]);
else
return(b + latab[address]);
}
void bit_allocate(uint_16 fscod, bsi_t *bsi, audblk_t *audblk)
{
uint_16 i;
sint_16 fgain;
sint_16 snroffset;
sint_16 start;
sint_16 end;
sint_16 fastleak;
sint_16 slowleak;
/* Only perform bit_allocation if the exponents have changed or we
* have new sideband information */
if (audblk->chexpstr[0] == 0 && audblk->chexpstr[1] == 0 &&
audblk->chexpstr[2] == 0 && audblk->chexpstr[3] == 0 &&
audblk->chexpstr[4] == 0 && audblk->cplexpstr == 0 &&
audblk->lfeexpstr == 0 && audblk->baie == 0 &&
audblk->snroffste == 0 && audblk->deltbaie == 0)
return;
/* Do some setup before we do the bit alloc */
sdecay = slowdec[audblk->sdcycod];
fdecay = fastdec[audblk->fdcycod];
sgain = slowgain[audblk->sgaincod];
dbknee = dbpbtab[audblk->dbpbcod];
floor = floortab[audblk->floorcod];
/* if all the SNR offset constants are zero then the whole block is zero */
if(!audblk->csnroffst && !audblk->fsnroffst[0] &&
!audblk->fsnroffst[1] && !audblk->fsnroffst[2] &&
!audblk->fsnroffst[3] && !audblk->fsnroffst[4] &&
!audblk->cplfsnroffst && !audblk->lfefsnroffst)
{
memset(audblk->fbw_bap,0,sizeof(uint_16) * 256 * 5);
memset(audblk->cpl_bap,0,sizeof(uint_16) * 256);
memset(audblk->lfe_bap,0,sizeof(uint_16) * 7);
return;
}
for(i = 0; i < bsi->nfchans; i++)
{
start = 0;
end = audblk->endmant[i] ;
fgain = fastgain[audblk->fgaincod[i]];
snroffset = (((audblk->csnroffst - 15) << 4) + audblk->fsnroffst[i]) << 2 ;
fastleak = 0;
slowleak = 0;
ba_compute_psd(start, end, audblk->fbw_exp[i], psd, bndpsd);
ba_compute_excitation(start, end , fgain, fastleak, slowleak, 0, bndpsd, excite);
ba_compute_mask(start, end, fscod, audblk->deltbae[i], audblk->deltnseg[i],
audblk->deltoffst[i], audblk->deltba[i], audblk->deltlen[i], excite, mask);
ba_compute_bap(start, end, snroffset, psd, mask, audblk->fbw_bap[i]);
}
if(audblk->cplinu)
{
start = audblk->cplstrtmant;
end = audblk->cplendmant;
fgain = fastgain[audblk->cplfgaincod];
snroffset = (((audblk->csnroffst - 15) << 4) + audblk->cplfsnroffst) << 2 ;
fastleak = (audblk->cplfleak << 8) + 768;
slowleak = (audblk->cplsleak << 8) + 768;
ba_compute_psd(start, end, audblk->cpl_exp, psd, bndpsd);
ba_compute_excitation(start, end , fgain, fastleak, slowleak, 0, bndpsd, excite);
ba_compute_mask(start, end, fscod, audblk->cpldeltbae, audblk->cpldeltnseg,
audblk->cpldeltoffst, audblk->cpldeltba, audblk->cpldeltlen, excite, mask);
ba_compute_bap(start, end, snroffset, psd, mask, audblk->cpl_bap);
}
if(bsi->lfeon)
{
start = 0;
end = 7;
fgain = fastgain[audblk->lfefgaincod];
snroffset = (((audblk->csnroffst - 15) << 4) + audblk->lfefsnroffst) << 2 ;
fastleak = 0;
slowleak = 0;
ba_compute_psd(start, end, audblk->lfe_exp, psd, bndpsd);
ba_compute_excitation(start, end , fgain, fastleak, slowleak, 1, bndpsd, excite);
/* Perform no delta bit allocation for lfe */
ba_compute_mask(start, end, fscod, 2, 0, 0, 0, 0, excite, mask);
ba_compute_bap(start, end, snroffset, psd, mask, audblk->lfe_bap);
}
}
static void ba_compute_psd(sint_16 start, sint_16 end, sint_16 exps[],
sint_16 psd[], sint_16 bndpsd[])
{
int bin,i,j,k;
sint_16 lastbin = 0;
/* Map the exponents into dBs */
for (bin=start; bin<end; bin++)
{
psd[bin] = (3072 - (exps[bin] << 7));
}
/* Integrate the psd function over each bit allocation band */
j = start;
k = masktab[start];
do
{
lastbin = min(bndtab[k] + bndsz[k], end);
bndpsd[k] = psd[j];
j++;
for (i = j; i < lastbin; i++)
{
bndpsd[k] = logadd(bndpsd[k], psd[j]);
j++;
}
k++;
} while (end > lastbin);
}
static void ba_compute_excitation(sint_16 start, sint_16 end,sint_16 fgain,
sint_16 fastleak, sint_16 slowleak, sint_16 is_lfe, sint_16 bndpsd[],
sint_16 excite[])
{
int bin;
sint_16 bndstrt;
sint_16 bndend;
sint_16 lowcomp = 0;
sint_16 begin = 0;
/* Compute excitation function */
bndstrt = masktab[start];
bndend = masktab[end - 1] + 1;
if (bndstrt == 0) /* For fbw and lfe channels */
{
lowcomp = calc_lowcomp(lowcomp, bndpsd[0], bndpsd[1], 0);
excite[0] = bndpsd[0] - fgain - lowcomp;
lowcomp = calc_lowcomp(lowcomp, bndpsd[1], bndpsd[2], 1);
excite[1] = bndpsd[1] - fgain - lowcomp;
begin = 7 ;
/* Note: Do not call calc_lowcomp() for the last band of the lfe channel, (bin = 6) */
for (bin = 2; bin < 7; bin++)
{
if (!(is_lfe && (bin == 6)))
lowcomp = calc_lowcomp(lowcomp, bndpsd[bin], bndpsd[bin+1], bin);
fastleak = bndpsd[bin] - fgain;
slowleak = bndpsd[bin] - sgain;
excite[bin] = fastleak - lowcomp;
if (!(is_lfe && (bin == 6)))
{
if (bndpsd[bin] <= bndpsd[bin+1])
{
begin = bin + 1 ;
break;
}
}
}
for (bin = begin; bin < min(bndend, 22); bin++)
{
if (!(is_lfe && (bin == 6)))
lowcomp = calc_lowcomp(lowcomp, bndpsd[bin], bndpsd[bin+1], bin);
fastleak -= fdecay ;
fastleak = max(fastleak, bndpsd[bin] - fgain);
slowleak -= sdecay ;
slowleak = max(slowleak, bndpsd[bin] - sgain);
excite[bin] = max(fastleak - lowcomp, slowleak);
}
begin = 22;
}
else /* For coupling channel */
{
begin = bndstrt;
}
for (bin = begin; bin < bndend; bin++)
{
fastleak -= fdecay;
fastleak = max(fastleak, bndpsd[bin] - fgain);
slowleak -= sdecay;
slowleak = max(slowleak, bndpsd[bin] - sgain);
excite[bin] = max(fastleak, slowleak) ;
}
}
static void ba_compute_mask(sint_16 start, sint_16 end, uint_16 fscod,
uint_16 deltbae, uint_16 deltnseg, uint_16 deltoffst[], uint_16 deltba[],
uint_16 deltlen[], sint_16 excite[], sint_16 mask[])
{
int bin,k;
sint_16 bndstrt;
sint_16 bndend;
sint_16 delta;
bndstrt = masktab[start];
bndend = masktab[end - 1] + 1;
/* Compute the masking curve */
for (bin = bndstrt; bin < bndend; bin++)
{
if (bndpsd[bin] < dbknee)
{
excite[bin] += ((dbknee - bndpsd[bin]) >> 2);
}
mask[bin] = max(excite[bin], hth[fscod][bin]);
}
/* Perform delta bit modulation if necessary */
if ((deltbae == DELTA_BIT_REUSE) || (deltbae == DELTA_BIT_NEW))
{
sint_16 band = 0;
sint_16 seg = 0;
for (seg = 0; seg < deltnseg+1; seg++)
{
band += deltoffst[seg];
if (deltba[seg] >= 4)
{
delta = (deltba[seg] - 3) << 7;
}
else
{
delta = (deltba[seg] - 4) << 7;
}
for (k = 0; k < deltlen[seg]; k++)
{
mask[band] += delta;
band++;
}
}
}
}
static void ba_compute_bap(sint_16 start, sint_16 end, sint_16 snroffset,
sint_16 psd[], sint_16 mask[], sint_16 bap[])
{
int i,j,k;
sint_16 lastbin = 0;
sint_16 address = 0;
/* Compute the bit allocation pointer for each bin */
i = start;
j = masktab[start];
do
{
lastbin = min(bndtab[j] + bndsz[j], end);
mask[j] -= snroffset;
mask[j] -= floor;
if (mask[j] < 0)
mask[j] = 0;
mask[j] &= 0x1fe0;
mask[j] += floor;
for (k = i; k < lastbin; k++)
{
address = (psd[i] - mask[j]) >> 5;
address = min(63, max(0, address));
bap[i] = baptab[address];
i++;
}
j++;
} while (end > lastbin);
}
static sint_16
calc_lowcomp(sint_16 a,sint_16 b0,sint_16 b1,sint_16 bin)
{
if (bin < 7)
{
if ((b0 + 256) == b1)
a = 384;
else if (b0 > b1)
a = max(0, a - 64);
}
else if (bin < 20)
{
if ((b0 + 256) == b1)
a = 320;
else if (b0 > b1)
a = max(0, a - 64) ;
}
else
a = max(0, a - 128);
return(a);
}

24
ac3dec/bit_allocate.h Normal file
View File

@ -0,0 +1,24 @@
/*
* bit_allocate.h
*
* Copyright (C) Aaron Holtzman - May 1999
*
* 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.
*
*/
void bit_allocate(uint_16 fscod, bsi_t *bsi, audblk_t *audblk);

76
ac3dec/bitstream.c Normal file
View File

@ -0,0 +1,76 @@
/*
* bitstream.c
*
* Copyright (C) Aaron Holtzman - Dec 1999
*
* This file is part of ac3dec, a free AC-3 audio 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.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include "ac3.h"
#include "ac3_internal.h"
#include "bitstream.h"
uint_8 *buffer_start = 0;
uint_32 bits_left = 0;
uint_32 current_word;
static inline void
bitstream_fill_current()
{
current_word = *((uint_32*)buffer_start)++;
current_word = swab32(current_word);
}
//
// The fast paths for _get is in the
// bitstream.h header file so it can be inlined.
//
// The "bottom half" of this routine is suffixed _bh
//
// -ah
//
uint_32
bitstream_get_bh(uint_32 num_bits)
{
uint_32 result;
num_bits -= bits_left;
result = (current_word << (32 - bits_left)) >> (32 - bits_left);
bitstream_fill_current();
if(num_bits != 0)
result = (result << num_bits) | (current_word >> (32 - num_bits));
bits_left = 32 - num_bits;
return result;
}
void
bitstream_init(uint_8 *start)
{
//initialize the start of the buffer
buffer_start = start;
bits_left = 0;
}

76
ac3dec/bitstream.h Normal file
View File

@ -0,0 +1,76 @@
/*
* bitstream.h
*
* Copyright (C) Aaron Holtzman - Dec 1999
*
* This file is part of ac3dec, a free AC-3 audio 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.
*
*/
//My new and improved vego-matic endian swapping routine
//(stolen from the kernel)
#ifdef WORDS_BIGENDIAN
# define swab32(x) (x)
#else
# if defined (__i386__)
# define swab32(x) __i386_swab32(x)
static inline const uint_32 __i386_swab32(uint_32 x)
{
__asm__("bswap %0" : "=r" (x) : "0" (x));
return x;
}
# else
# define swab32(x)\
((((uint_8*)&x)[0] << 24) | (((uint_8*)&x)[1] << 16) | \
(((uint_8*)&x)[2] << 8) | (((uint_8*)&x)[3]))
# endif
#endif
extern uint_32 bits_left;
extern uint_32 current_word;
void bitstream_init(uint_8 *start);
uint_8 bitstream_get_byte(void);
uint_8 *bitstream_get_buffer_start(void);
void bitstream_buffer_frame(uint_32 frame_size);
uint_32 bitstream_get_bh(uint_32 num_bits);
static inline uint_32
bitstream_get(uint_32 num_bits)
{
uint_32 result;
if(num_bits < bits_left)
{
result = (current_word << (32 - bits_left)) >> (32 - num_bits);
bits_left -= num_bits;
return result;
}
return bitstream_get_bh(num_bits);
}

353
ac3dec/coeff.c Normal file
View File

@ -0,0 +1,353 @@
/*
* coeff.c
*
* Copyright (C) Aaron Holtzman - May 1999
*
* 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.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include "ac3.h"
#include "ac3_internal.h"
#include "decode.h"
#include "bitstream.h"
#include "dither.h"
#include "coeff.h"
//
//Lookup tables of 0.15 two's complement quantization values
//
static const uint_16 q_1[3] =
{
( -2 << 15)/3, 0,( 2 << 15)/3
};
static const uint_16 q_2[5] =
{
( -4 << 15)/5,( -2 << 15)/5, 0,
( 2 << 15)/5,( 4 << 15)/5
};
static const uint_16 q_3[7] =
{
( -6 << 15)/7,( -4 << 15)/7,( -2 << 15)/7, 0,
( 2 << 15)/7,( 4 << 15)/7,( 6 << 15)/7
};
static const uint_16 q_4[11] =
{
(-10 << 15)/11,(-8 << 15)/11,(-6 << 15)/11, ( -4 << 15)/11,(-2 << 15)/11, 0,
( 2 << 15)/11,( 4 << 15)/11,( 6 << 15)/11, ( 8 << 15)/11,(10 << 15)/11
};
static const uint_16 q_5[15] =
{
(-14 << 15)/15,(-12 << 15)/15,(-10 << 15)/15,
( -8 << 15)/15,( -6 << 15)/15,( -4 << 15)/15,
( -2 << 15)/15, 0 ,( 2 << 15)/15,
( 4 << 15)/15,( 6 << 15)/15,( 8 << 15)/15,
( 10 << 15)/15,( 12 << 15)/15,( 14 << 15)/15
};
//
// Scale factors for convert_to_float
//
static const uint_32 u32_scale_factors[25] =
{
0x38000000, //2 ^ -(0 + 15)
0x37800000, //2 ^ -(1 + 15)
0x37000000, //2 ^ -(2 + 15)
0x36800000, //2 ^ -(3 + 15)
0x36000000, //2 ^ -(4 + 15)
0x35800000, //2 ^ -(5 + 15)
0x35000000, //2 ^ -(6 + 15)
0x34800000, //2 ^ -(7 + 15)
0x34000000, //2 ^ -(8 + 15)
0x33800000, //2 ^ -(9 + 15)
0x33000000, //2 ^ -(10 + 15)
0x32800000, //2 ^ -(11 + 15)
0x32000000, //2 ^ -(12 + 15)
0x31800000, //2 ^ -(13 + 15)
0x31000000, //2 ^ -(14 + 15)
0x30800000, //2 ^ -(15 + 15)
0x30000000, //2 ^ -(16 + 15)
0x2f800000, //2 ^ -(17 + 15)
0x2f000000, //2 ^ -(18 + 15)
0x2e800000, //2 ^ -(19 + 15)
0x2e000000, //2 ^ -(20 + 15)
0x2d800000, //2 ^ -(21 + 15)
0x2d000000, //2 ^ -(22 + 15)
0x2c800000, //2 ^ -(23 + 15)
0x2c000000 //2 ^ -(24 + 15)
};
static float *scale_factor = (float*)u32_scale_factors;
//These store the persistent state of the packed mantissas
static uint_16 m_1[3];
static uint_16 m_2[3];
static uint_16 m_4[2];
static uint_16 m_1_pointer;
static uint_16 m_2_pointer;
static uint_16 m_4_pointer;
//Conversion from bap to number of bits in the mantissas
//zeros account for cases 0,1,2,4 which are special cased
static uint_16 qnttztab[16] = { 0, 0, 0, 3, 0 , 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16};
static void coeff_reset(void);
static sint_16 coeff_get_mantissa(uint_16 bap, uint_16 dithflag);
static void coeff_uncouple_ch(float samples[],bsi_t *bsi,audblk_t *audblk,uint_32 ch);
//
// Convert a 0.15 fixed point number into IEEE single
// precision floating point and scale by 2^-exp
//
static inline float
convert_to_float(uint_16 exp, sint_16 mantissa)
{
float x;
//the scale by 2^-15 is built into the scale factor table
x = mantissa * scale_factor[exp];
return x;
}
void
coeff_unpack(bsi_t *bsi, audblk_t *audblk, stream_samples_t samples)
{
uint_16 i,j;
uint_32 done_cpl = 0;
sint_16 mantissa;
coeff_reset();
for(i=0; i< bsi->nfchans; i++)
{
for(j=0; j < audblk->endmant[i]; j++)
{
mantissa = coeff_get_mantissa(audblk->fbw_bap[i][j],audblk->dithflag[i]);
samples[i][j] = convert_to_float(audblk->fbw_exp[i][j],mantissa);
}
if(audblk->cplinu && audblk->chincpl[i] && !(done_cpl))
{
// ncplmant is equal to 12 * ncplsubnd
// Don't dither coupling channel until channel separation so that
// interchannel noise is uncorrelated
for(j=audblk->cplstrtmant; j < audblk->cplendmant; j++)
audblk->cplmant[j] = coeff_get_mantissa(audblk->cpl_bap[j],0);
done_cpl = 1;
}
}
//uncouple the channel if necessary
if(audblk->cplinu)
{
for(i=0; i< bsi->nfchans; i++)
{
if(audblk->chincpl[i])
coeff_uncouple_ch(samples[i],bsi,audblk,i);
}
}
if(bsi->lfeon)
{
// There are always 7 mantissas for lfe, no dither for lfe
for(j=0; j < 7 ; j++)
{
mantissa = coeff_get_mantissa(audblk->lfe_bap[j],0);
samples[5][j] = convert_to_float(audblk->lfe_exp[j],mantissa);
}
}
}
//
//Fetch a mantissa from the bitstream
//
//The mantissa returned is a signed 0.15 fixed point number
//
static sint_16
coeff_get_mantissa(uint_16 bap, uint_16 dithflag)
{
uint_16 mantissa;
uint_16 group_code;
//If the bap is 0-5 then we have special cases to take care of
switch(bap)
{
case 0:
if(dithflag)
mantissa = dither_gen();
else
mantissa = 0;
break;
case 1:
if(m_1_pointer > 2)
{
group_code = bitstream_get(5);
if(group_code > 26)
goto error;
m_1[0] = group_code / 9;
m_1[1] = (group_code % 9) / 3;
m_1[2] = (group_code % 9) % 3;
m_1_pointer = 0;
}
mantissa = m_1[m_1_pointer++];
mantissa = q_1[mantissa];
break;
case 2:
if(m_2_pointer > 2)
{
group_code = bitstream_get(7);
if(group_code > 124)
goto error;
m_2[0] = group_code / 25;
m_2[1] = (group_code % 25) / 5 ;
m_2[2] = (group_code % 25) % 5 ;
m_2_pointer = 0;
}
mantissa = m_2[m_2_pointer++];
mantissa = q_2[mantissa];
break;
case 3:
mantissa = bitstream_get(3);
if(mantissa > 6)
goto error;
mantissa = q_3[mantissa];
break;
case 4:
if(m_4_pointer > 1)
{
group_code = bitstream_get(7);
if(group_code > 120)
goto error;
m_4[0] = group_code / 11;
m_4[1] = group_code % 11;
m_4_pointer = 0;
}
mantissa = m_4[m_4_pointer++];
mantissa = q_4[mantissa];
break;
case 5:
mantissa = bitstream_get(4);
if(mantissa > 14)
goto error;
mantissa = q_5[mantissa];
break;
default:
mantissa = bitstream_get(qnttztab[bap]);
mantissa <<= 16 - qnttztab[bap];
}
return mantissa;
error:
if(!error_flag)
fprintf(stderr,"** Invalid mantissa - skipping frame **\n");
error_flag = 1;
return 0;
}
//
// Reset the mantissa state
//
static void
coeff_reset(void)
{
m_1[2] = m_1[1] = m_1[0] = 0;
m_2[2] = m_2[1] = m_2[0] = 0;
m_4[1] = m_4[0] = 0;
m_1_pointer = m_2_pointer = m_4_pointer = 3;
}
//
// Uncouple the coupling channel into a fbw channel
//
static void
coeff_uncouple_ch(float samples[],bsi_t *bsi,audblk_t *audblk,uint_32 ch)
{
uint_32 bnd = 0;
uint_32 sub_bnd = 0;
uint_32 i,j;
float cpl_coord = 1.0;
uint_32 cpl_exp_tmp;
uint_32 cpl_mant_tmp;
sint_16 mantissa;
for(i=audblk->cplstrtmant;i<audblk->cplendmant;)
{
if(!audblk->cplbndstrc[sub_bnd++])
{
cpl_exp_tmp = audblk->cplcoexp[ch][bnd] + 3 * audblk->mstrcplco[ch];
if(audblk->cplcoexp[ch][bnd] == 15)
cpl_mant_tmp = (audblk->cplcomant[ch][bnd]) << 11;
else
cpl_mant_tmp = ((0x10) | audblk->cplcomant[ch][bnd]) << 10;
cpl_coord = convert_to_float(cpl_exp_tmp,cpl_mant_tmp) * 8.0f;
//Invert the phase for the right channel if necessary
if(bsi->acmod == 0x2 && audblk->phsflginu && ch == 1 && audblk->phsflg[bnd])
cpl_coord *= -1;
bnd++;
}
for(j=0;j < 12; j++)
{
//Get new dither values for each channel if necessary, so
//the channels are uncorrelated
if(audblk->dithflag[ch] && audblk->cpl_bap[i] == 0)
mantissa = dither_gen();
else
mantissa = audblk->cplmant[i];
samples[i] = cpl_coord * convert_to_float(audblk->cpl_exp[i],mantissa);
i++;
}
}
}

24
ac3dec/coeff.h Normal file
View File

@ -0,0 +1,24 @@
/*
* coeff.h
*
* Copyright (C) Aaron Holtzman - Feb 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.
*
*/
void coeff_unpack(bsi_t *bsi, audblk_t *audblk,stream_samples_t samples);

96
ac3dec/crc.c Normal file
View File

@ -0,0 +1,96 @@
/*
* crc.c
*
* Copyright (C) Aaron Holtzman - May 1999
*
* 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.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include "ac3.h"
#include "ac3_internal.h"
#include <sys/time.h>
#include "crc.h"
static const uint_16 crc_lut[256] =
{
0x0000,0x8005,0x800f,0x000a,0x801b,0x001e,0x0014,0x8011,
0x8033,0x0036,0x003c,0x8039,0x0028,0x802d,0x8027,0x0022,
0x8063,0x0066,0x006c,0x8069,0x0078,0x807d,0x8077,0x0072,
0x0050,0x8055,0x805f,0x005a,0x804b,0x004e,0x0044,0x8041,
0x80c3,0x00c6,0x00cc,0x80c9,0x00d8,0x80dd,0x80d7,0x00d2,
0x00f0,0x80f5,0x80ff,0x00fa,0x80eb,0x00ee,0x00e4,0x80e1,
0x00a0,0x80a5,0x80af,0x00aa,0x80bb,0x00be,0x00b4,0x80b1,
0x8093,0x0096,0x009c,0x8099,0x0088,0x808d,0x8087,0x0082,
0x8183,0x0186,0x018c,0x8189,0x0198,0x819d,0x8197,0x0192,
0x01b0,0x81b5,0x81bf,0x01ba,0x81ab,0x01ae,0x01a4,0x81a1,
0x01e0,0x81e5,0x81ef,0x01ea,0x81fb,0x01fe,0x01f4,0x81f1,
0x81d3,0x01d6,0x01dc,0x81d9,0x01c8,0x81cd,0x81c7,0x01c2,
0x0140,0x8145,0x814f,0x014a,0x815b,0x015e,0x0154,0x8151,
0x8173,0x0176,0x017c,0x8179,0x0168,0x816d,0x8167,0x0162,
0x8123,0x0126,0x012c,0x8129,0x0138,0x813d,0x8137,0x0132,
0x0110,0x8115,0x811f,0x011a,0x810b,0x010e,0x0104,0x8101,
0x8303,0x0306,0x030c,0x8309,0x0318,0x831d,0x8317,0x0312,
0x0330,0x8335,0x833f,0x033a,0x832b,0x032e,0x0324,0x8321,
0x0360,0x8365,0x836f,0x036a,0x837b,0x037e,0x0374,0x8371,
0x8353,0x0356,0x035c,0x8359,0x0348,0x834d,0x8347,0x0342,
0x03c0,0x83c5,0x83cf,0x03ca,0x83db,0x03de,0x03d4,0x83d1,
0x83f3,0x03f6,0x03fc,0x83f9,0x03e8,0x83ed,0x83e7,0x03e2,
0x83a3,0x03a6,0x03ac,0x83a9,0x03b8,0x83bd,0x83b7,0x03b2,
0x0390,0x8395,0x839f,0x039a,0x838b,0x038e,0x0384,0x8381,
0x0280,0x8285,0x828f,0x028a,0x829b,0x029e,0x0294,0x8291,
0x82b3,0x02b6,0x02bc,0x82b9,0x02a8,0x82ad,0x82a7,0x02a2,
0x82e3,0x02e6,0x02ec,0x82e9,0x02f8,0x82fd,0x82f7,0x02f2,
0x02d0,0x82d5,0x82df,0x02da,0x82cb,0x02ce,0x02c4,0x82c1,
0x8243,0x0246,0x024c,0x8249,0x0258,0x825d,0x8257,0x0252,
0x0270,0x8275,0x827f,0x027a,0x826b,0x026e,0x0264,0x8261,
0x0220,0x8225,0x822f,0x022a,0x823b,0x023e,0x0234,0x8231,
0x8213,0x0216,0x021c,0x8219,0x0208,0x820d,0x8207,0x0202
};
static uint_16 state;
void
crc_init(void)
{
state = 0;
}
inline void crc_process_byte(uint_8 data)
{
state = crc_lut[data ^ (state>>8)] ^ (state<<8);
}
void
crc_process_frame(uint_8 *data,uint_32 num_bytes)
{
uint_32 i;
for(i=0;i<num_bytes;i++)
crc_process_byte(data[i]);
}
int
crc_validate(void)
{
return(state == 0);
}

27
ac3dec/crc.h Normal file
View File

@ -0,0 +1,27 @@
/*
* crc.h
*
* Copyright (C) Aaron Holtzman - May 1999
*
* 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.
*
*/
int crc_validate(void);
void crc_init(void);
void crc_process_byte(uint_8 data);
void crc_process_frame(uint_8 *data,uint_32 num_bytes);

58
ac3dec/debug.c Normal file
View File

@ -0,0 +1,58 @@
/*
*
* debug.c
*
* Copyright (C) Aaron Holtzman - May 1999
*
* 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.
*
*/
#include <stdlib.h>
#include "debug.h"
static int debug_level = -1;
// Determine is debug output is required.
// We could potentially have multiple levels of debug info
int debug_is_on(void)
{
char *env_var;
if(debug_level < 0)
{
env_var = getenv("AC3_DEBUG");
if (env_var)
{
debug_level = 1;
}
else
debug_level = 0;
}
return debug_level;
}
//If you don't have gcc, then ya don't get debug output
#ifndef __GNUC__
void dprintf(char fmt[],...)
{
int foo = 0;
}
#endif

37
ac3dec/debug.h Normal file
View File

@ -0,0 +1,37 @@
/*
*
* debug.h
*
* Copyright (C) Aaron Holtzman - May 1999
*
* 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.
*
*/
int debug_is_on(void);
#ifdef __GNUC__
#define dprintf(format,args...)\
{\
if (debug_is_on())\
{\
fprintf(stderr,format,## args);\
}\
}
#else
void dprintf(char fmt[],...);
#endif

269
ac3dec/decode.c Normal file
View File

@ -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;
}

22
ac3dec/decode.h Normal file
View File

@ -0,0 +1,22 @@
/*
* decode.h
*
* Copyright (C) Aaron Holtzman - May 1999
*
* 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.
*
*/

115
ac3dec/dither.c Normal file
View File

@ -0,0 +1,115 @@
/*
* dither.c
*
* Copyright (C) Aaron Holtzman - May 1999
*
* 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.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include "ac3.h"
#include "ac3_internal.h"
#include "dither.h"
const uint_16 dither_lut[256] =
{
0x0000, 0xa011, 0xe033, 0x4022, 0x6077, 0xc066, 0x8044, 0x2055,
0xc0ee, 0x60ff, 0x20dd, 0x80cc, 0xa099, 0x0088, 0x40aa, 0xe0bb,
0x21cd, 0x81dc, 0xc1fe, 0x61ef, 0x41ba, 0xe1ab, 0xa189, 0x0198,
0xe123, 0x4132, 0x0110, 0xa101, 0x8154, 0x2145, 0x6167, 0xc176,
0x439a, 0xe38b, 0xa3a9, 0x03b8, 0x23ed, 0x83fc, 0xc3de, 0x63cf,
0x8374, 0x2365, 0x6347, 0xc356, 0xe303, 0x4312, 0x0330, 0xa321,
0x6257, 0xc246, 0x8264, 0x2275, 0x0220, 0xa231, 0xe213, 0x4202,
0xa2b9, 0x02a8, 0x428a, 0xe29b, 0xc2ce, 0x62df, 0x22fd, 0x82ec,
0x8734, 0x2725, 0x6707, 0xc716, 0xe743, 0x4752, 0x0770, 0xa761,
0x47da, 0xe7cb, 0xa7e9, 0x07f8, 0x27ad, 0x87bc, 0xc79e, 0x678f,
0xa6f9, 0x06e8, 0x46ca, 0xe6db, 0xc68e, 0x669f, 0x26bd, 0x86ac,
0x6617, 0xc606, 0x8624, 0x2635, 0x0660, 0xa671, 0xe653, 0x4642,
0xc4ae, 0x64bf, 0x249d, 0x848c, 0xa4d9, 0x04c8, 0x44ea, 0xe4fb,
0x0440, 0xa451, 0xe473, 0x4462, 0x6437, 0xc426, 0x8404, 0x2415,
0xe563, 0x4572, 0x0550, 0xa541, 0x8514, 0x2505, 0x6527, 0xc536,
0x258d, 0x859c, 0xc5be, 0x65af, 0x45fa, 0xe5eb, 0xa5c9, 0x05d8,
0xae79, 0x0e68, 0x4e4a, 0xee5b, 0xce0e, 0x6e1f, 0x2e3d, 0x8e2c,
0x6e97, 0xce86, 0x8ea4, 0x2eb5, 0x0ee0, 0xaef1, 0xeed3, 0x4ec2,
0x8fb4, 0x2fa5, 0x6f87, 0xcf96, 0xefc3, 0x4fd2, 0x0ff0, 0xafe1,
0x4f5a, 0xef4b, 0xaf69, 0x0f78, 0x2f2d, 0x8f3c, 0xcf1e, 0x6f0f,
0xede3, 0x4df2, 0x0dd0, 0xadc1, 0x8d94, 0x2d85, 0x6da7, 0xcdb6,
0x2d0d, 0x8d1c, 0xcd3e, 0x6d2f, 0x4d7a, 0xed6b, 0xad49, 0x0d58,
0xcc2e, 0x6c3f, 0x2c1d, 0x8c0c, 0xac59, 0x0c48, 0x4c6a, 0xec7b,
0x0cc0, 0xacd1, 0xecf3, 0x4ce2, 0x6cb7, 0xcca6, 0x8c84, 0x2c95,
0x294d, 0x895c, 0xc97e, 0x696f, 0x493a, 0xe92b, 0xa909, 0x0918,
0xe9a3, 0x49b2, 0x0990, 0xa981, 0x89d4, 0x29c5, 0x69e7, 0xc9f6,
0x0880, 0xa891, 0xe8b3, 0x48a2, 0x68f7, 0xc8e6, 0x88c4, 0x28d5,
0xc86e, 0x687f, 0x285d, 0x884c, 0xa819, 0x0808, 0x482a, 0xe83b,
0x6ad7, 0xcac6, 0x8ae4, 0x2af5, 0x0aa0, 0xaab1, 0xea93, 0x4a82,
0xaa39, 0x0a28, 0x4a0a, 0xea1b, 0xca4e, 0x6a5f, 0x2a7d, 0x8a6c,
0x4b1a, 0xeb0b, 0xab29, 0x0b38, 0x2b6d, 0x8b7c, 0xcb5e, 0x6b4f,
0x8bf4, 0x2be5, 0x6bc7, 0xcbd6, 0xeb83, 0x4b92, 0x0bb0, 0xaba1
};
uint_16 lfsr_state = 1;
//
// see dither_gen (inline-able) in dither.h
//
#if 0
//
// this is the old dither_gen with is much slower than the new inlined
// lut version and is still here because it's easier to understand.
//
/*
* Generate eight bits of pseudo-entropy using a 16 bit linear
* feedback shift register (LFSR). The primitive polynomial used
* is 1 + x^4 + x^14 + x^16.
*
* The distribution is uniform, over the range [-0.707,0.707]
*
*/
uint_16 dither_gen(void)
{
int i;
uint_32 state;
//explicitly bring the state into a local var as gcc > 3.0?
//doesn't know how to optimize out the stores
state = lfsr_state;
//Generate eight pseudo random bits
for(i=0;i<8;i++)
{
state <<= 1;
if(state & 0x10000)
state ^= 0xa011;
}
lfsr_state = state;
return (((((sint_32)state<<8)>>8) * (sint_32) (0.707106 * 256.0))>>16);
}
#endif

37
ac3dec/dither.h Normal file
View File

@ -0,0 +1,37 @@
/*
* dither.h
*
* Copyright (C) Aaron Holtzman - May 1999
*
* 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.
*
*/
extern uint_16 lfsr_state;
extern const uint_16 dither_lut[256];
static inline uint_16 dither_gen(void)
{
sint_16 state;
state = dither_lut[lfsr_state >> 8] ^ (lfsr_state << 8);
lfsr_state = (uint_16) state;
return ((state * (sint_32) (0.707106 * 256.0))>>8);
}

428
ac3dec/downmix.c Normal file
View File

@ -0,0 +1,428 @@
/*
*
* downmix.c
*
* Copyright (C) Aaron Holtzman - Sept 1999
*
* Originally based on code by Yuqing Deng.
*
* 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.
*
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "ac3.h"
#include "ac3_internal.h"
#include "decode.h"
#include "downmix.h"
#include "debug.h"
//Pre-scaled downmix coefficients
static float cmixlev_lut[4] = { 0.2928, 0.2468, 0.2071, 0.2468 };
static float smixlev_lut[4] = { 0.2928, 0.2071, 0.0 , 0.2071 };
static void
downmix_3f_2r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
{
uint_32 j;
float right_tmp;
float left_tmp;
float clev,slev;
float *centre = 0, *left = 0, *right = 0, *left_sur = 0, *right_sur = 0;
left = samples[0];
centre = samples[1];
right = samples[2];
left_sur = samples[3];
right_sur = samples[4];
clev = cmixlev_lut[bsi->cmixlev];
slev = smixlev_lut[bsi->surmixlev];
#if defined DOLBY_SURROUND
for (j = 0; j < 256; j++)
{
right_tmp = *left_sur++ + *right_sur++;
left_tmp = 1.4142f * *left++ + *centre - right_tmp;
right_tmp += 1.4142f * *right++ + *centre++;
s16_samples[j * 2 ] = (sint_16) (left_tmp * 16000.0f);
s16_samples[j * 2 + 1] = (sint_16) (right_tmp * 16000.0f);
}
#else
for (j = 0; j < 256; j++)
{
left_tmp = 0.4142f * *left++ + clev * *centre + slev * *left_sur++;
right_tmp= 0.4142f * *right++ + clev * *centre++ + slev * *right_sur++;
s16_samples[j * 2 ] = (sint_16) (left_tmp * 32767.0f);
s16_samples[j * 2 + 1] = (sint_16) (right_tmp * 32767.0f);
}
#endif
}
static void
downmix_2f_2r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
{
uint_32 j;
float right_tmp;
float left_tmp;
float slev;
float *left = 0, *right = 0, *left_sur = 0, *right_sur = 0;
left = samples[0];
right = samples[1];
left_sur = samples[2];
right_sur = samples[3];
slev = smixlev_lut[bsi->surmixlev];
for (j = 0; j < 256; j++)
{
left_tmp = 0.4142f * *left++ + slev * *left_sur++;
right_tmp= 0.4142f * *right++ + slev * *right_sur++;
s16_samples[j * 2 ] = (sint_16) (left_tmp * 32767.0f);
s16_samples[j * 2 + 1] = (sint_16) (right_tmp * 32767.0f);
}
}
static void
downmix_3f_1r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
{
uint_32 j;
float right_tmp;
float left_tmp;
float clev,slev;
float *centre = 0, *left = 0, *right = 0, *sur = 0;
left = samples[0];
centre = samples[1];
right = samples[2];
//Mono surround
sur = samples[3];
clev = cmixlev_lut[bsi->cmixlev];
slev = smixlev_lut[bsi->surmixlev];
for (j = 0; j < 256; j++)
{
left_tmp = 0.4142f * *left++ + clev * *centre++ + slev * *sur;
right_tmp= 0.4142f * *right++ + clev * *centre + slev * *sur++;
s16_samples[j * 2 ] = (sint_16) (left_tmp * 32767.0f);
s16_samples[j * 2 + 1] = (sint_16) (right_tmp * 32767.0f);
}
}
static void
downmix_2f_1r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
{
uint_32 j;
float right_tmp;
float left_tmp;
float slev;
float *left = 0, *right = 0, *sur = 0;
left = samples[0];
right = samples[1];
//Mono surround
sur = samples[2];
slev = smixlev_lut[bsi->surmixlev];
for (j = 0; j < 256; j++)
{
left_tmp = 0.4142f * *left++ + slev * *sur;
right_tmp= 0.4142f * *right++ + slev * *sur++;
s16_samples[j * 2 ] = (sint_16) (left_tmp * 32767.0f);
s16_samples[j * 2 + 1] = (sint_16) (right_tmp * 32767.0f);
}
}
static void
downmix_3f_0r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
{
uint_32 j;
float right_tmp;
float left_tmp;
float clev;
float *centre = 0, *left = 0, *right = 0;
left = samples[0];
centre = samples[1];
right = samples[2];
clev = cmixlev_lut[bsi->cmixlev];
for (j = 0; j < 256; j++)
{
left_tmp = 0.4142f * *left++ + clev * *centre;
right_tmp= 0.4142f * *right++ + clev * *centre++;
s16_samples[j * 2 ] = (sint_16) (left_tmp * 32767.0f);
s16_samples[j * 2 + 1] = (sint_16) (right_tmp * 32767.0f);
}
}
static void
downmix_2f_0r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
{
uint_32 j;
float *left = 0, *right = 0;
left = samples[0];
right = samples[1];
for (j = 0; j < 256; j++)
{
s16_samples[j * 2 ] = (sint_16) (*left++ * 32767.0f);
s16_samples[j * 2 + 1] = (sint_16) (*right++ * 32767.0f);
}
}
static void
downmix_1f_0r_to_2ch(float *centre,sint_16 *s16_samples)
{
uint_32 j;
float tmp;
//Mono program!
for (j = 0; j < 256; j++)
{
tmp = 32767.0f * 0.7071f * *centre++;
s16_samples[j * 2 ] = s16_samples[j * 2 + 1] = (sint_16) tmp;
}
}
//
// Downmix into 2 or 4 channels (4 ch isn't in quite yet)
//
// The downmix function names have the following format
//
// downmix_Xf_Yr_to_[2|4]ch[_dolby]
//
// where X = number of front channels
// Y = number of rear channels
// [2|4] = number of output channels
// [_dolby] = with or without dolby surround mix
//
void downmix(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
{
if(bsi->acmod > 7)
dprintf("(downmix) invalid acmod number\n");
//
//There are two main cases, with or without Dolby Surround
//
if(ac3_config.flags & AC3_DOLBY_SURR_ENABLE)
{
fprintf(stderr,"Dolby Surround Mixes not currently enabled\n");
exit(1);
}
//Non-Dolby surround downmixes
switch(bsi->acmod)
{
// 3/2
case 7:
downmix_3f_2r_to_2ch(bsi,samples,s16_samples);
break;
// 2/2
case 6:
downmix_2f_2r_to_2ch(bsi,samples,s16_samples);
break;
// 3/1
case 5:
downmix_3f_1r_to_2ch(bsi,samples,s16_samples);
break;
// 2/1
case 4:
downmix_2f_1r_to_2ch(bsi,samples,s16_samples);
break;
// 3/0
case 3:
downmix_3f_0r_to_2ch(bsi,samples,s16_samples);
break;
case 2:
downmix_2f_0r_to_2ch(bsi,samples,s16_samples);
break;
// 1/0
case 1:
downmix_1f_0r_to_2ch(samples[0],s16_samples);
break;
// 1+1
case 0:
downmix_1f_0r_to_2ch(samples[ac3_config.dual_mono_ch_sel],s16_samples);
break;
}
}
#if 0
//the dolby mixes lay here for the time being
switch(bsi->acmod)
{
// 3/2
case 7:
left = samples[0];
centre = samples[1];
right = samples[2];
left_sur = samples[3];
right_sur = samples[4];
for (j = 0; j < 256; j++)
{
right_tmp = 0.2265f * *left_sur++ + 0.2265f * *right_sur++;
left_tmp = -1 * right_tmp;
right_tmp += 0.3204f * *right++ + 0.2265f * *centre;
left_tmp += 0.3204f * *left++ + 0.2265f * *centre++;
samples[1][j] = right_tmp;
samples[0][j] = left_tmp;
}
break;
// 2/2
case 6:
left = samples[0];
right = samples[1];
left_sur = samples[2];
right_sur = samples[3];
for (j = 0; j < 256; j++)
{
right_tmp = 0.2265f * *left_sur++ + 0.2265f * *right_sur++;
left_tmp = -1 * right_tmp;
right_tmp += 0.3204f * *right++;
left_tmp += 0.3204f * *left++ ;
samples[1][j] = right_tmp;
samples[0][j] = left_tmp;
}
break;
// 3/1
case 5:
left = samples[0];
centre = samples[1];
right = samples[2];
//Mono surround
right_sur = samples[3];
for (j = 0; j < 256; j++)
{
right_tmp = 0.2265f * *right_sur++;
left_tmp = -1 * right_tmp;
right_tmp += 0.3204f * *right++ + 0.2265f * *centre;
left_tmp += 0.3204f * *left++ + 0.2265f * *centre++;
samples[1][j] = right_tmp;
samples[0][j] = left_tmp;
}
break;
// 2/1
case 4:
left = samples[0];
right = samples[1];
//Mono surround
right_sur = samples[2];
for (j = 0; j < 256; j++)
{
right_tmp = 0.2265f * *right_sur++;
left_tmp = -1 * right_tmp;
right_tmp += 0.3204f * *right++;
left_tmp += 0.3204f * *left++;
samples[1][j] = right_tmp;
samples[0][j] = left_tmp;
}
break;
// 3/0
case 3:
left = samples[0];
centre = samples[1];
right = samples[2];
for (j = 0; j < 256; j++)
{
right_tmp = 0.3204f * *right++ + 0.2265f * *centre;
left_tmp = 0.3204f * *left++ + 0.2265f * *centre++;
samples[1][j] = right_tmp;
samples[0][j] = left_tmp;
}
break;
// 2/0
case 2:
//Do nothing!
break;
// 1/0
case 1:
//Mono program!
right = samples[0];
for (j = 0; j < 256; j++)
{
right_tmp = 0.7071f * *right++;
samples[1][j] = right_tmp;
samples[0][j] = right_tmp;
}
break;
// 1+1
case 0:
//Dual mono, output selected by user
right = samples[ac3_config.dual_mono_ch_sel];
for (j = 0; j < 256; j++)
{
right_tmp = 0.7071f * *right++;
samples[1][j] = right_tmp;
samples[0][j] = right_tmp;
}
break;
#endif

28
ac3dec/downmix.h Normal file
View File

@ -0,0 +1,28 @@
/*
*
* downmix.h
*
* Copyright (C) Aaron Holtzman - Sept 1999
*
* Originally based on code by Yeqing Deng.
*
* 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.
*
*
*/
void downmix(bsi_t* bsi, stream_samples_t stream_samples,sint_16 *s16_samples);

135
ac3dec/exponent.c Normal file
View File

@ -0,0 +1,135 @@
/*
* exponent.c
*
* Copyright (C) Aaron Holtzman - May 1999
*
* 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.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include "ac3.h"
#include "ac3_internal.h"
#include "decode.h"
#include "exponent.h"
static void exp_unpack_ch(uint_16 type,uint_16 expstr,uint_16 ngrps,uint_16 initial_exp,
uint_16 exps[], uint_16 *dest);
void
exponent_unpack( bsi_t *bsi, audblk_t *audblk)
{
uint_16 i;
for(i=0; i< bsi->nfchans; i++)
exp_unpack_ch(UNPACK_FBW, audblk->chexpstr[i], audblk->nchgrps[i], audblk->exps[i][0],
&audblk->exps[i][1], audblk->fbw_exp[i]);
if(audblk->cplinu)
exp_unpack_ch(UNPACK_CPL, audblk->cplexpstr, audblk->ncplgrps, audblk->cplabsexp << 1,
audblk->cplexps, &audblk->cpl_exp[audblk->cplstrtmant]);
if(bsi->lfeon)
exp_unpack_ch(UNPACK_LFE, audblk->lfeexpstr, 2, audblk->lfeexps[0],
&audblk->lfeexps[1], audblk->lfe_exp);
}
static void
exp_unpack_ch(uint_16 type,uint_16 expstr,uint_16 ngrps,uint_16 initial_exp,
uint_16 exps[], uint_16 *dest)
{
uint_16 i,j;
sint_16 exp_acc;
sint_16 exp_1,exp_2,exp_3;
if(expstr == EXP_REUSE)
return;
/* Handle the initial absolute exponent */
exp_acc = initial_exp;
j = 0;
/* In the case of a fbw channel then the initial absolute values is
* also an exponent */
if(type != UNPACK_CPL)
dest[j++] = exp_acc;
/* Loop through the groups and fill the dest array appropriately */
for(i=0; i< ngrps; i++)
{
if(exps[i] > 124)
goto error;
exp_1 = exps[i] / 25;
exp_2 = (exps[i] - (exp_1 * 25)) / 5;
exp_3 = exps[i] - (exp_1 * 25) - (exp_2 * 5) ;
exp_acc += (exp_1 - 2);
switch(expstr)
{
case EXP_D45:
dest[j++] = exp_acc;
dest[j++] = exp_acc;
case EXP_D25:
dest[j++] = exp_acc;
case EXP_D15:
dest[j++] = exp_acc;
}
exp_acc += (exp_2 - 2);
switch(expstr)
{
case EXP_D45:
dest[j++] = exp_acc;
dest[j++] = exp_acc;
case EXP_D25:
dest[j++] = exp_acc;
case EXP_D15:
dest[j++] = exp_acc;
}
exp_acc += (exp_3 - 2);
switch(expstr)
{
case EXP_D45:
dest[j++] = exp_acc;
dest[j++] = exp_acc;
case EXP_D25:
dest[j++] = exp_acc;
case EXP_D15:
dest[j++] = exp_acc;
}
}
return;
goto error;
error:
if(!error_flag)
fprintf(stderr,"** Invalid exponent - skipping frame **\n");
error_flag = 1;
}

28
ac3dec/exponent.h Normal file
View File

@ -0,0 +1,28 @@
/*
* exponent.h
*
* Copyright (C) Aaron Holtzman - May 1999
*
* 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.
*
*/
#define UNPACK_FBW 1
#define UNPACK_CPL 2
#define UNPACK_LFE 4
void exponent_unpack( bsi_t *bsi, audblk_t *audblk);

468
ac3dec/imdct.c Normal file
View File

@ -0,0 +1,468 @@
/*
* imdct.c
*
* Copyright (C) Aaron Holtzman - May 1999
*
* 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.
*
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "ac3.h"
#include "ac3_internal.h"
#include "decode.h"
#include "imdct.h"
void imdct_do_256(float data[],float delay[]);
void imdct_do_512(float data[],float delay[]);
typedef struct complex_s
{
float real;
float imag;
} complex_t;
#define N 512
/* 128 point bit-reverse LUT */
static uint_8 bit_reverse_512[128] = {
0x00, 0x40, 0x20, 0x60, 0x10, 0x50, 0x30, 0x70,
0x08, 0x48, 0x28, 0x68, 0x18, 0x58, 0x38, 0x78,
0x04, 0x44, 0x24, 0x64, 0x14, 0x54, 0x34, 0x74,
0x0c, 0x4c, 0x2c, 0x6c, 0x1c, 0x5c, 0x3c, 0x7c,
0x02, 0x42, 0x22, 0x62, 0x12, 0x52, 0x32, 0x72,
0x0a, 0x4a, 0x2a, 0x6a, 0x1a, 0x5a, 0x3a, 0x7a,
0x06, 0x46, 0x26, 0x66, 0x16, 0x56, 0x36, 0x76,
0x0e, 0x4e, 0x2e, 0x6e, 0x1e, 0x5e, 0x3e, 0x7e,
0x01, 0x41, 0x21, 0x61, 0x11, 0x51, 0x31, 0x71,
0x09, 0x49, 0x29, 0x69, 0x19, 0x59, 0x39, 0x79,
0x05, 0x45, 0x25, 0x65, 0x15, 0x55, 0x35, 0x75,
0x0d, 0x4d, 0x2d, 0x6d, 0x1d, 0x5d, 0x3d, 0x7d,
0x03, 0x43, 0x23, 0x63, 0x13, 0x53, 0x33, 0x73,
0x0b, 0x4b, 0x2b, 0x6b, 0x1b, 0x5b, 0x3b, 0x7b,
0x07, 0x47, 0x27, 0x67, 0x17, 0x57, 0x37, 0x77,
0x0f, 0x4f, 0x2f, 0x6f, 0x1f, 0x5f, 0x3f, 0x7f};
static uint_8 bit_reverse_256[64] = {
0x00, 0x20, 0x10, 0x30, 0x08, 0x28, 0x18, 0x38,
0x04, 0x24, 0x14, 0x34, 0x0c, 0x2c, 0x1c, 0x3c,
0x02, 0x22, 0x12, 0x32, 0x0a, 0x2a, 0x1a, 0x3a,
0x06, 0x26, 0x16, 0x36, 0x0e, 0x2e, 0x1e, 0x3e,
0x01, 0x21, 0x11, 0x31, 0x09, 0x29, 0x19, 0x39,
0x05, 0x25, 0x15, 0x35, 0x0d, 0x2d, 0x1d, 0x3d,
0x03, 0x23, 0x13, 0x33, 0x0b, 0x2b, 0x1b, 0x3b,
0x07, 0x27, 0x17, 0x37, 0x0f, 0x2f, 0x1f, 0x3f};
static complex_t buf[128];
/* Twiddle factor LUT */
static complex_t *w[7];
static complex_t w_1[1];
static complex_t w_2[2];
static complex_t w_4[4];
static complex_t w_8[8];
static complex_t w_16[16];
static complex_t w_32[32];
static complex_t w_64[64];
/* Twiddle factors for IMDCT */
static float xcos1[128];
static float xsin1[128];
static float xcos2[64];
static float xsin2[64];
/* Delay buffer for time domain interleaving */
static float delay[6][256];
/* Windowing function for Modified DCT - Thank you acroread */
static float window[] = {
0.00014, 0.00024, 0.00037, 0.00051, 0.00067, 0.00086, 0.00107, 0.00130,
0.00157, 0.00187, 0.00220, 0.00256, 0.00297, 0.00341, 0.00390, 0.00443,
0.00501, 0.00564, 0.00632, 0.00706, 0.00785, 0.00871, 0.00962, 0.01061,
0.01166, 0.01279, 0.01399, 0.01526, 0.01662, 0.01806, 0.01959, 0.02121,
0.02292, 0.02472, 0.02662, 0.02863, 0.03073, 0.03294, 0.03527, 0.03770,
0.04025, 0.04292, 0.04571, 0.04862, 0.05165, 0.05481, 0.05810, 0.06153,
0.06508, 0.06878, 0.07261, 0.07658, 0.08069, 0.08495, 0.08935, 0.09389,
0.09859, 0.10343, 0.10842, 0.11356, 0.11885, 0.12429, 0.12988, 0.13563,
0.14152, 0.14757, 0.15376, 0.16011, 0.16661, 0.17325, 0.18005, 0.18699,
0.19407, 0.20130, 0.20867, 0.21618, 0.22382, 0.23161, 0.23952, 0.24757,
0.25574, 0.26404, 0.27246, 0.28100, 0.28965, 0.29841, 0.30729, 0.31626,
0.32533, 0.33450, 0.34376, 0.35311, 0.36253, 0.37204, 0.38161, 0.39126,
0.40096, 0.41072, 0.42054, 0.43040, 0.44030, 0.45023, 0.46020, 0.47019,
0.48020, 0.49022, 0.50025, 0.51028, 0.52031, 0.53033, 0.54033, 0.55031,
0.56026, 0.57019, 0.58007, 0.58991, 0.59970, 0.60944, 0.61912, 0.62873,
0.63827, 0.64774, 0.65713, 0.66643, 0.67564, 0.68476, 0.69377, 0.70269,
0.71150, 0.72019, 0.72877, 0.73723, 0.74557, 0.75378, 0.76186, 0.76981,
0.77762, 0.78530, 0.79283, 0.80022, 0.80747, 0.81457, 0.82151, 0.82831,
0.83496, 0.84145, 0.84779, 0.85398, 0.86001, 0.86588, 0.87160, 0.87716,
0.88257, 0.88782, 0.89291, 0.89785, 0.90264, 0.90728, 0.91176, 0.91610,
0.92028, 0.92432, 0.92822, 0.93197, 0.93558, 0.93906, 0.94240, 0.94560,
0.94867, 0.95162, 0.95444, 0.95713, 0.95971, 0.96217, 0.96451, 0.96674,
0.96887, 0.97089, 0.97281, 0.97463, 0.97635, 0.97799, 0.97953, 0.98099,
0.98236, 0.98366, 0.98488, 0.98602, 0.98710, 0.98811, 0.98905, 0.98994,
0.99076, 0.99153, 0.99225, 0.99291, 0.99353, 0.99411, 0.99464, 0.99513,
0.99558, 0.99600, 0.99639, 0.99674, 0.99706, 0.99736, 0.99763, 0.99788,
0.99811, 0.99831, 0.99850, 0.99867, 0.99882, 0.99895, 0.99908, 0.99919,
0.99929, 0.99938, 0.99946, 0.99953, 0.99959, 0.99965, 0.99969, 0.99974,
0.99978, 0.99981, 0.99984, 0.99986, 0.99988, 0.99990, 0.99992, 0.99993,
0.99994, 0.99995, 0.99996, 0.99997, 0.99998, 0.99998, 0.99998, 0.99999,
0.99999, 0.99999, 0.99999, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000,
1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000 };
static inline void swap_cmplx(complex_t *a, complex_t *b)
{
complex_t tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
static inline complex_t cmplx_mult(complex_t a, complex_t b)
{
complex_t ret;
ret.real = a.real * b.real - a.imag * b.imag;
ret.imag = a.real * b.imag + a.imag * b.real;
return ret;
}
void imdct_init(void)
{
int i,k;
complex_t angle_step;
complex_t current_angle;
/* Twiddle factors to turn IFFT into IMDCT */
for( i=0; i < 128; i++)
{
xcos1[i] = -cos(2.0f * M_PI * (8*i+1)/(8*N)) ;
xsin1[i] = -sin(2.0f * M_PI * (8*i+1)/(8*N)) ;
}
/* More twiddle factors to turn IFFT into IMDCT */
for( i=0; i < 64; i++)
{
xcos2[i] = -cos(2.0f * M_PI * (8*i+1)/(4*N)) ;
xsin2[i] = -sin(2.0f * M_PI * (8*i+1)/(4*N)) ;
}
/* Canonical twiddle factors for FFT */
w[0] = w_1;
w[1] = w_2;
w[2] = w_4;
w[3] = w_8;
w[4] = w_16;
w[5] = w_32;
w[6] = w_64;
for( i = 0; i < 7; i++)
{
angle_step.real = cos(-2.0 * M_PI / (1 << (i+1)));
angle_step.imag = sin(-2.0 * M_PI / (1 << (i+1)));
current_angle.real = 1.0;
current_angle.imag = 0.0;
for (k = 0; k < 1 << i; k++)
{
w[i][k] = current_angle;
current_angle = cmplx_mult(current_angle,angle_step);
}
}
}
void
imdct_do_512(float data[],float delay[])
{
int i,k;
int p,q;
int m;
int two_m;
int two_m_plus_one;
float tmp_a_i;
float tmp_a_r;
float tmp_b_i;
float tmp_b_r;
float *data_ptr;
float *delay_ptr;
float *window_ptr;
//
// 512 IMDCT with source and dest data in 'data'
//
// Pre IFFT complex multiply plus IFFT cmplx conjugate and bit reverse
// permutation
for( i=0; i < 128; i++)
{
k = bit_reverse_512[i];
/* z[i] = (X[256-2*i-1] + j * X[2*i]) * (xcos1[i] + j * xsin1[i]) ; */
buf[k].real = (data[256-2*i-1] * xcos1[i]) - (data[2*i] * xsin1[i]);
buf[k].imag = -1.0 * ((data[2*i] * xcos1[i]) + (data[256-2*i-1] * xsin1[i]));
}
// FFT Merge
for (m=0; m < 7; m++)
{
if(m)
two_m = (1 << m);
else
two_m = 1;
two_m_plus_one = (1 << (m+1));
for(k = 0; k < two_m; k++)
{
for(i = 0; i < 128; i += two_m_plus_one)
{
p = k + i;
q = p + two_m;
tmp_a_r = buf[p].real;
tmp_a_i = buf[p].imag;
tmp_b_r = buf[q].real * w[m][k].real - buf[q].imag * w[m][k].imag;
tmp_b_i = buf[q].imag * w[m][k].real + buf[q].real * w[m][k].imag;
buf[p].real = tmp_a_r + tmp_b_r;
buf[p].imag = tmp_a_i + tmp_b_i;
buf[q].real = tmp_a_r - tmp_b_r;
buf[q].imag = tmp_a_i - tmp_b_i;
}
}
}
/* Post IFFT complex multiply plus IFFT complex conjugate*/
for( i=0; i < 128; i++)
{
/* y[n] = z[n] * (xcos1[n] + j * xsin1[n]) ; */
tmp_a_r = buf[i].real;
tmp_a_i = buf[i].imag;
//Note that I flipped the signs on the imaginary ops to do the complex conj
buf[i].real =(tmp_a_r * xcos1[i]) + (tmp_a_i * xsin1[i]);
buf[i].imag =(tmp_a_r * xsin1[i]) - (tmp_a_i * xcos1[i]);
}
data_ptr = data;
delay_ptr = delay;
window_ptr = window;
/* Window and convert to real valued signal */
for(i=0; i< 64; i++)
{
*data_ptr++ = 2.0f * (-buf[64+i].imag * *window_ptr++ + *delay_ptr++);
*data_ptr++ = 2.0f * ( buf[64-i-1].real * *window_ptr++ + *delay_ptr++);
}
for(i=0; i< 64; i++)
{
*data_ptr++ = 2.0f * (-buf[i].real * *window_ptr++ + *delay_ptr++);
*data_ptr++ = 2.0f * ( buf[128-i-1].imag * *window_ptr++ + *delay_ptr++);
}
/* The trailing edge of the window goes into the delay line */
delay_ptr = delay;
for(i=0; i< 64; i++)
{
*delay_ptr++ = -buf[64+i].real * *--window_ptr;
*delay_ptr++ = buf[64-i-1].imag * *--window_ptr;
}
for(i=0; i<64; i++)
{
*delay_ptr++ = buf[i].imag * *--window_ptr;
*delay_ptr++ = -buf[128-i-1].real * *--window_ptr;
}
}
void
imdct_do_256(float data[],float delay[])
{
int i,k;
int p,q;
int m;
int two_m;
int two_m_plus_one;
float tmp_a_i;
float tmp_a_r;
float tmp_b_i;
float tmp_b_r;
float *data_ptr;
float *delay_ptr;
float *window_ptr;
complex_t *buf_1, *buf_2;
buf_1 = &buf[0];
buf_2 = &buf[64];
// Pre IFFT complex multiply plus IFFT cmplx conjugate and bit reverse
// permutation
for(i=0; i<64; i++)
{
/* X1[i] = X[2*i] */
/* X2[i] = X[2*i+1] */
k = bit_reverse_256[i];
p = 2 * (128-2*i-1);
q = 2 * (2 * i);
/* Z1[i] = (X1[128-2*i-1] + j * X1[2*i]) * (xcos2[i] + j * xsin2[i]); */
buf_1[k].real = data[p] * xcos2[i] - data[q] * xsin2[i];
buf_1[k].imag = -1.0f * (data[q] * xcos2[i] + data[p] * xsin2[i]);
/* Z2[i] = (X2[128-2*i-1] + j * X2[2*i]) * (xcos2[i] + j * xsin2[i]); */
buf_2[k].real = data[p + 1] * xcos2[i] - data[q + 1] * xsin2[i];
buf_2[k].imag = -1.0f * ( data[q + 1] * xcos2[i] + data[p + 1] * xsin2[i]);
}
// FFT Merge
for (m=0; m < 6; m++)
{
two_m = (1 << m);
two_m_plus_one = (1 << (m+1));
if(m)
two_m = (1 << m);
else
two_m = 1;
for(k = 0; k < two_m; k++)
{
for(i = 0; i < 64; i += two_m_plus_one)
{
p = k + i;
q = p + two_m;
//Do block 1
tmp_a_r = buf_1[p].real;
tmp_a_i = buf_1[p].imag;
tmp_b_r = buf_1[q].real * w[m][k].real - buf_1[q].imag * w[m][k].imag;
tmp_b_i = buf_1[q].imag * w[m][k].real + buf_1[q].real * w[m][k].imag;
buf_1[p].real = tmp_a_r + tmp_b_r;
buf_1[p].imag = tmp_a_i + tmp_b_i;
buf_1[q].real = tmp_a_r - tmp_b_r;
buf_1[q].imag = tmp_a_i - tmp_b_i;
//Do block 2
tmp_a_r = buf_2[p].real;
tmp_a_i = buf_2[p].imag;
tmp_b_r = buf_2[q].real * w[m][k].real - buf_2[q].imag * w[m][k].imag;
tmp_b_i = buf_2[q].imag * w[m][k].real + buf_2[q].real * w[m][k].imag;
buf_2[p].real = tmp_a_r + tmp_b_r;
buf_2[p].imag = tmp_a_i + tmp_b_i;
buf_2[q].real = tmp_a_r - tmp_b_r;
buf_2[q].imag = tmp_a_i - tmp_b_i;
}
}
}
// Post IFFT complex multiply
for( i=0; i < 64; i++)
{
//Note that I flipped the signs on the imaginary ops to do the complex conj
/* y1[n] = z1[n] * (xcos2[n] + j * xs in2[n]) ; */
tmp_a_r = buf_1[i].real;
tmp_a_i = buf_1[i].imag;
buf_1[i].real =(tmp_a_r * xcos2[i]) + (tmp_a_i * xsin2[i]);
buf_1[i].imag =(tmp_a_r * xsin2[i]) - (tmp_a_i * xcos2[i]);
/* y2[n] = z2[n] * (xcos2[n] + j * xsin2[n]) ; */
tmp_a_r = buf_2[i].real;
tmp_a_i = buf_2[i].imag;
buf_2[i].real =(tmp_a_r * xcos2[i]) + (tmp_a_i * xsin2[i]);
buf_2[i].imag =(tmp_a_r * xsin2[i]) - (tmp_a_i * xcos2[i]);
}
data_ptr = data;
delay_ptr = delay;
window_ptr = window;
/* Window and convert to real valued signal */
for(i=0; i< 64; i++)
{
*data_ptr++ = 2.0f * (-buf_1[i].imag * *window_ptr++ + *delay_ptr++);
*data_ptr++ = 2.0f * ( buf_1[64-i-1].real * *window_ptr++ + *delay_ptr++);
}
for(i=0; i< 64; i++)
{
*data_ptr++ = 2.0f * (-buf_1[i].real * *window_ptr++ + *delay_ptr++);
*data_ptr++ = 2.0f * ( buf_1[64-i-1].imag * *window_ptr++ + *delay_ptr++);
}
delay_ptr = delay;
for(i=0; i< 64; i++)
{
*delay_ptr++ = -buf_2[i].real * *--window_ptr;
*delay_ptr++ = buf_2[64-i-1].imag * *--window_ptr;
}
for(i=0; i< 64; i++)
{
*delay_ptr++ = buf_2[i].imag * *--window_ptr;
*delay_ptr++ = -buf_2[64-i-1].real * *--window_ptr;
}
}
//FIXME remove - for timing code
///#include <sys/time.h>
//FIXME remove
void
imdct(bsi_t *bsi,audblk_t *audblk, stream_samples_t samples) {
int i;
//handy timing code
//struct timeval start,end;
//gettimeofday(&start,0);
for(i=0; i<bsi->nfchans;i++)
{
if(audblk->blksw[i])
imdct_do_256(samples[i],delay[i]);
else
imdct_do_512(samples[i],delay[i]);
}
//gettimeofday(&end,0);
//printf("imdct %ld us\n",(end.tv_sec - start.tv_sec) * 1000000 +
//end.tv_usec - start.tv_usec);
//XXX We don't bother with the IMDCT for the LFE as it's currently
//unused.
//if (bsi->lfeon)
// imdct_do_512(coeffs->lfe,samples->channel[5],delay[5]);
//
}

26
ac3dec/imdct.h Normal file
View File

@ -0,0 +1,26 @@
/*
* imdct.h
*
* Copyright (C) Aaron Holtzman - May 1999
*
* 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.
*
*
*/
void imdct(bsi_t *bsi,audblk_t *audblk, stream_samples_t samples);
void imdct_init(void);

597
ac3dec/parse.c Normal file
View File

@ -0,0 +1,597 @@
/*
* parse.c
*
* Copyright (C) Aaron Holtzman - May 1999
*
* 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.
*
*
*/
#include <stdlib.h>
#include <stdio.h>
#include "ac3.h"
#include "ac3_internal.h"
#include "bitstream.h"
#include "stats.h"
#include "debug.h"
#include "parse.h"
/* Misc LUT */
static const uint_16 nfchans[8] = {2,1,2,3,3,4,4,5};
struct frmsize_s
{
uint_16 bit_rate;
uint_16 frm_size[3];
};
static const struct frmsize_s frmsizecod_tbl[64] =
{
{ 32 ,{64 ,69 ,96 } },
{ 32 ,{64 ,70 ,96 } },
{ 40 ,{80 ,87 ,120 } },
{ 40 ,{80 ,88 ,120 } },
{ 48 ,{96 ,104 ,144 } },
{ 48 ,{96 ,105 ,144 } },
{ 56 ,{112 ,121 ,168 } },
{ 56 ,{112 ,122 ,168 } },
{ 64 ,{128 ,139 ,192 } },
{ 64 ,{128 ,140 ,192 } },
{ 80 ,{160 ,174 ,240 } },
{ 80 ,{160 ,175 ,240 } },
{ 96 ,{192 ,208 ,288 } },
{ 96 ,{192 ,209 ,288 } },
{ 112 ,{224 ,243 ,336 } },
{ 112 ,{224 ,244 ,336 } },
{ 128 ,{256 ,278 ,384 } },
{ 128 ,{256 ,279 ,384 } },
{ 160 ,{320 ,348 ,480 } },
{ 160 ,{320 ,349 ,480 } },
{ 192 ,{384 ,417 ,576 } },
{ 192 ,{384 ,418 ,576 } },
{ 224 ,{448 ,487 ,672 } },
{ 224 ,{448 ,488 ,672 } },
{ 256 ,{512 ,557 ,768 } },
{ 256 ,{512 ,558 ,768 } },
{ 320 ,{640 ,696 ,960 } },
{ 320 ,{640 ,697 ,960 } },
{ 384 ,{768 ,835 ,1152 } },
{ 384 ,{768 ,836 ,1152 } },
{ 448 ,{896 ,975 ,1344 } },
{ 448 ,{896 ,976 ,1344 } },
{ 512 ,{1024 ,1114 ,1536 } },
{ 512 ,{1024 ,1115 ,1536 } },
{ 576 ,{1152 ,1253 ,1728 } },
{ 576 ,{1152 ,1254 ,1728 } },
{ 640 ,{1280 ,1393 ,1920 } },
{ 640 ,{1280 ,1394 ,1920 } }
};
/* Parse a syncinfo structure, minus the sync word */
void
parse_syncinfo(syncinfo_t *syncinfo,uint_8 *data)
{
//
// We need to read in the entire syncinfo struct (0x0b77 + 24 bits)
// in order to determine how big the frame is
//
// Get the sampling rate
syncinfo->fscod = (data[2] >> 6) & 0x3;
if(syncinfo->fscod == 3)
{
//invalid sampling rate code
error_flag = 1;
return;
}
else if(syncinfo->fscod == 2)
syncinfo->sampling_rate = 32000;
else if(syncinfo->fscod == 1)
syncinfo->sampling_rate = 44100;
else
syncinfo->sampling_rate = 48000;
// Get the frame size code
syncinfo->frmsizecod = data[2] & 0x3f;
// Calculate the frame size and bitrate
syncinfo->frame_size =
frmsizecod_tbl[syncinfo->frmsizecod].frm_size[syncinfo->fscod];
syncinfo->bit_rate = frmsizecod_tbl[syncinfo->frmsizecod].bit_rate;
}
/*
* This routine fills a bsi struct from the AC3 stream
*/
void
parse_bsi(bsi_t *bsi)
{
uint_32 i;
/* Check the AC-3 version number */
bsi->bsid = bitstream_get(5);
/* Get the audio service provided by the steram */
bsi->bsmod = bitstream_get(3);
/* Get the audio coding mode (ie how many channels)*/
bsi->acmod = bitstream_get(3);
/* Predecode the number of full bandwidth channels as we use this
* number a lot */
bsi->nfchans = nfchans[bsi->acmod];
/* If it is in use, get the centre channel mix level */
if ((bsi->acmod & 0x1) && (bsi->acmod != 0x1))
bsi->cmixlev = bitstream_get(2);
/* If it is in use, get the surround channel mix level */
if (bsi->acmod & 0x4)
bsi->surmixlev = bitstream_get(2);
/* Get the dolby surround mode if in 2/0 mode */
if(bsi->acmod == 0x2)
bsi->dsurmod= bitstream_get(2);
/* Is the low frequency effects channel on? */
bsi->lfeon = bitstream_get(1);
/* Get the dialogue normalization level */
bsi->dialnorm = bitstream_get(5);
/* Does compression gain exist? */
bsi->compre = bitstream_get(1);
if (bsi->compre)
{
/* Get compression gain */
bsi->compr = bitstream_get(8);
}
/* Does language code exist? */
bsi->langcode = bitstream_get(1);
if (bsi->langcode)
{
/* Get langauge code */
bsi->langcod = bitstream_get(8);
}
/* Does audio production info exist? */
bsi->audprodie = bitstream_get(1);
if (bsi->audprodie)
{
/* Get mix level */
bsi->mixlevel = bitstream_get(5);
/* Get room type */
bsi->roomtyp = bitstream_get(2);
}
/* If we're in dual mono mode then get some extra info */
if (bsi->acmod ==0)
{
/* Get the dialogue normalization level two */
bsi->dialnorm2 = bitstream_get(5);
/* Does compression gain two exist? */
bsi->compr2e = bitstream_get(1);
if (bsi->compr2e)
{
/* Get compression gain two */
bsi->compr2 = bitstream_get(8);
}
/* Does language code two exist? */
bsi->langcod2e = bitstream_get(1);
if (bsi->langcod2e)
{
/* Get langauge code two */
bsi->langcod2 = bitstream_get(8);
}
/* Does audio production info two exist? */
bsi->audprodi2e = bitstream_get(1);
if (bsi->audprodi2e)
{
/* Get mix level two */
bsi->mixlevel2 = bitstream_get(5);
/* Get room type two */
bsi->roomtyp2 = bitstream_get(2);
}
}
/* Get the copyright bit */
bsi->copyrightb = bitstream_get(1);
/* Get the original bit */
bsi->origbs = bitstream_get(1);
/* Does timecode one exist? */
bsi->timecod1e = bitstream_get(1);
if(bsi->timecod1e)
bsi->timecod1 = bitstream_get(14);
/* Does timecode two exist? */
bsi->timecod2e = bitstream_get(1);
if(bsi->timecod2e)
bsi->timecod2 = bitstream_get(14);
/* Does addition info exist? */
bsi->addbsie = bitstream_get(1);
if(bsi->addbsie)
{
/* Get how much info is there */
bsi->addbsil = bitstream_get(6);
/* Get the additional info */
for(i=0;i<(bsi->addbsil + 1);i++)
bsi->addbsi[i] = bitstream_get(8);
}
stats_print_bsi(bsi);
}
/* More pain inducing parsing */
void
parse_audblk(bsi_t *bsi,audblk_t *audblk)
{
int i,j;
for (i=0;i < bsi->nfchans; i++)
{
/* Is this channel an interleaved 256 + 256 block ? */
audblk->blksw[i] = bitstream_get(1);
}
for (i=0;i < bsi->nfchans; i++)
{
/* Should we dither this channel? */
audblk->dithflag[i] = bitstream_get(1);
}
/* Does dynamic range control exist? */
audblk->dynrnge = bitstream_get(1);
if (audblk->dynrnge)
{
/* Get dynamic range info */
audblk->dynrng = bitstream_get(8);
}
/* If we're in dual mono mode then get the second channel DR info */
if (bsi->acmod == 0)
{
/* Does dynamic range control two exist? */
audblk->dynrng2e = bitstream_get(1);
if (audblk->dynrng2e)
{
/* Get dynamic range info */
audblk->dynrng2 = bitstream_get(8);
}
}
/* Does coupling strategy exist? */
audblk->cplstre = bitstream_get(1);
if (audblk->cplstre)
{
/* Is coupling turned on? */
audblk->cplinu = bitstream_get(1);
if(audblk->cplinu)
{
for(i=0;i < bsi->nfchans; i++)
audblk->chincpl[i] = bitstream_get(1);
if(bsi->acmod == 0x2)
audblk->phsflginu = bitstream_get(1);
audblk->cplbegf = bitstream_get(4);
audblk->cplendf = bitstream_get(4);
audblk->ncplsubnd = (audblk->cplendf + 2) - audblk->cplbegf + 1;
/* Calculate the start and end bins of the coupling channel */
audblk->cplstrtmant = (audblk->cplbegf * 12) + 37 ;
audblk->cplendmant = ((audblk->cplendf + 3) * 12) + 37;
/* The number of combined subbands is ncplsubnd minus each combined
* band */
audblk->ncplbnd = audblk->ncplsubnd;
for(i=1; i< audblk->ncplsubnd; i++)
{
audblk->cplbndstrc[i] = bitstream_get(1);
audblk->ncplbnd -= audblk->cplbndstrc[i];
}
}
}
if(audblk->cplinu)
{
/* Loop through all the channels and get their coupling co-ords */
for(i=0;i < bsi->nfchans;i++)
{
if(!audblk->chincpl[i])
continue;
/* Is there new coupling co-ordinate info? */
audblk->cplcoe[i] = bitstream_get(1);
if(audblk->cplcoe[i])
{
audblk->mstrcplco[i] = bitstream_get(2);
for(j=0;j < audblk->ncplbnd; j++)
{
audblk->cplcoexp[i][j] = bitstream_get(4);
audblk->cplcomant[i][j] = bitstream_get(4);
}
}
}
/* If we're in dual mono mode, there's going to be some phase info */
if( (bsi->acmod == 0x2) && audblk->phsflginu &&
(audblk->cplcoe[0] || audblk->cplcoe[1]))
{
for(j=0;j < audblk->ncplbnd; j++)
audblk->phsflg[j] = bitstream_get(1);
}
}
/* If we're in dual mono mode, there may be a rematrix strategy */
if(bsi->acmod == 0x2)
{
audblk->rematstr = bitstream_get(1);
if(audblk->rematstr)
{
if (audblk->cplinu == 0)
{
for(i = 0; i < 4; i++)
audblk->rematflg[i] = bitstream_get(1);
}
if((audblk->cplbegf > 2) && audblk->cplinu)
{
for(i = 0; i < 4; i++)
audblk->rematflg[i] = bitstream_get(1);
}
if((audblk->cplbegf <= 2) && audblk->cplinu)
{
for(i = 0; i < 3; i++)
audblk->rematflg[i] = bitstream_get(1);
}
if((audblk->cplbegf == 0) && audblk->cplinu)
for(i = 0; i < 2; i++)
audblk->rematflg[i] = bitstream_get(1);
}
}
if (audblk->cplinu)
{
/* Get the coupling channel exponent strategy */
audblk->cplexpstr = bitstream_get(2);
audblk->ncplgrps = (audblk->cplendmant - audblk->cplstrtmant) /
(3 << (audblk->cplexpstr-1));
}
for(i = 0; i < bsi->nfchans; i++)
audblk->chexpstr[i] = bitstream_get(2);
/* Get the exponent strategy for lfe channel */
if(bsi->lfeon)
audblk->lfeexpstr = bitstream_get(1);
/* Determine the bandwidths of all the fbw channels */
for(i = 0; i < bsi->nfchans; i++)
{
uint_16 grp_size;
if(audblk->chexpstr[i] != EXP_REUSE)
{
if (audblk->cplinu && audblk->chincpl[i])
{
audblk->endmant[i] = audblk->cplstrtmant;
}
else
{
audblk->chbwcod[i] = bitstream_get(6);
audblk->endmant[i] = ((audblk->chbwcod[i] + 12) * 3) + 37;
}
/* Calculate the number of exponent groups to fetch */
grp_size = 3 * (1 << (audblk->chexpstr[i] - 1));
audblk->nchgrps[i] = (audblk->endmant[i] - 1 + (grp_size - 3)) / grp_size;
}
}
/* Get the coupling exponents if they exist */
if(audblk->cplinu && (audblk->cplexpstr != EXP_REUSE))
{
audblk->cplabsexp = bitstream_get(4);
for(i=0;i< audblk->ncplgrps;i++)
audblk->cplexps[i] = bitstream_get(7);
}
/* Get the fwb channel exponents */
for(i=0;i < bsi->nfchans; i++)
{
if(audblk->chexpstr[i] != EXP_REUSE)
{
audblk->exps[i][0] = bitstream_get(4);
for(j=1;j<=audblk->nchgrps[i];j++)
audblk->exps[i][j] = bitstream_get(7);
audblk->gainrng[i] = bitstream_get(2);
}
}
/* Get the lfe channel exponents */
if(bsi->lfeon && (audblk->lfeexpstr != EXP_REUSE))
{
audblk->lfeexps[0] = bitstream_get(4);
audblk->lfeexps[1] = bitstream_get(7);
audblk->lfeexps[2] = bitstream_get(7);
}
/* Get the parametric bit allocation parameters */
audblk->baie = bitstream_get(1);
if(audblk->baie)
{
audblk->sdcycod = bitstream_get(2);
audblk->fdcycod = bitstream_get(2);
audblk->sgaincod = bitstream_get(2);
audblk->dbpbcod = bitstream_get(2);
audblk->floorcod = bitstream_get(3);
}
/* Get the SNR off set info if it exists */
audblk->snroffste = bitstream_get(1);
if(audblk->snroffste)
{
audblk->csnroffst = bitstream_get(6);
if(audblk->cplinu)
{
audblk->cplfsnroffst = bitstream_get(4);
audblk->cplfgaincod = bitstream_get(3);
}
for(i = 0;i < bsi->nfchans; i++)
{
audblk->fsnroffst[i] = bitstream_get(4);
audblk->fgaincod[i] = bitstream_get(3);
}
if(bsi->lfeon)
{
audblk->lfefsnroffst = bitstream_get(4);
audblk->lfefgaincod = bitstream_get(3);
}
}
/* Get coupling leakage info if it exists */
if(audblk->cplinu)
{
audblk->cplleake = bitstream_get(1);
if(audblk->cplleake)
{
audblk->cplfleak = bitstream_get(3);
audblk->cplsleak = bitstream_get(3);
}
}
/* Get the delta bit alloaction info */
audblk->deltbaie = bitstream_get(1);
if(audblk->deltbaie)
{
if(audblk->cplinu)
audblk->cpldeltbae = bitstream_get(2);
for(i = 0;i < bsi->nfchans; i++)
audblk->deltbae[i] = bitstream_get(2);
if (audblk->cplinu && (audblk->cpldeltbae == DELTA_BIT_NEW))
{
audblk->cpldeltnseg = bitstream_get(3);
for(i = 0;i < audblk->cpldeltnseg + 1; i++)
{
audblk->cpldeltoffst[i] = bitstream_get(5);
audblk->cpldeltlen[i] = bitstream_get(4);
audblk->cpldeltba[i] = bitstream_get(3);
}
}
for(i = 0;i < bsi->nfchans; i++)
{
if (audblk->deltbae[i] == DELTA_BIT_NEW)
{
audblk->deltnseg[i] = bitstream_get(3);
for(j = 0; j < audblk->deltnseg[i] + 1; j++)
{
audblk->deltoffst[i][j] = bitstream_get(5);
audblk->deltlen[i][j] = bitstream_get(4);
audblk->deltba[i][j] = bitstream_get(3);
}
}
}
}
/* Check to see if there's any dummy info to get */
if((audblk->skiple = bitstream_get(1)))
{
uint_16 skip_data;
audblk->skipl = bitstream_get(9);
//XXX remove
//fprintf(stderr,"(parse) skipping %d bytes\n",audblk->skipl);
for(i = 0; i < audblk->skipl ; i++)
{
skip_data = bitstream_get(8);
//XXX remove
//fprintf(stderr,"skipped data %2x\n",skip_data);
//if(skip_data != 0)
//{
//dprintf("(parse) Invalid skipped data %2x\n",skip_data);
//exit(1);
//}
}
}
stats_print_audblk(bsi,audblk);
}
void
parse_auxdata(syncinfo_t *syncinfo)
{
//FIXME keep this now that we don't really need it?
#if 0
int i;
int skip_length;
uint_16 crc;
uint_16 auxdatae;
skip_length = (syncinfo->frame_size * 16) - bitstream_get_total_bits() - 17 - 1;
//XXX remove
//dprintf("(auxdata) skipping %d auxbits\n",skip_length);
for(i=0; i < skip_length; i++)
//printf("Skipped bit %i\n",(uint_16)bitstream_get(1));
bitstream_get(1);
//get the auxdata exists bit
auxdatae = bitstream_get(1);
//XXX remove
//dprintf("auxdatae = %i\n",auxdatae);
//Skip the CRC reserved bit
bitstream_get(1);
//Get the crc
crc = bitstream_get(16);
#endif
}

28
ac3dec/parse.h Normal file
View File

@ -0,0 +1,28 @@
/*
* parse.h
*
* Copyright (C) Aaron Holtzman - May 1999
*
* 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.
*
*/
void parse_syncinfo(syncinfo_t *syncinfo,uint_8 *data);
void parse_audblk(bsi_t *bsi,audblk_t *audblk);
void parse_bsi(bsi_t *bsi);
void parse_auxdata(syncinfo_t *syncinfo);

83
ac3dec/rematrix.c Normal file
View File

@ -0,0 +1,83 @@
/*
* rematrix.c
*
* Copyright (C) Aaron Holtzman - July 1999
*
* 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.
*
*
*/
#include <stdlib.h>
#include <stdio.h>
#include "ac3.h"
#include "ac3_internal.h"
#include "decode.h"
#include "rematrix.h"
struct rematrix_band_s
{
uint_32 start;
uint_32 end;
};
struct rematrix_band_s rematrix_band[] = { {13,24}, {25,36}, {37 ,60}, {61,252}};
static inline uint_32 min(uint_32 a,uint_32 b);
static inline uint_32
min(uint_32 a,uint_32 b)
{
return (a < b ? a : b);
}
/* This routine simply does stereo rematixing for the 2 channel
* stereo mode */
void rematrix(audblk_t *audblk, stream_samples_t samples)
{
uint_32 num_bands;
uint_32 start;
uint_32 end;
uint_32 i,j;
float left,right;
if(!audblk->cplinu || audblk->cplbegf > 2)
num_bands = 4;
else if (audblk->cplbegf > 0)
num_bands = 3;
else
num_bands = 2;
for(i=0;i < num_bands; i++)
{
if(!audblk->rematflg[i])
continue;
start = rematrix_band[i].start;
end = min(rematrix_band[i].end ,12 * audblk->cplbegf + 36);
for(j=start;j < end; j++)
{
left = samples[0][j] + samples[1][j];
right = samples[0][j] - samples[1][j];
samples[0][j] = left;
samples[1][j] = right;
}
}
}

25
ac3dec/rematrix.h Normal file
View File

@ -0,0 +1,25 @@
/*
* rematrix.h
*
* Copyright (C) Aaron Holtzman - July 1999
*
* 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.
*
*
*/
void rematrix(audblk_t *audblk, stream_samples_t samples);

131
ac3dec/sanity_check.c Normal file
View File

@ -0,0 +1,131 @@
/*
* sanity_check.c
*
* Copyright (C) Aaron Holtzman - May 1999
*
* 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.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include "ac3.h"
#include "ac3_internal.h"
#include "sanity_check.h"
void
sanity_check_init(syncinfo_t *syncinfo, bsi_t *bsi, audblk_t *audblk)
{
syncinfo->magic = AC3_MAGIC_NUMBER;
bsi->magic = AC3_MAGIC_NUMBER;
audblk->magic1 = AC3_MAGIC_NUMBER;
audblk->magic2 = AC3_MAGIC_NUMBER;
audblk->magic3 = AC3_MAGIC_NUMBER;
}
void
sanity_check(syncinfo_t *syncinfo, bsi_t *bsi, audblk_t *audblk)
{
int i;
if(syncinfo->magic != AC3_MAGIC_NUMBER)
{
fprintf(stderr,"\n** Sanity check failed -- syncinfo magic number **");
error_flag = 1;
}
if(bsi->magic != AC3_MAGIC_NUMBER)
{
fprintf(stderr,"\n** Sanity check failed -- bsi magic number **");
error_flag = 1;
}
if(audblk->magic1 != AC3_MAGIC_NUMBER)
{
fprintf(stderr,"\n** Sanity check failed -- audblk magic number 1 **");
error_flag = 1;
}
if(audblk->magic2 != AC3_MAGIC_NUMBER)
{
fprintf(stderr,"\n** Sanity check failed -- audblk magic number 2 **");
error_flag = 1;
}
if(audblk->magic3 != AC3_MAGIC_NUMBER)
{
fprintf(stderr,"\n** Sanity check failed -- audblk magic number 3 **");
error_flag = 1;
}
for(i = 0;i < 5 ; i++)
{
if (audblk->fbw_exp[i][255] !=0 || audblk->fbw_exp[i][254] !=0 ||
audblk->fbw_exp[i][253] !=0)
{
fprintf(stderr,"\n** Sanity check failed -- fbw_exp out of bounds **");
error_flag = 1;
}
if (audblk->fbw_bap[i][255] !=0 || audblk->fbw_bap[i][254] !=0 ||
audblk->fbw_bap[i][253] !=0)
{
fprintf(stderr,"\n** Sanity check failed -- fbw_bap out of bounds **");
error_flag = 1;
}
}
if (audblk->cpl_exp[255] !=0 || audblk->cpl_exp[254] !=0 ||
audblk->cpl_exp[253] !=0)
{
fprintf(stderr,"\n** Sanity check failed -- cpl_exp out of bounds **");
error_flag = 1;
}
if (audblk->cpl_bap[255] !=0 || audblk->cpl_bap[254] !=0 ||
audblk->cpl_bap[253] !=0)
{
fprintf(stderr,"\n** Sanity check failed -- cpl_bap out of bounds **");
error_flag = 1;
}
if (audblk->cplmant[255] !=0 || audblk->cplmant[254] !=0 ||
audblk->cplmant[253] !=0)
{
fprintf(stderr,"\n** Sanity check failed -- cpl_mant out of bounds **");
error_flag = 1;
}
if ((audblk->cplinu == 1) && (audblk->cplbegf > (audblk->cplendf+2)))
{
fprintf(stderr,"\n** Sanity check failed -- cpl params inconsistent **");
error_flag = 1;
}
for(i=0; i < bsi->nfchans; i++)
{
if((audblk->chincpl[i] == 0) && (audblk->chbwcod[i] > 60))
{
fprintf(stderr,"\n** Sanity check failed -- chbwcod too big **");
error_flag = 1;
}
}
return;
}

27
ac3dec/sanity_check.h Normal file
View File

@ -0,0 +1,27 @@
/*
* sanity_check.h
*
* Copyright (C) Aaron Holtzman - May 1999
*
* 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.
*
*/
#define AC3_MAGIC_NUMBER 0xdeadbeef
void sanity_check_init(syncinfo_t *syncinfo, bsi_t *bsi, audblk_t *audblk);
void sanity_check(syncinfo_t *syncinfo, bsi_t *bsi, audblk_t *audblk);

178
ac3dec/stats.c Normal file
View File

@ -0,0 +1,178 @@
/*
* stats.c
*
* Copyright (C) Aaron Holtzman - May 1999
*
* 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.
*
*/
#include <stdlib.h>
#include <stdio.h>
//#include "config.h"
#include "ac3.h"
#include "ac3_internal.h"
#include "decode.h"
#include "stats.h"
#include "debug.h"
static const char *service_ids[8] =
{
"CM","ME","VI","HI",
"D", "C","E", "VO"
};
struct mixlev_s
{
float clev;
char *desc;
};
static const struct mixlev_s cmixlev_tbl[4] =
{
{0.707, "(-3.0 dB)"}, {0.595, "(-4.5 dB)"},
{0.500, "(-6.0 dB)"}, {1.0, "Invalid"}
};
static const struct mixlev_s smixlev_tbl[4] =
{
{0.707, "(-3.0 dB)"}, {0.500, "(-6.0 dB)"},
{ 0.0, "off "}, { 1.0, "Invalid"}
};
static const char *language[128] =
{
"unknown", "Albanian", "Breton", "Catalan", "Croatian", "Welsh", "Czech", "Danish",
"German", "English", "Spanish", "Esperanto", "Estonian", "Basque", "Faroese", "French",
"Frisian", "Irish", "Gaelic", "Galician", "Icelandic", "Italian", "Lappish", "Latin",
"Latvian", "Luxembourgian", "Lithuanian", "Hungarian", "Maltese", "Dutch", "Norwegian", "Occitan",
"Polish", "Portugese", "Romanian", "Romansh", "Serbian", "Slovak", "Slovene", "Finnish",
"Swedish", "Turkish", "Flemish", "Walloon", "0x2c", "0x2d", "0x2e", "0x2f",
"0x30", "0x31", "0x32", "0x33", "0x34", "0x35", "0x36", "0x37",
"0x38", "0x39", "0x3a", "0x3b", "0x3c", "0x3d", "0x3e", "0x3f",
"background", "0x41", "0x42", "0x43", "0x44", "Zulu", "Vietnamese", "Uzbek",
"Urdu", "Ukrainian", "Thai", "Telugu", "Tatar", "Tamil", "Tadzhik", "Swahili",
"Sranan Tongo", "Somali", "Sinhalese", "Shona", "Serbo-Croat", "Ruthenian", "Russian", "Quechua",
"Pustu", "Punjabi", "Persian", "Papamiento", "Oriya", "Nepali", "Ndebele", "Marathi",
"Moldavian", "Malaysian", "Malagasay", "Macedonian", "Laotian", "Korean", "Khmer", "Kazakh",
"Kannada", "Japanese", "Indonesian", "Hindi", "Hebrew", "Hausa", "Gurani", "Gujurati",
"Greek", "Georgian", "Fulani", "Dari", "Churash", "Chinese", "Burmese", "Bulgarian",
"Bengali", "Belorussian", "Bambora", "Azerbijani", "Assamese", "Armenian", "Arabic", "Amharic"
};
void stats_print_banner(syncinfo_t *syncinfo,bsi_t *bsi)
{
fprintf(stdout,"ac3dec-0.6.2-cvs (C) 2000 Aaron Holtzman (aholtzma@ess.engr.uvic.ca)\n");
fprintf(stdout,"%d.%d Mode ",bsi->nfchans,bsi->lfeon);
fprintf(stdout,"%2.1f KHz",syncinfo->sampling_rate * 1e-3);
fprintf(stdout,"%4d kbps ",syncinfo->bit_rate);
if (bsi->langcode && (bsi->langcod < 128))
fprintf(stdout,"%s ", language[bsi->langcod]);
switch(bsi->bsmod)
{
case 0:
fprintf(stdout,"Complete Main Audio Service");
break;
case 1:
fprintf(stdout,"Music and Effects Audio Service");
case 2:
fprintf(stdout,"Visually Impaired Audio Service");
break;
case 3:
fprintf(stdout,"Hearing Impaired Audio Service");
break;
case 4:
fprintf(stdout,"Dialogue Audio Service");
break;
case 5:
fprintf(stdout,"Commentary Audio Service");
break;
case 6:
fprintf(stdout,"Emergency Audio Service");
break;
case 7:
fprintf(stdout,"Voice Over Audio Service");
break;
}
fprintf(stdout,"\n");
}
void stats_print_syncinfo(syncinfo_t *syncinfo)
{
dprintf("(syncinfo) ");
switch (syncinfo->fscod)
{
case 2:
dprintf("32 KHz ");
break;
case 1:
dprintf("44.1 KHz ");
break;
case 0:
dprintf("48 KHz ");
break;
default:
dprintf("Invalid sampling rate ");
break;
}
dprintf("%4d kbps %4d words per frame\n",syncinfo->bit_rate,
syncinfo->frame_size);
}
void stats_print_bsi(bsi_t *bsi)
{
dprintf("(bsi) ");
dprintf("%s",service_ids[bsi->bsmod]);
dprintf(" %d.%d Mode ",bsi->nfchans,bsi->lfeon);
if ((bsi->acmod & 0x1) && (bsi->acmod != 0x1))
dprintf(" Centre Mix Level %s ",cmixlev_tbl[bsi->cmixlev].desc);
if (bsi->acmod & 0x4)
dprintf(" Sur Mix Level %s ",smixlev_tbl[bsi->cmixlev].desc);
dprintf("\n");
}
char *exp_strat_tbl[4] = {"R ","D15 ","D25 ","D45 "};
void stats_print_audblk(bsi_t *bsi,audblk_t *audblk)
{
uint_32 i;
dprintf("(audblk) ");
dprintf("%s ",audblk->cplinu ? "cpl on " : "cpl off");
dprintf("%s ",audblk->baie? "bai " : " ");
dprintf("%s ",audblk->snroffste? "snroffst " : " ");
dprintf("%s ",audblk->deltbaie? "deltba " : " ");
dprintf("%s ",audblk->phsflginu? "phsflg " : " ");
dprintf("(%s %s %s %s %s) ",exp_strat_tbl[audblk->chexpstr[0]],
exp_strat_tbl[audblk->chexpstr[1]],exp_strat_tbl[audblk->chexpstr[2]],
exp_strat_tbl[audblk->chexpstr[3]],exp_strat_tbl[audblk->chexpstr[4]]);
dprintf("[");
for(i=0;i<bsi->nfchans;i++)
dprintf("%1d",audblk->blksw[i]);
dprintf("]");
dprintf("\n");
}

27
ac3dec/stats.h Normal file
View File

@ -0,0 +1,27 @@
/*
* stats.h
*
* Copyright (C) Aaron Holtzman - May 1999
*
* 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.
*
*/
void stats_print_syncinfo(syncinfo_t *syncinfo);
void stats_print_bsi(bsi_t *bsi);
void stats_print_audblk(bsi_t *bsi,audblk_t *audblk);
void stats_print_banner(syncinfo_t *syncinfo,bsi_t *bsi);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: config.h 1.55 2001/07/27 13:32:53 kls Exp $ * $Id: config.h 1.56 2001/08/02 15:11:10 kls Exp $
*/ */
#ifndef __CONFIG_H #ifndef __CONFIG_H
@ -19,7 +19,7 @@
#include "eit.h" #include "eit.h"
#include "tools.h" #include "tools.h"
#define VDRVERSION "0.85" #define VDRVERSION "0.86"
#define MaxBuffer 10000 #define MaxBuffer 10000

1169
dvbapi.c

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: dvbapi.h 1.42 2001/07/27 11:40:38 kls Exp $ * $Id: dvbapi.h 1.43 2001/08/02 14:50:48 kls Exp $
*/ */
#ifndef __DVBAPI_H #ifndef __DVBAPI_H
@ -26,7 +26,9 @@
#include <ost/audio.h> #include <ost/audio.h>
#include <ost/osd.h> #include <ost/osd.h>
#include <stdio.h> #include <stdio.h>
#include "dvbosd.h" #include "dvbosd.h"
#include "dvd.h"
#include "eit.h" #include "eit.h"
#include "thread.h" #include "thread.h"
@ -44,7 +46,9 @@ int HMSFToIndex(const char *HMSF);
class cChannel; class cChannel;
class cRecordBuffer; class cRecordBuffer;
class cPlayBuffer;
class cReplayBuffer; class cReplayBuffer;
class cDVDplayBuffer;
class cTransferBuffer; class cTransferBuffer;
class cCuttingBuffer; class cCuttingBuffer;
@ -60,6 +64,7 @@ public:
class cDvbApi { class cDvbApi {
friend class cRecordBuffer; friend class cRecordBuffer;
friend class cReplayBuffer; friend class cReplayBuffer;
friend class cDVDplayBuffer;
friend class cTransferBuffer; friend class cTransferBuffer;
private: private:
int videoDev; int videoDev;
@ -202,7 +207,7 @@ private:
private: private:
cRecordBuffer *recordBuffer; cRecordBuffer *recordBuffer;
cReplayBuffer *replayBuffer; cPlayBuffer *replayBuffer;
int ca; int ca;
int priority; int priority;
int Ca(void) { return ca; } int Ca(void) { return ca; }
@ -238,6 +243,8 @@ public:
// Starts replaying the given file. // Starts replaying the given file.
// If there is already a replay session active, it will be stopped // If there is already a replay session active, it will be stopped
// and the new file will be played back. // and the new file will be played back.
bool StartDVDplay(cDVD *dvd, int TitleID);//XXX dvd parameter necessary???
// Starts replaying the given TitleID on the DVD.
void StopReplay(void); void StopReplay(void);
// Stops the current replay session (if any). // Stops the current replay session (if any).
void Pause(void); void Pause(void);

128
dvd.c Normal file
View File

@ -0,0 +1,128 @@
/*
* dvd.c: Functions for handling DVDs
*
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* Initially written by Andreas Schultz <aschultz@warp10.net>
*
* $Id: dvd.c 1.1 2001/08/03 12:35:38 kls Exp $
*/
//XXX //#define DVDDEBUG 1
//XXX //#define DEBUG_BUFFER 1
#include <fcntl.h>
#include <linux/cdrom.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "dvd.h"
// --- cDVD ----------------------------------------------------------------------------
const char *cDVD::deviceName = "/dev/dvd";
cDVD *cDVD::dvdInstance = NULL;
cDVD *cDVD::getDVD(void)
{
if (!dvdInstance)
new cDVD;
return dvdInstance;
}
cDVD::cDVD(void)
{
dvd = NULL;
title = NULL;
vmg_file = NULL;
vts_file = NULL;
dvdInstance = this;
}
cDVD::~cDVD()
{
Close();
}
void cDVD::SetDeviceName(const char *DeviceName)
{
deviceName = strdup(DeviceName);
}
const char *cDVD::DeviceName(void)
{
return deviceName;
}
void cDVD::Open(void)
{
if (!dvd)
dvd = DVDOpen(deviceName);
}
void cDVD::Close(void)
{
#ifdef DVDDEBUG
dsyslog(LOG_INFO, "DVD: cDVD::Close(%p): vts: %p, vmg: %p, title: %p, dvd: %p", this, vts_file, vmg_file, title, dvd);
#endif
if (vts_file)
ifoClose(vts_file);
if (vmg_file)
ifoClose(vmg_file);
if (title)
DVDCloseFile(title);
if (dvd)
DVDClose(dvd);
vts_file = NULL;
vmg_file = NULL;
title = NULL;
dvd = NULL;
}
void cDVD::Eject(void)
{
int fd;
Close();
// ignore all errors try our best :-)
if ((fd = open(deviceName, O_RDONLY)) > 0) {
ioctl(fd, CDROMEJECT, 0);
close(fd);
}
}
ifo_handle_t *cDVD::openVMG(void)
{
if (!isValid())
return NULL;
if (!vmg_file)
vmg_file = ifoOpen(dvd, 0);
return vmg_file;
}
ifo_handle_t *cDVD::openVTS(int TitleSet)
{
if (!isValid())
return NULL;
if (vts_file && (titleset != TitleSet)) {
ifoClose(vts_file);
vts_file = NULL;
}
if (!vts_file) {
titleset = TitleSet;
vts_file = ifoOpen(dvd, TitleSet);
}
return vts_file;
}
dvd_file_t *cDVD::openTitle(int Title, dvd_read_domain_t domain)
{
if (!isValid())
return NULL;
if (title)
DVDCloseFile(title);
title = DVDOpenFile(dvd, Title, domain);
return title;
}

46
dvd.h Normal file
View File

@ -0,0 +1,46 @@
/*
* dvd.h: Functions for handling DVDs
*
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* Initially written by Andreas Schultz <aschultz@warp10.net>
*
* $Id: dvd.h 1.1 2001/08/03 12:35:42 kls Exp $
*/
#ifndef __DVD_H
#define __DVD_H
#include <dvdread/dvd_reader.h>
#include <dvdread/ifo_types.h>
#include <dvdread/ifo_read.h>
#include <dvdread/dvd_udf.h>
#include <dvdread/nav_read.h>
#include <dvdread/nav_print.h>
class cDVD {
private:
static cDVD *dvdInstance;
static const char *deviceName;
dvd_reader_t *dvd;
dvd_file_t *title;
ifo_handle_t *vmg_file;
ifo_handle_t *vts_file;
int titleset;
public:
cDVD(void);
~cDVD();
void Open(void);
void Close(void);
void Eject(void);
bool isValid(void) { return (dvd != NULL); }
ifo_handle_t *openVMG(void);
ifo_handle_t *openVTS(int TitleSet);
dvd_file_t *openTitle(int Title, dvd_read_domain_t domain);
static cDVD *getDVD(void);
static void SetDeviceName(const char *DeviceName);
static const char *DeviceName(void);
};
#endif //__DVD_H

22
i18n.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: i18n.c 1.26 2001/07/27 13:32:43 kls Exp $ * $Id: i18n.c 1.27 2001/08/02 14:40:16 kls Exp $
* *
* Slovenian translations provided by Miha Setina <mihasetina@softhome.net> * Slovenian translations provided by Miha Setina <mihasetina@softhome.net>
* Italian translations provided by Alberto Carraro <bertocar@tin.it> * Italian translations provided by Alberto Carraro <bertocar@tin.it>
@ -113,6 +113,15 @@ const tPhrase Phrases[] = {
"Enregistrements", "Enregistrements",
"Opptak", "Opptak",
}, },
{ "DVD",
"DVD",
"DVD",
"DVD",
"DVD",
"DVD",
"DVD",
"DVD",
},
{ "Setup", { "Setup",
"Einstellungen", "Einstellungen",
"Nastavitve", "Nastavitve",
@ -194,7 +203,7 @@ const tPhrase Phrases[] = {
"Prochains programmes", "Prochains programmes",
"Hvilket program er neste?", "Hvilket program er neste?",
}, },
// Button texts (must not be more than 10 characters!): // Button texts (should not be more than 10 characters!):
{ "Edit", { "Edit",
"Editieren", "Editieren",
"Uredi", "Uredi",
@ -321,6 +330,15 @@ const tPhrase Phrases[] = {
"Langue", "Langue",
"Språk", "Språk",
}, },
{ "Eject DVD",
"DVD auswerfen",
"", // TODO
"", // TODO
"", // TODO
"", // TODO
"", // TODO
"", // TODO
},
// Confirmations: // Confirmations:
{ "Delete channel?", { "Delete channel?",
"Kanal löschen?", "Kanal löschen?",

166
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: menu.c 1.89 2001/07/31 15:28:10 kls Exp $ * $Id: menu.c 1.90 2001/08/03 14:18:08 kls Exp $
*/ */
#include "menu.h" #include "menu.h"
@ -1590,6 +1590,78 @@ eOSState cMenuRecordings::ProcessKey(eKeys Key)
return state; return state;
} }
// --- cMenuDVDItem ----------------------------------------------------------
class cMenuDVDItem : public cOsdItem {
private:
int title;
int chapters;
virtual void Set(void);
public:
cMenuDVDItem(int Title, int Chapters);
int Title(void) { return title; }
};
cMenuDVDItem::cMenuDVDItem(int Title, int Chapters)
{
title = Title;
chapters = Chapters;
Set();
}
void cMenuDVDItem::Set(void)
{
char *buffer = NULL;
asprintf(&buffer, " %2d.\tTitle - \t%2d\tChapters", title + 1, chapters);
SetText(buffer, false);
}
// --- cMenuDVD --------------------------------------------------------------
cMenuDVD::cMenuDVD(void)
:cOsdMenu(tr("DVD"), 5, 8, 3)
{
if ((dvd = cDVD::getDVD())) {
dvd->Open();
ifo_handle_t *vmg = dvd->openVMG();
if (vmg) {
dsyslog(LOG_INFO, "DVD: vmg: %p", vmg);//XXX
tt_srpt_t *tt_srpt = vmg->tt_srpt;
dsyslog(LOG_INFO, "DVD: tt_srpt: %p", tt_srpt);//XXX
for (int i = 0; i < tt_srpt->nr_of_srpts; i++)
Add(new cMenuDVDItem(i, tt_srpt->title[i].nr_of_ptts));
}
}
SetHelp(tr("Play"), NULL, NULL, NULL);
Display();
}
eOSState cMenuDVD::Play(void)
{
cMenuDVDItem *ri = (cMenuDVDItem *)Get(Current());
if (ri) {
cReplayControl::SetDVD(dvd, ri->Title());
isyslog(LOG_INFO, "DVD: playing title %d", ri->Title());
return osReplay;
}
return osContinue;
}
eOSState cMenuDVD::ProcessKey(eKeys Key)
{
eOSState state = cOsdMenu::ProcessKey(Key);
if (state == osUnknown) {
switch (Key) {
case kOk:
case kRed: return Play();
case kMenu: return osEnd;
default: break;
}
}
return state;
}
// --- cMenuSetup ------------------------------------------------------------ // --- cMenuSetup ------------------------------------------------------------
class cMenuSetup : public cOsdMenu { class cMenuSetup : public cOsdMenu {
@ -1714,40 +1786,46 @@ eOSState cMenuCommands::ProcessKey(eKeys Key)
#define STOP_RECORDING tr(" Stop recording ") #define STOP_RECORDING tr(" Stop recording ")
static const char *hk(int n, const char *s)
{
static char buffer[32];
snprintf(buffer, sizeof(buffer), " %d %s", n, s);
return buffer;
}
cMenuMain::cMenuMain(bool Replaying) cMenuMain::cMenuMain(bool Replaying)
:cOsdMenu(tr("Main")) :cOsdMenu(tr("Main"))
{ {
Add(new cOsdItem(hk(1, tr("Schedule")), osSchedule)); digit = 0;
Add(new cOsdItem(hk(2, tr("Channels")), osChannels)); Add(new cOsdItem(hk(tr("Schedule")), osSchedule));
Add(new cOsdItem(hk(3, tr("Timers")), osTimers)); Add(new cOsdItem(hk(tr("Channels")), osChannels));
Add(new cOsdItem(hk(4, tr("Recordings")), osRecordings)); Add(new cOsdItem(hk(tr("Timers")), osTimers));
Add(new cOsdItem(hk(5, tr("Setup")), osSetup)); Add(new cOsdItem(hk(tr("Recordings")), osRecordings));
Add(new cOsdItem(hk(tr("DVD")), osDVD));
Add(new cOsdItem(hk(tr("Setup")), osSetup));
if (Commands.Count()) if (Commands.Count())
Add(new cOsdItem(hk(6, tr("Commands")), osCommands)); Add(new cOsdItem(hk(tr("Commands")), osCommands));
if (Replaying) if (Replaying)
Add(new cOsdItem(tr(" Stop replaying"), osStopReplay)); Add(new cOsdItem(hk(tr(" Stop replaying")), osStopReplay));
const char *s = NULL; const char *s = NULL;
while ((s = cRecordControls::GetInstantId(s)) != NULL) { while ((s = cRecordControls::GetInstantId(s)) != NULL) {
char *buffer = NULL; char *buffer = NULL;
asprintf(&buffer, "%s%s", STOP_RECORDING, s); asprintf(&buffer, "%s%s", STOP_RECORDING, s);
Add(new cOsdItem(buffer, osStopRecord)); Add(new cOsdItem(hk(buffer), osStopRecord));
delete buffer; delete buffer;
} }
if (cVideoCutter::Active()) if (cVideoCutter::Active())
Add(new cOsdItem(tr(" Cancel editing"), osCancelEdit)); Add(new cOsdItem(hk(tr(" Cancel editing")), osCancelEdit));
SetHelp(tr("Record"), cDvbApi::PrimaryDvbApi->CanToggleAudioTrack() ? tr("Language") : NULL, NULL, cReplayControl::LastReplayed() ? tr("Resume") : NULL); SetHelp(tr("Record"), cDvbApi::PrimaryDvbApi->CanToggleAudioTrack() ? tr("Language") : NULL, /*XXX only if DVD loaded?*/tr("Eject DVD"), cReplayControl::LastReplayed() ? tr("Resume") : NULL);
Display(); Display();
lastActivity = time(NULL); lastActivity = time(NULL);
SetHasHotkeys(); SetHasHotkeys();
} }
const char *cMenuMain::hk(const char *s)
{
static char buffer[32];
if (digit < 9) {
snprintf(buffer, sizeof(buffer), " %d %s", ++digit, s);
return buffer;
}
else
return s;
}
eOSState cMenuMain::ProcessKey(eKeys Key) eOSState cMenuMain::ProcessKey(eKeys Key)
{ {
eOSState state = cOsdMenu::ProcessKey(Key); eOSState state = cOsdMenu::ProcessKey(Key);
@ -1757,6 +1835,7 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
case osChannels: return AddSubMenu(new cMenuChannels); case osChannels: return AddSubMenu(new cMenuChannels);
case osTimers: return AddSubMenu(new cMenuTimers); case osTimers: return AddSubMenu(new cMenuTimers);
case osRecordings: return AddSubMenu(new cMenuRecordings); case osRecordings: return AddSubMenu(new cMenuRecordings);
case osDVD: return AddSubMenu(new cMenuDVD);
case osSetup: return AddSubMenu(new cMenuSetup); case osSetup: return AddSubMenu(new cMenuSetup);
case osCommands: return AddSubMenu(new cMenuCommands); case osCommands: return AddSubMenu(new cMenuCommands);
case osStopRecord: if (Interface->Confirm(tr("Stop recording?"))) { case osStopRecord: if (Interface->Confirm(tr("Stop recording?"))) {
@ -1773,22 +1852,30 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
} }
break; break;
default: switch (Key) { default: switch (Key) {
case kMenu: state = osEnd; break; case kMenu: state = osEnd; break;
case kRed: if (!HasSubMenu()) case kRed: if (!HasSubMenu())
state = osRecord; state = osRecord;
break; break;
case kGreen: if (!HasSubMenu()) { case kGreen: if (!HasSubMenu()) {
if (cDvbApi::PrimaryDvbApi->CanToggleAudioTrack()) { if (cDvbApi::PrimaryDvbApi->CanToggleAudioTrack()) {
Interface->Clear(); Interface->Clear();
cDvbApi::PrimaryDvbApi->ToggleAudioTrack(); cDvbApi::PrimaryDvbApi->ToggleAudioTrack();
state = osEnd; state = osEnd;
} }
} }
break; break;
case kBlue: if (!HasSubMenu()) case kYellow: if (!HasSubMenu()) {
state = osReplay; cDVD *dvd;
break; if ((dvd = cDVD::getDVD())) {
default: break; dvd->Eject();
state = osEnd;
}
}
break;
case kBlue: if (!HasSubMenu())
state = osReplay;
break;
default: break;
} }
} }
if (Key != kNone) if (Key != kNone)
@ -2144,6 +2231,8 @@ void cProgressBar::Mark(int x, bool Start, bool Current)
char *cReplayControl::fileName = NULL; char *cReplayControl::fileName = NULL;
char *cReplayControl::title = NULL; char *cReplayControl::title = NULL;
cDVD *cReplayControl::dvd = NULL;//XXX
int cReplayControl::titleid = 0;//XXX
cReplayControl::cReplayControl(void) cReplayControl::cReplayControl(void)
{ {
@ -2155,6 +2244,8 @@ cReplayControl::cReplayControl(void)
marks.Load(fileName); marks.Load(fileName);
dvbApi->StartReplay(fileName); dvbApi->StartReplay(fileName);
} }
else if (dvd)
dvbApi->StartDVDplay(dvd, titleid);//XXX
} }
cReplayControl::~cReplayControl() cReplayControl::~cReplayControl()
@ -2171,6 +2262,13 @@ void cReplayControl::SetRecording(const char *FileName, const char *Title)
title = Title ? strdup(Title) : NULL; title = Title ? strdup(Title) : NULL;
} }
void cReplayControl::SetDVD(cDVD *DVD, int Title)//XXX
{
SetRecording(NULL, NULL);
dvd = DVD;
titleid = Title;
}
const char *cReplayControl::LastReplayed(void) const char *cReplayControl::LastReplayed(void)
{ {
return fileName; return fileName;

17
menu.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: menu.h 1.20 2001/07/28 13:59:29 kls Exp $ * $Id: menu.h 1.21 2001/08/02 14:53:29 kls Exp $
*/ */
#ifndef _MENU_H #ifndef _MENU_H
@ -19,6 +19,8 @@
class cMenuMain : public cOsdMenu { class cMenuMain : public cOsdMenu {
private: private:
time_t lastActivity; time_t lastActivity;
int digit;
const char *hk(const char *s);
public: public:
cMenuMain(bool Replaying); cMenuMain(bool Replaying);
virtual eOSState ProcessKey(eKeys Key); virtual eOSState ProcessKey(eKeys Key);
@ -39,6 +41,16 @@ public:
virtual eOSState ProcessKey(eKeys Key); virtual eOSState ProcessKey(eKeys Key);
}; };
class cMenuDVD : public cOsdMenu {
private:
cDVD *dvd;//XXX member really necessary???
eOSState Play(void);
eOSState Eject(void);
public:
cMenuDVD(void);
virtual eOSState ProcessKey(eKeys Key);
};
class cMenuRecordings : public cOsdMenu { class cMenuRecordings : public cOsdMenu {
private: private:
cRecordings Recordings; cRecordings Recordings;
@ -88,6 +100,8 @@ private:
void Show(int Seconds = 0); void Show(int Seconds = 0);
void Hide(void); void Hide(void);
static char *fileName; static char *fileName;
static cDVD *dvd;//XXX member really necessary???
static int titleid;//XXX
static char *title; static char *title;
bool ShowProgress(bool Initial); bool ShowProgress(bool Initial);
void MarkToggle(void); void MarkToggle(void);
@ -101,6 +115,7 @@ public:
virtual eOSState ProcessKey(eKeys Key); virtual eOSState ProcessKey(eKeys Key);
bool Visible(void) { return visible; } bool Visible(void) { return visible; }
static void SetRecording(const char *FileName, const char *Title); static void SetRecording(const char *FileName, const char *Title);
static void SetDVD(cDVD *DVD, int Title);//XXX
static const char *LastReplayed(void); static const char *LastReplayed(void);
static void ClearLastReplayed(const char *FileName); static void ClearLastReplayed(const char *FileName);
}; };

3
osd.c
View File

@ -4,11 +4,10 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: osd.c 1.16 2001/02/24 16:26:11 kls Exp $ * $Id: osd.c 1.17 2001/08/02 14:18:17 kls Exp $
*/ */
#include "osd.h" #include "osd.h"
#include <assert.h>
#include <string.h> #include <string.h>
#include "i18n.h" #include "i18n.h"

7
osd.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: osd.h 1.22 2001/07/27 11:33:30 kls Exp $ * $Id: osd.h 1.23 2001/08/02 13:48:34 kls Exp $
*/ */
#ifndef __OSD_H #ifndef __OSD_H
@ -27,6 +27,7 @@ enum eOSState { osUnknown,
osCommands, osCommands,
osRecord, osRecord,
osReplay, osReplay,
osDVD,
osStopRecord, osStopRecord,
osStopReplay, osStopReplay,
osCancelEdit, osCancelEdit,
@ -55,7 +56,7 @@ public:
virtual void Display(int Offset = -1, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground); virtual void Display(int Offset = -1, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground);
virtual void Set(void) {} virtual void Set(void) {}
virtual eOSState ProcessKey(eKeys Key); virtual eOSState ProcessKey(eKeys Key);
}; };
class cOsdBase { class cOsdBase {
protected: protected:
@ -67,7 +68,7 @@ public:
int Height(void) { return Interface->Height(); } int Height(void) { return Interface->Height(); }
bool NeedsFastResponse(void) { return needsFastResponse; } bool NeedsFastResponse(void) { return needsFastResponse; }
virtual eOSState ProcessKey(eKeys Key) = 0; virtual eOSState ProcessKey(eKeys Key) = 0;
}; };
class cOsdMenu : public cOsdBase, public cList<cOsdItem> { class cOsdMenu : public cOsdBase, public cList<cOsdItem> {
private: private:

View File

@ -7,7 +7,7 @@
* Parts of this file were inspired by the 'ringbuffy.c' from the * Parts of this file were inspired by the 'ringbuffy.c' from the
* LinuxDVB driver (see linuxtv.org). * LinuxDVB driver (see linuxtv.org).
* *
* $Id: ringbuffer.c 1.2 2001/05/20 11:58:08 kls Exp $ * $Id: ringbuffer.c 1.3 2001/08/02 13:48:38 kls Exp $
*/ */
#include "ringbuffer.h" #include "ringbuffer.h"
@ -69,9 +69,8 @@ int cRingBuffer::Available(void)
{ {
mutex.Lock(); mutex.Lock();
int diff = head - tail; int diff = head - tail;
int cont = (diff >= 0) ? diff : size + diff;
mutex.Unlock(); mutex.Unlock();
return cont; return (diff >= 0) ? diff : size + diff;
} }
void cRingBuffer::Clear(void) void cRingBuffer::Clear(void)

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: ringbuffer.h 1.2 2001/05/20 11:56:44 kls Exp $ * $Id: ringbuffer.h 1.3 2001/08/02 13:48:42 kls Exp $
*/ */
#ifndef __RINGBUFFER_H #ifndef __RINGBUFFER_H
@ -33,6 +33,7 @@ protected:
void Lock(void) { mutex.Lock(); } void Lock(void) { mutex.Lock(); }
void Unlock(void) { mutex.Unlock(); } void Unlock(void) { mutex.Unlock(); }
int Available(void); int Available(void);
int Free(void) { return size - Available() - 1; }
bool Busy(void) { return busy; } bool Busy(void) { return busy; }
void Clear(void); void Clear(void);
// Immediately clears the ring buffer. // Immediately clears the ring buffer.

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: thread.c 1.9 2001/06/27 11:34:41 kls Exp $ * $Id: thread.c 1.10 2001/08/02 13:48:45 kls Exp $
*/ */
#include "thread.h" #include "thread.h"
@ -14,6 +14,40 @@
#include <unistd.h> #include <unistd.h>
#include "tools.h" #include "tools.h"
// --- cCondVar --------------------------------------------------------------
cCondVar::cCondVar(void)
{
pthread_cond_init(&cond, 0);
}
cCondVar::~cCondVar()
{
pthread_cond_destroy(&cond);
}
bool cCondVar::Wait(cMutex &_mutex)
{
return pthread_cond_wait(&cond, &_mutex.mutex);
}
/*
bool cCondVar::TimedWait(cMutex &_mutex, unsigned long tmout)
{
return pthread_cond_timedwait(&cond, &_mutex.mutex, tmout);
}
*/
void cCondVar::Broadcast(void)
{
pthread_cond_broadcast(&cond);
}
void cCondVar::Signal(void)
{
pthread_cond_signal(&cond);
}
// --- cMutex ---------------------------------------------------------------- // --- cMutex ----------------------------------------------------------------
cMutex::cMutex(void) cMutex::cMutex(void)
@ -85,6 +119,7 @@ bool cThread::Start(void)
running = true; running = true;
parentPid = getpid(); parentPid = getpid();
pthread_create(&thread, NULL, (void *(*) (void *))&StartThread, (void *)this); pthread_create(&thread, NULL, (void *(*) (void *))&StartThread, (void *)this);
pthread_setschedparam(thread, SCHED_RR, 0);
usleep(10000); // otherwise calling Active() immediately after Start() causes a "pure virtual method called" error usleep(10000); // otherwise calling Active() immediately after Start() causes a "pure virtual method called" error
} }
return true; //XXX return value of pthread_create()??? return true; //XXX return value of pthread_create()???

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: thread.h 1.6 2001/06/27 11:22:04 kls Exp $ * $Id: thread.h 1.7 2001/08/02 13:48:48 kls Exp $
*/ */
#ifndef __THREAD_H #ifndef __THREAD_H
@ -13,7 +13,22 @@
#include <pthread.h> #include <pthread.h>
#include <sys/types.h> #include <sys/types.h>
class cMutex;
class cCondVar {
private:
pthread_cond_t cond;
public:
cCondVar(void);
~cCondVar();
bool Wait(cMutex &_mutex);
//bool TimedWait(cMutex &_mutex, unsigned long tmout);
void Broadcast(void);
void Signal(void);
};
class cMutex { class cMutex {
friend class cCondVar;
private: private:
pthread_mutex_t mutex; pthread_mutex_t mutex;
pid_t lockingPid; pid_t lockingPid;

14
vdr.c
View File

@ -22,7 +22,7 @@
* *
* The project's page is at http://www.cadsoft.de/people/kls/vdr * The project's page is at http://www.cadsoft.de/people/kls/vdr
* *
* $Id: vdr.c 1.58 2001/06/23 12:29:41 kls Exp $ * $Id: vdr.c 1.59 2001/08/02 13:48:51 kls Exp $
*/ */
#include <getopt.h> #include <getopt.h>
@ -31,6 +31,7 @@
#include <unistd.h> #include <unistd.h>
#include "config.h" #include "config.h"
#include "dvbapi.h" #include "dvbapi.h"
#include "dvd.h"
#include "i18n.h" #include "i18n.h"
#include "interface.h" #include "interface.h"
#include "menu.h" #include "menu.h"
@ -85,6 +86,7 @@ int main(int argc, char *argv[])
{ "log", required_argument, NULL, 'l' }, { "log", required_argument, NULL, 'l' },
{ "port", required_argument, NULL, 'p' }, { "port", required_argument, NULL, 'p' },
{ "video", required_argument, NULL, 'v' }, { "video", required_argument, NULL, 'v' },
{ "dvd", required_argument, NULL, 'V' },
{ "watchdog", required_argument, NULL, 'w' }, { "watchdog", required_argument, NULL, 'w' },
{ "terminal", required_argument, NULL, 't' }, { "terminal", required_argument, NULL, 't' },
{ 0 } { 0 }
@ -92,7 +94,7 @@ int main(int argc, char *argv[])
int c; int c;
int option_index = 0; int option_index = 0;
while ((c = getopt_long(argc, argv, "a:c:dD:hl:p:v:w:t:", long_options, &option_index)) != -1) { while ((c = getopt_long(argc, argv, "a:c:dD:hl:p:v:V:w:t:", long_options, &option_index)) != -1) {
switch (c) { switch (c) {
case 'a': cDvbApi::SetAudioCommand(optarg); case 'a': cDvbApi::SetAudioCommand(optarg);
break; break;
@ -124,6 +126,7 @@ int main(int argc, char *argv[])
" -p PORT, --port=PORT use PORT for SVDRP (default: %d)\n" " -p PORT, --port=PORT use PORT for SVDRP (default: %d)\n"
" 0 turns off SVDRP\n" " 0 turns off SVDRP\n"
" -v DIR, --video=DIR use DIR as video directory (default: %s)\n" " -v DIR, --video=DIR use DIR as video directory (default: %s)\n"
" -V DEV, --dvd=DEV use DEV as the DVD device (default: %s)\n"
" -w SEC, --watchdog=SEC activate the watchdog timer with a timeout of SEC\n" " -w SEC, --watchdog=SEC activate the watchdog timer with a timeout of SEC\n"
" seconds (default: %d); '0' disables the watchdog\n" " seconds (default: %d); '0' disables the watchdog\n"
" -t TTY, --terminal=TTY controlling tty\n" " -t TTY, --terminal=TTY controlling tty\n"
@ -131,6 +134,7 @@ int main(int argc, char *argv[])
"Report bugs to <vdr-bugs@cadsoft.de>\n", "Report bugs to <vdr-bugs@cadsoft.de>\n",
DEFAULTSVDRPPORT, DEFAULTSVDRPPORT,
VideoDirectory, VideoDirectory,
cDVD::DeviceName(),
DEFAULTWATCHDOG DEFAULTWATCHDOG
); );
return 0; return 0;
@ -158,6 +162,8 @@ int main(int argc, char *argv[])
while (optarg && *optarg && optarg[strlen(optarg) - 1] == '/') while (optarg && *optarg && optarg[strlen(optarg) - 1] == '/')
optarg[strlen(optarg) - 1] = 0; optarg[strlen(optarg) - 1] = 0;
break; break;
case 'V': cDVD::SetDeviceName(optarg);
break;
case 'w': if (isnumber(optarg)) { case 'w': if (isnumber(optarg)) {
int t = atoi(optarg); int t = atoi(optarg);
if (t >= 0) { if (t >= 0) {
@ -324,6 +330,10 @@ int main(int argc, char *argv[])
DELETENULL(ReplayControl); DELETENULL(ReplayControl);
ReplayControl = new cReplayControl; ReplayControl = new cReplayControl;
break; break;
case osDVD: DELETENULL(Menu);
DELETENULL(ReplayControl);
Menu = new cMenuDVD;
break;
case osStopReplay: case osStopReplay:
DELETENULL(*Interact); DELETENULL(*Interact);
DELETENULL(ReplayControl); DELETENULL(ReplayControl);