mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-10 16:32:36 +00:00
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:
parent
e261956ca6
commit
030ff93e82
12 changed files with 190 additions and 35 deletions
24
ChangeLog
24
ChangeLog
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
-------------------------
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue