summaryrefslogtreecommitdiffstats
path: root/ext/musepack/gstmusepackdec.c
diff options
context:
space:
mode:
authorTim-Philipp Müller <tim@centricular.net>2006-01-24 21:33:25 +0000
committerTim-Philipp Müller <tim@centricular.net>2006-01-24 21:33:25 +0000
commitb92a9c4e2bbd81abe0d90cb31efb926f4e696fc2 (patch)
tree1b31881507183265d775d0512f392fcd45947c31 /ext/musepack/gstmusepackdec.c
parent883bcdafbbd4552cfc2cfa1f96c5b0b807e42037 (diff)
downloadgst-plugins-bad-b92a9c4e2bbd81abe0d90cb31efb926f4e696fc2.tar.gz
gst-plugins-bad-b92a9c4e2bbd81abe0d90cb31efb926f4e696fc2.tar.bz2
gst-plugins-bad-b92a9c4e2bbd81abe0d90cb31efb926f4e696fc2.zip
ext/musepack/: Fix seeking in musepack files (it's still incredibly slow, but I don't think that is our plugin's faul...
Original commit message from CVS: * ext/musepack/gstmusepackdec.c: (gst_musepackdec_base_init), (gst_musepackdec_class_init), (gst_musepackdec_init), (gst_musepackdec_send_newsegment), (gst_musepackdec_handle_seek_event), (gst_musepackdec_src_event), (gst_musepackdec_src_query), (gst_musepackdec_src_convert), (gst_musepack_stream_init), (gst_musepackdec_sink_activate_pull), (gst_musepackdec_loop), (gst_musepackdec_change_state): * ext/musepack/gstmusepackdec.h: * ext/musepack/gstmusepackreader.c: (gst_musepack_reader_peek), (gst_musepack_reader_seek), (gst_musepack_reader_tell), (gst_musepack_reader_get_size): * ext/musepack/gstmusepackreader.h: Fix seeking in musepack files (it's still incredibly slow, but I don't think that is our plugin's fault). Clean up code and get rid of old cruft. Post tags with all kind of neat information like replay gain and such on the bus, if it is available. Add a 'musepackdec' debug category.
Diffstat (limited to 'ext/musepack/gstmusepackdec.c')
-rw-r--r--ext/musepack/gstmusepackdec.c486
1 files changed, 286 insertions, 200 deletions
diff --git a/ext/musepack/gstmusepackdec.c b/ext/musepack/gstmusepackdec.c
index 2216b591..9a32c1c8 100644
--- a/ext/musepack/gstmusepackdec.c
+++ b/ext/musepack/gstmusepackdec.c
@@ -1,5 +1,6 @@
/* GStreamer Musepack decoder plugin
* Copyright (C) 2004 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -24,6 +25,9 @@
#include "gstmusepackdec.h"
#include "gstmusepackreader.h"
+GST_DEBUG_CATEGORY (musepackdec_debug);
+#define GST_CAT_DEFAULT musepackdec_debug
+
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
@@ -39,8 +43,7 @@ static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
#else
#define BASE_CAPS \
"audio/x-raw-float, " \
- "width = (int) 32, " \
- "buffer-frames = (int) 0"
+ "width = (int) 32"
#endif
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
@@ -51,16 +54,14 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
"rate = (int) [ 8000, 96000 ], " "channels = (int) [ 1, 2 ]")
);
-static void gst_musepackdec_base_init (GstMusepackDecClass * klass);
-static void gst_musepackdec_class_init (GstMusepackDecClass * klass);
-static void gst_musepackdec_init (GstMusepackDec * musepackdec);
static void gst_musepackdec_dispose (GObject * obj);
static gboolean gst_musepackdec_src_event (GstPad * pad, GstEvent * event);
static const GstQueryType *gst_musepackdec_get_src_query_types (GstPad * pad);
static gboolean gst_musepackdec_src_query (GstPad * pad, GstQuery * query);
-
-static gboolean gst_musepackdec_sink_event (GstPad * pad, GstEvent * event);
+static gboolean gst_musepackdec_src_convert (GstPad * pad,
+ GstFormat src_format, gint64 src_value, GstFormat * dest_format,
+ gint64 * dest_value);
static gboolean gst_musepackdec_sink_activate (GstPad * sinkpad);
static gboolean
gst_musepackdec_sink_activate_pull (GstPad * sinkpad, gboolean active);
@@ -69,37 +70,9 @@ static void gst_musepackdec_loop (GstPad * sinkpad);
static GstStateChangeReturn
gst_musepackdec_change_state (GstElement * element, GstStateChange transition);
-static GstElementClass *parent_class = NULL;
+GST_BOILERPLATE (GstMusepackDec, gst_musepackdec, GstElement, GST_TYPE_ELEMENT)
-/* static guint gst_musepackdec_signals[LAST_SIGNAL] = { 0 }; */
-
-GType
-gst_musepackdec_get_type (void)
-{
- static GType gst_musepackdec_type = 0;
-
- if (!gst_musepackdec_type) {
- static const GTypeInfo gst_musepackdec_info = {
- sizeof (GstMusepackDecClass),
- (GBaseInitFunc) gst_musepackdec_base_init,
- NULL,
- (GClassInitFunc) gst_musepackdec_class_init,
- NULL,
- NULL,
- sizeof (GstMusepackDec),
- 0,
- (GInstanceInitFunc) gst_musepackdec_init,
- };
-
- gst_musepackdec_type = g_type_register_static (GST_TYPE_ELEMENT,
- "GstMusepackDec", &gst_musepackdec_info, (GTypeFlags) 0);
- }
-
- return gst_musepackdec_type;
-}
-
-static void
-gst_musepackdec_base_init (GstMusepackDecClass * klass)
+ static void gst_musepackdec_base_init (gpointer klass)
{
static GstElementDetails gst_musepackdec_details =
GST_ELEMENT_DETAILS ("Musepack decoder",
@@ -114,34 +87,31 @@ gst_musepackdec_base_init (GstMusepackDecClass * klass)
gst_static_pad_template_get (&sink_template));
gst_element_class_set_details (element_class, &gst_musepackdec_details);
+
+ GST_DEBUG_CATEGORY_INIT (musepackdec_debug, "musepackdec", 0, "mpc decoder");
}
static void
gst_musepackdec_class_init (GstMusepackDecClass * klass)
{
- parent_class = GST_ELEMENT_CLASS (g_type_class_ref (GST_TYPE_ELEMENT));
+ GST_ELEMENT_CLASS (klass)->change_state =
+ GST_DEBUG_FUNCPTR (gst_musepackdec_change_state);
- GST_ELEMENT_CLASS (klass)->change_state = gst_musepackdec_change_state;
- G_OBJECT_CLASS (klass)->dispose = gst_musepackdec_dispose;
+ G_OBJECT_CLASS (klass)->dispose = GST_DEBUG_FUNCPTR (gst_musepackdec_dispose);
}
static void
-gst_musepackdec_init (GstMusepackDec * musepackdec)
+gst_musepackdec_init (GstMusepackDec * musepackdec, GstMusepackDecClass * klass)
{
musepackdec->offset = 0;
musepackdec->r = g_new (mpc_reader, 1);
musepackdec->d = g_new (mpc_decoder, 1);
musepackdec->init = FALSE;
- musepackdec->seek_pending = FALSE;
- musepackdec->flush_pending = FALSE;
- musepackdec->eos = FALSE;
musepackdec->sinkpad =
gst_pad_new_from_template (gst_static_pad_template_get (&sink_template),
"sink");
- gst_pad_set_event_function (musepackdec->sinkpad,
- GST_DEBUG_FUNCPTR (gst_musepackdec_sink_event));
gst_element_add_pad (GST_ELEMENT (musepackdec), musepackdec->sinkpad);
gst_pad_set_activate_function (musepackdec->sinkpad,
@@ -161,8 +131,6 @@ gst_musepackdec_init (GstMusepackDec * musepackdec)
GST_DEBUG_FUNCPTR (gst_musepackdec_get_src_query_types));
gst_pad_use_fixed_caps (musepackdec->srcpad);
gst_element_add_pad (GST_ELEMENT (musepackdec), musepackdec->srcpad);
-
-
}
static void
@@ -178,116 +146,187 @@ gst_musepackdec_dispose (GObject * obj)
G_OBJECT_CLASS (parent_class)->dispose (obj);
}
-static gboolean
-gst_musepackdec_sink_event (GstPad * pad, GstEvent * event)
+static void
+gst_musepackdec_send_newsegment (GstMusepackDec * dec, gboolean update)
{
- GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (gst_pad_get_parent (pad));
- gboolean res = TRUE;
+ GstSegment *s = &dec->segment;
+ GstFormat target_format = GST_FORMAT_TIME;
+ gint64 stop_time = GST_CLOCK_TIME_NONE;
+ gint64 start_time = 0;
+
+ /* segment is in DEFAULT format, but we want to send a TIME newsegment */
+ if (!gst_musepackdec_src_convert (dec->srcpad, GST_FORMAT_DEFAULT,
+ s->start, &target_format, &start_time)) {
+ GST_WARNING_OBJECT (dec, "failed to convert segment start %"
+ G_GINT64_FORMAT " to TIME", s->start);
+ return;
+ }
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_FLUSH_START:
- musepackdec->flush_pending = TRUE;
- goto done;
- break;
- case GST_EVENT_NEWSEGMENT:
- musepackdec->flush_pending = TRUE;
- musepackdec->seek_pending = TRUE;
- goto done;
- break;
- case GST_EVENT_EOS:
- musepackdec->eos = TRUE;
- /* fall through */
- default:
- res = gst_pad_event_default (pad, event);
- gst_object_unref (musepackdec);
- return res;
- break;
+ if (s->stop != -1 && !gst_musepackdec_src_convert (dec->srcpad,
+ GST_FORMAT_DEFAULT, s->stop, &target_format, &stop_time)) {
+ GST_WARNING_OBJECT (dec, "failed to convert segment stop to TIME");
+ return;
}
-done:
- gst_event_unref (event);
- gst_object_unref (musepackdec);
- return res;
+ GST_DEBUG_OBJECT (dec, "sending newsegment from %" GST_TIME_FORMAT
+ " to %" GST_TIME_FORMAT, GST_TIME_ARGS (start_time),
+ GST_TIME_ARGS (stop_time));
+ gst_pad_push_event (dec->srcpad,
+ gst_event_new_new_segment (update, s->rate, GST_FORMAT_TIME,
+ start_time, stop_time, start_time));
}
-
static gboolean
-gst_musepackdec_src_event (GstPad * pad, GstEvent * event)
+gst_musepackdec_handle_seek_event (GstMusepackDec * dec, GstEvent * event)
{
- GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (gst_pad_get_parent (pad));
- gboolean res;
+ GstSeekType start_type, stop_type;
+ GstSeekFlags flags;
+ GstSegment segment;
+ GstFormat format;
+ gboolean only_update;
+ gboolean seek_ok;
+ gboolean flush;
+ gdouble rate;
+ gint64 start, stop;
+
+ gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
+ &stop_type, &stop);
+
+ if (format != GST_FORMAT_TIME && format != GST_FORMAT_DEFAULT) {
+ GST_DEBUG_OBJECT (dec, "seek failed: only TIME or DEFAULT format allowed");
+ return FALSE;
+ }
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_SEEK:{
+ GST_OBJECT_LOCK (dec);
- gdouble rate;
- GstFormat format;
- GstSeekFlags flags;
- GstSeekType cur_type;
- gint64 cur;
- GstSeekType stop_type;
- gint64 stop;
+ if (format == GST_FORMAT_TIME) {
+ format = GST_FORMAT_DEFAULT;
+ if (start_type != GST_SEEK_TYPE_NONE &&
+ !gst_musepackdec_src_convert (dec->srcpad, GST_FORMAT_TIME,
+ start, &format, &start)) {
+ GST_DEBUG_OBJECT (dec, "failed to convert start to to DEFAULT format");
+ goto failed;
+ }
+ if (stop_type != GST_SEEK_TYPE_NONE &&
+ !gst_musepackdec_src_convert (dec->srcpad, GST_FORMAT_TIME,
+ stop, &format, &stop)) {
+ GST_DEBUG_OBJECT (dec, "failed to convert stop to to DEFAULT format");
+ goto failed;
+ }
+ }
- gst_event_parse_seek (event, &rate, &format, &flags,
- &cur_type, &cur, &stop_type, &stop);
+ flush = ((flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH);
+ /* operate on segment copy until we know the seek worked */
+ segment = dec->segment;
+ GST_OBJECT_UNLOCK (dec);
- gint64 offset, len, pos;
- GstFormat fmt = GST_FORMAT_TIME;
+ gst_segment_set_seek (&segment, rate, GST_FORMAT_DEFAULT,
+ flags, start_type, start, stop_type, stop, &only_update);
- if (!gst_musepackdec_src_convert (pad, format, cur, &fmt, &offset)) {
+ if (flush) {
+ gst_pad_push_event (dec->srcpad, gst_event_new_flush_start ());
+ } else {
+ gst_pad_stop_task (dec->sinkpad);
+ }
- }
- if (!gst_musepackdec_src_convert (pad, GST_FORMAT_DEFAULT,
- musepackdec->len, &fmt, &len)) {
- res = FALSE;
- break;
- }
- if (!gst_musepackdec_src_convert (pad, GST_FORMAT_DEFAULT,
- musepackdec->pos, &fmt, &pos)) {
- res = FALSE;
- break;
- }
+ gst_pad_push_event (dec->sinkpad, gst_event_new_flush_start ());
+ GST_PAD_STREAM_LOCK (dec->sinkpad);
+ gst_pad_push_event (dec->sinkpad, gst_event_new_flush_stop ());
- /* offset from start */
- switch (cur_type) {
- case GST_SEEK_TYPE_SET:
- break;
- case GST_SEEK_TYPE_CUR:
- offset += pos;
- break;
- case GST_SEEK_TYPE_END:
- offset = len - offset;
- break;
- default:
- res = FALSE;
- goto done;
- }
+ GST_OBJECT_LOCK (dec);
- /* only valid seeks */
- if (offset >= len || offset < 0) {
- res = FALSE;
- break;
- }
+#if 0
+ if (only_update) {
+ dec->segment = segment;
+ gst_musepackdec_send_newsegment (dec, TRUE);
+ goto done;
+ }
+#endif
+
+ GST_DEBUG_OBJECT (dec, "segment: [%" G_GINT64_FORMAT "-%" G_GINT64_FORMAT
+ "] = [%" GST_TIME_FORMAT "-%" GST_TIME_FORMAT "]",
+ segment.start, segment.stop,
+ GST_TIME_ARGS (segment.start * GST_SECOND / dec->rate),
+ GST_TIME_ARGS (segment.stop * GST_SECOND / dec->rate));
+
+ GST_DEBUG_OBJECT (dec, "performing seek to sample %" G_GINT64_FORMAT,
+ segment.start);
+
+ if (flush) {
+ gst_pad_push_event (dec->srcpad, gst_event_new_flush_stop ());
+ }
+
+ if (segment.start < 0 || segment.start >= segment.duration) {
+ GST_WARNING_OBJECT (dec, "seek out of bounds");
+ GST_PAD_STREAM_UNLOCK (dec->sinkpad);
+ goto failed;
+ }
- /* store */
- musepackdec->seek_pending = TRUE;
- musepackdec->flush_pending = flags & GST_SEEK_FLAG_FLUSH;
- musepackdec->seek_time = offset;
- res = TRUE;
+ seek_ok = mpc_decoder_seek_sample (dec->d, segment.start);
+ if (!seek_ok) {
+ GST_PAD_STREAM_UNLOCK (dec->sinkpad);
+ goto failed;
+ }
+
+ /* FIXME: support segment seeks
+ if ((seek_flags & GST_SEEK_FLAG_SEGMENT) != 0) {
+ GST_DEBUG_OBJECT (dec, "posting SEGMENT_START message");
+ GST_OBJECT_UNLOCK (dec);
+ gst_element_post_message (GST_ELEMENT (dec),
+ gst_message_new_segment_start (GST_OBJECT (dec),
+ GST_FORMAT_DEFAULT, dec->segment.start));
+ GST_OBJECT_LOCK (dec);
+ }
+ */
+
+ gst_segment_set_last_stop (&segment, GST_FORMAT_DEFAULT, segment.start);
+ dec->segment = segment;
+ gst_musepackdec_send_newsegment (dec, FALSE);
+
+ GST_DEBUG_OBJECT (dec, "seek successful");
+
+#if 0
+done:
+#endif
+
+ GST_PAD_STREAM_UNLOCK (dec->sinkpad);
+
+ gst_pad_start_task (dec->sinkpad,
+ (GstTaskFunction) gst_musepackdec_loop, dec->sinkpad);
+
+ GST_OBJECT_UNLOCK (dec);
+ return TRUE;
+
+failed:
+ {
+ GST_WARNING_OBJECT (dec, "seek failed");
+ GST_OBJECT_UNLOCK (dec);
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_musepackdec_src_event (GstPad * pad, GstEvent * event)
+{
+ GstMusepackDec *dec;
+ gboolean res;
+
+ dec = GST_MUSEPACK_DEC (gst_pad_get_parent (pad));
+
+ GST_DEBUG_OBJECT (dec, "handling %s event", GST_EVENT_TYPE_NAME (event));
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_SEEK:
+ res = gst_musepackdec_handle_seek_event (dec, event);
break;
- }
default:
res = gst_pad_event_default (pad, event);
- gst_object_unref (musepackdec);
- return res;
break;
}
-done:
- gst_event_unref (event);
- gst_object_unref (musepackdec);
+ gst_object_unref (dec);
return res;
}
@@ -313,6 +352,8 @@ gst_musepackdec_src_query (GstPad * pad, GstQuery * query)
gint64 value, dest_value;
gboolean res = TRUE;
+ GST_OBJECT_LOCK (musepackdec);
+
if (!musepackdec->init) {
res = FALSE;
goto done;
@@ -321,16 +362,16 @@ gst_musepackdec_src_query (GstPad * pad, GstQuery * query)
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_POSITION:
gst_query_parse_position (query, &dest_format, NULL);
- if (!gst_musepackdec_src_convert (pad, format, musepackdec->pos,
- &dest_format, &dest_value)) {
+ if (!gst_musepackdec_src_convert (pad, format,
+ musepackdec->segment.last_stop, &dest_format, &dest_value)) {
res = FALSE;
}
gst_query_set_position (query, dest_format, dest_value);
break;
case GST_QUERY_DURATION:
gst_query_parse_duration (query, &dest_format, NULL);
- if (!gst_musepackdec_src_convert (pad, format, musepackdec->len,
- &dest_format, &dest_value)) {
+ if (!gst_musepackdec_src_convert (pad, format,
+ musepackdec->segment.duration, &dest_format, &dest_value)) {
res = FALSE;
break;
}
@@ -346,16 +387,17 @@ gst_musepackdec_src_query (GstPad * pad, GstQuery * query)
gst_query_set_convert (query, format, value, dest_format, dest_value);
break;
default:
- res = FALSE;
+ res = gst_pad_query_default (pad, query);
break;
}
done:
+ GST_OBJECT_UNLOCK (musepackdec);
gst_object_unref (musepackdec);
return res;
}
-gboolean
+static gboolean
gst_musepackdec_src_convert (GstPad * pad, GstFormat src_format,
gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
{
@@ -363,6 +405,7 @@ gst_musepackdec_src_convert (GstPad * pad, GstFormat src_format,
gboolean res = TRUE;
if (!musepackdec->init) {
+ GST_DEBUG_OBJECT (musepackdec, "conversion failed: not initialiased yet");
gst_object_unref (musepackdec);
return FALSE;
}
@@ -371,7 +414,8 @@ gst_musepackdec_src_convert (GstPad * pad, GstFormat src_format,
case GST_FORMAT_DEFAULT:
switch (*dest_format) {
case GST_FORMAT_TIME:
- *dest_value = src_value * GST_SECOND / musepackdec->rate;
+ *dest_value = gst_util_uint64_scale_int (src_value,
+ GST_SECOND, musepackdec->rate);
break;
case GST_FORMAT_BYTES:
*dest_value = src_value * musepackdec->bps;
@@ -385,11 +429,12 @@ gst_musepackdec_src_convert (GstPad * pad, GstFormat src_format,
case GST_FORMAT_TIME:
switch (*dest_format) {
case GST_FORMAT_DEFAULT:
- *dest_value = src_value * musepackdec->rate / GST_SECOND;
+ *dest_value = gst_util_uint64_scale_int (src_value,
+ musepackdec->rate, GST_SECOND);
break;
case GST_FORMAT_BYTES:
- *dest_value = src_value * musepackdec->rate *
- musepackdec->bps / GST_SECOND;
+ *dest_value = gst_util_uint64_scale_int (src_value,
+ musepackdec->rate * musepackdec->bps, GST_SECOND);
break;
default:
res = FALSE;
@@ -403,8 +448,8 @@ gst_musepackdec_src_convert (GstPad * pad, GstFormat src_format,
*dest_value = src_value / musepackdec->bps;
break;
case GST_FORMAT_TIME:
- *dest_value = src_value * GST_SECOND /
- (musepackdec->bps * musepackdec->rate);
+ *dest_value = gst_util_uint64_scale_int (src_value,
+ GST_SECOND, musepackdec->bps * musepackdec->rate);
break;
default:
res = FALSE;
@@ -418,13 +463,14 @@ gst_musepackdec_src_convert (GstPad * pad, GstFormat src_format,
}
gst_object_unref (musepackdec);
- return TRUE;
+ return res;
}
static gboolean
gst_musepack_stream_init (GstMusepackDec * musepackdec)
{
mpc_streaminfo i;
+ GstTagList *tags;
GstCaps *caps;
/* set up reading */
@@ -459,9 +505,46 @@ gst_musepack_stream_init (GstMusepackDec * musepackdec)
musepackdec->bps = 4 * i.channels;;
musepackdec->rate = i.sample_freq;
- musepackdec->pos = 0;
- musepackdec->len = mpc_streaminfo_get_length_samples (&i);
- musepackdec->init = TRUE;
+
+ gst_segment_set_last_stop (&musepackdec->segment, GST_FORMAT_DEFAULT, 0);
+ gst_segment_set_duration (&musepackdec->segment, GST_FORMAT_DEFAULT,
+ mpc_streaminfo_get_length_samples (&i));
+
+ /* send basic tags */
+ tags = gst_tag_list_new ();
+ gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
+ GST_TAG_AUDIO_CODEC, "Musepack", NULL);
+
+ if (i.encoder[0] != '\0' && i.encoder_version > 0) {
+ gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
+ GST_TAG_ENCODER, i.encoder,
+ GST_TAG_ENCODER_VERSION, i.encoder_version, NULL);
+ }
+
+ if (i.bitrate > 0) {
+ gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
+ GST_TAG_BITRATE, i.bitrate, NULL);
+ } else if (i.average_bitrate > 0.0) {
+ gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
+ GST_TAG_BITRATE, (guint) i.average_bitrate, NULL);
+ }
+
+ /* FIXME: are these values correct in the end? */
+ if (i.gain_title != 0 || i.gain_album != 0) {
+ gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
+ GST_TAG_TRACK_GAIN, (gdouble) i.gain_title / 100.0,
+ GST_TAG_ALBUM_GAIN, (gdouble) i.gain_album / 100.0, NULL);
+ }
+
+ /* FIXME: are these values correct in the end? */
+ if (i.peak_title != 0 && i.peak_album != 0) {
+ gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
+ GST_TAG_TRACK_PEAK, (gdouble) i.peak_title,
+ GST_TAG_ALBUM_PEAK, (gdouble) i.peak_album, NULL);
+ }
+
+ GST_LOG_OBJECT (musepackdec, "Posting tags: %" GST_PTR_FORMAT, tags);
+ gst_element_found_tags (GST_ELEMENT (musepackdec), tags);
return TRUE;
}
@@ -484,7 +567,6 @@ gst_musepackdec_sink_activate_pull (GstPad * sinkpad, gboolean active)
gboolean result;
if (active) {
-
result = gst_pad_start_task (sinkpad,
(GstTaskFunction) gst_musepackdec_loop, sinkpad);
} else {
@@ -497,72 +579,67 @@ gst_musepackdec_sink_activate_pull (GstPad * sinkpad, gboolean active)
static void
gst_musepackdec_loop (GstPad * sinkpad)
{
- GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (GST_PAD_PARENT (sinkpad));
+ GstMusepackDec *musepackdec;
+ GstFlowReturn flow;
GstBuffer *out;
- GstFormat fmt;
- gint ret;
guint32 update_acc, update_bits;
+ gint num_samples;
+
+ musepackdec = GST_MUSEPACK_DEC (GST_PAD_PARENT (sinkpad));
if (!musepackdec->init) {
if (!gst_musepack_stream_init (musepackdec))
- return;
- gst_pad_push_event (musepackdec->srcpad,
- gst_event_new_new_segment (FALSE, 1.0,
- GST_FORMAT_TIME, musepackdec->pos, GST_CLOCK_TIME_NONE, 0));
- }
-
- if (musepackdec->seek_pending) {
- gdouble seek_time = (gdouble) musepackdec->seek_time / GST_SECOND;
+ goto pause_task;
- musepackdec->seek_pending = FALSE;
- if (mpc_decoder_seek_seconds (musepackdec->d, seek_time)) {
- if (musepackdec->flush_pending) {
- musepackdec->flush_pending = FALSE;
- gst_pad_push_event (musepackdec->srcpad, gst_event_new_flush_start ());
- }
- gst_pad_push_event (musepackdec->srcpad,
- gst_event_new_new_segment (FALSE, 1.0,
- GST_FORMAT_TIME, musepackdec->seek_time, GST_CLOCK_TIME_NONE, 0));
- fmt = GST_FORMAT_DEFAULT;
- gst_musepackdec_src_convert (musepackdec->srcpad,
- GST_FORMAT_TIME, musepackdec->seek_time,
- &fmt, (gint64 *) & musepackdec->pos);
- }
+ musepackdec->init = TRUE;
+ gst_musepackdec_send_newsegment (musepackdec, FALSE);
}
out = gst_buffer_new_and_alloc (MPC_DECODER_BUFFER_LENGTH * 4);
- ret = mpc_decoder_decode (musepackdec->d,
+
+ num_samples = mpc_decoder_decode (musepackdec->d,
(MPC_SAMPLE_FORMAT *) GST_BUFFER_DATA (out), &update_acc, &update_bits);
- if (ret <= 0 || musepackdec->eos) {
- if (ret < 0) {
- GST_ERROR_OBJECT (musepackdec, "Failed to decode sample");
- } else if (!musepackdec->eos) {
- musepackdec->eos = TRUE;
- gst_pad_push_event (musepackdec->sinkpad, gst_event_new_eos ());
- }
- gst_buffer_unref (out);
- return;
+
+ if (num_samples < 0) {
+ GST_ERROR_OBJECT (musepackdec, "Failed to decode sample");
+ GST_ELEMENT_ERROR (musepackdec, STREAM, DECODE, (NULL), (NULL));
+ goto pause_task;
+ } else if (num_samples == 0) {
+ GST_DEBUG_OBJECT (musepackdec, "EOS");
+ gst_pad_push_event (musepackdec->srcpad, gst_event_new_eos ());
+ goto pause_task;
}
- GST_BUFFER_SIZE (out) = ret * musepackdec->bps;
- fmt = GST_FORMAT_TIME;
+ GST_BUFFER_SIZE (out) = num_samples * musepackdec->bps;
- gint64 value;
+ GST_BUFFER_OFFSET (out) = musepackdec->segment.last_stop;
+ GST_BUFFER_TIMESTAMP (out) =
+ gst_util_uint64_scale_int (musepackdec->segment.last_stop,
+ GST_SECOND, musepackdec->rate);
+ GST_BUFFER_DURATION (out) =
+ gst_util_uint64_scale_int (num_samples, GST_SECOND, musepackdec->rate);
- gst_musepackdec_src_convert (musepackdec->srcpad,
- GST_FORMAT_BYTES, GST_BUFFER_SIZE (out), &fmt, &value);
- GST_BUFFER_DURATION (out) = value;
+ gst_buffer_set_caps (out, GST_PAD_CAPS (musepackdec->srcpad));
- gst_musepackdec_src_convert (musepackdec->srcpad,
- GST_FORMAT_DEFAULT, musepackdec->pos, &fmt, &value);
- GST_BUFFER_TIMESTAMP (out) = value;
+ musepackdec->segment.last_stop += num_samples;
- GST_DEBUG ("Pushing buffer, timestamp %" GST_TIME_FORMAT,
+ GST_LOG_OBJECT (musepackdec, "Pushing buffer, timestamp %" GST_TIME_FORMAT,
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (out)));
- musepackdec->pos += GST_BUFFER_SIZE (out) / musepackdec->bps;
- gst_buffer_set_caps (out, GST_PAD_CAPS (musepackdec->srcpad));
- gst_pad_push (musepackdec->srcpad, out);
+ flow = gst_pad_push (musepackdec->srcpad, out);
+ if (flow != GST_FLOW_OK && flow != GST_FLOW_NOT_LINKED) {
+ GST_DEBUG_OBJECT (musepackdec, "Flow: %s", gst_flow_get_name (flow));
+ goto pause_task;
+ }
+
+ return;
+
+pause_task:
+ {
+ GST_DEBUG_OBJECT (musepackdec, "Pausing task");
+ gst_pad_pause_task (sinkpad);
+ return;
+ }
}
static GstStateChangeReturn
@@ -571,14 +648,23 @@ gst_musepackdec_change_state (GstElement * element, GstStateChange transition)
GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (element);
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+ switch (transition) {
+ case GST_STATE_CHANGE_READY_TO_PAUSED:
+ gst_segment_init (&musepackdec->segment, GST_FORMAT_DEFAULT);
+ gst_segment_set_last_stop (&musepackdec->segment, GST_FORMAT_DEFAULT, 0);
+ break;
+ default:
+ break;
+ }
+
if (GST_ELEMENT_CLASS (parent_class)->change_state)
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_READY:
- musepackdec->seek_pending = FALSE;
+ gst_segment_init (&musepackdec->segment, GST_FORMAT_UNDEFINED);
musepackdec->init = FALSE;
+ musepackdec->offset = 0;
break;
default:
break;