Commit e5c6a7af authored by Stéphane Borel's avatar Stéphane Borel

-new audio output using direct ac3 pass-through with some sound

cards: it sends raw ac3 frames to an external ac3 decoder. It is very
experimental yet, hasn't any synchro ... but it works well with my
sblive and my dtt3500 speakers (note that you need a patched emu10k1
driver for this to work).

-bug fix in gnome intf thanks to Shane Harper.

-bug fix in input_dvd for chapter change.
parent d3aacbfc
...@@ -57,7 +57,8 @@ AUDIO_OUTPUT = src/audio_output/audio_output.o \ ...@@ -57,7 +57,8 @@ AUDIO_OUTPUT = src/audio_output/audio_output.o \
src/audio_output/aout_u8.o \ src/audio_output/aout_u8.o \
src/audio_output/aout_s8.o \ src/audio_output/aout_s8.o \
src/audio_output/aout_u16.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 \ VIDEO_OUTPUT = src/video_output/video_output.o \
src/video_output/video_text.o \ src/video_output/video_text.o \
...@@ -75,6 +76,9 @@ AC3_DECODER = src/ac3_decoder/ac3_decoder_thread.o \ ...@@ -75,6 +76,9 @@ AC3_DECODER = src/ac3_decoder/ac3_decoder_thread.o \
src/ac3_decoder/ac3_downmix.o \ src/ac3_decoder/ac3_downmix.o \
src/ac3_decoder/ac3_downmix_c.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 \ LPCM_DECODER = src/lpcm_decoder/lpcm_decoder_thread.o \
src/lpcm_decoder/lpcm_decoder.o src/lpcm_decoder/lpcm_decoder.o
...@@ -107,6 +111,7 @@ C_OBJ = $(INTERFACE) \ ...@@ -107,6 +111,7 @@ C_OBJ = $(INTERFACE) \
$(VIDEO_OUTPUT) \ $(VIDEO_OUTPUT) \
$(AUDIO_OUTPUT) \ $(AUDIO_OUTPUT) \
$(AC3_DECODER) \ $(AC3_DECODER) \
$(AC3_SPDIF) \
$(LPCM_DECODER) \ $(LPCM_DECODER) \
$(AUDIO_DECODER) \ $(AUDIO_DECODER) \
$(SPU_DECODER) \ $(SPU_DECODER) \
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* audio_output.h : audio output thread interface * audio_output.h : audio output thread interface
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * 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> * Authors: Michel Kaempf <maxx@via.ecp.fr>
* *
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
/* /*
* Macros * 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_FIFO_ISFULL( fifo ) ( ((((fifo).l_end_frame + 1) - (fifo).l_start_frame) & AOUT_FIFO_SIZE) == 0 )
/***************************************************************************** /*****************************************************************************
...@@ -192,6 +192,8 @@ typedef struct aout_thread_s ...@@ -192,6 +192,8 @@ typedef struct aout_thread_s
#define AOUT_FMT_S8 0x00000040 #define AOUT_FMT_S8 0x00000040
#define AOUT_FMT_U16_LE 0x00000080 /* Little endian U16 */ #define AOUT_FMT_U16_LE 0x00000080 /* Little endian U16 */
#define AOUT_FMT_U16_BE 0x00000100 /* Big endian U16 */ #define AOUT_FMT_U16_BE 0x00000100 /* Big endian U16 */
#define AOUT_FMT_AC3 0x00000400 /* Dolby Digital AC3 */
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
#define AOUT_FMT_S16_NE AOUT_FMT_S16_BE #define AOUT_FMT_S16_NE AOUT_FMT_S16_BE
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* Declaration and extern access to global program object. * Declaration and extern access to global program object.
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * 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> * Authors: Vincent Seguin <seguin@via.ecp.fr>
* *
...@@ -48,7 +48,7 @@ typedef struct ...@@ -48,7 +48,7 @@ typedef struct
boolean_t b_audio; /* is audio output allowed ? */ boolean_t b_audio; /* is audio output allowed ? */
boolean_t b_video; /* is video output allowed ? */ boolean_t b_video; /* is video output allowed ? */
boolean_t b_channels; /* is channel changing supported ? */ boolean_t b_channels; /* is channel changing supported ? */
boolean_t b_dvd; /* DVD mode ? */ boolean_t b_spdif; /* spdif mode ? */
/* Unique threads */ /* Unique threads */
p_vout_thread_t p_vout; /* video output thread */ p_vout_thread_t p_vout; /* video output thread */
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* -dvd_udf to find files * -dvd_udf to find files
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * 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: Stphane Borel <stef@via.ecp.fr> * Author: Stphane Borel <stef@via.ecp.fr>
* *
...@@ -380,8 +380,8 @@ static void DVDInit( input_thread_t * p_input ) ...@@ -380,8 +380,8 @@ static void DVDInit( input_thread_t * p_input )
/* reading several block once seems to cause lock-up /* reading several block once seems to cause lock-up
* when using input_ToggleES * when using input_ToggleES
* who wrote thez damn buggy piece of shit ??? --stef */ * who wrote thez damn buggy piece of shit ??? --stef */
p_dvd->i_block_once = 1;//32; p_dvd->i_block_once = 32;
p_input->i_read_once = 8;//128; p_input->i_read_once = 128;
i = CSSTest( p_input->i_handle ); i = CSSTest( p_input->i_handle );
...@@ -398,7 +398,7 @@ static void DVDInit( input_thread_t * p_input ) ...@@ -398,7 +398,7 @@ static void DVDInit( input_thread_t * p_input )
/* Reading structures initialisation */ /* Reading structures initialisation */
p_input->p_method_data = 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" ); intf_WarnMsg( 2, "dvd info: netlist initialized" );
/* Ifo allocation & initialisation */ /* Ifo allocation & initialisation */
...@@ -552,6 +552,7 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -552,6 +552,7 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
u16 i_id; u16 i_id;
u8 i_ac3; u8 i_ac3;
u8 i_mpeg; u8 i_mpeg;
u8 i_lpcm;
u8 i_sub_pic; u8 i_sub_pic;
u8 i; u8 i;
int j; int j;
...@@ -741,6 +742,7 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -741,6 +742,7 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
i_ac3 = 0x7f; i_ac3 = 0x7f;
i_mpeg = 0xc0; i_mpeg = 0xc0;
i_lpcm = 0x9f;
for( i = 1 ; i <= vts.manager_inf.i_audio_nb ; i++ ) for( i = 1 ; i <= vts.manager_inf.i_audio_nb ; i++ )
{ {
...@@ -795,8 +797,24 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -795,8 +797,24 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
break; break;
case 0x04: /* LPCM */ 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; i_id = 0;
intf_ErrMsg( "dvd warning: LPCM audio not handled yet" ); intf_ErrMsg( "dvd warning: LPCM audio not handled yet" );
#endif
break; break;
case 0x06: /* DTS */ case 0x06: /* DTS */
i_id = 0; i_id = 0;
...@@ -946,6 +964,7 @@ static int DVDRead( input_thread_t * p_input, ...@@ -946,6 +964,7 @@ static int DVDRead( input_thread_t * p_input,
{ {
thread_dvd_data_t * p_dvd; thread_dvd_data_t * p_dvd;
dvd_netlist_t * p_netlist; dvd_netlist_t * p_netlist;
input_area_t * p_area;
struct iovec * p_vec; struct iovec * p_vec;
struct data_packet_s * pp_data[p_input->i_read_once]; struct data_packet_s * pp_data[p_input->i_read_once];
u8 * pi_cur; u8 * pi_cur;
...@@ -958,6 +977,7 @@ static int DVDRead( input_thread_t * p_input, ...@@ -958,6 +977,7 @@ static int DVDRead( input_thread_t * p_input,
int i_read_blocks; int i_read_blocks;
off_t i_off; off_t i_off;
boolean_t b_eof; boolean_t b_eof;
boolean_t b_eot;
p_dvd = (thread_dvd_data_t *)p_input->p_plugin_data; p_dvd = (thread_dvd_data_t *)p_input->p_plugin_data;
p_netlist = (dvd_netlist_t *)p_input->p_method_data; p_netlist = (dvd_netlist_t *)p_input->p_method_data;
...@@ -994,6 +1014,8 @@ static int DVDRead( input_thread_t * p_input, ...@@ -994,6 +1014,8 @@ static int DVDRead( input_thread_t * p_input,
/* update chapter : it will be easier when we have navigation /* update chapter : it will be easier when we have navigation
* ES support */ * ES support */
if( p_dvd->i_chapter < ( p_dvd->i_chapter_nb - 1 ) )
{
if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 ) if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 )
{ {
i_angle = p_dvd->i_angle - 1; i_angle = p_dvd->i_angle - 1;
...@@ -1002,11 +1024,12 @@ static int DVDRead( input_thread_t * p_input, ...@@ -1002,11 +1024,12 @@ static int DVDRead( input_thread_t * p_input,
{ {
i_angle = 0; i_angle = 0;
} }
if( title.chapter_map.pi_start_cell[p_dvd->i_chapter-1] <= if( title.chapter_map.pi_start_cell[p_dvd->i_chapter] <=
( p_dvd->i_prg_cell - i_angle ) ) ( p_dvd->i_prg_cell - i_angle + 1 ) )
{ {
p_dvd->i_chapter++; p_dvd->i_chapter++;
} }
}
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
...@@ -1015,7 +1038,7 @@ static int DVDRead( input_thread_t * p_input, ...@@ -1015,7 +1038,7 @@ static int DVDRead( input_thread_t * p_input,
p_input->stream.p_selected_area->i_part = p_dvd->i_chapter; p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
/* the synchro has to be reinitialized when we change cell */ /* 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_unlock( &p_input->stream.stream_lock );
...@@ -1115,18 +1138,30 @@ static int DVDRead( input_thread_t * p_input, ...@@ -1115,18 +1138,30 @@ static int DVDRead( input_thread_t * p_input,
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.p_selected_area->i_tell += i_read_bytes; 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 ); 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; return 0;
} }
else
if( i_read_blocks == i_block_once )
{ {
return 1; return 0;
} }
return -1;
} }
/***************************************************************************** /*****************************************************************************
...@@ -1163,7 +1198,7 @@ static void DVDSeek( input_thread_t * p_input, off_t i_off ) ...@@ -1163,7 +1198,7 @@ static void DVDSeek( input_thread_t * p_input, off_t i_off )
p_dvd->i_sector = i_pos >> 11; p_dvd->i_sector = i_pos >> 11;
i_prg_cell = 0; i_prg_cell = 0;
i_chapter = 1; i_chapter = 0;
/* parse vobu address map to find program cell */ /* parse vobu address map to find program cell */
while( title.p_cell_play[i_prg_cell].i_end_sector < p_dvd->i_sector ) while( title.p_cell_play[i_prg_cell].i_end_sector < p_dvd->i_sector )
...@@ -1224,8 +1259,9 @@ static void DVDSeek( input_thread_t * p_input, off_t i_off ) ...@@ -1224,8 +1259,9 @@ static void DVDSeek( input_thread_t * p_input, off_t i_off )
{ {
i_angle = 0; i_angle = 0;
} }
while( title.chapter_map.pi_start_cell[i_chapter-1] <= while( ( title.chapter_map.pi_start_cell[i_chapter] <=
( p_dvd->i_prg_cell - i_angle ) ) ( p_dvd->i_prg_cell - i_angle + 1 ) ) &&
( i_chapter < ( p_dvd->i_chapter_nb - 1 ) ) )
{ {
i_chapter++; i_chapter++;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* intf_gnome.c: Gnome interface * intf_gnome.c: Gnome interface
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * 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> * Authors: Samuel Hocevar <sam@zoy.org>
* Stphane Borel <stef@via.ecp.fr> * Stphane Borel <stef@via.ecp.fr>
...@@ -444,7 +444,7 @@ static gint GnomeLanguageMenus( gpointer p_data, ...@@ -444,7 +444,7 @@ static gint GnomeLanguageMenus( gpointer p_data,
GtkWidget * p_item; GtkWidget * p_item;
GtkWidget * p_item_active; GtkWidget * p_item_active;
GSList * p_group; GSList * p_group;
char * psz_name; char psz_name[12];
gint i_item; gint i_item;
gint i; gint i;
...@@ -463,7 +463,7 @@ static gint GnomeLanguageMenus( gpointer p_data, ...@@ -463,7 +463,7 @@ static gint GnomeLanguageMenus( gpointer p_data,
p_menu = gtk_menu_new(); p_menu = gtk_menu_new();
/* special case for "off" item */ /* 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_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 ) ); p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
...@@ -491,7 +491,7 @@ static gint GnomeLanguageMenus( gpointer p_data, ...@@ -491,7 +491,7 @@ static gint GnomeLanguageMenus( gpointer p_data,
if( p_intf->p_input->stream.pp_es[i]->i_cat == i_cat ) if( p_intf->p_input->stream.pp_es[i]->i_cat == i_cat )
{ {
i_item++; 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' ) if( psz_name[0] == '\0' )
{ {
sprintf( psz_name, "Language %d", i_item ); sprintf( psz_name, "Language %d", i_item );
...@@ -547,7 +547,7 @@ static gint GnomeAngleMenu( gpointer p_data, GtkWidget * p_angle, ...@@ -547,7 +547,7 @@ static gint GnomeAngleMenu( gpointer p_data, GtkWidget * p_angle,
void(*pf_toggle)( GtkCheckMenuItem *, gpointer ) ) void(*pf_toggle)( GtkCheckMenuItem *, gpointer ) )
{ {
intf_thread_t * p_intf; intf_thread_t * p_intf;
char psz_name[10]; char psz_name[12];
GtkWidget * p_angle_menu; GtkWidget * p_angle_menu;
GSList * p_angle_group; GSList * p_angle_group;
GtkWidget * p_item; GtkWidget * p_item;
...@@ -618,7 +618,7 @@ static gint GnomeChapterMenu( gpointer p_data, GtkWidget * p_chapter, ...@@ -618,7 +618,7 @@ static gint GnomeChapterMenu( gpointer p_data, GtkWidget * p_chapter,
void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) ) void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
{ {
intf_thread_t * p_intf; intf_thread_t * p_intf;
char psz_name[10]; char psz_name[12];
GtkWidget * p_chapter_menu; GtkWidget * p_chapter_menu;
GtkWidget * p_chapter_submenu; GtkWidget * p_chapter_submenu;
GtkWidget * p_menu_item; GtkWidget * p_menu_item;
...@@ -733,7 +733,7 @@ static gint GnomeTitleMenu( gpointer p_data, ...@@ -733,7 +733,7 @@ static gint GnomeTitleMenu( gpointer p_data,
void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) ) void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
{ {
intf_thread_t * p_intf; intf_thread_t * p_intf;
char psz_name[10]; char psz_name[12];
GtkWidget * p_title_menu; GtkWidget * p_title_menu;
GtkWidget * p_title_submenu; GtkWidget * p_title_submenu;
GtkWidget * p_title_item; GtkWidget * p_title_item;
......
/*****************************************************************************
* 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: Stphane 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;
}
/*****************************************************************************
* 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: Stphane 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
/*****************************************************************************
* 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: Stphane 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;
}
}
/*****************************************************************************
* 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
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* aout_common.h: audio output inner functions * aout_common.h: audio output inner functions
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN * 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> * Authors: Michel Kaempf <maxx@via.ecp.fr>
* *
...@@ -32,6 +32,7 @@ void aout_U16MonoThread ( aout_thread_t * p_aout ); ...@@ -32,6 +32,7 @@ void aout_U16MonoThread ( aout_thread_t * p_aout );
void aout_U16StereoThread ( aout_thread_t * p_aout ); void aout_U16StereoThread ( aout_thread_t * p_aout );
void aout_S16MonoThread ( aout_thread_t * p_aout ); void aout_S16MonoThread ( aout_thread_t * p_aout );
void aout_S16StereoThread ( 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 ) \ #define UPDATE_INCREMENT( increment, integer ) \
if ( ((increment).l_remainder += (increment).l_euclidean_remainder) >= 0 )\ if ( ((increment).l_remainder += (increment).l_euclidean_remainder) >= 0 )\
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* audio_output.c : audio output thread * audio_output.c : audio output thread
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN * 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> * Authors: Michel Kaempf <maxx@via.ecp.fr>
* *
...@@ -119,6 +119,14 @@ aout_thread_t *aout_CreateThread( int *pi_status ) ...@@ -119,6 +119,14 @@ aout_thread_t *aout_CreateThread( int *pi_status )
return( NULL ); 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 ?? */ /* FIXME: only works for i_channels == 1 or 2 ?? */
p_aout->b_stereo = ( p_aout->i_channels == 2 ) ? 1 : 0; p_aout->b_stereo = ( p_aout->i_channels == 2 ) ? 1 : 0;
...@@ -209,6 +217,11 @@ static int aout_SpawnThread( aout_thread_t * p_aout ) ...@@ -209,6 +217,11 @@ static int aout_SpawnThread( aout_thread_t * p_aout )
l_bytes = 1 * sizeof(s16) * p_aout->l_units; l_bytes = 1 * sizeof(s16) * p_aout->l_units;
aout_thread = (void *)aout_S16MonoThread; aout_thread = (void *)aout_S16MonoThread;
break; 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)", intf_ErrMsg( "aout error: unknown audio output format (%i)",
...@@ -246,7 +259,6 @@ static int aout_SpawnThread( aout_thread_t * p_aout ) ...@@ -246,7 +259,6 @@ static int aout_SpawnThread( aout_thread_t * p_aout )
l_bytes = 2 * sizeof(s16) * p_aout->l_units; l_bytes = 2 * sizeof(s16) * p_aout->l_units;
aout_thread = (void *)aout_S16StereoThread; aout_thread = (void *)aout_S16StereoThread;
break; break;
default: default:
intf_ErrMsg( "aout error: unknown audio output format %i", intf_ErrMsg( "aout error: unknown audio output format %i",
p_aout->i_format ); p_aout->i_format );
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_programs.c: es_descriptor_t, pgrm_descriptor_t management * input_programs.c: es_descriptor_t, pgrm_descriptor_t management
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * 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> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -599,6 +599,8 @@ static adec_config_t * GetAdecConfig( input_thread_t * p_input, ...@@ -599,6 +599,8 @@ static adec_config_t * GetAdecConfig( input_thread_t * p_input,
/* FIXME */ /* FIXME */
vlc_thread_t adec_CreateThread( void * ); vlc_thread_t adec_CreateThread( void * );
vlc_thread_t ac3dec_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 vpar_CreateThread( void * );
vlc_thread_t spudec_CreateThread( void * ); vlc_thread_t spudec_CreateThread( void * );
...@@ -658,8 +660,16 @@ int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es ) ...@@ -658,8 +660,16 @@ int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es )
case AC3_AUDIO_ES: case AC3_AUDIO_ES:
if( p_main->b_audio ) if( p_main->b_audio )
{
if( !p_main->b_spdif )
{ {
decoder.pf_create_thread = ac3dec_CreateThread; decoder.pf_create_thread = ac3dec_CreateThread;
}
else
{
decoder.pf_create_thread = spdif_CreateThread;
}
p_config = (void *)GetAdecConfig( p_input, p_es ); p_config = (void *)GetAdecConfig( p_input, p_es );
/* Release the lock, not to block the input thread during /* Release the lock, not to block the input thread during
...@@ -669,7 +679,30 @@ int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es ) ...@@ -669,7 +679,30 @@ int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es )
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
} }
break; 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: case DVD_SPU_ES:
if( p_main->b_video ) if( p_main->b_video )
{ {
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* and spawn threads. * and spawn threads.
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN * 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> * Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org> * Samuel Hocevar <sam@zoy.org>
...@@ -94,6 +94,7 @@ ...@@ -94,6 +94,7 @@
#define OPT_NOAUDIO 150 #define OPT_NOAUDIO 150
#define OPT_STEREO 151 #define OPT_STEREO 151
#define OPT_MONO 152 #define OPT_MONO 152
#define OPT_SPDIF 153
#define OPT_NOVIDEO 160 #define OPT_NOVIDEO 160
#define OPT_DISPLAY 161 #define OPT_DISPLAY 161
...@@ -141,6 +142,7 @@ static const struct option longopts[] = ...@@ -141,6 +142,7 @@ static const struct option longopts[] =
{ "aout", 1, 0, 'A' }, { "aout", 1, 0, 'A' },
{ "stereo", 0, 0, OPT_STEREO }, { "stereo", 0, 0, OPT_STEREO },
{ "mono", 0, 0, OPT_MONO }, { "mono", 0, 0, OPT_MONO },
{ "spdif", 0, 0, OPT_SPDIF },
/* Video options */ /* Video options */
{ "novideo", 0, 0, OPT_NOVIDEO }, { "novideo", 0, 0, OPT_NOVIDEO },
...@@ -522,6 +524,7 @@ static int GetConfiguration( int *pi_argc, char *ppsz_argv[], char *ppsz_env[] ) ...@@ -522,6 +524,7 @@ static int GetConfiguration( int *pi_argc, char *ppsz_argv[], char *ppsz_env[] )
p_main->b_audio = 1; p_main->b_audio = 1;
p_main->b_video = 1; p_main->b_video = 1;
p_main->b_channels = 0; p_main->b_channels = 0;
p_main->b_spdif = 0;
p_main->i_warning_level = 4; p_main->i_warning_level = 4;
...@@ -605,6 +608,9 @@ static int GetConfiguration( int *pi_argc, char *ppsz_argv[], char *ppsz_env[] ) ...@@ -605,6 +608,9 @@ static int GetConfiguration( int *pi_argc, char *ppsz_argv[], char *ppsz_env[] )
case OPT_MONO: /* --mono */ case OPT_MONO: /* --mono */
main_PutIntVariable( AOUT_STEREO_VAR, 0 ); main_PutIntVariable( AOUT_STEREO_VAR, 0 );
break; break;
case OPT_SPDIF: /* --spdif */
p_main->b_spdif = 1;
break;
/* Video options */ /* Video options */
case OPT_NOVIDEO: /* --novideo */ case OPT_NOVIDEO: /* --novideo */
...@@ -757,6 +763,7 @@ static void Usage( int i_fashion ) ...@@ -757,6 +763,7 @@ static void Usage( int i_fashion )
"\n --noaudio \tdisable audio" "\n --noaudio \tdisable audio"
"\n -A, --aout <module> \taudio output method" "\n -A, --aout <module> \taudio output method"
"\n --stereo, --mono \tstereo/mono audio" "\n --stereo, --mono \tstereo/mono audio"
"\n --spdif \tac3 pass-through mode"
"\n" "\n"
"\n --novideo \tdisable video" "\n --novideo \tdisable video"
"\n -V, --vout <module> \tvideo output method" "\n -V, --vout <module> \tvideo output method"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment