diff --git a/Makefile b/Makefile index 307efd1e4091a63d16fcc9758436512475819a07..bf4cb478639596825a2e43e68be5c7f1741ae532 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,7 @@ PLUGINS_DIR := ac3_adec \ idct \ imdct \ kde \ - liba52_adec \ + a52 \ lirc \ lpcm_adec \ macosx \ @@ -95,7 +95,7 @@ PLUGINS_TARGETS := ac3_adec/ac3_adec \ imdct/imdct3dn \ imdct/imdctsse \ kde/kde \ - liba52_adec/liba52_adec \ + a52/a52 \ lirc/lirc \ lpcm_adec/lpcm_adec \ macosx/macosx \ diff --git a/Makefile.opts.in b/Makefile.opts.in index 2285c5c1d68c00d7278d6c2d8cc506afb7da1a18..8606424850bb3f72a39dba18a2f2333bb2cc2e3f 100644 --- a/Makefile.opts.in +++ b/Makefile.opts.in @@ -84,7 +84,7 @@ LIB_IMDCT = @LIB_IMDCT@ LIB_IMDCT3DN = @LIB_IMDCT3DN@ LIB_IMDCTSSE = @LIB_IMDCTSSE@ LIB_KDE = @LIB_KDE@ -LIB_LIBA52_ADEC = @LIB_LIBA52_ADEC@ +LIB_A52 = @LIB_A52@ LIB_LIBDVDCSS = @LIB_LIBDVDCSS@ LIB_LIBDVDREAD = @LIB_LIBDVDREAD@ LIB_LIRC = @LIB_LIRC@ diff --git a/configure b/configure index 01a1f7483139a001d9f8155252b142d53e17a2ff..dd90ab180f79fcb69ce3aa52fff27c9252cd1730 100755 --- a/configure +++ b/configure @@ -67,7 +67,7 @@ ac_help="$ac_help ac_help="$ac_help --disable-qnx QNX RTOS support (default enabled on QNX RTOS)" ac_help="$ac_help - --disable-liba52 AC3 support with liba52 (default enabled)" + --disable-a52 AC3 support with liba52 (default enabled)" ac_help="$ac_help --enable-fb Linux framebuffer support (default disabled)" ac_help="$ac_help @@ -6925,9 +6925,9 @@ done fi -# Check whether --enable-liba52 or --disable-liba52 was given. -if test "${enable_liba52+set}" = set; then - enableval="$enable_liba52" +# Check whether --enable-a52 or --disable-a52 was given. +if test "${enable_a52+set}" = set; then + enableval="$enable_a52" : fi @@ -6968,8 +6968,8 @@ if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then #define $ac_tr_hdr 1 EOF - BUILTINS="${BUILTINS} liba52_adec" - LIB_LIBA52_ADEC="${LIB_LIBA52_ADEC} -la52" + BUILTINS="${BUILTINS} a52" + LIB_A52="${LIB_A52} -la52" else echo "$ac_t""no" 1>&6 @@ -8316,7 +8316,7 @@ s%@LIB_IMDCT@%$LIB_IMDCT%g s%@LIB_IMDCT3DN@%$LIB_IMDCT3DN%g s%@LIB_IMDCTSSE@%$LIB_IMDCTSSE%g s%@LIB_KDE@%$LIB_KDE%g -s%@LIB_LIBA52_ADEC@%$LIB_LIBA52_ADEC%g +s%@LIB_A52@%$LIB_A52%g s%@LIB_LIBDVDCSS@%$LIB_LIBDVDCSS%g s%@LIB_LIBDVDREAD@%$LIB_LIBDVDREAD%g s%@LIB_LIRC@%$LIB_LIRC%g diff --git a/configure.in b/configure.in index 9e25b8779d2a2d43dab9933306927d113e90a55e..846e11cd16a4edb73cc85d9e49e9e0f627cbfd78 100644 --- a/configure.in +++ b/configure.in @@ -1061,15 +1061,15 @@ AC_ARG_ENABLE(qnx, fi dnl -dnl Liba52 AC3 decoder plugin +dnl a52 AC3 decoder plugin dnl -AC_ARG_ENABLE(liba52, - [ --disable-liba52 AC3 support with liba52 (default enabled)]) +AC_ARG_ENABLE(a52, + [ --disable-a52 AC3 support with liba52 (default enabled)]) if ((test "x$enableval" != "xno") && (test x$SYS != xmingw32)) then AC_CHECK_HEADERS(a52dec/a52.h, [ - BUILTINS="${BUILTINS} liba52_adec" - LIB_LIBA52_ADEC="${LIB_LIBA52_ADEC} -la52" + BUILTINS="${BUILTINS} a52" + LIB_A52="${LIB_A52} -la52" ],[]) fi @@ -1526,7 +1526,7 @@ AC_SUBST(LIB_IMDCT) AC_SUBST(LIB_IMDCT3DN) AC_SUBST(LIB_IMDCTSSE) AC_SUBST(LIB_KDE) -AC_SUBST(LIB_LIBA52_ADEC) +AC_SUBST(LIB_A52) AC_SUBST(LIB_LIBDVDCSS) AC_SUBST(LIB_LIBDVDREAD) AC_SUBST(LIB_LIRC) diff --git a/debian/rules b/debian/rules index 07ba1fe49fa6b07c6e8e68114b02ce8187d19e06..ccd57f7a61beeb7d2b01c32865858c2ec835b5b2 100755 --- a/debian/rules +++ b/debian/rules @@ -9,7 +9,7 @@ export DH_COMPAT=3 # Compilation options -export CONFIG_FLAGS="--enable-release --prefix=/usr --enable-gnome --enable-gtk --enable-fb --with-ggi --enable-sdl --enable-esd --enable-qt --with-mad --enable-arts --enable-alsa --enable-lirc --enable-liba52" +export CONFIG_FLAGS="--enable-release --prefix=/usr --enable-gnome --enable-gtk --enable-fb --with-ggi --enable-sdl --enable-esd --enable-qt --with-mad --enable-arts --enable-alsa --enable-lirc --enable-a52" export LIBDVDCSS_FLAGS="--with-dvdcss=local-shared" export VIDDIR="usr/share/videolan" export PIXDIR="usr/share/pixmaps" diff --git a/plugins/a52/.cvsignore b/plugins/a52/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..435f39ed89bdf3cf66192588af795ed084062909 --- /dev/null +++ b/plugins/a52/.cvsignore @@ -0,0 +1,4 @@ +.dep +*.lo +*.o.* +*.lo.* diff --git a/plugins/a52/Makefile b/plugins/a52/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..ba23988e5069f4e98ea9ed5341bca896513d8ead --- /dev/null +++ b/plugins/a52/Makefile @@ -0,0 +1 @@ +a52_SOURCES = a52.c diff --git a/plugins/a52/a52.c b/plugins/a52/a52.c new file mode 100644 index 0000000000000000000000000000000000000000..2a544cc845962540e40acee0b95736fc4980e1fa --- /dev/null +++ b/plugins/a52/a52.c @@ -0,0 +1,349 @@ +/***************************************************************************** + * a52.c: ATSC A/52 aka AC-3 decoder plugin for vlc. + * This plugin makes use of liba52 to decode A/52 audio + * (http://liba52.sf.net/). + ***************************************************************************** + * Copyright (C) 2001 VideoLAN + * $Id: a52.c,v 1.1 2002/02/06 20:44:22 gbazin Exp $ + * + * Authors: Gildas Bazin <gbazin@netcourrier.com> + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ +#include <stdlib.h> /* malloc(), free() */ +#include <string.h> /* strdup() */ + +#include <videolan/vlc.h> + +#include "audio_output.h" + +#include "stream_control.h" +#include "input_ext-dec.h" + +#include "debug.h" + +#include <a52dec/a52.h> /* liba52 header file */ +#include "a52.h" + +#define AC3DEC_FRAME_SIZE 1536 + +/***************************************************************************** + * Local prototypes + *****************************************************************************/ +static int decoder_Probe ( probedata_t * ); +static int decoder_Run ( decoder_config_t * ); +static int DecodeFrame ( a52_adec_thread_t * ); +static int InitThread ( a52_adec_thread_t * ); +static void EndThread ( a52_adec_thread_t * ); + +static void BitstreamCallback ( bit_stream_t *, boolean_t ); +static void float2s16_2 ( float *, int16_t * ); +static __inline__ int16_t convert ( int32_t ); + +/***************************************************************************** + * Capabilities + *****************************************************************************/ +void _M( adec_getfunctions )( function_list_t * p_function_list ) +{ + p_function_list->pf_probe = decoder_Probe; + p_function_list->functions.dec.pf_run = decoder_Run; +} + +/***************************************************************************** + * Build configuration tree. + *****************************************************************************/ +MODULE_CONFIG_START +MODULE_CONFIG_STOP + +MODULE_INIT_START + SET_DESCRIPTION( "a52 ATSC A/52 aka AC-3 audio decoder plugin" ) + ADD_CAPABILITY( DECODER, 40 ) + ADD_SHORTCUT( "a52" ) +MODULE_INIT_STOP + +MODULE_ACTIVATE_START + _M( adec_getfunctions )( &p_module->p_functions->dec ); +MODULE_ACTIVATE_STOP + +MODULE_DEACTIVATE_START +MODULE_DEACTIVATE_STOP + +/***************************************************************************** + * decoder_Probe: probe the decoder and return score + ***************************************************************************** + * Tries to launch a decoder and return score so that the interface is able + * to choose. + *****************************************************************************/ +static int decoder_Probe( probedata_t *p_data ) +{ + return ( p_data->i_type == AC3_AUDIO_ES ); +} + +/***************************************************************************** + * decoder_Run: this function is called just after the thread is created + *****************************************************************************/ +static int decoder_Run ( decoder_config_t *p_config ) +{ + a52_adec_thread_t *p_a52_adec; + + /* Allocate the memory needed to store the thread's structure */ + p_a52_adec = + (a52_adec_thread_t *)malloc( sizeof(a52_adec_thread_t) ); + if (p_a52_adec == NULL) + { + intf_ErrMsg ( "a52 error: not enough memory " + "for decoder_Run() to allocate p_a52_adec" ); + DecoderError( p_config->p_decoder_fifo ); + return( -1 ); + } + + /* FIXME */ + p_a52_adec->i_channels = 2; + + /* + * Initialize the thread properties + */ + p_a52_adec->p_config = p_config; + p_a52_adec->p_fifo = p_a52_adec->p_config->p_decoder_fifo; + if( InitThread( p_a52_adec ) ) + { + intf_ErrMsg( "a52 error: could not initialize thread" ); + DecoderError( p_config->p_decoder_fifo ); + free( p_a52_adec ); + return( -1 ); + } + + /* liba52 decoder thread's main loop */ + while( !p_a52_adec->p_fifo->b_die && !p_a52_adec->p_fifo->b_error ) + { + + /* look for sync word - should be 0x0b77 */ + RealignBits(&p_a52_adec->bit_stream); + while( (ShowBits( &p_a52_adec->bit_stream, 16 ) ) != 0x0b77 && + (!p_a52_adec->p_fifo->b_die) && (!p_a52_adec->p_fifo->b_error)) + { + RemoveBits( &p_a52_adec->bit_stream, 8 ); + } + + /* get a52 frame header */ + GetChunk( &p_a52_adec->bit_stream, p_a52_adec->p_frame_buffer, 7 ); + + /* check if frame is valid and get frame info */ + p_a52_adec->frame_size = a52_syncinfo( p_a52_adec->p_frame_buffer, + &p_a52_adec->flags, + &p_a52_adec->sample_rate, + &p_a52_adec->bit_rate ); + + if( !p_a52_adec->frame_size ) + { + intf_WarnMsg( 3, "a52: a52_syncinfo failed" ); + continue; + } + + if( DecodeFrame( p_a52_adec ) ) + { + DecoderError( p_config->p_decoder_fifo ); + free( p_a52_adec ); + return( -1 ); + } + + } + + /* If b_error is set, the decoder thread enters the error loop */ + if( p_a52_adec->p_fifo->b_error ) + { + DecoderError( p_a52_adec->p_fifo ); + } + + /* End of the liba52 decoder thread */ + EndThread( p_a52_adec ); + + return( 0 ); +} + +/***************************************************************************** + * InitThread: initialize data before entering main loop + *****************************************************************************/ +static int InitThread( a52_adec_thread_t * p_a52_adec ) +{ + intf_WarnMsg( 3, "a52: InitThread" ); + + /* Initialize liba52 */ + p_a52_adec->p_decoded_samples = a52_init( 0 ); + if( p_a52_adec->p_decoded_samples == NULL ) + { + intf_ErrMsg ( "a52 error: InitThread() unable to initialize " + "liba52" ); + return -1; + } + + /* Init the BitStream */ + InitBitstream( &p_a52_adec->bit_stream, + p_a52_adec->p_fifo, + BitstreamCallback, NULL ); + + return( 0 ); +} + +/***************************************************************************** + * DecodeFrame: decodes an ATSC A/52 frame. + *****************************************************************************/ +static int DecodeFrame( a52_adec_thread_t * p_a52_adec ) +{ + sample_t sample_level = 1; + byte_t *p_buffer; + int i; + + if( ( p_a52_adec->p_aout_fifo != NULL ) && + ( p_a52_adec->p_aout_fifo->l_rate != p_a52_adec->sample_rate ) ) + { + /* Make sure the output thread leaves the NextFrame() function */ + vlc_mutex_lock (&(p_a52_adec->p_aout_fifo->data_lock)); + aout_DestroyFifo (p_a52_adec->p_aout_fifo); + vlc_cond_signal (&(p_a52_adec->p_aout_fifo->data_wait)); + vlc_mutex_unlock (&(p_a52_adec->p_aout_fifo->data_lock)); + + p_a52_adec->p_aout_fifo = NULL; + } + + /* Creating the audio output fifo if not created yet */ + if (p_a52_adec->p_aout_fifo == NULL ) + { + p_a52_adec->p_aout_fifo = aout_CreateFifo( AOUT_ADEC_STEREO_FIFO, + p_a52_adec->i_channels, + p_a52_adec->sample_rate, 0, + AC3DEC_FRAME_SIZE * p_a52_adec->i_channels, + NULL ); + + if ( p_a52_adec->p_aout_fifo == NULL ) + { + return( -1 ); + } + } + + /* Set the Presentation Time Stamp */ + CurrentPTS( &p_a52_adec->bit_stream, + &p_a52_adec->p_aout_fifo->date[ + p_a52_adec->p_aout_fifo->l_end_frame], + NULL ); + + if( !p_a52_adec->p_aout_fifo->date[ + p_a52_adec->p_aout_fifo->l_end_frame] ) + { + p_a52_adec->p_aout_fifo->date[ + p_a52_adec->p_aout_fifo->l_end_frame] = LAST_MDATE; + } + + + + p_buffer = ((byte_t *)p_a52_adec->p_aout_fifo->buffer) + + ( p_a52_adec->p_aout_fifo->l_end_frame * AC3DEC_FRAME_SIZE * + p_a52_adec->i_channels * sizeof(s16) ); + + /* FIXME */ + p_a52_adec->flags = A52_STEREO | A52_ADJUST_LEVEL; + + /* Get the complete frame */ + GetChunk( &p_a52_adec->bit_stream, p_a52_adec->p_frame_buffer + 7, + p_a52_adec->frame_size - 7 ); + + /* do the actual decoding now */ + a52_frame( &p_a52_adec->a52_state, p_a52_adec->p_frame_buffer, + &p_a52_adec->flags, &sample_level, 384 ); + + for( i = 0; i < 6; i++ ) + { + if( a52_block(&p_a52_adec->a52_state, p_a52_adec->p_decoded_samples) ) + intf_WarnMsg( 5, "a52: a52_block failed for block %i", i ); + + float2s16_2( p_a52_adec->p_decoded_samples, + ((int16_t *)p_buffer) + i * 256 * p_a52_adec->i_channels ); + } + + + vlc_mutex_lock( &p_a52_adec->p_aout_fifo->data_lock ); + p_a52_adec->p_aout_fifo->l_end_frame = + (p_a52_adec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE; + vlc_cond_signal (&p_a52_adec->p_aout_fifo->data_wait); + vlc_mutex_unlock (&p_a52_adec->p_aout_fifo->data_lock); + + return 0; +} + +/***************************************************************************** + * EndThread : liba52 decoder thread destruction + *****************************************************************************/ +static void EndThread (a52_adec_thread_t *p_a52_adec) +{ + intf_WarnMsg ( 3, "a52: EndThread" ); + + /* If the audio output fifo was created, we destroy it */ + if (p_a52_adec->p_aout_fifo != NULL) + { + aout_DestroyFifo (p_a52_adec->p_aout_fifo); + + /* Make sure the output thread leaves the NextFrame() function */ + vlc_mutex_lock (&(p_a52_adec->p_aout_fifo->data_lock)); + vlc_cond_signal (&(p_a52_adec->p_aout_fifo->data_wait)); + vlc_mutex_unlock (&(p_a52_adec->p_aout_fifo->data_lock)); + } + + free( p_a52_adec ); + +} + +/***************************************************************************** + * float2s16_2 : converts floats to ints using a trick based on the IEEE + * floating-point format + *****************************************************************************/ +static __inline__ int16_t convert (int32_t i) +{ + if (i > 0x43c07fff) + return 32767; + else if (i < 0x43bf8000) + return -32768; + else + return i - 0x43c00000; +} + +static void float2s16_2 (float * _f, int16_t * s16) +{ + int i; + int32_t * f = (int32_t *) _f; + + for (i = 0; i < 256; i++) { + s16[2*i] = convert (f[i]); + s16[2*i+1] = convert (f[i+256]); + } +} + +/***************************************************************************** + * BitstreamCallback: Import parameters from the new data/PES packet + ***************************************************************************** + * This function is called by input's NextDataPacket. + *****************************************************************************/ +static void BitstreamCallback ( bit_stream_t * p_bit_stream, + boolean_t b_new_pes ) +{ + if( b_new_pes ) + { + /* Drop special AC3 header */ + p_bit_stream->p_byte += 3; + } +} diff --git a/plugins/a52/a52.h b/plugins/a52/a52.h new file mode 100644 index 0000000000000000000000000000000000000000..6d48e8df0537b40574d8b16ca3b8c92ee3eff47f --- /dev/null +++ b/plugins/a52/a52.h @@ -0,0 +1,60 @@ +/***************************************************************************** + * a52.h: ATSC A/52 aka AC-3 decoder plugin for vlc. + * This plugin makes use of liba52 to decode A/52 audio + * (http://liba52.sf.net/). + ***************************************************************************** + * Copyright (C) 2001 VideoLAN + * $Id: a52.h,v 1.1 2002/02/06 20:44:22 gbazin Exp $ + * + * Authors: Gildas Bazin <gbazin@netcourrier.com> + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + *****************************************************************************/ + +/***************************************************************************** + * a52_adec_thread_t : a52 decoder thread descriptor + *****************************************************************************/ +typedef struct a52_adec_thread_s +{ + /* + * liba52 properties + */ + a52_state_t a52_state; + int frame_size; + int flags; + int sample_rate; + int bit_rate; + sample_t *p_decoded_samples; + + /* The bit stream structure handles the PES stream at the bit level */ + bit_stream_t bit_stream; + + /* + * Input properties + */ + decoder_fifo_t *p_fifo; /* stores the PES stream data */ + data_packet_t *p_data; + decoder_config_t *p_config; + + /* + * Output properties + */ + aout_fifo_t *p_aout_fifo; /* stores the decompressed audio frames */ + int i_channels; + + /* temporary buffer to store the raw frame to be decoded */ + u8 p_frame_buffer[3840]; + +} a52_adec_thread_t; diff --git a/src/interface/main.c b/src/interface/main.c index b9ba517abba593a7887ffc35271f2b3aac099f46..b9a3761cf0c72a26477f25cc207bd14bd1f575e1 100644 --- a/src/interface/main.c +++ b/src/interface/main.c @@ -4,7 +4,7 @@ * and spawn threads. ***************************************************************************** * Copyright (C) 1998-2001 VideoLAN - * $Id: main.c,v 1.147 2002/02/05 21:46:41 gbazin Exp $ + * $Id: main.c,v 1.148 2002/02/06 20:44:23 gbazin Exp $ * * Authors: Vincent Seguin <seguin@via.ecp.fr> * Samuel Hocevar <sam@zoy.org> @@ -1002,7 +1002,7 @@ static void Usage( int i_fashion ) "\n --channelserver <host> \tchannel server address" "\n" "\n --mpeg_adec <builtin|mad> \tchoose MPEG audio decoder" - "\n --ac3_adec <builtin|liba52> \tchoose AC3 audio decoder" + "\n --ac3_adec <builtin|a52> \tchoose AC3 audio decoder" "\n" "\n --nommx \tdisable CPU's MMX support" "\n --no3dnow \tdisable CPU's 3D Now! support" @@ -1083,7 +1083,7 @@ static void Usage( int i_fashion ) /* Decoder parameters */ intf_MsgImm( "\nDecoder parameters:" "\n " ADEC_MPEG_VAR "=<builtin|mad> \tMPEG audio decoder" - "\n " ADEC_AC3_VAR "=<builtin|liba52> \tAC3 audio decoder" ); + "\n " ADEC_AC3_VAR "=<builtin|a52> \tAC3 audio decoder" ); } /*****************************************************************************