Ported sidplay.

Original commit message from CVS:
* configure.ac:
* ext/sidplay/gstsiddec.cc:
* ext/sidplay/gstsiddec.h:
Ported sidplay.
This commit is contained in:
Wim Taymans 2005-05-06 17:24:44 +00:00
parent 8493bcee4f
commit 9c1aaafba4
4 changed files with 172 additions and 104 deletions

View file

@ -1,3 +1,10 @@
2005-05-06 Wim Taymans <wim@fluendo.com>
* configure.ac:
* ext/sidplay/gstsiddec.cc:
* ext/sidplay/gstsiddec.h:
Ported sidplay.
2005-05-06 Christian Schaller <uraeus@gnome.org> 2005-05-06 Christian Schaller <uraeus@gnome.org>
* configure.ac: * configure.ac:

View file

@ -295,7 +295,8 @@ dnl these are all the gst plug-ins, compilable without additional libs
GST_PLUGINS_ALL="\ GST_PLUGINS_ALL="\
videofilter \ videofilter \
effectv \ effectv \
law" law \
sidplay"
dnl see if we can build C++ plug-ins dnl see if we can build C++ plug-ins
if test "x$HAVE_CXX" = "xyes"; then if test "x$HAVE_CXX" = "xyes"; then
@ -348,6 +349,12 @@ dnl ])
dnl ]) dnl ])
dnl ]) dnl ])
dnl *** sidplay : works with libsidplay 1.36.x (not 2.x.x) ***
translit(dnm, m, l) AM_CONDITIONAL(USE_SIDPLAY, true)
GST_CHECK_FEATURE(SIDPLAY, [sidplay plug-in], sidplay, [
GST_PATH_SIDPLAY()
])
dnl *** mad *** dnl *** mad ***
dnl FIXME: we could use header checks here as well IMO dnl FIXME: we could use header checks here as well IMO
translit(dnm, m, l) AM_CONDITIONAL(USE_MAD, true) translit(dnm, m, l) AM_CONDITIONAL(USE_MAD, true)
@ -431,6 +438,7 @@ gst/videofilter/Makefile
sys/Makefile sys/Makefile
ext/Makefile ext/Makefile
ext/mad/Makefile ext/mad/Makefile
ext/sidplay/Makefile
common/Makefile common/Makefile
common/m4/Makefile common/m4/Makefile
m4/Makefile m4/Makefile

View file

@ -68,12 +68,6 @@ static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
"rate = (int) [ 8000, 48000 ], " "channels = (int) [ 1, 2 ]") "rate = (int) [ 8000, 48000 ], " "channels = (int) [ 1, 2 ]")
); );
enum
{
SID_STATE_NEED_TUNE = 1,
SID_STATE_LOAD_TUNE = 2,
SID_STATE_PLAY_TUNE = 3
};
#define GST_TYPE_SID_CLOCK (gst_sid_clock_get_type()) #define GST_TYPE_SID_CLOCK (gst_sid_clock_get_type())
static GType static GType
@ -114,7 +108,8 @@ static void gst_siddec_base_init (gpointer g_class);
static void gst_siddec_class_init (GstSidDec * klass); static void gst_siddec_class_init (GstSidDec * klass);
static void gst_siddec_init (GstSidDec * siddec); static void gst_siddec_init (GstSidDec * siddec);
static void gst_siddec_loop (GstElement * element); static GstFlowReturn gst_siddec_chain (GstPad * pad, GstBuffer * buffer);
static gboolean gst_siddec_sink_event (GstPad * pad, GstEvent * event);
static gboolean gst_siddec_src_convert (GstPad * pad, GstFormat src_format, static gboolean gst_siddec_src_convert (GstPad * pad, GstFormat src_format,
gint64 src_value, GstFormat * dest_format, gint64 * dest_value); gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
@ -187,6 +182,9 @@ gst_siddec_class_init (GstSidDec * klass)
parent_class = GST_ELEMENT_CLASS (g_type_class_ref (GST_TYPE_ELEMENT)); parent_class = GST_ELEMENT_CLASS (g_type_class_ref (GST_TYPE_ELEMENT));
gobject_class->set_property = gst_siddec_set_property;
gobject_class->get_property = gst_siddec_get_property;
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TUNE, g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TUNE,
g_param_spec_int ("tune", "tune", "tune", g_param_spec_int ("tune", "tune", "tune",
1, 100, 1, (GParamFlags) G_PARAM_READWRITE)); 1, 100, 1, (GParamFlags) G_PARAM_READWRITE));
@ -216,9 +214,6 @@ gst_siddec_class_init (GstSidDec * klass)
g_object_class_install_property (gobject_class, ARG_METADATA, g_object_class_install_property (gobject_class, ARG_METADATA,
g_param_spec_boxed ("metadata", "Metadata", "Metadata", GST_TYPE_CAPS, g_param_spec_boxed ("metadata", "Metadata", "Metadata", GST_TYPE_CAPS,
(GParamFlags) G_PARAM_READABLE)); (GParamFlags) G_PARAM_READABLE));
gobject_class->set_property = gst_siddec_set_property;
gobject_class->get_property = gst_siddec_get_property;
} }
static void static void
@ -227,9 +222,11 @@ gst_siddec_init (GstSidDec * siddec)
siddec->sinkpad = siddec->sinkpad =
gst_pad_new_from_template (gst_static_pad_template_get (&sink_templ), gst_pad_new_from_template (gst_static_pad_template_get (&sink_templ),
"sink"); "sink");
gst_element_add_pad (GST_ELEMENT (siddec), siddec->sinkpad);
gst_pad_set_query_function (siddec->sinkpad, NULL); gst_pad_set_query_function (siddec->sinkpad, NULL);
gst_pad_set_convert_function (siddec->sinkpad, NULL); gst_pad_set_convert_function (siddec->sinkpad, NULL);
gst_pad_set_event_function (siddec->sinkpad, gst_siddec_sink_event);
gst_pad_set_chain_function (siddec->sinkpad, gst_siddec_chain);
gst_element_add_pad (GST_ELEMENT (siddec), siddec->sinkpad);
siddec->srcpad = siddec->srcpad =
gst_pad_new_from_template (gst_static_pad_template_get (&src_templ), gst_pad_new_from_template (gst_static_pad_template_get (&src_templ),
@ -239,8 +236,6 @@ gst_siddec_init (GstSidDec * siddec)
gst_pad_set_query_function (siddec->srcpad, gst_siddec_src_query); gst_pad_set_query_function (siddec->srcpad, gst_siddec_src_query);
gst_element_add_pad (GST_ELEMENT (siddec), siddec->srcpad); gst_element_add_pad (GST_ELEMENT (siddec), siddec->srcpad);
gst_element_set_loop_function (GST_ELEMENT (siddec), gst_siddec_loop);
siddec->engine = new emuEngine (); siddec->engine = new emuEngine ();
siddec->tune = new sidTune (0); siddec->tune = new sidTune (0);
siddec->config = (emuConfig *) g_malloc (sizeof (emuConfig)); siddec->config = (emuConfig *) g_malloc (sizeof (emuConfig));
@ -267,7 +262,6 @@ gst_siddec_init (GstSidDec * siddec)
siddec->engine->setConfig (*siddec->config); siddec->engine->setConfig (*siddec->config);
siddec->engine->setDefaultFilterStrength (); siddec->engine->setDefaultFilterStrength ();
siddec->state = SID_STATE_NEED_TUNE;
siddec->tune_buffer = (guchar *) g_malloc (maxSidtuneFileLen); siddec->tune_buffer = (guchar *) g_malloc (maxSidtuneFileLen);
siddec->tune_len = 0; siddec->tune_len = 0;
siddec->tune_number = 1; siddec->tune_number = 1;
@ -358,16 +352,14 @@ siddec_negotiate (GstSidDec * siddec)
siddec->config->sampleFormat = siddec->config->sampleFormat =
(sign ? SIDEMU_SIGNED_PCM : SIDEMU_UNSIGNED_PCM); (sign ? SIDEMU_SIGNED_PCM : SIDEMU_UNSIGNED_PCM);
if (!gst_pad_try_set_caps (siddec->srcpad, gst_pad_set_caps (siddec->srcpad,
gst_caps_new_simple ("audio/x-raw-int", gst_caps_new_simple ("audio/x-raw-int",
"endianness", G_TYPE_INT, G_BYTE_ORDER, "endianness", G_TYPE_INT, G_BYTE_ORDER,
"signed", G_TYPE_BOOLEAN, sign, "signed", G_TYPE_BOOLEAN, sign,
"width", G_TYPE_INT, siddec->config->bitsPerSample, "width", G_TYPE_INT, siddec->config->bitsPerSample,
"depth", G_TYPE_INT, siddec->config->bitsPerSample, "depth", G_TYPE_INT, siddec->config->bitsPerSample,
"rate", G_TYPE_INT, siddec->config->frequency, "rate", G_TYPE_INT, siddec->config->frequency,
"channels", G_TYPE_INT, siddec->config->channels, NULL))) { "channels", G_TYPE_INT, siddec->config->channels, NULL));
return FALSE;
}
siddec->engine->setConfig (*siddec->config); siddec->engine->setConfig (*siddec->config);
@ -375,97 +367,159 @@ siddec_negotiate (GstSidDec * siddec)
} }
static void static void
gst_siddec_loop (GstElement * element) play_loop (GstPad * pad)
{
GstFlowReturn ret;
GstSidDec *siddec;
GstBuffer *out;
GstFormat format;
gint64 value, offset, time;
siddec = GST_SIDDEC (GST_PAD_PARENT (pad));
GST_STREAM_LOCK (pad);
out = gst_buffer_new_and_alloc (siddec->blocksize);
gst_buffer_set_caps (out, GST_PAD_CAPS (pad));
sidEmuFillBuffer (*siddec->engine, *siddec->tune,
GST_BUFFER_DATA (out), GST_BUFFER_SIZE (out));
/* get offset in samples */
format = GST_FORMAT_DEFAULT;
gst_siddec_src_query (siddec->srcpad, GST_QUERY_POSITION, &format, &offset);
GST_BUFFER_OFFSET (out) = offset;
/* get current timestamp */
format = GST_FORMAT_TIME;
gst_siddec_src_query (siddec->srcpad, GST_QUERY_POSITION, &format, &time);
GST_BUFFER_TIMESTAMP (out) = time;
/* update position and get new timestamp to calculate duration */
siddec->total_bytes += siddec->blocksize;
/* get offset in samples */
format = GST_FORMAT_DEFAULT;
gst_siddec_src_query (siddec->srcpad, GST_QUERY_POSITION, &format, &value);
GST_BUFFER_OFFSET_END (out) = value;
format = GST_FORMAT_TIME;
gst_siddec_src_query (siddec->srcpad, GST_QUERY_POSITION, &format, &value);
GST_BUFFER_DURATION (out) = value - time;
if ((ret = gst_pad_push (siddec->srcpad, out)) != GST_FLOW_OK)
goto pause;
GST_STREAM_UNLOCK (pad);
return;
pause:
{
gst_task_pause (GST_RPAD_TASK (pad));
GST_STREAM_UNLOCK (pad);
}
}
static gboolean
start_play_tune (GstSidDec * siddec)
{
gboolean res;
if (!siddec->tune->load (siddec->tune_buffer, siddec->tune_len))
goto could_not_load;
//update_metadata (siddec);
if (!siddec_negotiate (siddec))
goto could_not_negotiate;
if (!sidEmuInitializeSong (*siddec->engine, *siddec->tune,
siddec->tune_number))
goto could_not_init;
if (GST_ELEMENT_SCHEDULER (siddec)) {
GST_STREAM_LOCK (siddec->srcpad);
GST_RPAD_TASK (siddec->srcpad) =
gst_scheduler_create_task (GST_ELEMENT_SCHEDULER (siddec),
(GstTaskFunction) play_loop, siddec->srcpad);
gst_task_start (GST_RPAD_TASK (siddec->srcpad));
GST_STREAM_UNLOCK (siddec->srcpad);
res = TRUE;
}
return res;
/* ERRORS */
could_not_load:
{
GST_ELEMENT_ERROR (siddec, LIBRARY, TOO_LAZY, (NULL), (NULL));
return FALSE;
}
could_not_negotiate:
{
GST_ELEMENT_ERROR (siddec, CORE, NEGOTIATION, (NULL), (NULL));
return FALSE;
}
could_not_init:
{
GST_ELEMENT_ERROR (siddec, LIBRARY, TOO_LAZY, (NULL), (NULL));
return FALSE;
}
}
static gboolean
gst_siddec_sink_event (GstPad * pad, GstEvent * event)
{ {
GstSidDec *siddec; GstSidDec *siddec;
gboolean res;
siddec = GST_SIDDEC (element); siddec = GST_SIDDEC (GST_PAD_PARENT (pad));
if (siddec->state == SID_STATE_NEED_TUNE) { switch (GST_EVENT_TYPE (event)) {
GstData *data = gst_pad_pull (siddec->sinkpad); case GST_EVENT_EOS:
GST_STREAM_LOCK (pad);
g_assert (data != NULL); res = start_play_tune (siddec);
GST_STREAM_UNLOCK (pad);
if (GST_IS_EVENT (data)) { break;
GstEvent *event = GST_EVENT (data); case GST_EVENT_DISCONTINUOUS:
res = FALSE;
switch (GST_EVENT_TYPE (event)) { break;
case GST_EVENT_EOS: default:
siddec->state = SID_STATE_LOAD_TUNE; res = FALSE;
break; break;
case GST_EVENT_DISCONTINUOUS:
break;
default:
// bail out, we're not going to do anything
gst_event_unref (event);
gst_pad_send_event (siddec->srcpad, gst_event_new (GST_EVENT_EOS));
gst_element_set_eos (element);
return;
}
gst_event_unref (event);
} else {
GstBuffer *buf = GST_BUFFER (data);
memcpy (siddec->tune_buffer + siddec->tune_len, GST_BUFFER_DATA (buf),
GST_BUFFER_SIZE (buf));
siddec->tune_len += GST_BUFFER_SIZE (buf);
gst_buffer_unref (buf);
}
} }
if (siddec->state == SID_STATE_LOAD_TUNE) { gst_event_unref (event);
if (!siddec->tune->load (siddec->tune_buffer, siddec->tune_len)) {
GST_ELEMENT_ERROR (siddec, LIBRARY, TOO_LAZY, (NULL), (NULL));
return;
}
//update_metadata (siddec);
if (!siddec_negotiate (siddec)) { return res;
GST_ELEMENT_ERROR (siddec, CORE, NEGOTIATION, (NULL), (NULL)); }
return;
}
if (!sidEmuInitializeSong (*siddec->engine, *siddec->tune, static GstFlowReturn
siddec->tune_number)) { gst_siddec_chain (GstPad * pad, GstBuffer * buffer)
GST_ELEMENT_ERROR (siddec, LIBRARY, TOO_LAZY, (NULL), (NULL)); {
return; GstSidDec *siddec;
} guint64 size;
siddec->state = SID_STATE_PLAY_TUNE; siddec = GST_SIDDEC (GST_PAD_PARENT (pad));
}
if (siddec->state == SID_STATE_PLAY_TUNE) {
GstBuffer *out;
GstFormat format;
gint64 value, offset, time;
out = gst_buffer_new_and_alloc (siddec->blocksize); size = GST_BUFFER_SIZE (buffer);
if (siddec->tune_len + size > maxSidtuneFileLen)
goto overflow;
sidEmuFillBuffer (*siddec->engine, *siddec->tune, GST_STREAM_LOCK (pad);
GST_BUFFER_DATA (out), GST_BUFFER_SIZE (out));
/* get offset in samples */ memcpy (siddec->tune_buffer + siddec->tune_len, GST_BUFFER_DATA (buffer),
format = GST_FORMAT_DEFAULT; size);
gst_siddec_src_query (siddec->srcpad, GST_QUERY_POSITION, &format, &offset); siddec->tune_len += size;
GST_BUFFER_OFFSET (out) = offset;
/* get current timestamp */ GST_STREAM_UNLOCK (pad);
format = GST_FORMAT_TIME;
gst_siddec_src_query (siddec->srcpad, GST_QUERY_POSITION, &format, &time);
GST_BUFFER_TIMESTAMP (out) = time;
/* update position and get new timestamp to calculate duration */ gst_buffer_unref (buffer);
siddec->total_bytes += siddec->blocksize;
/* get offset in samples */ return GST_FLOW_OK;
format = GST_FORMAT_DEFAULT;
gst_siddec_src_query (siddec->srcpad, GST_QUERY_POSITION, &format, &value);
GST_BUFFER_OFFSET_END (out) = value;
format = GST_FORMAT_TIME; overflow:
gst_siddec_src_query (siddec->srcpad, GST_QUERY_POSITION, &format, &value); {
GST_BUFFER_DURATION (out) = value - time; return GST_FLOW_ERROR;
gst_pad_push (siddec->srcpad, GST_DATA (out));
} }
} }
@ -478,7 +532,7 @@ gst_siddec_src_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
GstSidDec *siddec; GstSidDec *siddec;
gint bytes_per_sample; gint bytes_per_sample;
siddec = GST_SIDDEC (gst_pad_get_parent (pad)); siddec = GST_SIDDEC (GST_PAD_PARENT (pad));
bytes_per_sample = bytes_per_sample =
(siddec->config->bitsPerSample >> 3) * siddec->config->channels; (siddec->config->bitsPerSample >> 3) * siddec->config->channels;
@ -545,7 +599,7 @@ gst_siddec_src_query (GstPad * pad, GstQueryType type,
gboolean res = TRUE; gboolean res = TRUE;
GstSidDec *siddec; GstSidDec *siddec;
siddec = GST_SIDDEC (gst_pad_get_parent (pad)); siddec = GST_SIDDEC (GST_PAD_PARENT (pad));
switch (type) { switch (type) {
case GST_QUERY_POSITION: case GST_QUERY_POSITION:

View file

@ -50,7 +50,6 @@ struct _GstSidDec {
GstPad *sinkpad, GstPad *sinkpad,
*srcpad; *srcpad;
gint state;
guchar *tune_buffer; guchar *tune_buffer;
gint tune_len; gint tune_len;
gint tune_number; gint tune_number;