Commit fd05dc69 authored by Gildas Bazin's avatar Gildas Bazin

* modules/access/vcdx/*: Brand new VCD input module using libcdio, libvcd and libvcdinfo. Courtesy of Rocky Bernstein.
* modules/access/cddax.c: Brand new CDDA input module using libcdio. Courtesy of Rocky Bernstein.
* modules/LIST: update.
parent 0f814562
dnl Autoconf settings for vlc
dnl $Id: configure.ac,v 1.83 2003/10/04 11:59:59 gbazin Exp $
dnl $Id: configure.ac,v 1.84 2003/10/04 18:55:12 gbazin Exp $
AC_INIT(vlc,0.6.3-cvs)
......@@ -79,7 +79,7 @@ case "${target_os}" in
bsdi*)
SYS=bsdi
CFLAGS_save="${CFLAGS_save} -pthread"; CFLAGS="${CFLAGS_save}"
AX_ADD_LDFLAGS([dvd dvdcss vcd cdda],[-ldvd])
AX_ADD_LDFLAGS([dvd dvdcss vcd cdda vcdx cddax],[-ldvd])
;;
*bsd*)
SYS="${target_os}"
......@@ -1439,6 +1439,29 @@ then
fi
fi
dnl
dnl VCDX and CDX modules
dnl
AC_ARG_ENABLE(vcdx,
[ --enable-vcdx VCD support with Navigation for Linux and Win32 (default enabled)])
if test "${enable_vcdx}" != "no"
then
PKG_CHECK_MODULES(LIBCDIO, libcdio >= 0.63,
enable_cdda="no"
AX_ADD_LDFLAGS([cddax],[$LIBCDIO_LIBS])
AX_ADD_CFLAGS([cddax],[$LIBCDIO_CFLAGS])
AX_ADD_PLUGINS([cddax]),
[AC_MSG_WARN(libcdio library not found)])
PKG_CHECK_MODULES(VCDINFO, libvcdinfo >= 0.7.18-cdio,
enable_vcd="no"
AX_ADD_LDFLAGS([vcdx],[$VCDINFO_LIBS])
AX_ADD_CFLAGS([vcdx],[$VCDINFO_CFLAGS])
AX_ADD_PLUGINS([vcdx]),
[AC_MSG_WARN(vcdinfo library not found)])
fi
dnl
dnl Satellite input module
dnl
......@@ -3360,6 +3383,7 @@ AC_OUTPUT([
modules/access/satellite/Makefile
modules/access/v4l/Makefile
modules/access/vcd/Makefile
modules/access/vcdx/Makefile
modules/access_output/Makefile
modules/audio_filter/Makefile
modules/audio_filter/channel_mixer/Makefile
......
List of vlc plugins (221)
$Id: LIST,v 1.12 2003/09/18 16:46:02 lool Exp $
$Id: LIST,v 1.13 2003/10/04 18:55:13 gbazin Exp $
* a52: A/52 basic parser
* a52: A/52 basic parser/packetizer
* a52old: Old A/52 decoder
* a52sys: A/52 decapsulation demuxer.
* a52tofloat32: A/52 audio converter & decoder plugin, using liba52
......@@ -63,6 +61,8 @@ $Id: LIST,v 1.12 2003/09/18 16:46:02 lool Exp $
* cdda: input module to read audio CDs
* cddax: input module to read audio CDs vi libcdio
* cinepak: Cinepack video decoder
* clone: Clone video filter
......@@ -85,15 +85,9 @@ $Id: LIST,v 1.12 2003/09/18 16:46:02 lool Exp $
* distort: miscellaneous image effects filter.
* downmix3dn: 3D Now! accelerated version of downmix.
* downmix: downmix module, used by the AC3 decoder.
* downmixsse: SSE accelerated version of downmix.
* dshow: DirectShow access plugin for encoding cards under Windows
* dts: DTS basic parser
* dts: DTS basic parser/packetizer
* dtstospdif: Audio converter that encapsulates DTS into S/PDIF
......@@ -196,22 +190,6 @@ $Id: LIST,v 1.12 2003/09/18 16:46:02 lool Exp $
* id3tag: ID3 tag parser/skipper using libid3tag
* idctaltivec: AltiVec accelerated version of idct.
* idctclassic: another version of idct.
* idct: inverse DCT module, used by mpeg_video_old
* idctmmxext: MMX EXT accelerated version of idct.
* idctmmx: MMX accelerated version of idct.
* imdct3dn: 3D Now! Accelerated A/52 DCT
* imdct: IMDCT module for the A/52 decoder
* imdctsse: SSE accelerated A/52 DCT
* invert: inverse video filter.
* ipv4: IPv4 network abstraction layer
......@@ -254,26 +232,14 @@ $Id: LIST,v 1.12 2003/09/18 16:46:02 lool Exp $
* mkv: Matroska demuxer
* motion3dnow: 3D Now! accelerated version of motion.
* motionaltivec: AltiVec accelerated version of motion.
* motionblur: Motion blur filter
* motionmmxext: MMX EXT accelerated version of motion.
* motionmmx: MMX accelerated version of motion.
* motion: motion compensation module for mpeg_video_old
* mp4: MP4 file input module
* mpeg_audio: MPEG audio parser and packetizer
* mpeg_audio: MPEG audio parser/packetizer
* mpeg_system: helper module for TS, PS and PES management
* mpeg_video_old: MPEG and MPEG2 video decoder.
* mpga: MPEG-I/II Audio demuxer
* mpgatofixed32: MPEG-1 & 2 audio layer I,II,III audio decoder using MAD
......@@ -300,20 +266,14 @@ $Id: LIST,v 1.12 2003/09/18 16:46:02 lool Exp $
* oss: audio output module using the OSS /dev/dsp interface.
* packetizer_a52: A/52 audio packetizer
* packetizer_copy: Simple copy packetizer
* packetizer_mpeg4audio: MPEG4 audio packetizer
* packetizer_mpeg4video: MPEG4 video packetizer
* packetizer_mpegaudio: MPEG audio packetizer
* packetizer_mpegvideo: MPEG video packetizer
* packetizer_vorbis: Vorbis packetizer
* pda: interface for iPaq using the Gtk2+ widget set.
* postprocessing_c: Video Postprocessing module
......@@ -378,7 +338,7 @@ $Id: LIST,v 1.12 2003/09/18 16:46:02 lool Exp $
* stream_out_transcode: audio & video transcoder using ffmpeg
* subsdec: Another SPU decoder
* subsdec: Another SPU decoder for text subtitles
* svgalib: SGVAlib output plugin
......@@ -392,7 +352,7 @@ $Id: LIST,v 1.12 2003/09/18 16:46:02 lool Exp $
* test4: Stress test module
* theora: a theora video decoder using the libtheora library.
* theora: a theora video decoder/packetizer using the libtheora library.
* transform: filter for horizontal and vertical image flips and
90 rotations.
......@@ -419,9 +379,11 @@ $Id: LIST,v 1.12 2003/09/18 16:46:02 lool Exp $
* vcd: input module for accessing Video CDs.
* vcdx: input module for accessing Video CDs with navigation & stills
* visual: visualisation system
* vorbis: a vorbis audio decoder using the libvorbis library.
* vorbis: a vorbis audio decoder/packetizer using the libvorbis library.
* vout_directx: video output module using the DirectX API.
......
......@@ -10,3 +10,7 @@ SOURCES_cdda = \
vcd/cdrom.h \
vcd/cdrom_internals.h \
$(NULL)
SOURCES_cddax = \
cddax.c \
vcdx/cdrom.c \
vcdx/cdrom.h
/*****************************************************************************
* cddax.c : CD digital audio input module for vlc using libcdio
*****************************************************************************
* Copyright (C) 2000 VideoLAN
* $Id: cddax.c,v 1.1 2003/10/04 18:55:13 gbazin Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Gildas Bazin <gbazin@netcourrier.com>
* Rocky Bernstein <rocky@panix.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 <stdio.h>
#include <stdlib.h>
#include <vlc/vlc.h>
#include <vlc/input.h>
#include <sys/types.h>
#include <cdio/cdio.h>
#include <cdio/cd_types.h>
#include "codecs.h"
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <string.h>
#include "vcdx/cdrom.h"
/* how many blocks CDDAOpen will read in each loop */
#define CDDA_BLOCKS_ONCE 1
#define CDDA_DATA_ONCE (CDDA_BLOCKS_ONCE * CDIO_CD_FRAMESIZE_RAW)
/*****************************************************************************
* cdda_data_t: CD audio information
*****************************************************************************/
typedef struct cdda_data_s
{
cddev_t *p_cddev; /* CD device descriptor */
int i_nb_tracks; /* Nb of tracks (titles) */
int i_track; /* Current track */
lsn_t i_sector; /* Current Sector */
lsn_t * p_sectors; /* Track sectors */
vlc_bool_t b_end_of_track; /* If the end of track was reached */
} cdda_data_t;
struct demux_sys_t
{
es_descriptor_t *p_es;
mtime_t i_pts;
};
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int CDDAOpen ( vlc_object_t * );
static void CDDAClose ( vlc_object_t * );
static int CDDARead ( input_thread_t *, byte_t *, size_t );
static void CDDASeek ( input_thread_t *, off_t );
static int CDDASetArea ( input_thread_t *, input_area_t * );
static int CDDASetProgram ( input_thread_t *, pgrm_descriptor_t * );
static int CDDAOpenDemux ( vlc_object_t * );
static void CDDACloseDemux ( vlc_object_t * );
static int CDDADemux ( input_thread_t * p_input );
/*****************************************************************************
* Module descriptior
*****************************************************************************/
#define CACHING_TEXT N_("Caching value in ms")
#define CACHING_LONGTEXT N_( \
"Allows you to modify the default caching value for cdda streams. This " \
"value should be set in miliseconds units." )
vlc_module_begin();
set_description( _("CD Audio input") );
set_capability( "access", 75 /* slightly higher than cdda */ );
add_integer( "cddax-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
set_callbacks( CDDAOpen, CDDAClose );
add_shortcut( "cdda" );
add_submodule();
set_description( _("CD Audio demux") );
set_capability( "demux", 0 );
set_callbacks( CDDAOpenDemux, CDDACloseDemux );
add_shortcut( "cdda" );
vlc_module_end();
/*****************************************************************************
* CDDAOpen: open cdda
*****************************************************************************/
static int CDDAOpen( vlc_object_t *p_this )
{
input_thread_t * p_input = (input_thread_t *)p_this;
char * psz_orig;
char * psz_parser;
char * psz_source;
cdda_data_t * p_cdda;
int i;
input_area_t * p_area;
int i_title = 1;
cddev_t *p_cddev;
/* parse the options passed in command line : */
psz_orig = psz_parser = psz_source = strdup( p_input->psz_name );
if( !psz_orig )
{
return( -1 );
}
while( *psz_parser && *psz_parser != '@' )
{
psz_parser++;
}
if( *psz_parser == '@' )
{
/* Found options */
*psz_parser = '\0';
++psz_parser;
if ('T' == *psz_parser || 't' == *psz_parser )
++psz_parser;
i_title = (int)strtol( psz_parser, NULL, 10 );
i_title = i_title ? i_title : 1;
}
if( !*psz_source ) {
/* No source specified, so figure it out. */
if( !p_input->psz_access ) {
free( psz_orig );
return -1;
}
psz_source = config_GetPsz( p_input, MODULE_STRING "-device" );
if( !psz_source ) {
/* Scan for a CD with a VCD in it. */
char **cd_drives =
cdio_get_devices_with_cap(NULL, CDIO_FS_AUDIO, false);
if (NULL == cd_drives) return -1;
if (cd_drives[0] == NULL) {
cdio_free_device_list(cd_drives);
return -1;
}
psz_source = strdup(cd_drives[0]);
cdio_free_device_list(cd_drives);
}
}
/* Open CDDA */
if( !(p_cddev = ioctl_Open( p_this, psz_source )) )
{
msg_Warn( p_input, "could not open %s", psz_source );
free( psz_source );
return -1;
}
free( psz_source );
p_cdda = malloc( sizeof(cdda_data_t) );
if( p_cdda == NULL )
{
msg_Err( p_input, "out of memory" );
free( psz_source );
return -1;
}
p_cdda->p_cddev = p_cddev;
p_input->p_access_data = (void *)p_cdda;
p_input->i_mtu = CDDA_DATA_ONCE;
/* We read the Table Of Content information */
p_cdda->i_nb_tracks = ioctl_GetTracksMap( VLC_OBJECT(p_input),
p_cdda->p_cddev->cdio, &p_cdda->p_sectors );
if( p_cdda->i_nb_tracks < 0 )
msg_Err( p_input, "unable to count tracks" );
else if( p_cdda->i_nb_tracks <= 0 )
msg_Err( p_input, "no audio tracks found" );
if( p_cdda->i_nb_tracks <= 1)
{
ioctl_Close( p_cdda->p_cddev );
free( p_cdda );
return -1;
}
if( i_title >= p_cdda->i_nb_tracks || i_title < 1 )
i_title = 1;
/* Set stream and area data */
vlc_mutex_lock( &p_input->stream.stream_lock );
/* Initialize ES structures */
input_InitStream( p_input, 0 );
/* cdda input method */
p_input->stream.i_method = INPUT_METHOD_CDDA;
p_input->stream.b_pace_control = 1;
p_input->stream.b_seekable = 1;
p_input->stream.i_mux_rate = 44100 * 4 / 50;
#define area p_input->stream.pp_areas
for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ )
{
input_AddArea( p_input, i, 1 );
/* Absolute start offset and size */
area[i]->i_start =
(off_t)p_cdda->p_sectors[i-1] * (off_t)CDIO_CD_FRAMESIZE_RAW;
area[i]->i_size =
(off_t)(p_cdda->p_sectors[i] - p_cdda->p_sectors[i-1])
* (off_t)CDIO_CD_FRAMESIZE_RAW;
}
#undef area
p_area = p_input->stream.pp_areas[i_title];
CDDASetArea( p_input, p_area );
vlc_mutex_unlock( &p_input->stream.stream_lock );
if( !p_input->psz_demux || !*p_input->psz_demux )
{
p_input->psz_demux = "cdda";
}
p_input->pf_read = CDDARead;
p_input->pf_seek = CDDASeek;
p_input->pf_set_area = CDDASetArea;
p_input->pf_set_program = CDDASetProgram;
/* Update default_pts to a suitable value for cdda access */
p_input->i_pts_delay = config_GetInt( p_input, "cddax-caching" ) * 1000;
return 0;
}
/*****************************************************************************
* CDDAClose: closes cdda
*****************************************************************************/
static void CDDAClose( vlc_object_t *p_this )
{
input_thread_t * p_input = (input_thread_t *)p_this;
cdda_data_t *p_cdda = (cdda_data_t *)p_input->p_access_data;
ioctl_Close( p_cdda->p_cddev );
free( p_cdda );
}
/*****************************************************************************
* CDDARead: reads from the CDDA into PES packets.
*****************************************************************************
* Returns -1 in case of error, 0 in case of EOF, otherwise the number of
* bytes.
*****************************************************************************/
static int CDDARead( input_thread_t * p_input, byte_t * p_buffer,
size_t i_len )
{
cdda_data_t * p_cdda;
int i_blocks;
int i_index;
int i_read;
p_cdda = (cdda_data_t *)p_input->p_access_data;
i_read = 0;
/* Compute the number of blocks we have to read */
i_blocks = i_len / CDIO_CD_FRAMESIZE_RAW;
for ( i_index = 0; i_index < i_blocks; i_index++ )
{
if (cdio_read_audio_sector(p_cdda->p_cddev->cdio, p_buffer,
p_cdda->i_sector) != 0)
{
msg_Err( p_input, "could not read sector %d", p_cdda->i_sector );
return -1;
}
p_cdda->i_sector ++;
if ( p_cdda->i_sector == p_cdda->p_sectors[p_cdda->i_track + 1] )
{
input_area_t *p_area;
if ( p_cdda->i_track >= p_cdda->i_nb_tracks - 1 )
return 0; /* EOF */
vlc_mutex_lock( &p_input->stream.stream_lock );
p_area = p_input->stream.pp_areas[
p_input->stream.p_selected_area->i_id + 1 ];
msg_Dbg( p_input, "new title" );
p_area->i_part = 1;
CDDASetArea( p_input, p_area );
vlc_mutex_unlock( &p_input->stream.stream_lock );
}
i_read += CDIO_CD_FRAMESIZE_RAW;
}
if ( i_len % CDIO_CD_FRAMESIZE_RAW ) /* this should not happen */
{
msg_Err( p_input, "must read full sectors" );
}
return i_read;
}
/*****************************************************************************
* CDDASetProgram: Does nothing since a CDDA is mono_program
*****************************************************************************/
static int CDDASetProgram( input_thread_t * p_input,
pgrm_descriptor_t * p_program)
{
return 0;
}
/*****************************************************************************
* CDDASetArea: initialize input data for title x.
* It should be called for each user navigation request.
****************************************************************************/
static int CDDASetArea( input_thread_t * p_input, input_area_t * p_area )
{
cdda_data_t *p_cdda = (cdda_data_t*)p_input->p_access_data;
vlc_value_t val;
/* we can't use the interface slider until initilization is complete */
p_input->stream.b_seekable = 0;
if( p_area != p_input->stream.p_selected_area )
{
/* Change the default area */
p_input->stream.p_selected_area = p_area;
/* Change the current track */
p_cdda->i_track = p_area->i_id - 1;
p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track];
/* Update the navigation variables without triggering a callback */
val.i_int = p_area->i_id;
var_Change( p_input, "title", VLC_VAR_SETVALUE, &val, NULL );
}
p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track];
p_input->stream.p_selected_area->i_tell =
(off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW
- p_input->stream.p_selected_area->i_start;
/* warn interface that something has changed */
p_input->stream.b_seekable = 1;
p_input->stream.b_changed = 1;
return 0;
}
/****************************************************************************
* CDDASeek
****************************************************************************/
static void CDDASeek( input_thread_t * p_input, off_t i_off )
{
cdda_data_t * p_cdda;
p_cdda = (cdda_data_t *) p_input->p_access_data;
p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track]
+ i_off / (off_t)CDIO_CD_FRAMESIZE_RAW;
vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.p_selected_area->i_tell =
(off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW
- p_input->stream.p_selected_area->i_start;
vlc_mutex_unlock( &p_input->stream.stream_lock );
}
/****************************************************************************
* Demux Part
****************************************************************************/
static int CDDAOpenDemux ( vlc_object_t * p_this)
{
input_thread_t *p_input = (input_thread_t *)p_this;
demux_sys_t *p_demux;
WAVEFORMATEX *p_wf;
if( p_input->stream.i_method != INPUT_METHOD_CDDA )
{
return VLC_EGENERIC;
}
p_demux = malloc( sizeof( es_descriptor_t ) );
p_demux->i_pts = 0;
p_demux->p_es = NULL;
p_input->pf_demux = CDDADemux;
p_input->pf_rewind = NULL;
p_input->p_demux_data = p_demux;
vlc_mutex_lock( &p_input->stream.stream_lock );
if( input_AddProgram( p_input, 0, 0) == NULL )
{
msg_Err( p_input, "cannot add program" );
free( p_input->p_demux_data );
return( -1 );
}
p_input->stream.pp_programs[0]->b_is_ok = 0;
p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
/* create our ES */
p_demux->p_es = input_AddES( p_input,
p_input->stream.p_selected_program,
1 /* id */, AUDIO_ES, NULL, 0 );
if( !p_demux->p_es )
{
vlc_mutex_unlock( &p_input->stream.stream_lock );
msg_Err( p_input, "out of memory" );
free( p_input->p_demux_data );
return( -1 );
}
p_demux->p_es->i_stream_id = 1;
p_demux->p_es->i_fourcc = VLC_FOURCC('a','r','a','w');
p_demux->p_es->p_waveformatex = p_wf = malloc( sizeof( WAVEFORMATEX ) );
p_wf->wFormatTag = WAVE_FORMAT_PCM;
p_wf->nChannels = 2;
p_wf->nSamplesPerSec = 44100;
p_wf->nAvgBytesPerSec = 2 * 44100 * 2;
p_wf->nBlockAlign = 4;
p_wf->wBitsPerSample = 16;
p_wf->cbSize = 0;
input_SelectES( p_input, p_demux->p_es );
p_input->stream.p_selected_program->b_is_ok = 1;
vlc_mutex_unlock( &p_input->stream.stream_lock );
return VLC_SUCCESS;
}