vlc | branch: master | Alan Fischer <[email protected]> | Fri Dec 10 17:34:57 2010 -0600| [eaa7e2e869d2c9b5e37862611b9b15353612528d] | committer: Rémi Denis-Courmont
Added C64 sid demux module Signed-off-by: Rémi Denis-Courmont <[email protected]> > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=eaa7e2e869d2c9b5e37862611b9b15353612528d --- configure.ac | 6 + modules/demux/Modules.am | 1 + modules/demux/sid.cpp | 283 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 290 insertions(+), 0 deletions(-) diff --git a/configure.ac b/configure.ac index 6333e1e..82c54c0 100644 --- a/configure.ac +++ b/configure.ac @@ -2310,6 +2310,12 @@ AS_IF([test "${enable_gme}" != "no"], [ dnl +dnl SIDPlay plugin +dnl +PKG_ENABLE_MODULES_VLC([SID], [], [libsidplay2], [C64 sid demux support], [auto], [], [-lresid-builder]) + + +dnl dnl ogg demux plugin dnl PKG_ENABLE_MODULES_VLC([OGG], [], [ogg >= 1.0], [Ogg demux support], [auto]) diff --git a/modules/demux/Modules.am b/modules/demux/Modules.am index e4950e4..f05c16b 100644 --- a/modules/demux/Modules.am +++ b/modules/demux/Modules.am @@ -30,6 +30,7 @@ SOURCES_vc1 = vc1.c SOURCES_demux_cdg = cdg.c SOURCES_smf = smf.c SOURCES_gme = gme.c dummy.cpp +SOURCES_sid = sid.cpp SOURCES_dirac = dirac.c SOURCES_image = image.c diff --git a/modules/demux/sid.cpp b/modules/demux/sid.cpp new file mode 100644 index 0000000..2fac337 --- /dev/null +++ b/modules/demux/sid.cpp @@ -0,0 +1,283 @@ +/** + * @file sid.cpp + * @brief Sidplay demux module for VLC media player + */ +/***************************************************************************** + * Copyright © 2010 Rémi Denis-Courmont + * Copyright © 2010 Alan Fischer <[email protected]> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library 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 Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +/* INT64_C and UINT64_C are only exposed to c++ if this is defined */ +#ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +#endif + +#include <vlc_common.h> +#include <vlc_input.h> +#include <vlc_demux.h> +#include <vlc_plugin.h> + +#include <limits.h> + +#include <sidplay/sidplay2.h> +#include <sidplay/builders/resid.h> + +static int Open (vlc_object_t *); +static void Close (vlc_object_t *); + +vlc_module_begin () + set_shortname ("sid") + set_description ( N_("C64 sid demuxer") ) + set_category (CAT_INPUT) + set_subcategory (SUBCAT_INPUT_DEMUX) + set_capability ("demux", 100) + set_callbacks (Open, Close) +vlc_module_end () + +struct demux_sys_t +{ + sidplay2 *player; + sid2_config_t config; + sid2_info_t info; + SidTune *tune; + SidTuneInfo tuneInfo; + + int bytes_per_frame; + int block_size; + es_out_id_t *es; + date_t pts; +}; + + +static int Demux (demux_t *); +static int Control (demux_t *, int, va_list); + +static int Open (vlc_object_t *obj) +{ + demux_t *demux = (demux_t *)obj; + demux_sys_t *sys = NULL; + es_format_t fmt; + bool result = false; + SidTune *tune = NULL; + sidplay2 *player = NULL; + ReSIDBuilder *builder = NULL; + + int64_t size = stream_Size (demux->s); + if (size < 4 || size > LONG_MAX) /* We need to load the whole file for sidplay */ + return VLC_EGENERIC; + + const uint8_t *peek; + if (stream_Peek (demux->s, &peek, 4) < 4) + return VLC_EGENERIC; + + /* sidplay2 can read PSID and the newer RSID formats */ + if(memcmp(peek,"PSID",4)!=0 && memcmp(peek,"RSID",4)!=0) + return VLC_EGENERIC; + + uint8_t *data = (uint8_t*) malloc(size); + if (unlikely (data==NULL)) + goto error; + + if (stream_Read (demux->s,data,size) < size) { + free (data); + goto error; + } + + tune = new SidTune(0); + if (unlikely (tune==NULL)) { + free (data); + goto error; + } + + result = tune->read (data, size); + free (data); + if (result==false) + goto error; + + player = new sidplay2(); + if (unlikely(player==NULL)) + goto error; + + sys = (demux_sys_t*) calloc (1, sizeof(demux_sys_t)); + if (unlikely(sys==NULL)) + goto error; + + sys->player = player; + sys->tune = tune; + + tune->getInfo (sys->tuneInfo); + + sys->info = player->info(); + sys->config = player->config(); + + builder = new ReSIDBuilder ("ReSID"); + if (unlikely(builder==NULL)) + goto error; + + builder->create (sys->info.maxsids); + builder->sampling (sys->config.frequency); + + sys->config.sidEmulation = builder; + sys->config.precision = 16; + sys->config.playback = (sys->info.channels == 2 ? sid2_stereo : sid2_mono); + + player->config (sys->config); + + sys->bytes_per_frame = sys->info.channels * sys->config.precision / 8; + sys->block_size = sys->config.frequency / 10 * sys->bytes_per_frame; + + es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_S16N); + + fmt.audio.i_channels = sys->info.channels; + fmt.audio.i_bitspersample = sys->config.precision; + fmt.audio.i_rate = sys->config.frequency; + fmt.audio.i_bytes_per_frame = sys->bytes_per_frame; + fmt.audio.i_frame_length = fmt.audio.i_bytes_per_frame; + fmt.audio.i_blockalign = fmt.audio.i_bytes_per_frame; + + fmt.i_bitrate = fmt.audio.i_rate * fmt.audio.i_bytes_per_frame; + + sys->es = es_out_Add (demux->out, &fmt); + + date_Init (&sys->pts, fmt.audio.i_rate, 1); + date_Set (&sys->pts, 0); + + sys->tune->selectSong (0); + result = (sys->player->load (sys->tune) >=0 ); + sys->player->fastForward (100); + if (result==false) + goto error; + + /* Callbacks */ + demux->pf_demux = Demux; + demux->pf_control = Control; + demux->p_sys = sys; + + return VLC_SUCCESS; + +error: + msg_Err (demux, "An error occured during sid demuxing" ); + delete player; + delete builder; + delete tune; + free (sys); + return VLC_EGENERIC; +} + + +static void Close (vlc_object_t *obj) +{ + demux_t *demux = (demux_t *)obj; + demux_sys_t *sys = demux->p_sys; + + delete sys->player; + delete sys->config.sidEmulation; + delete sys->tune; + free (sys); +} + +static int Demux (demux_t *demux) +{ + demux_sys_t *sys = demux->p_sys; + + block_t *block = block_New( p_demux, sys->block_size); + if (unlikely(block==NULL)) + return 0; + + if (sys->tune->getStatus() == false) { + block_Release (block); + return 0; + } + + int i_read = sys->player->play ((void*)block->p_buffer, block->i_buffer); + if (i_read <= 0) { + block_Release (block); + return 0; + } + block->i_buffer = i_read; + block->i_pts = block->i_dts = VLC_TS_0 + date_Get (&sys->pts); + + es_out_Control (demux->out, ES_OUT_SET_PCR, block->i_pts); + + es_out_Send (demux->out, sys->es, block); + + date_Increment (&sys->pts, i_read / sys->bytes_per_frame); + + return 1; +} + + +static int Control (demux_t *demux, int query, va_list args) +{ + demux_sys_t *sys = demux->p_sys; + + switch (query) + { + case DEMUX_GET_TIME : { + int64_t *v = va_arg (args, int64_t*); + *v = sys->player->time() * sys->player->timebase() * (CLOCK_FREQ / 100); + return VLC_SUCCESS; + } + + case DEMUX_GET_META : { + vlc_meta_t *p_meta = (vlc_meta_t *) va_arg (args, vlc_meta_t*); + + /* These are specified in the sid tune class as 0 = Title, 1 = Artist, 2 = Copyright/Publisher */ + vlc_meta_SetTitle( p_meta, sys->tuneInfo.infoString[0] ); + vlc_meta_SetArtist( p_meta, sys->tuneInfo.infoString[1] ); + vlc_meta_SetCopyright( p_meta, sys->tuneInfo.infoString[2] ); + + return VLC_SUCCESS; + } + + case DEMUX_GET_TITLE_INFO : + if ( sys->tuneInfo.songs > 1 ) { + input_title_t ***ppp_title = (input_title_t***) va_arg (args, input_title_t***); + int *pi_int = (int*)va_arg( args, int* ); + + *pi_int = sys->tuneInfo.songs; + *ppp_title = (input_title_t**) malloc( sizeof (input_title_t**) * sys->tuneInfo.songs); + + for( int i = 0; i < sys->tuneInfo.songs; i++ ) { + (*ppp_title)[i] = vlc_input_title_New(); + } + + return VLC_SUCCESS; + } + return VLC_EGENERIC; + + case DEMUX_SET_TITLE : { + int i_idx = (int) va_arg (args, int); + sys->tune->selectSong (i_idx+1); + bool result = (sys->player->load (sys->tune) >=0 ); + if (result == false) + return VLC_EGENERIC; + + demux->info.i_title = i_idx; + demux->info.i_update = INPUT_UPDATE_TITLE; + msg_Dbg( demux, "set song %i", i_idx); + + return VLC_SUCCESS; + } + } + + return VLC_EGENERIC; +} _______________________________________________ vlc-commits mailing list [email protected] http://mailman.videolan.org/listinfo/vlc-commits
