src/audio_output/aout_u8.o \
src/audio_output/aout_s8.o \
src/audio_output/aout_u16.o \
- src/audio_output/aout_s16.o
+ src/audio_output/aout_s16.o \
+ src/audio_output/aout_spdif.o
VIDEO_OUTPUT = src/video_output/video_output.o \
src/video_output/video_text.o \
src/ac3_decoder/ac3_downmix.o \
src/ac3_decoder/ac3_downmix_c.o
+AC3_SPDIF = src/ac3_spdif/ac3_spdif.o \
+ src/ac3_spdif/ac3_iec958.o
+
LPCM_DECODER = src/lpcm_decoder/lpcm_decoder_thread.o \
src/lpcm_decoder/lpcm_decoder.o
$(VIDEO_OUTPUT) \
$(AUDIO_OUTPUT) \
$(AC3_DECODER) \
+ $(AC3_SPDIF) \
$(LPCM_DECODER) \
$(AUDIO_DECODER) \
$(SPU_DECODER) \
* audio_output.h : audio output thread interface
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
- * $Id: audio_output.h,v 1.31 2001/03/21 13:42:33 sam Exp $
+ * $Id: audio_output.h,v 1.32 2001/04/29 02:48:51 stef Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
*
/*
* Macros
*/
-#define AOUT_FIFO_ISEMPTY( fifo ) ( (fifo).l_end_frame == (fifo).i_start_frame )
+#define AOUT_FIFO_ISEMPTY( fifo ) ( (fifo).l_end_frame == (fifo).l_start_frame )
#define AOUT_FIFO_ISFULL( fifo ) ( ((((fifo).l_end_frame + 1) - (fifo).l_start_frame) & AOUT_FIFO_SIZE) == 0 )
/*****************************************************************************
#define AOUT_FMT_S8 0x00000040
#define AOUT_FMT_U16_LE 0x00000080 /* Little endian U16 */
#define AOUT_FMT_U16_BE 0x00000100 /* Big endian U16 */
+#define AOUT_FMT_AC3 0x00000400 /* Dolby Digital AC3 */
+
#ifdef WORDS_BIGENDIAN
#define AOUT_FMT_S16_NE AOUT_FMT_S16_BE
* Declaration and extern access to global program object.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
- * $Id: main.h,v 1.15 2001/04/11 02:01:24 henri Exp $
+ * $Id: main.h,v 1.16 2001/04/29 02:48:51 stef Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
*
boolean_t b_audio; /* is audio output allowed ? */
boolean_t b_video; /* is video output allowed ? */
boolean_t b_channels; /* is channel changing supported ? */
- boolean_t b_dvd; /* DVD mode ? */
+ boolean_t b_spdif; /* spdif mode ? */
/* Unique threads */
p_vout_thread_t p_vout; /* video output thread */
* -dvd_udf to find files
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
- * $Id: input_dvd.c,v 1.51 2001/04/28 03:36:25 sam Exp $
+ * $Id: input_dvd.c,v 1.52 2001/04/29 02:48:51 stef Exp $
*
* Author: Stéphane Borel <stef@via.ecp.fr>
*
/* reading several block once seems to cause lock-up
* when using input_ToggleES
* who wrote thez damn buggy piece of shit ??? --stef */
- p_dvd->i_block_once = 1;//32;
- p_input->i_read_once = 8;//128;
+ p_dvd->i_block_once = 32;
+ p_input->i_read_once = 128;
i = CSSTest( p_input->i_handle );
/* Reading structures initialisation */
p_input->p_method_data =
- DVDNetlistInit( 2048, 8192, 2048, DVD_LB_SIZE, p_dvd->i_block_once );
+ DVDNetlistInit( 8192, 16384, 2048, DVD_LB_SIZE, p_dvd->i_block_once );
intf_WarnMsg( 2, "dvd info: netlist initialized" );
/* Ifo allocation & initialisation */
u16 i_id;
u8 i_ac3;
u8 i_mpeg;
+ u8 i_lpcm;
u8 i_sub_pic;
u8 i;
int j;
i_ac3 = 0x7f;
i_mpeg = 0xc0;
+ i_lpcm = 0x9f;
for( i = 1 ; i <= vts.manager_inf.i_audio_nb ; i++ )
{
break;
case 0x04: /* LPCM */
+#if 0
+ i_id = ( ( i_lpcm + i ) << 8 ) | 0xbd;
+ p_es = input_AddES( p_input,
+ p_input->stream.pp_programs[0], i_id, 0 );
+ p_es->i_stream_id = i_id;
+ p_es->i_type = LPCM_AUDIO_ES;
+ p_es->b_audio = 1;
+ p_es->i_cat = AUDIO_ES;
+ strcpy( p_es->psz_desc, Language( hton16(
+ vts.manager_inf.p_audio_attr[i-1].i_lang_code ) ) );
+ strcat( p_es->psz_desc, " (lpcm)" );
+
+ intf_WarnMsg( 1, "dvd info: audio stream %d %s\t(0x%x)",
+ i, p_es->psz_desc, i_id );
+#else
i_id = 0;
intf_ErrMsg( "dvd warning: LPCM audio not handled yet" );
+#endif
break;
case 0x06: /* DTS */
i_id = 0;
{
thread_dvd_data_t * p_dvd;
dvd_netlist_t * p_netlist;
+ input_area_t * p_area;
struct iovec * p_vec;
struct data_packet_s * pp_data[p_input->i_read_once];
u8 * pi_cur;
int i_read_blocks;
off_t i_off;
boolean_t b_eof;
+ boolean_t b_eot;
p_dvd = (thread_dvd_data_t *)p_input->p_plugin_data;
p_netlist = (dvd_netlist_t *)p_input->p_method_data;
/* update chapter : it will be easier when we have navigation
* ES support */
- if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 )
- {
- i_angle = p_dvd->i_angle - 1;
- }
- else
- {
- i_angle = 0;
- }
- if( title.chapter_map.pi_start_cell[p_dvd->i_chapter-1] <=
- ( p_dvd->i_prg_cell - i_angle ) )
+ if( p_dvd->i_chapter < ( p_dvd->i_chapter_nb - 1 ) )
{
- p_dvd->i_chapter++;
+ if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 )
+ {
+ i_angle = p_dvd->i_angle - 1;
+ }
+ else
+ {
+ i_angle = 0;
+ }
+ if( title.chapter_map.pi_start_cell[p_dvd->i_chapter] <=
+ ( p_dvd->i_prg_cell - i_angle + 1 ) )
+ {
+ p_dvd->i_chapter++;
+ }
}
vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
/* the synchro has to be reinitialized when we change cell */
- p_input->stream.pp_programs[0]->i_synchro_state = SYNCHRO_START;
+ p_input->stream.pp_programs[0]->i_synchro_state = SYNCHRO_REINIT;
vlc_mutex_unlock( &p_input->stream.stream_lock );
vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.p_selected_area->i_tell += i_read_bytes;
- b_eof = !( p_input->stream.p_selected_area->i_tell < p_dvd->i_size );
+ b_eot = !( p_input->stream.p_selected_area->i_tell < p_dvd->i_size );
+ b_eof = b_eot && ( ( p_dvd->i_title + 1 ) < p_input->stream.i_area_nb );
+ p_area = p_input->stream.pp_areas[p_dvd->i_title + 1];
vlc_mutex_unlock( &p_input->stream.stream_lock );
- if( ( i_read_blocks == i_block_once ) && ( !b_eof ) )
+ if( b_eof )
{
+ return 1;
+ }
+
+ if( b_eot )
+ {
+ p_dvd->i_title++;
+ DVDSetArea( p_input, p_area );
return 0;
}
- else
+
+ if( i_read_blocks == i_block_once )
{
- return 1;
+ return 0;
}
+
+ return -1;
}
/*****************************************************************************
p_dvd->i_sector = i_pos >> 11;
i_prg_cell = 0;
- i_chapter = 1;
+ i_chapter = 0;
/* parse vobu address map to find program cell */
while( title.p_cell_play[i_prg_cell].i_end_sector < p_dvd->i_sector )
{
i_angle = 0;
}
- while( title.chapter_map.pi_start_cell[i_chapter-1] <=
- ( p_dvd->i_prg_cell - i_angle ) )
+ while( ( title.chapter_map.pi_start_cell[i_chapter] <=
+ ( p_dvd->i_prg_cell - i_angle + 1 ) ) &&
+ ( i_chapter < ( p_dvd->i_chapter_nb - 1 ) ) )
{
i_chapter++;
}
* intf_gnome.c: Gnome interface
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
- * $Id: intf_gnome.c,v 1.32 2001/04/22 00:08:26 stef Exp $
+ * $Id: intf_gnome.c,v 1.33 2001/04/29 02:48:51 stef Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Stéphane Borel <stef@via.ecp.fr>
GtkWidget * p_item;
GtkWidget * p_item_active;
GSList * p_group;
- char * psz_name;
+ char psz_name[12];
gint i_item;
gint i;
p_menu = gtk_menu_new();
/* special case for "off" item */
- psz_name = "Off";
+ sprintf( psz_name, "Off" );
p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
if( p_intf->p_input->stream.pp_es[i]->i_cat == i_cat )
{
i_item++;
- psz_name = p_intf->p_input->stream.pp_es[i]->psz_desc;
+ strcpy( psz_name, p_intf->p_input->stream.pp_es[i]->psz_desc );
if( psz_name[0] == '\0' )
{
sprintf( psz_name, "Language %d", i_item );
void(*pf_toggle)( GtkCheckMenuItem *, gpointer ) )
{
intf_thread_t * p_intf;
- char psz_name[10];
+ char psz_name[12];
GtkWidget * p_angle_menu;
GSList * p_angle_group;
GtkWidget * p_item;
void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
{
intf_thread_t * p_intf;
- char psz_name[10];
+ char psz_name[12];
GtkWidget * p_chapter_menu;
GtkWidget * p_chapter_submenu;
GtkWidget * p_menu_item;
void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
{
intf_thread_t * p_intf;
- char psz_name[10];
+ char psz_name[12];
GtkWidget * p_title_menu;
GtkWidget * p_title_submenu;
GtkWidget * p_title_item;
--- /dev/null
+/*****************************************************************************
+ * ac3_iec958.c: ac3 to spdif converter
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: ac3_iec958.c,v 1.1 2001/04/29 02:48:51 stef Exp $
+ *
+ * Authors: Stéphane Borel <stef@via.ecp.fr>
+ * Juha Yrjola <jyrjola@cc.hut.fi>
+ * German Gomez Garcia <german@piraos.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 "defs.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "config.h"
+#include "common.h"
+#include "threads.h"
+#include "mtime.h"
+
+#include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
+
+#include "stream_control.h"
+#include "input_ext-dec.h"
+
+#include "audio_output.h"
+
+#include "ac3_spdif.h"
+#include "ac3_iec958.h"
+
+/****************************************************************************
+ * Local structures and tables
+ ****************************************************************************/
+typedef struct frame_size_s
+{
+ u16 i_bit_rate;
+ u16 i_frame_size[3];
+} frame_size_t;
+
+static const frame_size_t p_frame_size_code[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 } }
+};
+
+/****************************************************************************
+ * ac3_iec958_build_burst: builds an iec958/spdif frame based on an ac3 frame
+ ****************************************************************************/
+void ac3_iec958_build_burst( int i_length, u8 * pi_data, u8 * pi_out )
+{
+ const u8 pi_sync[4] = { 0x72, 0xF8, 0x1F, 0x4E };
+
+ /* add the spdif headers */
+ memcpy( pi_out, pi_sync, 4 );
+ if( i_length )
+ pi_out[4] = 0x01;
+ else
+ pi_out[4] = 0;
+ pi_out[5] = 0x00;
+ pi_out[6] = ( i_length *8 ) & 0xFF;
+ pi_out[7] = ( ( i_length *8 ) >> 8 ) & 0xFF;
+
+ swab( pi_data, pi_out + 8, i_length );
+ /* adds zero to complete the spdif frame
+ * they will be ignored by the decoder */
+ memset( pi_out + 8 + i_length, 0, SPDIF_FRAME - 8 - i_length );
+}
+
+/****************************************************************************
+ * ac3_iec958_parse_syncinfo: parse ac3 sync info
+ ****************************************************************************/
+int ac3_iec958_parse_syncinfo( ac3_spdif_thread_t *p_spdif,
+ ac3_info_t *ac3_info,
+ u8 * pi_ac3 )
+{
+ int pi_sample_rates[4] = { 48000, 44100, 32000, -1 };
+ int i_frame_rate_code;
+ int i_frame_size_code;
+// u8 * pi_tmp;
+ sync_frame_t * p_sync_frame;
+
+ /* find sync word */
+ while( ShowBits( &p_spdif->bit_stream, 16 ) != 0xb77 )
+ {
+ RemoveBits( &p_spdif->bit_stream, 8 );
+ }
+
+ /* read sync frame */
+ pi_ac3 = malloc( sizeof(sync_frame_t) );
+ GetChunk( &p_spdif->bit_stream, pi_ac3, sizeof(sync_frame_t) );
+ p_sync_frame = (sync_frame_t*)pi_ac3;
+
+ /* compute frame rate */
+ i_frame_rate_code = (p_sync_frame->syncinfo.code >> 6) & 0x03;
+ ac3_info->i_sample_rate = pi_sample_rates[i_frame_rate_code];
+ if (ac3_info->i_sample_rate == -1)
+ {
+ return -1;
+ }
+
+ /* compute frame size */
+ i_frame_size_code = p_sync_frame->syncinfo.code & 0x3f;
+ ac3_info->i_frame_size = 2 *
+ p_frame_size_code[i_frame_size_code].i_frame_size[i_frame_rate_code];
+ ac3_info->i_bit_rate = p_frame_size_code[i_frame_size_code].i_bit_rate;
+
+ if( ( ( p_sync_frame->bsi.bsidmod >> 3 ) & 0x1f ) != 0x08 )
+ {
+ return -1;
+ }
+
+ ac3_info->i_bs_mod = p_sync_frame->bsi.bsidmod & 0x7;
+
+// free( pi_tmp );
+
+ return 0;
+}
--- /dev/null
+/*****************************************************************************
+ * ac3_iec958.h: ac3 to spdif converter headers
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: ac3_iec958.h,v 1.1 2001/04/29 02:48:51 stef Exp $
+ *
+ * Authors: Stéphane Borel <stef@via.ecp.fr>
+ * Juha Yrjola <jyrjola@cc.hut.fi>
+ * German Gomez Garcia <german@piraos.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.
+ ****************************************************************************/
+
+#ifndef _AC3_IEC958_H
+#define _AC3_IEC958_H
+
+/****************************************************************************
+ * information about ac3 frame
+ ****************************************************************************/
+typedef struct ac3_info_s
+{
+ int i_bit_rate;
+ int i_frame_size;
+ int i_sample_rate;
+ int i_bs_mod;
+} ac3_info_t;
+
+typedef struct sync_frame_s
+{
+ struct syncinfo
+ {
+ u8 syncword[2];
+ u8 crc1[2];
+ u8 code;
+ } syncinfo;
+
+ struct bsi
+ {
+ u8 bsidmod;
+ u8 acmod;
+ } bsi;
+} sync_frame_t;
+
+/****************************************************************************
+ * Prototypes
+ ****************************************************************************/
+void ac3_iec958_build_burst ( int, u8 *, u8 * );
+int ac3_iec958_parse_syncinfo ( struct ac3_spdif_thread_s *,
+ struct ac3_info_s *, u8 * );
+#endif
--- /dev/null
+/*****************************************************************************
+ * ac3_spdif.c: ac3 pass-through to external decoder with enabled soundcard
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: ac3_spdif.c,v 1.1 2001/04/29 02:48:51 stef Exp $
+ *
+ * Authors: Stéphane Borel <stef@via.ecp.fr>
+ * Juha Yrjola <jyrjola@cc.hut.fi>
+ * German Gomez Garcia <german@piraos.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 "defs.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "config.h"
+#include "common.h"
+#include "threads.h"
+#include "mtime.h"
+
+#include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
+
+#include "stream_control.h"
+#include "input_ext-dec.h"
+
+#include "audio_output.h"
+
+#include "ac3_spdif.h"
+#include "ac3_iec958.h"
+
+#define FRAME_NB 8
+
+/****************************************************************************
+ * Local Prototypes
+ ****************************************************************************/
+static int InitThread ( ac3_spdif_thread_t * );
+static void RunThread ( ac3_spdif_thread_t * );
+static void ErrorThread ( ac3_spdif_thread_t * );
+static void EndThread ( ac3_spdif_thread_t * );
+static void BitstreamCallback( bit_stream_t *, boolean_t );
+
+/****************************************************************************
+ * spdif_CreateThread: initialize the spdif thread
+ ****************************************************************************/
+vlc_thread_t spdif_CreateThread( adec_config_t * p_config )
+{
+ ac3_spdif_thread_t * p_spdif;
+
+ intf_DbgMsg( "spdif debug: creating ac3 pass-through thread" );
+
+ /* Allocate the memory needed to store the thread's structure */
+ if( ( p_spdif = malloc( sizeof(ac3_spdif_thread_t) ) ) == NULL )
+ {
+ intf_ErrMsg ( "spdif error: not enough memory "
+ "for spdif_CreateThread() to create the new thread");
+ return 0;
+ }
+
+ /*
+ * Initialize the thread properties
+ */
+ p_spdif->p_config = p_config;
+ p_spdif->p_fifo = p_config->decoder_config.p_decoder_fifo;
+
+ p_spdif->p_aout = p_config->p_aout;
+ p_spdif->p_aout_fifo = NULL;
+
+ /* Spawn the ac3 to spdif thread */
+ if (vlc_thread_create(&p_spdif->thread_id, "spdif",
+ (vlc_thread_func_t)RunThread, (void *)p_spdif))
+ {
+ intf_ErrMsg( "spdif error: can't spawn spdif thread" );
+ free( p_spdif );
+ return 0;
+ }
+
+ intf_DbgMsg( "spdif debug: spdif thread (%p) created", p_spdif );
+
+ return p_spdif->thread_id;
+}
+
+/*
+ * Local functions
+ */
+
+/****************************************************************************
+ * InitThread: initialize thread data and create output fifo
+ ****************************************************************************/
+static int InitThread( ac3_spdif_thread_t * p_spdif )
+{
+ aout_fifo_t aout_fifo;
+
+ p_spdif->p_config->decoder_config.pf_init_bit_stream(
+ &p_spdif->bit_stream,
+ p_spdif->p_config->decoder_config.p_decoder_fifo,
+ BitstreamCallback, (void*)p_spdif );
+
+ aout_fifo.i_type = AOUT_ADEC_MONO_FIFO;
+ aout_fifo.i_channels = 1;
+ aout_fifo.b_stereo = 0;
+
+ aout_fifo.l_frame_size = SPDIF_FRAME;
+
+ /* Creating the audio output fifo */
+ if( (p_spdif->p_aout_fifo =
+ aout_CreateFifo( p_spdif->p_aout, &aout_fifo ) ) == NULL )
+ {
+ return -1;
+ }
+
+ intf_WarnMsg( 1, "aout fifo for spdif created" );
+
+ return 0;
+}
+
+/****************************************************************************
+ * RunThread: loop that reads ac3 ES and transform it to
+ * an spdif compliant stream.
+ ****************************************************************************/
+static void RunThread( ac3_spdif_thread_t * p_spdif )
+{
+ ac3_info_t ac3_info;
+ u8 * pi_ac3;
+ u8 * pi_iec;
+
+ InitThread( p_spdif );
+
+ /* temporary buffer to store ac3 frames to be transformed */
+ pi_ac3 = malloc( /*ac3_info.i_frame_size*/SPDIF_FRAME );
+
+ /* check stream properties */
+ if( ac3_iec958_parse_syncinfo( p_spdif, &ac3_info, pi_ac3 ) < 0)
+ {
+ intf_ErrMsg( "spdif error: stream not valid");
+ exit(1);
+ }
+
+ if( ac3_info.i_sample_rate != 48000) {
+ intf_ErrMsg( "spdif error: Only 48000 Hz streams supported");
+ exit(1);
+ }
+
+ GetChunk( &p_spdif->bit_stream, pi_ac3 + sizeof(sync_frame_t),
+ ac3_info.i_frame_size - sizeof(sync_frame_t) );
+
+ vlc_cond_signal( &p_spdif->p_aout_fifo->data_wait );
+ while( !p_spdif->p_fifo->b_die && !p_spdif->p_fifo->b_error )
+ {
+ /* handle the dates */
+ if(DECODER_FIFO_START(*p_spdif->p_fifo)->i_pts)
+ {
+ p_spdif->p_aout_fifo->date[p_spdif->p_aout_fifo->l_end_frame] =
+ DECODER_FIFO_START(*p_spdif->p_fifo)->i_pts;
+ DECODER_FIFO_START(*p_spdif->p_fifo)->i_pts = 0;
+ }
+ else
+ {
+ p_spdif->p_aout_fifo->date[p_spdif->p_aout_fifo->l_end_frame] =
+ LAST_MDATE;
+ }
+
+ /* write in the first free packet of aout fifo */
+ pi_iec = (p_spdif->p_aout_fifo->buffer) +
+ (p_spdif->p_aout_fifo->l_end_frame * SPDIF_FRAME );
+
+ /* build burst to be sent to hardware decoder */
+ ac3_iec958_build_burst( ac3_info.i_frame_size, pi_ac3, pi_iec );
+
+ vlc_mutex_lock (&p_spdif->p_aout_fifo->data_lock);
+
+ p_spdif->p_aout_fifo->l_end_frame =
+ (p_spdif->p_aout_fifo->l_end_frame + 1 ) & AOUT_FIFO_SIZE;
+
+ vlc_mutex_unlock (&p_spdif->p_aout_fifo->data_lock);
+
+ /* find syncword */
+ while( ShowBits( &p_spdif->bit_stream, 16 ) != 0xb77 )
+ {
+ RemoveBits( &p_spdif->bit_stream, 8 );
+ }
+
+ /* read data from bitstream */
+ GetChunk( &p_spdif->bit_stream, pi_ac3, ac3_info.i_frame_size );
+ }
+
+ free( pi_ac3 );
+
+ /* If b_error is set, the ac3 spdif thread enters the error loop */
+ if( p_spdif->p_fifo->b_error )
+ {
+ ErrorThread( p_spdif );
+ }
+
+ /* End of the ac3 decoder thread */
+ EndThread( p_spdif );
+
+ return;
+}
+
+/*****************************************************************************
+ * ErrorThread : ac3 spdif's RunThread() error loop
+ *****************************************************************************/
+static void ErrorThread( ac3_spdif_thread_t * p_spdif )
+{
+ /* We take the lock, because we are going to read/write the start/end
+ * indexes of the decoder fifo */
+ vlc_mutex_lock (&p_spdif->p_fifo->data_lock);
+
+ /* Wait until a `die' order is sent */
+ while( !p_spdif->p_fifo->b_die )
+ {
+ /* Trash all received PES packets */
+ while( !DECODER_FIFO_ISEMPTY( *p_spdif->p_fifo ) )
+ {
+ p_spdif->p_fifo->pf_delete_pes(p_spdif->p_fifo->p_packets_mgt,
+ DECODER_FIFO_START( *p_spdif->p_fifo ) );
+ DECODER_FIFO_INCSTART( *p_spdif->p_fifo );
+ }
+
+ /* Waiting for the input thread to put new PES packets in the fifo */
+ vlc_cond_wait( &p_spdif->p_fifo->data_wait,
+ &p_spdif->p_fifo->data_lock );
+ }
+
+ /* We can release the lock before leaving */
+ vlc_mutex_unlock( &p_spdif->p_fifo->data_lock );
+}
+
+/*****************************************************************************
+ * EndThread : ac3 spdif thread destruction
+ *****************************************************************************/
+static void EndThread( ac3_spdif_thread_t * p_spdif )
+{
+ intf_DbgMsg( "spdif debug: destroying thread %p", p_spdif );
+
+ /* If the audio output fifo was created, we destroy it */
+ if( p_spdif->p_aout_fifo != NULL )
+ {
+ aout_DestroyFifo( p_spdif->p_aout_fifo );
+
+ /* Make sure the output thread leaves the NextFrame() function */
+ vlc_mutex_lock( &(p_spdif->p_aout_fifo->data_lock ) );
+ vlc_cond_signal( &(p_spdif->p_aout_fifo->data_wait ) );
+ vlc_mutex_unlock( &(p_spdif->p_aout_fifo->data_lock ) );
+
+ }
+
+ /* Destroy descriptor */
+ free( p_spdif->p_config );
+ free( p_spdif );
+
+ intf_DbgMsg ("spdif debug: thread %p destroyed", p_spdif );
+}
+
+/*****************************************************************************
+ * 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 )
+ {
+ p_bit_stream->p_byte += 3;
+ }
+}
--- /dev/null
+/*****************************************************************************
+ * ac3_spdif.h: header for ac3 pass-through
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: ac3_spdif.h,v 1.1 2001/04/29 02:48:51 stef Exp $
+ *
+ * Authors: Stéphane Borel <stef@via.ecp.fr>
+ *
+ * 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.
+ ****************************************************************************/
+
+#ifndef _AC3_SPDIF_H
+#define _AC3_SPDIF_H
+
+#define SPDIF_FRAME 6144
+
+/*****************************************************************************
+ * ac3_spdif_thread_t : ac3 pass-through thread descriptor
+ *****************************************************************************/
+typedef struct ac3_spdif_thread_s
+{
+ /*
+ * Thread properties
+ */
+ vlc_thread_t thread_id; /* id for thread functions */
+
+ /*
+ * Input properties
+ */
+ decoder_fifo_t * p_fifo; /* stores the PES stream data */
+ adec_config_t * p_config;
+
+ /* The bit stream structure handles the PES stream at the bit level */
+ bit_stream_t bit_stream;
+ int i_available;
+
+ /*
+ * Output properties
+ */
+ aout_fifo_t * p_aout_fifo;/* stores the decompressed audio frames */
+ aout_thread_t * p_aout; /* needed to create the audio fifo */
+
+} ac3_spdif_thread_t;
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+vlc_thread_t spdif_CreateThread( adec_config_t * p_config );
+
+#endif
* aout_common.h: audio output inner functions
*****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN
- * $Id: aout_common.h,v 1.2 2001/03/21 13:42:34 sam Exp $
+ * $Id: aout_common.h,v 1.3 2001/04/29 02:48:51 stef Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
*
void aout_U16StereoThread ( aout_thread_t * p_aout );
void aout_S16MonoThread ( aout_thread_t * p_aout );
void aout_S16StereoThread ( aout_thread_t * p_aout );
+void aout_SpdifThread ( aout_thread_t * p_aout );
#define UPDATE_INCREMENT( increment, integer ) \
if ( ((increment).l_remainder += (increment).l_euclidean_remainder) >= 0 )\
* audio_output.c : audio output thread
*****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN
- * $Id: audio_output.c,v 1.57 2001/04/28 03:36:25 sam Exp $
+ * $Id: audio_output.c,v 1.58 2001/04/29 02:48:51 stef Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
*
return( NULL );
}
+ /* special setting for ac3 pass-through mode */
+ if( p_main->b_spdif )
+ {
+ p_aout->i_format = AOUT_FMT_AC3;
+ p_aout->i_channels = 1;
+ p_aout->l_rate = 48000;
+ }
+
/* FIXME: only works for i_channels == 1 or 2 ?? */
p_aout->b_stereo = ( p_aout->i_channels == 2 ) ? 1 : 0;
l_bytes = 1 * sizeof(s16) * p_aout->l_units;
aout_thread = (void *)aout_S16MonoThread;
break;
+ case AOUT_FMT_AC3:
+ intf_WarnMsg( 2, "aout info: ac3 pass-through thread" );
+ l_bytes = 0;
+ aout_thread = (void *)aout_SpdifThread;
+ break;
- default:
+ default:
intf_ErrMsg( "aout error: unknown audio output format (%i)",
p_aout->i_format );
return( -1 );
l_bytes = 2 * sizeof(s16) * p_aout->l_units;
aout_thread = (void *)aout_S16StereoThread;
break;
-
default:
intf_ErrMsg( "aout error: unknown audio output format %i",
p_aout->i_format );
* input_programs.c: es_descriptor_t, pgrm_descriptor_t management
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
- * $Id: input_programs.c,v 1.52 2001/04/28 03:36:25 sam Exp $
+ * $Id: input_programs.c,v 1.53 2001/04/29 02:48:51 stef Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
/* FIXME */
vlc_thread_t adec_CreateThread( void * );
vlc_thread_t ac3dec_CreateThread( void * );
+vlc_thread_t ac3spdif_CreateThread( void * );
+vlc_thread_t spdif_CreateThread( void * );
vlc_thread_t vpar_CreateThread( void * );
vlc_thread_t spudec_CreateThread( void * );
case AC3_AUDIO_ES:
if( p_main->b_audio )
{
- decoder.pf_create_thread = ac3dec_CreateThread;
+ if( !p_main->b_spdif )
+ {
+ decoder.pf_create_thread = ac3dec_CreateThread;
+ }
+ else
+ {
+ decoder.pf_create_thread = spdif_CreateThread;
+ }
+
p_config = (void *)GetAdecConfig( p_input, p_es );
/* Release the lock, not to block the input thread during
vlc_mutex_lock( &p_input->stream.stream_lock );
}
break;
+#if 0
+ case LPCM_AUDIO_ES:
+ if( p_main->b_audio )
+ {
+ if( p_main->b_spdif )
+ {
+ decoder.pf_create_thread = spdif_CreateThread;
+ }
+ else
+ {
+ intf_ErrMsg( "input error: LPCM audio not handled yet" );
+ break;
+ }
+
+ p_config = (void *)GetAdecConfig( p_input, p_es );
+ /* Release the lock, not to block the input thread during
+ * the creation of the thread. */
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ p_es->thread_id = input_RunDecoder( &decoder, p_config );
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ }
+ break;
+#endif
case DVD_SPU_ES:
if( p_main->b_video )
{
* and spawn threads.
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: main.c,v 1.89 2001/04/28 03:36:25 sam Exp $
+ * $Id: main.c,v 1.90 2001/04/29 02:48:51 stef Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
#define OPT_NOAUDIO 150
#define OPT_STEREO 151
#define OPT_MONO 152
+#define OPT_SPDIF 153
#define OPT_NOVIDEO 160
#define OPT_DISPLAY 161
{ "aout", 1, 0, 'A' },
{ "stereo", 0, 0, OPT_STEREO },
{ "mono", 0, 0, OPT_MONO },
+ { "spdif", 0, 0, OPT_SPDIF },
/* Video options */
{ "novideo", 0, 0, OPT_NOVIDEO },
p_main->b_audio = 1;
p_main->b_video = 1;
p_main->b_channels = 0;
+ p_main->b_spdif = 0;
p_main->i_warning_level = 4;
case OPT_MONO: /* --mono */
main_PutIntVariable( AOUT_STEREO_VAR, 0 );
break;
+ case OPT_SPDIF: /* --spdif */
+ p_main->b_spdif = 1;
+ break;
/* Video options */
case OPT_NOVIDEO: /* --novideo */
"\n --noaudio \tdisable audio"
"\n -A, --aout <module> \taudio output method"
"\n --stereo, --mono \tstereo/mono audio"
+ "\n --spdif \tac3 pass-through mode"
"\n"
"\n --novideo \tdisable video"
"\n -V, --vout <module> \tvideo output method"