docs/design/part-seeking.txt: Some small additions.

Original commit message from CVS:
* docs/design/part-seeking.txt:
Some small additions.

* gst/base/gstbasesink.c: (gst_base_sink_handle_object),
(gst_base_sink_get_times), (gst_base_sink_do_sync),
(gst_base_sink_activate_push), (gst_base_sink_activate_pull):
* gst/base/gstbasesink.h:
discont values are gint64, handle the math correctly.

* gst/base/gstbasesrc.c: (gst_base_src_loop):
Make the basesrc report error if the source pad is not linked.

* gst/gstqueue.c: (gst_queue_link_src), (gst_queue_chain),
(gst_queue_loop), (gst_queue_handle_src_query),
(gst_queue_src_activate_push):
Make queue collect data even if the srcpad is not linked.
Start pushing out data as soon as it is linked.

* gst/gstutils.c: (gst_element_unlink), (gst_flow_get_name):
* gst/gstutils.h:
Added gst_flow_get_name() to ease error reporting.
This commit is contained in:
Wim Taymans 2005-07-21 17:22:13 +00:00
parent e261956ca6
commit 030ff93e82
12 changed files with 190 additions and 35 deletions

View file

@ -1,3 +1,27 @@
2005-07-21 Wim Taymans <wim@fluendo.com>
* docs/design/part-seeking.txt:
Some small additions.
* gst/base/gstbasesink.c: (gst_base_sink_handle_object),
(gst_base_sink_get_times), (gst_base_sink_do_sync),
(gst_base_sink_activate_push), (gst_base_sink_activate_pull):
* gst/base/gstbasesink.h:
discont values are gint64, handle the math correctly.
* gst/base/gstbasesrc.c: (gst_base_src_loop):
Make the basesrc report error if the source pad is not linked.
* gst/gstqueue.c: (gst_queue_link_src), (gst_queue_chain),
(gst_queue_loop), (gst_queue_handle_src_query),
(gst_queue_src_activate_push):
Make queue collect data even if the srcpad is not linked.
Start pushing out data as soon as it is linked.
* gst/gstutils.c: (gst_element_unlink), (gst_flow_get_name):
* gst/gstutils.h:
Added gst_flow_get_name() to ease error reporting.
2005-07-20 Wim Taymans <wim@fluendo.com> 2005-07-20 Wim Taymans <wim@fluendo.com>
* gst/gstmessage.c: (gst_message_new_segment_start), * gst/gstmessage.c: (gst_message_new_segment_start),

View file

@ -2,7 +2,7 @@ Seeking
------- -------
Seeking in GStreamer means configuring the pipeline for playback of the Seeking in GStreamer means configuring the pipeline for playback of the
media between a certain start and stop time. media between a certain start and stop time, called a segment.
Different kinds of seeking exist: Different kinds of seeking exist:
@ -30,6 +30,10 @@ earliest element in the pipeline, typically a demuxer. After receiving
the message, the application can reconnect the pipeline or issue other the message, the application can reconnect the pipeline or issue other
seek events in the pipeline. seek events in the pipeline.
The seek can also change the playback speed of the configured segment.
A speed of 1.0 is normal speed, 2.0 is double speed. Negative values
mean backward playback.
Generating seeking events Generating seeking events
------------------------- -------------------------

View file

@ -472,8 +472,7 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
/* the discont event is needed to bring the buffer timestamps to the /* the discont event is needed to bring the buffer timestamps to the
* stream time */ * stream time */
if (!gst_event_discont_get_value (event, GST_FORMAT_TIME, if (!gst_event_discont_get_value (event, GST_FORMAT_TIME,
(gint64 *) & basesink->discont_start, &basesink->discont_start, &basesink->discont_stop)) {
(gint64 *) & basesink->discont_stop)) {
basesink->discont_start = 0; basesink->discont_start = 0;
basesink->discont_stop = 0; basesink->discont_stop = 0;
} }
@ -730,15 +729,26 @@ gst_base_sink_get_times (GstBaseSink * basesink, GstBuffer * buffer,
timestamp = GST_BUFFER_TIMESTAMP (buffer); timestamp = GST_BUFFER_TIMESTAMP (buffer);
if (GST_CLOCK_TIME_IS_VALID (timestamp)) { if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
GstClockTimeDiff diff;
/* bring timestamp to stream time using last /* bring timestamp to stream time using last
* discont offset. */ * discont offset. */
timestamp -= basesink->discont_start; if ((diff = timestamp - basesink->discont_start) < 0)
goto too_late;
/* get duration to calculate end time */ /* get duration to calculate end time */
duration = GST_BUFFER_DURATION (buffer); duration = GST_BUFFER_DURATION (buffer);
if (GST_CLOCK_TIME_IS_VALID (duration)) { if (GST_CLOCK_TIME_IS_VALID (duration)) {
*end = timestamp + duration; *end = diff + duration;
} }
*start = timestamp; *start = diff;
}
return;
too_late:
{
*start = GST_CLOCK_TIME_NONE;
*end = GST_CLOCK_TIME_NONE;
} }
} }

View file

@ -67,8 +67,8 @@ struct _GstBaseSink {
GstClockTime end_time; GstClockTime end_time;
gboolean have_discont; gboolean have_discont;
GstClockTime discont_start; GstClockTimeDiff discont_start;
GstClockTime discont_stop; GstClockTimeDiff discont_stop;
gboolean eos; gboolean eos;
gboolean need_preroll; gboolean need_preroll;

View file

@ -702,11 +702,11 @@ pause:
{ {
GST_DEBUG_OBJECT (src, "pausing task"); GST_DEBUG_OBJECT (src, "pausing task");
gst_pad_pause_task (pad); gst_pad_pause_task (pad);
if (GST_FLOW_IS_FATAL (ret)) { if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
/* for fatal errors we post an error message */ /* for fatal errors we post an error message */
GST_ELEMENT_ERROR (src, STREAM, STOPPED, GST_ELEMENT_ERROR (src, STREAM, STOPPED,
("streaming stopped, reason %d", ret), ("streaming stopped, reason %s", gst_flow_get_name (ret)),
("streaming stopped, reason %d", ret)); ("streaming stopped, reason %s", gst_flow_get_name (ret)));
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS)); gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
} }
return; return;

View file

@ -29,6 +29,7 @@
#include "gstevent.h" #include "gstevent.h"
#include "gstinfo.h" #include "gstinfo.h"
#include "gsterror.h" #include "gsterror.h"
#include "gstutils.h"
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK, GST_PAD_SINK,
@ -406,10 +407,28 @@ static GstPadLinkReturn
gst_queue_link_src (GstPad * pad, GstPad * peer) gst_queue_link_src (GstPad * pad, GstPad * peer)
{ {
GstPadLinkReturn result = GST_PAD_LINK_OK; GstPadLinkReturn result = GST_PAD_LINK_OK;
GstQueue *queue;
/* FIXME, see if we need to push or get pulled */ queue = GST_QUEUE (gst_pad_get_parent (pad));
if (GST_PAD_LINKFUNC (peer))
GST_DEBUG ("queue linking source pad");
if (GST_PAD_LINKFUNC (peer)) {
result = GST_PAD_LINKFUNC (peer) (peer, pad); result = GST_PAD_LINKFUNC (peer) (peer, pad);
}
if (GST_PAD_LINK_SUCCESSFUL (result)) {
GST_QUEUE_MUTEX_LOCK (queue);
if (queue->srcresult == GST_FLOW_OK) {
gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad);
GST_DEBUG ("starting task as pad is linked");
} else {
GST_DEBUG ("not starting task reason %s",
gst_flow_get_name (queue->srcresult));
}
GST_QUEUE_MUTEX_UNLOCK (queue);
}
gst_object_unref (queue);
return result; return result;
} }
@ -673,9 +692,10 @@ out_unref:
out_flushing: out_flushing:
{ {
GstFlowReturn ret = queue->srcresult; GstFlowReturn ret = queue->srcresult;
const gchar *flowname = gst_flow_get_name (ret);
GST_CAT_LOG_OBJECT (queue_dataflow, queue, GST_CAT_LOG_OBJECT (queue_dataflow, queue,
"exit because task paused, reason: %d", ret); "exit because task paused, reason: %s", flowname);
GST_QUEUE_MUTEX_UNLOCK (queue); GST_QUEUE_MUTEX_UNLOCK (queue);
gst_buffer_unref (buffer); gst_buffer_unref (buffer);
@ -746,13 +766,18 @@ restart:
/* can opt to check for srcresult here but the push should /* can opt to check for srcresult here but the push should
* return an error value that is more accurate */ * return an error value that is more accurate */
if (result != GST_FLOW_OK) { if (result != GST_FLOW_OK) {
const gchar *flowname;
flowname = gst_flow_get_name (result);
queue->srcresult = result; queue->srcresult = result;
if (GST_FLOW_IS_FATAL (result)) { if (GST_FLOW_IS_FATAL (result)) {
GST_ELEMENT_ERROR (queue, STREAM, STOPPED, GST_ELEMENT_ERROR (queue, STREAM, STOPPED,
("streaming stopped, reason %d", result), ("streaming stopped, reason %s", flowname),
("streaming stopped, reason %d", result)); ("streaming stopped, reason %s", flowname));
gst_pad_push_event (queue->srcpad, gst_event_new (GST_EVENT_EOS)); gst_pad_push_event (queue->srcpad, gst_event_new (GST_EVENT_EOS));
} }
GST_DEBUG ("pausing queue, reason %s", flowname);
gst_pad_pause_task (queue->srcpad); gst_pad_pause_task (queue->srcpad);
} }
} else { } else {
@ -760,6 +785,7 @@ restart:
/* all incomming data is now unexpected */ /* all incomming data is now unexpected */
queue->srcresult = GST_FLOW_UNEXPECTED; queue->srcresult = GST_FLOW_UNEXPECTED;
/* and we don't need to process anymore */ /* and we don't need to process anymore */
GST_DEBUG ("pausing queue, we're EOS now");
gst_pad_pause_task (queue->srcpad); gst_pad_pause_task (queue->srcpad);
restart = FALSE; restart = FALSE;
} }
@ -780,8 +806,10 @@ restart:
out_flushing: out_flushing:
{ {
const gchar *flowname = gst_flow_get_name (queue->srcresult);
GST_CAT_LOG_OBJECT (queue_dataflow, queue, GST_CAT_LOG_OBJECT (queue_dataflow, queue,
"exit because task paused, reason: %d", queue->srcresult); "exit because task paused, reason: %s", flowname);
GST_QUEUE_MUTEX_UNLOCK (queue); GST_QUEUE_MUTEX_UNLOCK (queue);
return; return;
@ -890,7 +918,13 @@ gst_queue_src_activate_push (GstPad * pad, gboolean active)
if (active) { if (active) {
GST_QUEUE_MUTEX_LOCK (queue); GST_QUEUE_MUTEX_LOCK (queue);
queue->srcresult = GST_FLOW_OK; queue->srcresult = GST_FLOW_OK;
/* we do not start the task yet if the pad is not connected */
if (gst_pad_is_linked (pad))
result = gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad); result = gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad);
else {
GST_DEBUG ("not starting task as pad is not linked");
result = TRUE;
}
GST_QUEUE_MUTEX_UNLOCK (queue); GST_QUEUE_MUTEX_UNLOCK (queue);
} else { } else {
/* step 1, unblock chain and loop functions */ /* step 1, unblock chain and loop functions */

View file

@ -1671,6 +1671,41 @@ gst_pad_get_parent_element (GstPad * pad)
return GST_ELEMENT_CAST (p); return GST_ELEMENT_CAST (p);
} }
/**
* gst_flow_get_name:
* @state: a #GstFlowReturn to get the name of.
*
* Gets a string representing the given flow return.
*
* Returns: a string with the name of the flow return.
*/
G_CONST_RETURN gchar *
gst_flow_get_name (GstFlowReturn ret)
{
switch (ret) {
case GST_FLOW_RESEND:
return "need to resend buffer";
case GST_FLOW_OK:
return "OK";
/* expected failures */
case GST_FLOW_NOT_LINKED:
return "pad not linked";
case GST_FLOW_WRONG_STATE:
return "pad in wrong state";
/* error cases */
case GST_FLOW_UNEXPECTED:
return "unexpected data on pad";
case GST_FLOW_NOT_NEGOTIATED:
return "pad not negotiated";
case GST_FLOW_ERROR:
return "fatal error occured";
case GST_FLOW_NOT_SUPPORTED:
return "unsupported function called";
default:
return "unknown error";
}
}
/** /**
* gst_object_default_error: * gst_object_default_error:
* @object: a #GObject that signalled the error. * @object: a #GObject that signalled the error.

View file

@ -280,6 +280,10 @@ gboolean gst_pad_proxy_setcaps (GstPad * pad, GstCaps * caps);
GstElement* gst_pad_get_parent_element (GstPad *pad); GstElement* gst_pad_get_parent_element (GstPad *pad);
/* flow */
G_CONST_RETURN gchar* gst_flow_get_name (GstFlowReturn ret);
/* util query functions */ /* util query functions */
gboolean gst_pad_query_position (GstPad *pad, GstFormat *format, gboolean gst_pad_query_position (GstPad *pad, GstFormat *format,
gint64 *cur, gint64 *end); gint64 *cur, gint64 *end);

View file

@ -472,8 +472,7 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
/* the discont event is needed to bring the buffer timestamps to the /* the discont event is needed to bring the buffer timestamps to the
* stream time */ * stream time */
if (!gst_event_discont_get_value (event, GST_FORMAT_TIME, if (!gst_event_discont_get_value (event, GST_FORMAT_TIME,
(gint64 *) & basesink->discont_start, &basesink->discont_start, &basesink->discont_stop)) {
(gint64 *) & basesink->discont_stop)) {
basesink->discont_start = 0; basesink->discont_start = 0;
basesink->discont_stop = 0; basesink->discont_stop = 0;
} }
@ -730,15 +729,26 @@ gst_base_sink_get_times (GstBaseSink * basesink, GstBuffer * buffer,
timestamp = GST_BUFFER_TIMESTAMP (buffer); timestamp = GST_BUFFER_TIMESTAMP (buffer);
if (GST_CLOCK_TIME_IS_VALID (timestamp)) { if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
GstClockTimeDiff diff;
/* bring timestamp to stream time using last /* bring timestamp to stream time using last
* discont offset. */ * discont offset. */
timestamp -= basesink->discont_start; if ((diff = timestamp - basesink->discont_start) < 0)
goto too_late;
/* get duration to calculate end time */ /* get duration to calculate end time */
duration = GST_BUFFER_DURATION (buffer); duration = GST_BUFFER_DURATION (buffer);
if (GST_CLOCK_TIME_IS_VALID (duration)) { if (GST_CLOCK_TIME_IS_VALID (duration)) {
*end = timestamp + duration; *end = diff + duration;
} }
*start = timestamp; *start = diff;
}
return;
too_late:
{
*start = GST_CLOCK_TIME_NONE;
*end = GST_CLOCK_TIME_NONE;
} }
} }

View file

@ -67,8 +67,8 @@ struct _GstBaseSink {
GstClockTime end_time; GstClockTime end_time;
gboolean have_discont; gboolean have_discont;
GstClockTime discont_start; GstClockTimeDiff discont_start;
GstClockTime discont_stop; GstClockTimeDiff discont_stop;
gboolean eos; gboolean eos;
gboolean need_preroll; gboolean need_preroll;

View file

@ -702,11 +702,11 @@ pause:
{ {
GST_DEBUG_OBJECT (src, "pausing task"); GST_DEBUG_OBJECT (src, "pausing task");
gst_pad_pause_task (pad); gst_pad_pause_task (pad);
if (GST_FLOW_IS_FATAL (ret)) { if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
/* for fatal errors we post an error message */ /* for fatal errors we post an error message */
GST_ELEMENT_ERROR (src, STREAM, STOPPED, GST_ELEMENT_ERROR (src, STREAM, STOPPED,
("streaming stopped, reason %d", ret), ("streaming stopped, reason %s", gst_flow_get_name (ret)),
("streaming stopped, reason %d", ret)); ("streaming stopped, reason %s", gst_flow_get_name (ret)));
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS)); gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
} }
return; return;

View file

@ -29,6 +29,7 @@
#include "gstevent.h" #include "gstevent.h"
#include "gstinfo.h" #include "gstinfo.h"
#include "gsterror.h" #include "gsterror.h"
#include "gstutils.h"
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK, GST_PAD_SINK,
@ -406,10 +407,28 @@ static GstPadLinkReturn
gst_queue_link_src (GstPad * pad, GstPad * peer) gst_queue_link_src (GstPad * pad, GstPad * peer)
{ {
GstPadLinkReturn result = GST_PAD_LINK_OK; GstPadLinkReturn result = GST_PAD_LINK_OK;
GstQueue *queue;
/* FIXME, see if we need to push or get pulled */ queue = GST_QUEUE (gst_pad_get_parent (pad));
if (GST_PAD_LINKFUNC (peer))
GST_DEBUG ("queue linking source pad");
if (GST_PAD_LINKFUNC (peer)) {
result = GST_PAD_LINKFUNC (peer) (peer, pad); result = GST_PAD_LINKFUNC (peer) (peer, pad);
}
if (GST_PAD_LINK_SUCCESSFUL (result)) {
GST_QUEUE_MUTEX_LOCK (queue);
if (queue->srcresult == GST_FLOW_OK) {
gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad);
GST_DEBUG ("starting task as pad is linked");
} else {
GST_DEBUG ("not starting task reason %s",
gst_flow_get_name (queue->srcresult));
}
GST_QUEUE_MUTEX_UNLOCK (queue);
}
gst_object_unref (queue);
return result; return result;
} }
@ -673,9 +692,10 @@ out_unref:
out_flushing: out_flushing:
{ {
GstFlowReturn ret = queue->srcresult; GstFlowReturn ret = queue->srcresult;
const gchar *flowname = gst_flow_get_name (ret);
GST_CAT_LOG_OBJECT (queue_dataflow, queue, GST_CAT_LOG_OBJECT (queue_dataflow, queue,
"exit because task paused, reason: %d", ret); "exit because task paused, reason: %s", flowname);
GST_QUEUE_MUTEX_UNLOCK (queue); GST_QUEUE_MUTEX_UNLOCK (queue);
gst_buffer_unref (buffer); gst_buffer_unref (buffer);
@ -746,13 +766,18 @@ restart:
/* can opt to check for srcresult here but the push should /* can opt to check for srcresult here but the push should
* return an error value that is more accurate */ * return an error value that is more accurate */
if (result != GST_FLOW_OK) { if (result != GST_FLOW_OK) {
const gchar *flowname;
flowname = gst_flow_get_name (result);
queue->srcresult = result; queue->srcresult = result;
if (GST_FLOW_IS_FATAL (result)) { if (GST_FLOW_IS_FATAL (result)) {
GST_ELEMENT_ERROR (queue, STREAM, STOPPED, GST_ELEMENT_ERROR (queue, STREAM, STOPPED,
("streaming stopped, reason %d", result), ("streaming stopped, reason %s", flowname),
("streaming stopped, reason %d", result)); ("streaming stopped, reason %s", flowname));
gst_pad_push_event (queue->srcpad, gst_event_new (GST_EVENT_EOS)); gst_pad_push_event (queue->srcpad, gst_event_new (GST_EVENT_EOS));
} }
GST_DEBUG ("pausing queue, reason %s", flowname);
gst_pad_pause_task (queue->srcpad); gst_pad_pause_task (queue->srcpad);
} }
} else { } else {
@ -760,6 +785,7 @@ restart:
/* all incomming data is now unexpected */ /* all incomming data is now unexpected */
queue->srcresult = GST_FLOW_UNEXPECTED; queue->srcresult = GST_FLOW_UNEXPECTED;
/* and we don't need to process anymore */ /* and we don't need to process anymore */
GST_DEBUG ("pausing queue, we're EOS now");
gst_pad_pause_task (queue->srcpad); gst_pad_pause_task (queue->srcpad);
restart = FALSE; restart = FALSE;
} }
@ -780,8 +806,10 @@ restart:
out_flushing: out_flushing:
{ {
const gchar *flowname = gst_flow_get_name (queue->srcresult);
GST_CAT_LOG_OBJECT (queue_dataflow, queue, GST_CAT_LOG_OBJECT (queue_dataflow, queue,
"exit because task paused, reason: %d", queue->srcresult); "exit because task paused, reason: %s", flowname);
GST_QUEUE_MUTEX_UNLOCK (queue); GST_QUEUE_MUTEX_UNLOCK (queue);
return; return;
@ -890,7 +918,13 @@ gst_queue_src_activate_push (GstPad * pad, gboolean active)
if (active) { if (active) {
GST_QUEUE_MUTEX_LOCK (queue); GST_QUEUE_MUTEX_LOCK (queue);
queue->srcresult = GST_FLOW_OK; queue->srcresult = GST_FLOW_OK;
/* we do not start the task yet if the pad is not connected */
if (gst_pad_is_linked (pad))
result = gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad); result = gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad);
else {
GST_DEBUG ("not starting task as pad is not linked");
result = TRUE;
}
GST_QUEUE_MUTEX_UNLOCK (queue); GST_QUEUE_MUTEX_UNLOCK (queue);
} else { } else {
/* step 1, unblock chain and loop functions */ /* step 1, unblock chain and loop functions */