[vlc-commits] commit: Added C64 sid demux module (Alan Fischer )

git at videolan.org git at videolan.org
Sat Dec 11 02:13:41 CET 2010


vlc | branch: master | Alan Fischer <alan at lightningtoads.com> | 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 <remi at remlab.net>

> 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 <alan at lightningtoads.com>
+ *
+ * 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;
+}



More information about the vlc-commits mailing list