From: Wim Taymans Date: Mon, 7 Jan 2008 11:23:00 +0000 (+0000) Subject: libs/gst/base/gstbasesrc.c: Don't update the last_stop position in do_seek, that... X-Git-Tag: RELEASE-0_10_16~27 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;ds=sidebyside;h=f473d727192609ddc7173e5fa5652add91b3be9c;p=platform%2Fupstream%2Fgstreamer.git 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. --- diff --git a/ChangeLog b/ChangeLog index 9b3b4da..a5fc46a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2008-01-07 Wim Taymans + + * 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 Patch by: Alexis Ballier diff --git a/libs/gst/base/gstbasesrc.c b/libs/gst/base/gstbasesrc.c index d113e35..3cc0520 100644 --- a/libs/gst/base/gstbasesrc.c +++ b/libs/gst/base/gstbasesrc.c @@ -895,11 +895,9 @@ gst_base_src_default_do_seek (GstBaseSrc * src, GstSegment * segment) /* update our offset if the start/stop position was updated */ if (segment->format == GST_FORMAT_BYTES) { - segment->last_stop = segment->start; segment->time = segment->start; } else if (segment->start == 0) { /* seek to start, we can implement a default for this. */ - segment->last_stop = 0; segment->time = 0; res = TRUE; } else @@ -1973,6 +1971,7 @@ gst_base_src_loop (GstPad * pad) GstFlowReturn ret; gint64 position; gboolean eos; + gulong blocksize; eos = FALSE; @@ -1988,13 +1987,26 @@ gst_base_src_loop (GstPad * pad) src->priv->last_sent_eos = FALSE; + blocksize = src->blocksize; + /* 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; - 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; - 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)) { GST_INFO_OBJECT (src, "pausing after gst_base_src_get_range() = %s", gst_flow_get_name (ret)); @@ -2018,8 +2030,14 @@ gst_base_src_loop (GstPad * pad) /* figure out the new position */ switch (src->segment.format) { 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; + } case GST_FORMAT_TIME: { GstClockTime start, duration; @@ -2032,23 +2050,44 @@ gst_base_src_loop (GstPad * pad) else position = src->segment.last_stop; - if (GST_CLOCK_TIME_IS_VALID (duration)) - position += duration; + if (GST_CLOCK_TIME_IS_VALID (duration)) { + if (src->segment.rate >= 0.0) + position += duration; + else if (position > duration) + position -= duration; + else + position = 0; + } break; } 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; default: position = -1; break; } if (position != -1) { - if (src->segment.stop != -1) { - if (position >= src->segment.stop) { + if (src->segment.rate >= 0.0) { + /* positive rate, check if we reached the stop */ + if (src->segment.stop != -1) { + 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.stop; + 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); } diff --git a/tests/check/elements/filesrc.c b/tests/check/elements/filesrc.c index 0f6549b..1c8c1a1 100644 --- a/tests/check/elements/filesrc.c +++ b/tests/check/elements/filesrc.c @@ -25,9 +25,11 @@ #include -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", GST_PAD_SINK, @@ -37,14 +39,31 @@ static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", gboolean event_func (GstPad * pad, GstEvent * event) { + gboolean res = TRUE; + + g_mutex_lock (event_mutex); if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { have_eos = TRUE; - gst_event_unref (event); - return TRUE; + GST_DEBUG ("signal EOS"); + g_cond_broadcast (eos_cond); } + g_mutex_unlock (event_mutex); 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 * @@ -57,6 +76,10 @@ setup_filesrc () mysinkpad = gst_check_setup_sink_pad (filesrc, &sinktemplate, NULL); gst_pad_set_event_function (mysinkpad, event_func); gst_pad_set_active (mysinkpad, TRUE); + + eos_cond = g_cond_new (); + event_mutex = g_mutex_new (); + return filesrc; } @@ -66,6 +89,9 @@ cleanup_filesrc (GstElement * filesrc) gst_pad_set_active (mysinkpad, FALSE); gst_check_teardown_sink_pad (filesrc); gst_check_teardown_element (filesrc); + + g_cond_free (eos_cond); + g_mutex_free (event_mutex); } GST_START_TEST (test_seeking) @@ -101,6 +127,41 @@ GST_START_TEST (test_seeking) 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) { GstElement *src; @@ -323,6 +384,7 @@ filesrc_suite (void) suite_add_tcase (s, tc_chain); 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_coverage); tcase_add_test (tc_chain, test_uri_interface);