gst/gstpipeline.c: Don't ref a NULL clock in _provide_clock_func().

Original commit message from CVS:
* gst/gstpipeline.c: (gst_pipeline_change_state),
(gst_pipeline_provide_clock_func), (gst_pipeline_set_delay):
Don't ref a NULL clock in _provide_clock_func().
Don't allow an INVALID delay.
Don't try to calculate base_time with an invalid start_time.
Also distribute and notify a NULL clock when it was selected.
* tools/gst-launch.c: (event_loop):
Don't crash when a NULL clock was selected in the pipeline.
This commit is contained in:
Wim Taymans 2007-02-23 17:42:06 +00:00
parent 77614f97aa
commit c574a01484
3 changed files with 52 additions and 34 deletions

View file

@ -1,3 +1,15 @@
2007-02-23 Wim Taymans <wim@fluendo.com>
* gst/gstpipeline.c: (gst_pipeline_change_state),
(gst_pipeline_provide_clock_func), (gst_pipeline_set_delay):
Don't ref a NULL clock in _provide_clock_func().
Don't allow an INVALID delay.
Don't try to calculate base_time with an invalid start_time.
Also distribute and notify a NULL clock when it was selected.
* tools/gst-launch.c: (event_loop):
Don't crash when a NULL clock was selected in the pipeline.
2007-02-23 Tim-Philipp Müller <tim at centricular dot net> 2007-02-23 Tim-Philipp Müller <tim at centricular dot net>
* docs/design/Makefile.am: * docs/design/Makefile.am:

View file

@ -433,53 +433,55 @@ gst_pipeline_change_state (GstElement * element, GstStateChange transition)
case GST_STATE_CHANGE_PAUSED_TO_PLAYING: case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
{ {
GstClockTime new_base_time; GstClockTime new_base_time;
GstClockTime start_time, stream_time, delay;
gboolean new_clock;
/* when going to playing, select a clock */ /* when going to playing, select a clock */
clock = gst_element_provide_clock (element); clock = gst_element_provide_clock (element);
if (clock) { if (clock) {
GstClockTime start_time, stream_time, delay;
gboolean new_clock;
start_time = gst_clock_get_time (clock); start_time = gst_clock_get_time (clock);
GST_OBJECT_LOCK (element);
new_clock = element->clock != clock;
stream_time = pipeline->stream_time;
delay = pipeline->delay;
GST_OBJECT_UNLOCK (element);
if (new_clock) {
/* now distribute the clock (which could be NULL). If some
* element refuses the clock, this will return FALSE and
* we effectively fail the state change. */
if (!gst_element_set_clock (element, clock))
goto invalid_clock;
/* if we selected and distributed a new clock, let the app
* know about it */
gst_element_post_message (element,
gst_message_new_new_clock (GST_OBJECT_CAST (element), clock));
}
if (stream_time != GST_CLOCK_TIME_NONE)
new_base_time = start_time - stream_time + delay;
else
new_base_time = GST_CLOCK_TIME_NONE;
gst_object_unref (clock);
} else { } else {
GST_DEBUG ("no clock, using base time of 0"); start_time = GST_CLOCK_TIME_NONE;
new_base_time = 0; GST_DEBUG ("no clock, using base time of NONE");
new_base_time = GST_CLOCK_TIME_NONE;
} }
GST_OBJECT_LOCK (element);
new_clock = element->clock != clock;
stream_time = pipeline->stream_time;
delay = pipeline->delay;
GST_OBJECT_UNLOCK (element);
if (new_clock) {
/* now distribute the clock (which could be NULL). If some
* element refuses the clock, this will return FALSE and
* we effectively fail the state change. */
if (!gst_element_set_clock (element, clock))
goto invalid_clock;
/* if we selected and distributed a new clock, let the app
* know about it */
gst_element_post_message (element,
gst_message_new_new_clock (GST_OBJECT_CAST (element), clock));
}
if (stream_time != GST_CLOCK_TIME_NONE
&& start_time != GST_CLOCK_TIME_NONE)
new_base_time = start_time - stream_time + delay;
else
new_base_time = GST_CLOCK_TIME_NONE;
if (clock)
gst_object_unref (clock);
if (new_base_time != GST_CLOCK_TIME_NONE) if (new_base_time != GST_CLOCK_TIME_NONE)
gst_element_set_base_time (element, new_base_time); gst_element_set_base_time (element, new_base_time);
else else
GST_DEBUG_OBJECT (pipeline, GST_DEBUG_OBJECT (pipeline,
"NOT adjusting base time because stream time is NONE"); "NOT adjusting base time because stream time is NONE");
}
break; break;
}
case GST_STATE_CHANGE_PLAYING_TO_PAUSED: case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
break; break;
case GST_STATE_CHANGE_PAUSED_TO_READY: case GST_STATE_CHANGE_PAUSED_TO_READY:
@ -559,6 +561,8 @@ invalid_clock:
("Pipeline cannot operate with selected clock")); ("Pipeline cannot operate with selected clock"));
GST_DEBUG_OBJECT (pipeline, GST_DEBUG_OBJECT (pipeline,
"Pipeline cannot operate with selected clock %p", clock); "Pipeline cannot operate with selected clock %p", clock);
if (clock)
gst_object_unref (clock);
return GST_STATE_CHANGE_FAILURE; return GST_STATE_CHANGE_FAILURE;
} }
} }
@ -653,7 +657,8 @@ gst_pipeline_provide_clock_func (GstElement * element)
GST_OBJECT_LOCK (pipeline); GST_OBJECT_LOCK (pipeline);
if (GST_OBJECT_FLAG_IS_SET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK)) { if (GST_OBJECT_FLAG_IS_SET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK)) {
clock = pipeline->fixed_clock; clock = pipeline->fixed_clock;
gst_object_ref (clock); if (clock)
gst_object_ref (clock);
GST_OBJECT_UNLOCK (pipeline); GST_OBJECT_UNLOCK (pipeline);
GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using fixed clock %p (%s)", GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using fixed clock %p (%s)",
@ -802,6 +807,7 @@ void
gst_pipeline_set_delay (GstPipeline * pipeline, GstClockTime delay) gst_pipeline_set_delay (GstPipeline * pipeline, GstClockTime delay)
{ {
g_return_if_fail (GST_IS_PIPELINE (pipeline)); g_return_if_fail (GST_IS_PIPELINE (pipeline));
g_return_if_fail (delay != GST_CLOCK_TIME_NONE);
GST_OBJECT_LOCK (pipeline); GST_OBJECT_LOCK (pipeline);
pipeline->delay = delay; pipeline->delay = delay;

View file

@ -411,7 +411,7 @@ event_loop (GstElement * pipeline, gboolean blocking, GstState target_state)
gst_message_parse_new_clock (message, &clock); gst_message_parse_new_clock (message, &clock);
g_print ("New clock: %s\n", GST_OBJECT_NAME (clock)); g_print ("New clock: %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
break; break;
} }
case GST_MESSAGE_EOS: case GST_MESSAGE_EOS: