gst/adder/gstadder.c: Fix adder seeking.

Original commit message from CVS:
* gst/adder/gstadder.c: (gst_adder_query_duration),
(forward_event_func), (forward_event), (gst_adder_src_event):
Fix adder seeking.
Make query/seeking code threadsafe.
* tests/check/Makefile.am:
* tests/check/elements/adder.c: (test_event_message_received),
(GST_START_TEST), (test_play_twice_message_received):
Fix adder test case.
This commit is contained in:
Wim Taymans 2006-05-29 15:49:53 +00:00
parent e3b4b0a97c
commit b375dde1a7
4 changed files with 133 additions and 49 deletions

View file

@ -1,3 +1,15 @@
2006-05-29 Wim Taymans <wim@fluendo.com>
* gst/adder/gstadder.c: (gst_adder_query_duration),
(forward_event_func), (forward_event), (gst_adder_src_event):
Fix adder seeking.
Make query/seeking code threadsafe.
* tests/check/Makefile.am:
* tests/check/elements/adder.c: (test_event_message_received),
(GST_START_TEST), (test_play_twice_message_received):
Fix adder test case.
2006-05-29 Tim-Philipp Müller <tim at centricular dot net>
Patch by: Young-Ho Cha <ganadist at chollian net>

View file

@ -245,47 +245,70 @@ not_supported:
* eachother which we can get from the first timestamps we see.
* When we add a new stream (or remove a stream) the duration might
* also become invalid again and we need to post a new DURATION
* message to ntify this fact to the parent.
* message to notify this fact to the parent.
* For now we take the max of all the upstream elements so the simple
* cases work at least somewhat. */
static gboolean
gst_adder_query_duration (GstAdder * adder, GstQuery * query)
{
GList *pads;
gint64 max;
gboolean res;
GstFormat format;
max = -1;
res = TRUE;
GstIterator *it;
gboolean done;
/* parse format */
gst_query_parse_duration (query, &format, NULL);
GST_OBJECT_LOCK (adder);
pads = GST_ELEMENT_CAST (adder)->sinkpads;
for (; pads; pads = g_list_next (pads)) {
GstPad *pad = GST_PAD_CAST (pads->data);
gint64 duration;
max = -1;
res = TRUE;
done = FALSE;
/* ask sink peer for duration */
res &= gst_pad_query_peer_duration (pad, &format, &duration);
/* take max from all valid return values */
if (res) {
/* valid unknown length, stop searching */
if (duration == -1) {
max = duration;
it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (adder));
while (!done) {
GstIteratorResult ires;
gpointer item;
ires = gst_iterator_next (it, &item);
switch (ires) {
case GST_ITERATOR_DONE:
done = TRUE;
break;
case GST_ITERATOR_OK:
{
GstPad *pad = GST_PAD_CAST (item);
gint64 duration;
/* ask sink peer for duration */
res &= gst_pad_query_peer_duration (pad, &format, &duration);
/* take max from all valid return values */
if (res) {
/* valid unknown length, stop searching */
if (duration == -1) {
max = duration;
done = TRUE;
}
/* else see if bigger than current max */
else if (duration > max)
max = duration;
}
break;
}
/* else see if bigger than current max */
else if (duration > max)
max = duration;
case GST_ITERATOR_RESYNC:
max = -1;
res = TRUE;
break;
default:
res = FALSE;
done = TRUE;
break;
}
}
GST_OBJECT_UNLOCK (adder);
/* and store the max */
gst_query_set_duration (query, format, max);
if (res) {
/* and store the max */
gst_query_set_duration (query, format, max);
}
return res;
}
@ -332,6 +355,22 @@ gst_adder_query (GstPad * pad, GstQuery * query)
return res;
}
static gboolean
forward_event_func (GstPad * pad, GValue * ret, GstEvent * event)
{
gst_event_ref (event);
if (!gst_pad_push_event (pad, event)) {
g_value_set_boolean (ret, FALSE);
GST_WARNING_OBJECT (pad, "Sending event %p (%s) failed.",
event, GST_EVENT_TYPE_NAME (event));
} else {
GST_LOG_OBJECT (pad, "Sent event %p (%s).",
event, GST_EVENT_TYPE_NAME (event));
}
gst_object_unref (pad);
return TRUE;
}
/* forwards the event to all sinkpads, takes ownership of the
* event
*
@ -342,34 +381,24 @@ static gboolean
forward_event (GstAdder * adder, GstEvent * event)
{
gboolean ret;
GList *pads;
GstIterator *it;
GValue vret = { 0 };
GST_LOG_OBJECT (adder, "Forwarding event %p (%s)", event,
GST_EVENT_TYPE_NAME (event));
ret = TRUE;
GST_OBJECT_LOCK (adder);
pads = GST_ELEMENT_CAST (adder)->sinkpads;
for (; pads; pads = g_list_next (pads)) {
GstPad *pad = GST_PAD_CAST (pads->data);
gst_event_ref (event);
ret &= gst_pad_push_event (pad, event);
if (!ret) {
GST_WARNING_OBJECT (pad, "Sending event %p (%s) failed.",
event, GST_EVENT_TYPE_NAME (event));
break;
} else {
GST_LOG_OBJECT (pad, "Sent event %p (%s).",
event, GST_EVENT_TYPE_NAME (event));
}
}
GST_OBJECT_UNLOCK (adder);
g_value_init (&vret, G_TYPE_BOOLEAN);
g_value_set_boolean (&vret, TRUE);
it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (adder));
gst_iterator_fold (it, (GstIteratorFoldFunction) forward_event_func, &vret,
event);
gst_iterator_free (it);
gst_event_unref (event);
ret = g_value_get_boolean (&vret);
return ret;
}
@ -387,9 +416,33 @@ gst_adder_src_event (GstPad * pad, GstEvent * event)
result = FALSE;
break;
case GST_EVENT_SEEK:
/* FIXME seek needs something smarter. */
{
GstSeekFlags flags;
/* parse the flushing flag */
gst_event_parse_seek (event, NULL, NULL, &flags, NULL, NULL, NULL, NULL);
/* if we are not flushing, just forward */
if (!flags & GST_SEEK_FLAG_FLUSH)
goto done;
/* make sure we accept nothing anymore and return WRONG_STATE */
gst_collect_pads_set_flushing (adder->collect, TRUE);
/* flushing seek, start flush downstream, the flush will be done
* when all pads received a FLUSH_STOP. */
gst_pad_push_event (adder->srcpad, gst_event_new_flush_start ());
/* now wait for the collected to be finished and mark a new
* segment */
GST_OBJECT_LOCK (adder->collect);
adder->segment_pending = TRUE;
GST_OBJECT_UNLOCK (adder->collect);
done:
result = forward_event (adder, event);
break;
}
case GST_EVENT_NAVIGATION:
/* navigation is rather pointless. */
result = FALSE;

View file

@ -43,6 +43,7 @@ check_PROGRAMS = \
$(check_alsa) \
$(check_vorbis) \
$(check_theora) \
elements/adder \
elements/audioconvert \
elements/audioresample \
elements/audiotestsrc \

View file

@ -76,6 +76,7 @@ test_event_message_received (GstBus * bus, GstMessage * message,
g_main_loop_quit (main_loop);
break;
default:
g_assert_not_reached ();
break;
}
}
@ -114,7 +115,7 @@ GST_START_TEST (test_event)
fail_unless (res == TRUE, NULL);
seek_event = gst_event_new_seek (1.0, GST_FORMAT_TIME,
GST_SEEK_FLAG_SEGMENT,
GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH,
GST_SEEK_TYPE_SET, (GstClockTime) 0,
GST_SEEK_TYPE_SET, (GstClockTime) 2 * GST_SECOND);
@ -134,9 +135,10 @@ GST_START_TEST (test_event)
res = gst_element_set_state (bin, GST_STATE_PAUSED);
fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL);
/* FIXME, PAUSED is async and seek might not work before being prerolled.
* though it should work in this case, as audiotestsrc is a live source
*/
/* wait for completion */
res = gst_element_get_state (bin, NULL, NULL, GST_CLOCK_TIME_NONE);
fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL);
res = gst_element_send_event (bin, seek_event);
fail_unless (res == TRUE, NULL);
@ -184,9 +186,18 @@ test_play_twice_message_received (GstBus * bus, GstMessage * message,
res = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL);
/* wait for completion */
res =
gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
GST_CLOCK_TIME_NONE);
fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL);
res = gst_element_send_event (GST_ELEMENT (bin), play_seek_event);
fail_unless (res == TRUE, NULL);
/* event is now gone */
play_seek_event = NULL;
res = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL);
} else {
@ -194,6 +205,7 @@ test_play_twice_message_received (GstBus * bus, GstMessage * message,
}
break;
default:
g_assert_not_reached ();
break;
}
}
@ -228,7 +240,7 @@ GST_START_TEST (test_play_twice)
fail_unless (res == TRUE, NULL);
play_seek_event = gst_event_new_seek (1.0, GST_FORMAT_TIME,
GST_SEEK_FLAG_SEGMENT,
GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH,
GST_SEEK_TYPE_SET, (GstClockTime) 0,
GST_SEEK_TYPE_SET, (GstClockTime) 2 * GST_SECOND);
@ -247,6 +259,12 @@ GST_START_TEST (test_play_twice)
res = gst_element_set_state (bin, GST_STATE_PAUSED);
fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL);
/* wait for completion */
res =
gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
GST_CLOCK_TIME_NONE);
fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL);
res = gst_element_send_event (bin, gst_event_ref (play_seek_event));
fail_unless (res == TRUE, NULL);