diff options
author | Wim Taymans <wim.taymans@gmail.com> | 2008-06-02 11:59:07 +0000 |
---|---|---|
committer | Wim Taymans <wim.taymans@gmail.com> | 2008-06-02 11:59:07 +0000 |
commit | 8a0500bf3b82aa69dcd4a85f82bc41cf26970e13 (patch) | |
tree | ff7771352c46e0de5c3dfe59d06e4d456feef2c6 | |
parent | c2e3aede74201d7f4d0a3b670e149923fd7ad5ac (diff) | |
download | gstreamer-plugins-ugly-8a0500bf3b82aa69dcd4a85f82bc41cf26970e13.tar.gz |
ext/a52dec/gsta52dec.*: Add segment handling, buffer clipping and basic reverse playback.
Original commit message from CVS:
* ext/a52dec/gsta52dec.c: (clear_queued), (flush_queued),
(gst_a52dec_drain), (gst_a52dec_push), (gst_a52dec_sink_event),
(gst_a52dec_chain), (gst_a52dec_change_state):
* ext/a52dec/gsta52dec.h:
Add segment handling, buffer clipping and basic reverse playback.
-rw-r--r-- | ChangeLog | 8 | ||||
m--------- | common | 0 | ||||
-rw-r--r-- | ext/a52dec/gsta52dec.c | 109 | ||||
-rw-r--r-- | ext/a52dec/gsta52dec.h | 3 |
4 files changed, 101 insertions, 19 deletions
@@ -1,3 +1,11 @@ +2008-06-02 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/a52dec/gsta52dec.c: (clear_queued), (flush_queued), + (gst_a52dec_drain), (gst_a52dec_push), (gst_a52dec_sink_event), + (gst_a52dec_chain), (gst_a52dec_change_state): + * ext/a52dec/gsta52dec.h: + Add segment handling, buffer clipping and basic reverse playback. + 2008-05-28 Stefan Kost <ensonic@users.sf.net> * docs/plugins/Makefile.am: diff --git a/common b/common -Subproject 032f2d973bd5c9a9b457cb5fc72d13dafe85c01 +Subproject 130fa8f739ff09aedb520c33239f53d06cfe9bd diff --git a/ext/a52dec/gsta52dec.c b/ext/a52dec/gsta52dec.c index a6625c48..6409d27b 100644 --- a/ext/a52dec/gsta52dec.c +++ b/ext/a52dec/gsta52dec.c @@ -341,6 +341,48 @@ gst_a52dec_channels (int flags, GstAudioChannelPosition ** _pos) return chans; } +static void +clear_queued (GstA52Dec * dec) +{ + g_list_foreach (dec->queued, (GFunc) gst_mini_object_unref, NULL); + g_list_free (dec->queued); + dec->queued = NULL; +} + +static GstFlowReturn +flush_queued (GstA52Dec * dec) +{ + GstFlowReturn ret = GST_FLOW_OK; + + while (dec->queued) { + GstBuffer *buf = GST_BUFFER_CAST (dec->queued->data); + + GST_LOG_OBJECT (dec, "pushing buffer %p, timestamp %" + GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT, buf, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (buf))); + + /* iterate ouput queue an push downstream */ + ret = gst_pad_push (dec->srcpad, buf); + + dec->queued = g_list_delete_link (dec->queued, dec->queued); + } + return ret; +} + +static GstFlowReturn +gst_a52dec_drain (GstA52Dec * dec) +{ + GstFlowReturn ret = GST_FLOW_OK; + + if (dec->segment.rate < 0.0) { + /* if we have some queued frames for reverse playback, flush + * them now */ + ret = flush_queued (dec); + } + return ret; +} + static GstFlowReturn gst_a52dec_push (GstA52Dec * a52dec, GstPad * srcpad, int flags, sample_t * samples, GstClockTime timestamp) @@ -371,19 +413,31 @@ gst_a52dec_push (GstA52Dec * a52dec, } GST_BUFFER_TIMESTAMP (buf) = timestamp; GST_BUFFER_DURATION (buf) = 256 * GST_SECOND / a52dec->sample_rate; - /* set discont when needed */ - if (a52dec->discont) { - GST_LOG_OBJECT (a52dec, "marking DISCONT"); - GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); - a52dec->discont = FALSE; - } - GST_DEBUG_OBJECT (a52dec, - "Pushing buffer with ts %" GST_TIME_FORMAT " duration %" GST_TIME_FORMAT, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), - GST_TIME_ARGS (GST_BUFFER_DURATION (buf))); + result = GST_FLOW_OK; + if ((buf = gst_audio_buffer_clip (buf, &a52dec->segment, + a52dec->sample_rate, (SAMPLE_WIDTH / 8) * chans))) { + /* set discont when needed */ + if (a52dec->discont) { + GST_LOG_OBJECT (a52dec, "marking DISCONT"); + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); + a52dec->discont = FALSE; + } + + if (a52dec->segment.rate > 0.0) { + GST_DEBUG_OBJECT (a52dec, + "Pushing buffer with ts %" GST_TIME_FORMAT " duration %" + GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (buf))); - return gst_pad_push (srcpad, buf); + result = gst_pad_push (srcpad, buf); + } else { + /* reverse playback, queue frame till later when we get a discont. */ + GST_DEBUG_OBJECT (a52dec, "queued frame"); + a52dec->queued = g_list_prepend (a52dec->queued, buf); + } + } + return result; } static gboolean @@ -428,26 +482,40 @@ gst_a52dec_sink_event (GstPad * pad, GstEvent * event) GST_LOG ("Handling %s event", GST_EVENT_TYPE_NAME (event)); switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_NEWSEGMENT:{ - GstFormat format; - gint64 val; + case GST_EVENT_NEWSEGMENT: + { + GstFormat fmt; + gboolean update; + gint64 start, end, pos; + gdouble rate; - gst_event_parse_new_segment (event, NULL, NULL, &format, &val, NULL, - NULL); - if (format != GST_FORMAT_TIME || !GST_CLOCK_TIME_IS_VALID (val)) { + gst_event_parse_new_segment (event, &update, &rate, &fmt, &start, &end, + &pos); + + if (fmt != GST_FORMAT_TIME || !GST_CLOCK_TIME_IS_VALID (start)) { GST_WARNING ("No time in newsegment event %p (format is %s)", - event, gst_format_get_name (format)); + event, gst_format_get_name (fmt)); gst_event_unref (event); a52dec->sent_segment = FALSE; + /* set some dummy values, FIXME do proper conversion */ } else { - a52dec->time = val; + a52dec->time = start; a52dec->sent_segment = TRUE; ret = gst_pad_push_event (a52dec->srcpad, event); } + /* drain queued buffers before activating the segment so that we can clip + * against the old segment first */ + gst_a52dec_drain (a52dec); + + gst_segment_set_newsegment (&a52dec->segment, update, rate, fmt, start, + end, pos); break; } case GST_EVENT_TAG: + ret = gst_pad_push_event (a52dec->srcpad, event); + break; case GST_EVENT_EOS: + gst_a52dec_drain (a52dec); ret = gst_pad_push_event (a52dec->srcpad, event); break; case GST_EVENT_FLUSH_START: @@ -458,6 +526,7 @@ gst_a52dec_sink_event (GstPad * pad, GstEvent * event) gst_buffer_unref (a52dec->cache); a52dec->cache = NULL; } + clear_queued (a52dec); gst_segment_init (&a52dec->segment, GST_FORMAT_UNDEFINED); ret = gst_pad_push_event (a52dec->srcpad, event); break; @@ -626,6 +695,7 @@ gst_a52dec_chain (GstPad * pad, GstBuffer * buf) if (GST_BUFFER_IS_DISCONT (buf)) { GST_LOG_OBJECT (a52dec, "received DISCONT"); + gst_a52dec_drain (a52dec); /* clear cache on discont and mark a discont in the element */ if (a52dec->cache) { gst_buffer_unref (a52dec->cache); @@ -827,6 +897,7 @@ gst_a52dec_change_state (GstElement * element, GstStateChange transition) gst_buffer_unref (a52dec->cache); a52dec->cache = NULL; } + clear_queued (a52dec); break; case GST_STATE_CHANGE_READY_TO_NULL: a52_free (a52dec->state); diff --git a/ext/a52dec/gsta52dec.h b/ext/a52dec/gsta52dec.h index 51a2bffb..c837c396 100644 --- a/ext/a52dec/gsta52dec.h +++ b/ext/a52dec/gsta52dec.h @@ -65,6 +65,9 @@ struct _GstA52Dec { GstBuffer *cache; GstClockTime time; + + /* reverse */ + GList *queued; }; struct _GstA52DecClass { |