gst/base/gstbasesrc.c: Fix seeking.

Original commit message from CVS:
* gst/base/gstbasesrc.c: (gst_base_src_init),
(gst_base_src_do_seek), (gst_base_src_loop), (gst_base_src_start):
Fix seeking.
This commit is contained in:
Wim Taymans 2005-10-21 16:14:34 +00:00
parent 5cce351ef3
commit 5b63b6489e
3 changed files with 118 additions and 66 deletions

View file

@ -1,3 +1,9 @@
2005-10-21 Wim Taymans <wim@fluendo.com>
* gst/base/gstbasesrc.c: (gst_base_src_init),
(gst_base_src_do_seek), (gst_base_src_loop), (gst_base_src_start):
Fix seeking.
2005-10-21 Wim Taymans <wim@fluendo.com> 2005-10-21 Wim Taymans <wim@fluendo.com>
* docs/design/part-segments.txt: * docs/design/part-segments.txt:

View file

@ -211,6 +211,7 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
GST_DEBUG_OBJECT (basesrc, "adding src pad"); GST_DEBUG_OBJECT (basesrc, "adding src pad");
gst_element_add_pad (GST_ELEMENT (basesrc), pad); gst_element_add_pad (GST_ELEMENT (basesrc), pad);
basesrc->segment_loop = FALSE;
basesrc->segment_start = -1; basesrc->segment_start = -1;
basesrc->segment_end = -1; basesrc->segment_end = -1;
basesrc->need_newsegment = TRUE; basesrc->need_newsegment = TRUE;
@ -424,6 +425,8 @@ gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
GstSeekFlags flags; GstSeekFlags flags;
GstSeekType cur_type, stop_type; GstSeekType cur_type, stop_type;
gint64 cur, stop; gint64 cur, stop;
gboolean flush;
gboolean update_stop = TRUE, update_start = TRUE;
gst_event_parse_seek (event, &rate, &format, &flags, gst_event_parse_seek (event, &rate, &format, &flags,
&cur_type, &cur, &stop_type, &stop); &cur_type, &cur, &stop_type, &stop);
@ -433,13 +436,18 @@ gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
format = GST_FORMAT_BYTES; format = GST_FORMAT_BYTES;
/* we can only seek bytes */ /* we can only seek bytes */
if (format != GST_FORMAT_BYTES) if (format != GST_FORMAT_BYTES)
return FALSE; goto unsupported_seek;
flush = flags & GST_SEEK_FLAG_FLUSH;
/* get seek positions */ /* get seek positions */
src->segment_loop = flags & GST_SEEK_FLAG_SEGMENT; src->segment_loop = (flags & GST_SEEK_FLAG_SEGMENT) != 0;
/* send flush start */ /* send flush start */
gst_pad_push_event (src->srcpad, gst_event_new_flush_start ()); if (flush)
gst_pad_push_event (src->srcpad, gst_event_new_flush_start ());
else
gst_pad_pause_task (src->srcpad);
/* unblock streaming thread */ /* unblock streaming thread */
gst_base_src_unlock (src); gst_base_src_unlock (src);
@ -447,52 +455,49 @@ gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
/* grab streaming lock */ /* grab streaming lock */
GST_STREAM_LOCK (src->srcpad); GST_STREAM_LOCK (src->srcpad);
/* send flush stop */
gst_pad_push_event (src->srcpad, gst_event_new_flush_stop ());
/* perform the seek */ /* perform the seek */
switch (cur_type) { switch (cur_type) {
case GST_SEEK_TYPE_NONE: case GST_SEEK_TYPE_NONE:
/* no update to segment */
cur = src->segment_start;
update_start = FALSE;
break; break;
case GST_SEEK_TYPE_SET: case GST_SEEK_TYPE_SET:
if (cur < 0) /* cur hold desired position */
goto error;
src->offset = MIN (cur, src->size);
src->segment_start = src->offset;
break; break;
case GST_SEEK_TYPE_CUR: case GST_SEEK_TYPE_CUR:
src->offset = CLAMP (src->offset + cur, 0, src->size); /* add cur to currently configure segment */
src->segment_start = src->offset; cur = src->segment_start + cur;
break; break;
case GST_SEEK_TYPE_END: case GST_SEEK_TYPE_END:
if (cur > 0) /* add cur to total length */
goto error; cur = src->size + cur;
src->offset = MAX (0, src->size + cur);
src->segment_start = src->offset;
break; break;
default:
goto error;
} }
/* bring in sane range */
cur = CLAMP (cur, 0, src->size);
switch (stop_type) { switch (stop_type) {
case GST_SEEK_TYPE_NONE: case GST_SEEK_TYPE_NONE:
stop = src->segment_end;
update_stop = FALSE;
break; break;
case GST_SEEK_TYPE_SET: case GST_SEEK_TYPE_SET:
if (stop < 0)
goto error;
src->segment_end = MIN (stop, src->size);
break; break;
case GST_SEEK_TYPE_CUR: case GST_SEEK_TYPE_CUR:
src->segment_end = CLAMP (src->segment_end + stop, 0, src->size); stop = src->segment_end + stop;
break; break;
case GST_SEEK_TYPE_END: case GST_SEEK_TYPE_END:
if (stop > 0) stop = src->size + stop;
goto error;
src->segment_end = src->size + stop;
break; break;
default:
goto error;
} }
stop = CLAMP (stop, 0, src->size);
src->segment_start = cur;
src->segment_end = stop;
/* update our offset */
src->offset = cur;
GST_DEBUG_OBJECT (src, "seek pending for segment from %" G_GINT64_FORMAT GST_DEBUG_OBJECT (src, "seek pending for segment from %" G_GINT64_FORMAT
" to %" G_GINT64_FORMAT, src->segment_start, src->segment_end); " to %" G_GINT64_FORMAT, src->segment_start, src->segment_end);
@ -500,9 +505,20 @@ gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
/* now make sure the newsegment will be send */ /* now make sure the newsegment will be send */
src->need_newsegment = TRUE; src->need_newsegment = TRUE;
if (flush)
/* send flush stop */
gst_pad_push_event (src->srcpad, gst_event_new_flush_stop ());
if (src->segment_loop) {
gst_element_post_message (GST_ELEMENT (src),
gst_message_new_segment_start (GST_OBJECT (src), GST_FORMAT_BYTES,
cur));
}
/* and restart the task */ /* and restart the task */
gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop, gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop,
src->srcpad); src->srcpad);
GST_STREAM_UNLOCK (src->srcpad); GST_STREAM_UNLOCK (src->srcpad);
gst_event_unref (event); gst_event_unref (event);
@ -510,11 +526,12 @@ gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
return TRUE; return TRUE;
/* ERROR */ /* ERROR */
error: unsupported_seek:
{ {
GST_DEBUG_OBJECT (src, "seek error"); GST_DEBUG_OBJECT (src, "invalid format");
GST_STREAM_UNLOCK (src->srcpad); GST_ELEMENT_WARNING (src, STREAM, NOT_IMPLEMENTED,
gst_event_unref (event); ("Seek aborted, unsupported format"),
("Seek aborted, unsupported format"));
return FALSE; return FALSE;
} }
} }
@ -740,7 +757,12 @@ eos:
{ {
GST_DEBUG_OBJECT (src, "going to EOS"); GST_DEBUG_OBJECT (src, "going to EOS");
gst_pad_pause_task (pad); gst_pad_pause_task (pad);
gst_pad_push_event (pad, gst_event_new_eos ()); if (src->segment_loop) {
gst_element_post_message (GST_ELEMENT (src),
gst_message_new_segment_done (GST_OBJECT (src),
GST_FORMAT_BYTES, src->segment_end));
} else
gst_pad_push_event (pad, gst_event_new_eos ());
return; return;
} }
pause: pause:
@ -938,7 +960,8 @@ gst_base_src_start (GstBaseSrc * basesrc)
GST_DEBUG ("size %d %lld", result, basesrc->size); GST_DEBUG ("size %d %lld", result, basesrc->size);
/* we always run to the end */ /* we always run to the end when starting */
basesrc->segment_loop = FALSE;
basesrc->segment_start = 0; basesrc->segment_start = 0;
basesrc->segment_end = basesrc->size; basesrc->segment_end = basesrc->size;
basesrc->need_newsegment = TRUE; basesrc->need_newsegment = TRUE;

View file

@ -211,6 +211,7 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
GST_DEBUG_OBJECT (basesrc, "adding src pad"); GST_DEBUG_OBJECT (basesrc, "adding src pad");
gst_element_add_pad (GST_ELEMENT (basesrc), pad); gst_element_add_pad (GST_ELEMENT (basesrc), pad);
basesrc->segment_loop = FALSE;
basesrc->segment_start = -1; basesrc->segment_start = -1;
basesrc->segment_end = -1; basesrc->segment_end = -1;
basesrc->need_newsegment = TRUE; basesrc->need_newsegment = TRUE;
@ -424,6 +425,8 @@ gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
GstSeekFlags flags; GstSeekFlags flags;
GstSeekType cur_type, stop_type; GstSeekType cur_type, stop_type;
gint64 cur, stop; gint64 cur, stop;
gboolean flush;
gboolean update_stop = TRUE, update_start = TRUE;
gst_event_parse_seek (event, &rate, &format, &flags, gst_event_parse_seek (event, &rate, &format, &flags,
&cur_type, &cur, &stop_type, &stop); &cur_type, &cur, &stop_type, &stop);
@ -433,13 +436,18 @@ gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
format = GST_FORMAT_BYTES; format = GST_FORMAT_BYTES;
/* we can only seek bytes */ /* we can only seek bytes */
if (format != GST_FORMAT_BYTES) if (format != GST_FORMAT_BYTES)
return FALSE; goto unsupported_seek;
flush = flags & GST_SEEK_FLAG_FLUSH;
/* get seek positions */ /* get seek positions */
src->segment_loop = flags & GST_SEEK_FLAG_SEGMENT; src->segment_loop = (flags & GST_SEEK_FLAG_SEGMENT) != 0;
/* send flush start */ /* send flush start */
gst_pad_push_event (src->srcpad, gst_event_new_flush_start ()); if (flush)
gst_pad_push_event (src->srcpad, gst_event_new_flush_start ());
else
gst_pad_pause_task (src->srcpad);
/* unblock streaming thread */ /* unblock streaming thread */
gst_base_src_unlock (src); gst_base_src_unlock (src);
@ -447,52 +455,49 @@ gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
/* grab streaming lock */ /* grab streaming lock */
GST_STREAM_LOCK (src->srcpad); GST_STREAM_LOCK (src->srcpad);
/* send flush stop */
gst_pad_push_event (src->srcpad, gst_event_new_flush_stop ());
/* perform the seek */ /* perform the seek */
switch (cur_type) { switch (cur_type) {
case GST_SEEK_TYPE_NONE: case GST_SEEK_TYPE_NONE:
/* no update to segment */
cur = src->segment_start;
update_start = FALSE;
break; break;
case GST_SEEK_TYPE_SET: case GST_SEEK_TYPE_SET:
if (cur < 0) /* cur hold desired position */
goto error;
src->offset = MIN (cur, src->size);
src->segment_start = src->offset;
break; break;
case GST_SEEK_TYPE_CUR: case GST_SEEK_TYPE_CUR:
src->offset = CLAMP (src->offset + cur, 0, src->size); /* add cur to currently configure segment */
src->segment_start = src->offset; cur = src->segment_start + cur;
break; break;
case GST_SEEK_TYPE_END: case GST_SEEK_TYPE_END:
if (cur > 0) /* add cur to total length */
goto error; cur = src->size + cur;
src->offset = MAX (0, src->size + cur);
src->segment_start = src->offset;
break; break;
default:
goto error;
} }
/* bring in sane range */
cur = CLAMP (cur, 0, src->size);
switch (stop_type) { switch (stop_type) {
case GST_SEEK_TYPE_NONE: case GST_SEEK_TYPE_NONE:
stop = src->segment_end;
update_stop = FALSE;
break; break;
case GST_SEEK_TYPE_SET: case GST_SEEK_TYPE_SET:
if (stop < 0)
goto error;
src->segment_end = MIN (stop, src->size);
break; break;
case GST_SEEK_TYPE_CUR: case GST_SEEK_TYPE_CUR:
src->segment_end = CLAMP (src->segment_end + stop, 0, src->size); stop = src->segment_end + stop;
break; break;
case GST_SEEK_TYPE_END: case GST_SEEK_TYPE_END:
if (stop > 0) stop = src->size + stop;
goto error;
src->segment_end = src->size + stop;
break; break;
default:
goto error;
} }
stop = CLAMP (stop, 0, src->size);
src->segment_start = cur;
src->segment_end = stop;
/* update our offset */
src->offset = cur;
GST_DEBUG_OBJECT (src, "seek pending for segment from %" G_GINT64_FORMAT GST_DEBUG_OBJECT (src, "seek pending for segment from %" G_GINT64_FORMAT
" to %" G_GINT64_FORMAT, src->segment_start, src->segment_end); " to %" G_GINT64_FORMAT, src->segment_start, src->segment_end);
@ -500,9 +505,20 @@ gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
/* now make sure the newsegment will be send */ /* now make sure the newsegment will be send */
src->need_newsegment = TRUE; src->need_newsegment = TRUE;
if (flush)
/* send flush stop */
gst_pad_push_event (src->srcpad, gst_event_new_flush_stop ());
if (src->segment_loop) {
gst_element_post_message (GST_ELEMENT (src),
gst_message_new_segment_start (GST_OBJECT (src), GST_FORMAT_BYTES,
cur));
}
/* and restart the task */ /* and restart the task */
gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop, gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop,
src->srcpad); src->srcpad);
GST_STREAM_UNLOCK (src->srcpad); GST_STREAM_UNLOCK (src->srcpad);
gst_event_unref (event); gst_event_unref (event);
@ -510,11 +526,12 @@ gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
return TRUE; return TRUE;
/* ERROR */ /* ERROR */
error: unsupported_seek:
{ {
GST_DEBUG_OBJECT (src, "seek error"); GST_DEBUG_OBJECT (src, "invalid format");
GST_STREAM_UNLOCK (src->srcpad); GST_ELEMENT_WARNING (src, STREAM, NOT_IMPLEMENTED,
gst_event_unref (event); ("Seek aborted, unsupported format"),
("Seek aborted, unsupported format"));
return FALSE; return FALSE;
} }
} }
@ -740,7 +757,12 @@ eos:
{ {
GST_DEBUG_OBJECT (src, "going to EOS"); GST_DEBUG_OBJECT (src, "going to EOS");
gst_pad_pause_task (pad); gst_pad_pause_task (pad);
gst_pad_push_event (pad, gst_event_new_eos ()); if (src->segment_loop) {
gst_element_post_message (GST_ELEMENT (src),
gst_message_new_segment_done (GST_OBJECT (src),
GST_FORMAT_BYTES, src->segment_end));
} else
gst_pad_push_event (pad, gst_event_new_eos ());
return; return;
} }
pause: pause:
@ -938,7 +960,8 @@ gst_base_src_start (GstBaseSrc * basesrc)
GST_DEBUG ("size %d %lld", result, basesrc->size); GST_DEBUG ("size %d %lld", result, basesrc->size);
/* we always run to the end */ /* we always run to the end when starting */
basesrc->segment_loop = FALSE;
basesrc->segment_start = 0; basesrc->segment_start = 0;
basesrc->segment_end = basesrc->size; basesrc->segment_end = basesrc->size;
basesrc->need_newsegment = TRUE; basesrc->need_newsegment = TRUE;