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>
* 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
media between a certain start and stop time.
media between a certain start and stop time, called a segment.
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
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
-------------------------

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
* stream time */
if (!gst_event_discont_get_value (event, GST_FORMAT_TIME,
(gint64 *) & basesink->discont_start,
(gint64 *) & basesink->discont_stop)) {
&basesink->discont_start, &basesink->discont_stop)) {
basesink->discont_start = 0;
basesink->discont_stop = 0;
}
@ -730,15 +729,26 @@ gst_base_sink_get_times (GstBaseSink * basesink, GstBuffer * buffer,
timestamp = GST_BUFFER_TIMESTAMP (buffer);
if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
GstClockTimeDiff diff;
/* bring timestamp to stream time using last
* discont offset. */
timestamp -= basesink->discont_start;
if ((diff = timestamp - basesink->discont_start) < 0)
goto too_late;
/* get duration to calculate end time */
duration = GST_BUFFER_DURATION (buffer);
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;
gboolean have_discont;
GstClockTime discont_start;
GstClockTime discont_stop;
GstClockTimeDiff discont_start;
GstClockTimeDiff discont_stop;
gboolean eos;
gboolean need_preroll;

View file

@ -702,11 +702,11 @@ pause:
{
GST_DEBUG_OBJECT (src, "pausing task");
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 */
GST_ELEMENT_ERROR (src, STREAM, STOPPED,
("streaming stopped, reason %d", ret),
("streaming stopped, reason %d", ret));
("streaming stopped, reason %s", gst_flow_get_name (ret)),
("streaming stopped, reason %s", gst_flow_get_name (ret)));
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
}
return;

View file

@ -29,6 +29,7 @@
#include "gstevent.h"
#include "gstinfo.h"
#include "gsterror.h"
#include "gstutils.h"
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
@ -406,10 +407,28 @@ static GstPadLinkReturn
gst_queue_link_src (GstPad * pad, GstPad * peer)
{
GstPadLinkReturn result = GST_PAD_LINK_OK;
GstQueue *queue;
/* FIXME, see if we need to push or get pulled */
if (GST_PAD_LINKFUNC (peer))
queue = GST_QUEUE (gst_pad_get_parent (pad));
GST_DEBUG ("queue linking source pad");
if (GST_PAD_LINKFUNC (peer)) {
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;
}
@ -673,9 +692,10 @@ out_unref:
out_flushing:
{
GstFlowReturn ret = queue->srcresult;
const gchar *flowname = gst_flow_get_name (ret);
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_buffer_unref (buffer);
@ -746,13 +766,18 @@ restart:
/* can opt to check for srcresult here but the push should
* return an error value that is more accurate */
if (result != GST_FLOW_OK) {
const gchar *flowname;
flowname = gst_flow_get_name (result);
queue->srcresult = result;
if (GST_FLOW_IS_FATAL (result)) {
GST_ELEMENT_ERROR (queue, STREAM, STOPPED,
("streaming stopped, reason %d", result),
("streaming stopped, reason %d", result));
("streaming stopped, reason %s", flowname),
("streaming stopped, reason %s", flowname));
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);
}
} else {
@ -760,6 +785,7 @@ restart:
/* all incomming data is now unexpected */
queue->srcresult = GST_FLOW_UNEXPECTED;
/* and we don't need to process anymore */
GST_DEBUG ("pausing queue, we're EOS now");
gst_pad_pause_task (queue->srcpad);
restart = FALSE;
}
@ -780,8 +806,10 @@ restart:
out_flushing:
{
const gchar *flowname = gst_flow_get_name (queue->srcresult);
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);
return;
@ -890,7 +918,13 @@ gst_queue_src_activate_push (GstPad * pad, gboolean active)
if (active) {
GST_QUEUE_MUTEX_LOCK (queue);
queue->srcresult = GST_FLOW_OK;
result = gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad);
/* 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);
else {
GST_DEBUG ("not starting task as pad is not linked");
result = TRUE;
}
GST_QUEUE_MUTEX_UNLOCK (queue);
} else {
/* 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);
}
/**
* 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:
* @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);
/* flow */
G_CONST_RETURN gchar* gst_flow_get_name (GstFlowReturn ret);
/* util query functions */
gboolean gst_pad_query_position (GstPad *pad, GstFormat *format,
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
* stream time */
if (!gst_event_discont_get_value (event, GST_FORMAT_TIME,
(gint64 *) & basesink->discont_start,
(gint64 *) & basesink->discont_stop)) {
&basesink->discont_start, &basesink->discont_stop)) {
basesink->discont_start = 0;
basesink->discont_stop = 0;
}
@ -730,15 +729,26 @@ gst_base_sink_get_times (GstBaseSink * basesink, GstBuffer * buffer,
timestamp = GST_BUFFER_TIMESTAMP (buffer);
if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
GstClockTimeDiff diff;
/* bring timestamp to stream time using last
* discont offset. */
timestamp -= basesink->discont_start;
if ((diff = timestamp - basesink->discont_start) < 0)
goto too_late;
/* get duration to calculate end time */
duration = GST_BUFFER_DURATION (buffer);
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;
gboolean have_discont;
GstClockTime discont_start;
GstClockTime discont_stop;
GstClockTimeDiff discont_start;
GstClockTimeDiff discont_stop;
gboolean eos;
gboolean need_preroll;

View file

@ -702,11 +702,11 @@ pause:
{
GST_DEBUG_OBJECT (src, "pausing task");
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 */
GST_ELEMENT_ERROR (src, STREAM, STOPPED,
("streaming stopped, reason %d", ret),
("streaming stopped, reason %d", ret));
("streaming stopped, reason %s", gst_flow_get_name (ret)),
("streaming stopped, reason %s", gst_flow_get_name (ret)));
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
}
return;

View file

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