summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthieu Bouron <matthieu.bouron@collabora.com>2013-08-13 18:42:55 +0100
committerTim-Philipp Müller <tim@centricular.net>2013-08-17 00:25:49 +0100
commitd69b6e53e463bc96b7457c3a3f99f1d07c891610 (patch)
tree64993bccce73868f4c51cc89e7e59441167f8ca3
parent27bceba4adf6eaf3f0643958b4da4f8df791a0da (diff)
downloadgstreamer-plugins-bad-d69b6e53e463bc96b7457c3a3f99f1d07c891610.tar.gz
aiffparse: fix push mode
Fix push mode by handling sink events (CAPS, SEGMENT) properly. https://bugzilla.gnome.org/show_bug.cgi?id=705993
-rw-r--r--gst/aiff/aiffparse.c128
1 files changed, 128 insertions, 0 deletions
diff --git a/gst/aiff/aiffparse.c b/gst/aiff/aiffparse.c
index 9549caedf..6b6540d74 100644
--- a/gst/aiff/aiffparse.c
+++ b/gst/aiff/aiffparse.c
@@ -74,6 +74,8 @@ static gboolean gst_aiff_parse_sink_activate (GstPad * sinkpad,
GstObject * parent);
static gboolean gst_aiff_parse_sink_activate_mode (GstPad * sinkpad,
GstObject * parent, GstPadMode mode, gboolean active);
+static gboolean gst_aiff_parse_sink_event (GstPad * pad, GstObject * parent,
+ GstEvent * buf);
static gboolean gst_aiff_parse_send_event (GstElement * element,
GstEvent * event);
static GstStateChangeReturn gst_aiff_parse_change_state (GstElement * element,
@@ -191,6 +193,8 @@ gst_aiff_parse_init (GstAiffParse * aiffparse)
GST_DEBUG_FUNCPTR (gst_aiff_parse_sink_activate));
gst_pad_set_activatemode_function (aiffparse->sinkpad,
GST_DEBUG_FUNCPTR (gst_aiff_parse_sink_activate_mode));
+ gst_pad_set_event_function (aiffparse->sinkpad,
+ GST_DEBUG_FUNCPTR (gst_aiff_parse_sink_event));
gst_pad_set_chain_function (aiffparse->sinkpad,
GST_DEBUG_FUNCPTR (gst_aiff_parse_chain));
gst_element_add_pad (GST_ELEMENT_CAST (aiffparse), aiffparse->sinkpad);
@@ -1670,6 +1674,130 @@ gst_aiff_parse_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
return res;
};
+static GstFlowReturn
+gst_aiff_parse_flush_data (GstAiffParse * aiff)
+{
+ GstFlowReturn ret = GST_FLOW_OK;
+ guint av;
+
+ if ((av = gst_adapter_available (aiff->adapter)) > 0) {
+ aiff->dataleft = av;
+ aiff->end_offset = aiff->offset + av;
+ ret = gst_aiff_parse_stream_data (aiff);
+ }
+
+ return ret;
+}
+
+
+static gboolean
+gst_aiff_parse_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
+{
+ GstAiffParse *aiff = GST_AIFF_PARSE (parent);
+ gboolean ret = TRUE;
+
+ GST_DEBUG_OBJECT (aiff, "handling %s event", GST_EVENT_TYPE_NAME (event));
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_CAPS:
+ {
+ /* discard, we'll come up with proper src caps */
+ gst_event_unref (event);
+ break;
+ }
+ case GST_EVENT_SEGMENT:
+ {
+ gint64 start, stop, offset = 0, end_offset = -1;
+ GstSegment segment;
+
+ /* some debug output */
+ gst_event_copy_segment (event, &segment);
+ GST_DEBUG_OBJECT (aiff, "received segment %" GST_SEGMENT_FORMAT,
+ &segment);
+
+ /* now we are either committed to TIME or BYTE format,
+ * and we only expect a BYTE segment, e.g. following a seek */
+ if (segment.format == GST_FORMAT_BYTES) {
+ /* handle (un)signed issues */
+ start = segment.start;
+ stop = segment.stop;
+ if (start > 0) {
+ offset = start;
+ start -= aiff->datastart;
+ start = MAX (start, 0);
+ }
+ if (stop > 0) {
+ end_offset = stop;
+ segment.stop -= aiff->datastart;
+ segment.stop = MAX (stop, 0);
+ }
+ if (aiff->state == AIFF_PARSE_DATA &&
+ aiff->segment.format == GST_FORMAT_TIME) {
+ guint64 bps = aiff->bps;
+
+ /* operating in format TIME, so we can convert */
+ if (bps) {
+ if (start >= 0)
+ start =
+ gst_util_uint64_scale_ceil (start, GST_SECOND,
+ (guint64) aiff->bps);
+ if (stop >= 0)
+ stop =
+ gst_util_uint64_scale_ceil (stop, GST_SECOND,
+ (guint64) aiff->bps);
+ } else {
+ GST_DEBUG_OBJECT (aiff, "unable to compute segment start/stop");
+ goto exit;
+ }
+ }
+ } else {
+ GST_DEBUG_OBJECT (aiff, "unsupported segment format, ignoring");
+ goto exit;
+ }
+
+ segment.start = start;
+ segment.stop = stop;
+
+ /* accept upstream's notion of segment and distribute along */
+ if (aiff->state == AIFF_PARSE_DATA) {
+ segment.format = aiff->segment.format;
+ segment.time = segment.position = segment.start;
+ segment.duration = aiff->segment.duration;
+ segment.base = gst_segment_to_running_time (&aiff->segment,
+ GST_FORMAT_TIME, aiff->segment.position);
+ }
+
+ gst_segment_copy_into (&segment, &aiff->segment);
+
+ if (aiff->start_segment)
+ gst_event_unref (aiff->start_segment);
+
+ aiff->start_segment = gst_event_new_segment (&segment);
+
+ /* stream leftover data in current segment */
+ if (aiff->state == AIFF_PARSE_DATA)
+ gst_aiff_parse_flush_data (aiff);
+ /* and set up streaming thread for next one */
+ aiff->offset = offset;
+ aiff->end_offset = end_offset;
+ if (aiff->end_offset > 0) {
+ aiff->dataleft = aiff->end_offset - aiff->offset;
+ } else {
+ /* infinity; upstream will EOS when done */
+ aiff->dataleft = G_MAXUINT64;
+ }
+ exit:
+ gst_event_unref (event);
+ break;
+ }
+ default:
+ ret = gst_pad_event_default (aiff->sinkpad, parent, event);
+ break;
+ }
+
+ return ret;
+}
+
static GstStateChangeReturn
gst_aiff_parse_change_state (GstElement * element, GstStateChange transition)
{