ext/amrnb/amrnbparse.*: Add flush seek handler. Fixes #536274.

Original commit message from CVS:
Patch by: Benoit Fouet <benoit dot fouet at purplelabs dot com>
* ext/amrnb/amrnbparse.c: (gst_amrnbparse_init),
(gst_amrnbparse_handle_pull_seek),
(gst_amrnbparse_handle_push_seek), (gst_amrnbparse_src_event),
(gst_amrnbparse_sink_activate_push),
(gst_amrnbparse_sink_activate_pull):
* ext/amrnb/amrnbparse.h:
Add flush seek handler. Fixes #536274.
This commit is contained in:
Benoit Fouet 2008-09-26 10:04:35 +00:00 committed by Wim Taymans
parent f0d2495012
commit be573f752f
3 changed files with 186 additions and 0 deletions

View file

@ -1,3 +1,15 @@
2008-09-26 Wim Taymans <wim.taymans@collabora.co.uk>
Patch by: Benoit Fouet <benoit dot fouet at purplelabs dot com>
* ext/amrnb/amrnbparse.c: (gst_amrnbparse_init),
(gst_amrnbparse_handle_pull_seek),
(gst_amrnbparse_handle_push_seek), (gst_amrnbparse_src_event),
(gst_amrnbparse_sink_activate_push),
(gst_amrnbparse_sink_activate_pull):
* ext/amrnb/amrnbparse.h:
Add flush seek handler. Fixes #536274.
2008-09-26 Wim Taymans <wim.taymans@collabora.co.uk>
Patch by: Benoit Fouet <benoit dot fouet at purplelabs dot com>

View file

@ -62,11 +62,14 @@ static const GstQueryType *gst_amrnbparse_querytypes (GstPad * pad);
static gboolean gst_amrnbparse_query (GstPad * pad, GstQuery * query);
static gboolean gst_amrnbparse_sink_event (GstPad * pad, GstEvent * event);
static gboolean gst_amrnbparse_src_event (GstPad * pad, GstEvent * event);
static GstFlowReturn gst_amrnbparse_chain (GstPad * pad, GstBuffer * buffer);
static void gst_amrnbparse_loop (GstPad * pad);
static gboolean gst_amrnbparse_sink_activate (GstPad * sinkpad);
static gboolean gst_amrnbparse_sink_activate_pull (GstPad * sinkpad,
gboolean active);
static gboolean gst_amrnbparse_sink_activate_push (GstPad * sinkpad,
gboolean active);
static GstStateChangeReturn gst_amrnbparse_state_change (GstElement * element,
GstStateChange transition);
@ -120,10 +123,14 @@ gst_amrnbparse_init (GstAmrnbParse * amrnbparse, GstAmrnbParseClass * klass)
gst_amrnbparse_sink_activate);
gst_pad_set_activatepull_function (amrnbparse->sinkpad,
gst_amrnbparse_sink_activate_pull);
gst_pad_set_activatepush_function (amrnbparse->sinkpad,
gst_amrnbparse_sink_activate_push);
gst_element_add_pad (GST_ELEMENT (amrnbparse), amrnbparse->sinkpad);
/* create the src pad */
amrnbparse->srcpad = gst_pad_new_from_static_template (&src_template, "src");
gst_pad_set_event_function (amrnbparse->srcpad,
GST_DEBUG_FUNCPTR (gst_amrnbparse_src_event));
gst_pad_set_query_function (amrnbparse->srcpad,
GST_DEBUG_FUNCPTR (gst_amrnbparse_query));
gst_pad_set_query_type_function (amrnbparse->srcpad,
@ -243,6 +250,149 @@ gst_amrnbparse_query (GstPad * pad, GstQuery * query)
}
static gboolean
gst_amrnbparse_handle_pull_seek (GstAmrnbParse * amrnbparse, GstPad * pad,
GstEvent * event)
{
GstFormat format;
gdouble rate;
GstSeekFlags flags;
GstSeekType cur_type, stop_type;
gint64 cur, stop;
gint64 byte_cur = -1, byte_stop = -1;
gboolean flush;
gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
&stop_type, &stop);
GST_DEBUG_OBJECT (amrnbparse, "Performing seek to %" GST_TIME_FORMAT,
GST_TIME_ARGS (cur));
/* For any format other than TIME, see if upstream handles
* it directly or fail. For TIME, try upstream, but do it ourselves if
* it fails upstream */
if (format != GST_FORMAT_TIME) {
return gst_pad_push_event (amrnbparse->sinkpad, event);
} else {
if (gst_pad_push_event (amrnbparse->sinkpad, event))
return TRUE;
}
flush = flags & GST_SEEK_FLAG_FLUSH;
/* send flush start */
if (flush)
gst_pad_push_event (amrnbparse->sinkpad, gst_event_new_flush_start ());
/* we only handle FLUSH seeks at the moment */
else
return FALSE;
/* grab streaming lock, this should eventually be possible, either
* because the task is paused or our streaming thread stopped
* because our peer is flushing. */
GST_PAD_STREAM_LOCK (amrnbparse->sinkpad);
/* Convert the TIME to the appropriate BYTE position at which to resume
* decoding. */
cur = cur / (20 * GST_MSECOND) * (20 * GST_MSECOND);
if (cur != -1)
byte_cur = amrnbparse->block * (cur / 20 / GST_MSECOND) + 6;
if (stop != -1)
byte_stop = amrnbparse->block * (stop / 20 / GST_MSECOND) + 6;
amrnbparse->offset = byte_cur;
amrnbparse->ts = cur;
GST_DEBUG_OBJECT (amrnbparse, "Seeking to byte range %" G_GINT64_FORMAT
" to %" G_GINT64_FORMAT, byte_cur, cur);
/* and prepare to continue streaming */
/* send flush stop, peer will accept data and events again. We
* are not yet providing data as we still have the STREAM_LOCK. */
gst_pad_push_event (amrnbparse->sinkpad, gst_event_new_flush_stop ());
gst_pad_push_event (amrnbparse->srcpad, gst_event_new_new_segment (FALSE,
rate, format, cur, -1, cur));
/* and restart the task in case it got paused explicitely or by
* the FLUSH_START event we pushed out. */
gst_pad_start_task (amrnbparse->sinkpad,
(GstTaskFunction) gst_amrnbparse_loop, amrnbparse->sinkpad);
/* and release the lock again so we can continue streaming */
GST_PAD_STREAM_UNLOCK (amrnbparse->sinkpad);
return TRUE;
}
static gboolean
gst_amrnbparse_handle_push_seek (GstAmrnbParse * amrnbparse, GstPad * pad,
GstEvent * event)
{
GstFormat format;
gdouble rate;
GstSeekFlags flags;
GstSeekType cur_type, stop_type;
gint64 cur, stop;
gint64 byte_cur = -1, byte_stop = -1;
gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
&stop_type, &stop);
GST_DEBUG_OBJECT (amrnbparse, "Performing seek to %" GST_TIME_FORMAT,
GST_TIME_ARGS (cur));
/* For any format other than TIME, see if upstream handles
* it directly or fail. For TIME, try upstream, but do it ourselves if
* it fails upstream */
if (format != GST_FORMAT_TIME) {
return gst_pad_push_event (amrnbparse->sinkpad, event);
} else {
if (gst_pad_push_event (amrnbparse->sinkpad, event))
return TRUE;
}
/* Convert the TIME to the appropriate BYTE position at which to resume
* decoding. */
cur = cur / (20 * GST_MSECOND) * (20 * GST_MSECOND);
if (cur != -1)
byte_cur = amrnbparse->block * (cur / 20 / GST_MSECOND) + 6;
if (stop != -1)
byte_stop = amrnbparse->block * (stop / 20 / GST_MSECOND) + 6;
amrnbparse->ts = cur;
GST_DEBUG_OBJECT (amrnbparse, "Seeking to byte range %" G_GINT64_FORMAT
" to %" G_GINT64_FORMAT, byte_cur, byte_stop);
/* Send BYTE based seek upstream */
event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type,
byte_cur, stop_type, byte_stop);
return gst_pad_push_event (amrnbparse->sinkpad, event);
}
static gboolean
gst_amrnbparse_src_event (GstPad * pad, GstEvent * event)
{
GstAmrnbParse *amrnbparse = GST_AMRNBPARSE (gst_pad_get_parent (pad));
gboolean res;
GST_DEBUG_OBJECT (amrnbparse, "handling event %d", GST_EVENT_TYPE (event));
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_SEEK:
if (amrnbparse->seek_handler)
res = amrnbparse->seek_handler (amrnbparse, pad, event);
else
res = FALSE;
break;
default:
res = gst_pad_push_event (amrnbparse->sinkpad, event);
break;
}
gst_object_unref (amrnbparse);
return res;
}
/*
* Data reading.
*/
@ -560,15 +710,33 @@ gst_amrnbparse_sink_activate (GstPad * sinkpad)
return result;
}
static gboolean
gst_amrnbparse_sink_activate_push (GstPad * sinkpad, gboolean active)
{
GstAmrnbParse *amrnbparse = GST_AMRNBPARSE (gst_pad_get_parent (sinkpad));
if (active) {
amrnbparse->seek_handler = gst_amrnbparse_handle_push_seek;
} else {
amrnbparse->seek_handler = NULL;
}
gst_object_unref (amrnbparse);
return TRUE;
}
static gboolean
gst_amrnbparse_sink_activate_pull (GstPad * sinkpad, gboolean active)
{
gboolean result;
GstAmrnbParse *amrnbparse = GST_AMRNBPARSE (gst_pad_get_parent (sinkpad));
if (active) {
amrnbparse->seek_handler = gst_amrnbparse_handle_pull_seek;
result = gst_pad_start_task (sinkpad,
(GstTaskFunction) gst_amrnbparse_loop, sinkpad);
} else {
amrnbparse->seek_handler = NULL;
result = gst_pad_stop_task (sinkpad);
}

View file

@ -39,6 +39,10 @@ G_BEGIN_DECLS
typedef struct _GstAmrnbParse GstAmrnbParse;
typedef struct _GstAmrnbParseClass GstAmrnbParseClass;
typedef gboolean (*GstAmrnbSeekHandler) (GstAmrnbParse * amrnbparse, GstPad * pad,
GstEvent * event);
struct _GstAmrnbParse {
GstElement element;
@ -52,6 +56,8 @@ struct _GstAmrnbParse {
gint64 offset;
gint block;
GstAmrnbSeekHandler seek_handler;
guint64 ts;
/* for seeking etc */