libs/gst/base/gstbasesrc.c: Don't update the last_stop position in do_seek, that's the position we did a seek to.

Original commit message from CVS:
* libs/gst/base/gstbasesrc.c: (gst_base_src_default_do_seek),
(gst_base_src_loop):
Don't update the last_stop position in do_seek, that's the position we
did a seek to.
Read backwards when we have a negative rate.
* tests/check/elements/filesrc.c: (event_func), (wait_eos),
(setup_filesrc), (cleanup_filesrc), (GST_START_TEST),
(filesrc_suite):
Add check for reverse reading.
This commit is contained in:
Wim Taymans 2008-01-07 11:23:00 +00:00
parent 91a59d5af5
commit f473d72719
3 changed files with 132 additions and 18 deletions

View file

@ -1,3 +1,16 @@
2008-01-07 Wim Taymans <wim.taymans@collabora.co.uk>
* libs/gst/base/gstbasesrc.c: (gst_base_src_default_do_seek),
(gst_base_src_loop):
Don't update the last_stop position in do_seek, that's the position we
did a seek to.
Read backwards when we have a negative rate.
* tests/check/elements/filesrc.c: (event_func), (wait_eos),
(setup_filesrc), (cleanup_filesrc), (GST_START_TEST),
(filesrc_suite):
Add check for reverse reading.
2008-01-07 Tim-Philipp Müller <tim at centricular dot net> 2008-01-07 Tim-Philipp Müller <tim at centricular dot net>
Patch by: Alexis Ballier <aballier at gentoo org> Patch by: Alexis Ballier <aballier at gentoo org>

View file

@ -895,11 +895,9 @@ gst_base_src_default_do_seek (GstBaseSrc * src, GstSegment * segment)
/* update our offset if the start/stop position was updated */ /* update our offset if the start/stop position was updated */
if (segment->format == GST_FORMAT_BYTES) { if (segment->format == GST_FORMAT_BYTES) {
segment->last_stop = segment->start;
segment->time = segment->start; segment->time = segment->start;
} else if (segment->start == 0) { } else if (segment->start == 0) {
/* seek to start, we can implement a default for this. */ /* seek to start, we can implement a default for this. */
segment->last_stop = 0;
segment->time = 0; segment->time = 0;
res = TRUE; res = TRUE;
} else } else
@ -1973,6 +1971,7 @@ gst_base_src_loop (GstPad * pad)
GstFlowReturn ret; GstFlowReturn ret;
gint64 position; gint64 position;
gboolean eos; gboolean eos;
gulong blocksize;
eos = FALSE; eos = FALSE;
@ -1988,13 +1987,26 @@ gst_base_src_loop (GstPad * pad)
src->priv->last_sent_eos = FALSE; src->priv->last_sent_eos = FALSE;
blocksize = src->blocksize;
/* if we operate in bytes, we can calculate an offset */ /* if we operate in bytes, we can calculate an offset */
if (src->segment.format == GST_FORMAT_BYTES) if (src->segment.format == GST_FORMAT_BYTES) {
position = src->segment.last_stop; position = src->segment.last_stop;
else /* for negative rates, start with subtracting the blocksize */
if (src->segment.rate < 0.0) {
/* we cannot go below segment.start */
if (position > src->segment.start + blocksize)
position -= blocksize;
else {
/* last block, remainder up to segment.start */
blocksize = position - src->segment.start;
position = src->segment.start;
}
}
} else
position = -1; position = -1;
ret = gst_base_src_get_range (src, position, src->blocksize, &buf); ret = gst_base_src_get_range (src, position, blocksize, &buf);
if (G_UNLIKELY (ret != GST_FLOW_OK)) { if (G_UNLIKELY (ret != GST_FLOW_OK)) {
GST_INFO_OBJECT (src, "pausing after gst_base_src_get_range() = %s", GST_INFO_OBJECT (src, "pausing after gst_base_src_get_range() = %s",
gst_flow_get_name (ret)); gst_flow_get_name (ret));
@ -2018,8 +2030,14 @@ gst_base_src_loop (GstPad * pad)
/* figure out the new position */ /* figure out the new position */
switch (src->segment.format) { switch (src->segment.format) {
case GST_FORMAT_BYTES: case GST_FORMAT_BYTES:
position += GST_BUFFER_SIZE (buf); {
guint bufsize = GST_BUFFER_SIZE (buf);
/* we subtracted above for negative rates */
if (src->segment.rate >= 0.0)
position += bufsize;
break; break;
}
case GST_FORMAT_TIME: case GST_FORMAT_TIME:
{ {
GstClockTime start, duration; GstClockTime start, duration;
@ -2032,23 +2050,44 @@ gst_base_src_loop (GstPad * pad)
else else
position = src->segment.last_stop; position = src->segment.last_stop;
if (GST_CLOCK_TIME_IS_VALID (duration)) if (GST_CLOCK_TIME_IS_VALID (duration)) {
position += duration; if (src->segment.rate >= 0.0)
position += duration;
else if (position > duration)
position -= duration;
else
position = 0;
}
break; break;
} }
case GST_FORMAT_DEFAULT: case GST_FORMAT_DEFAULT:
position = GST_BUFFER_OFFSET_END (buf); if (src->segment.rate >= 0.0)
position = GST_BUFFER_OFFSET_END (buf);
else
position = GST_BUFFER_OFFSET (buf);
break; break;
default: default:
position = -1; position = -1;
break; break;
} }
if (position != -1) { if (position != -1) {
if (src->segment.stop != -1) { if (src->segment.rate >= 0.0) {
if (position >= src->segment.stop) { /* positive rate, check if we reached the stop */
eos = TRUE; if (src->segment.stop != -1) {
position = src->segment.stop; if (position >= src->segment.stop) {
eos = TRUE;
position = src->segment.stop;
}
} }
} else {
/* negative rate, check if we reached the start. start is always set to
* something different from -1 */
if (position <= src->segment.start) {
eos = TRUE;
position = src->segment.start;
}
/* when going reverse, all buffers are DISCONT */
src->priv->discont = TRUE;
} }
gst_segment_set_last_stop (&src->segment, src->segment.format, position); gst_segment_set_last_stop (&src->segment, src->segment.format, position);
} }

View file

@ -25,9 +25,11 @@
#include <gst/check/gstcheck.h> #include <gst/check/gstcheck.h>
gboolean have_eos = FALSE; static gboolean have_eos = FALSE;
static GCond *eos_cond;
static GMutex *event_mutex;
GstPad *mysinkpad; static GstPad *mysinkpad;
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK, GST_PAD_SINK,
@ -37,14 +39,31 @@ static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
gboolean gboolean
event_func (GstPad * pad, GstEvent * event) event_func (GstPad * pad, GstEvent * event)
{ {
gboolean res = TRUE;
g_mutex_lock (event_mutex);
if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
have_eos = TRUE; have_eos = TRUE;
gst_event_unref (event); GST_DEBUG ("signal EOS");
return TRUE; g_cond_broadcast (eos_cond);
} }
g_mutex_unlock (event_mutex);
gst_event_unref (event); gst_event_unref (event);
return FALSE;
return res;
}
void
wait_eos (void)
{
g_mutex_lock (event_mutex);
GST_DEBUG ("waiting for EOS");
while (!have_eos) {
g_cond_wait (eos_cond, event_mutex);
}
GST_DEBUG ("received EOS");
g_mutex_unlock (event_mutex);
} }
GstElement * GstElement *
@ -57,6 +76,10 @@ setup_filesrc ()
mysinkpad = gst_check_setup_sink_pad (filesrc, &sinktemplate, NULL); mysinkpad = gst_check_setup_sink_pad (filesrc, &sinktemplate, NULL);
gst_pad_set_event_function (mysinkpad, event_func); gst_pad_set_event_function (mysinkpad, event_func);
gst_pad_set_active (mysinkpad, TRUE); gst_pad_set_active (mysinkpad, TRUE);
eos_cond = g_cond_new ();
event_mutex = g_mutex_new ();
return filesrc; return filesrc;
} }
@ -66,6 +89,9 @@ cleanup_filesrc (GstElement * filesrc)
gst_pad_set_active (mysinkpad, FALSE); gst_pad_set_active (mysinkpad, FALSE);
gst_check_teardown_sink_pad (filesrc); gst_check_teardown_sink_pad (filesrc);
gst_check_teardown_element (filesrc); gst_check_teardown_element (filesrc);
g_cond_free (eos_cond);
g_mutex_free (event_mutex);
} }
GST_START_TEST (test_seeking) GST_START_TEST (test_seeking)
@ -101,6 +127,41 @@ GST_START_TEST (test_seeking)
GST_END_TEST; GST_END_TEST;
GST_START_TEST (test_reverse)
{
GstElement *src;
#ifndef TESTFILE
#error TESTFILE not defined
#endif
src = setup_filesrc ();
g_object_set (G_OBJECT (src), "location", TESTFILE, NULL);
/* we're going to perform the seek in ready */
fail_unless (gst_element_set_state (src,
GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS,
"could not set to ready");
/* reverse seek from end to start */
gst_element_seek (src, -1.0, GST_FORMAT_BYTES, 0, GST_SEEK_TYPE_SET, 100,
GST_SEEK_TYPE_SET, -1);
fail_unless (gst_element_set_state (src,
GST_STATE_PAUSED) == GST_STATE_CHANGE_SUCCESS,
"could not set to paused");
/* wait for EOS */
wait_eos ();
fail_unless (gst_element_set_state (src,
GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
/* cleanup */
cleanup_filesrc (src);
}
GST_END_TEST;
GST_START_TEST (test_pull) GST_START_TEST (test_pull)
{ {
GstElement *src; GstElement *src;
@ -323,6 +384,7 @@ filesrc_suite (void)
suite_add_tcase (s, tc_chain); suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_seeking); tcase_add_test (tc_chain, test_seeking);
tcase_add_test (tc_chain, test_reverse);
tcase_add_test (tc_chain, test_pull); tcase_add_test (tc_chain, test_pull);
tcase_add_test (tc_chain, test_coverage); tcase_add_test (tc_chain, test_coverage);
tcase_add_test (tc_chain, test_uri_interface); tcase_add_test (tc_chain, test_uri_interface);