mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-04 22:48:49 +00:00
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.
This commit is contained in:
parent
c2e3aede74
commit
8a0500bf3b
4 changed files with 103 additions and 21 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:
|
||||
|
|
2
common
2
common
|
@ -1 +1 @@
|
|||
Subproject commit 032f2d973bd5c9a9b457cb5fc72d13dafe85c01e
|
||||
Subproject commit 130fa8f739ff09aedb520c33239f53d06cfe9bd5
|
|
@ -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;
|
||||
|
||||
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)));
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
|
|
|
@ -65,6 +65,9 @@ struct _GstA52Dec {
|
|||
|
||||
GstBuffer *cache;
|
||||
GstClockTime time;
|
||||
|
||||
/* reverse */
|
||||
GList *queued;
|
||||
};
|
||||
|
||||
struct _GstA52DecClass {
|
||||
|
|
Loading…
Reference in a new issue