mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 09:10:36 +00:00
decklink: Require a clock when going from PAUSED_TO_PLAYING and don't crash if there is none
Also when going from PLAYING_TO_PAUSED, the clock might've been unset in the meantime, e.g. because the element was removed from its surrounding bin.
This commit is contained in:
parent
42e1dcac00
commit
d8327b397d
2 changed files with 78 additions and 34 deletions
|
@ -748,6 +748,14 @@ gst_decklink_video_sink_start_scheduled_playback (GstElement * element)
|
||||||
GstClockTime start_time;
|
GstClockTime start_time;
|
||||||
HRESULT res;
|
HRESULT res;
|
||||||
bool active;
|
bool active;
|
||||||
|
GstClock *clock;
|
||||||
|
|
||||||
|
clock = gst_element_get_clock (element);
|
||||||
|
if (!clock) {
|
||||||
|
GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL),
|
||||||
|
("Scheduled playback supposed to start but we have no clock"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (self->output->video_enabled && (!self->output->audiosink
|
if (self->output->video_enabled && (!self->output->audiosink
|
||||||
|| self->output->audio_enabled)
|
|| self->output->audio_enabled)
|
||||||
|
@ -760,7 +768,7 @@ gst_decklink_video_sink_start_scheduled_playback (GstElement * element)
|
||||||
// but what we need here is the start time of this element!
|
// but what we need here is the start time of this element!
|
||||||
start_time = gst_element_get_base_time (element);
|
start_time = gst_element_get_base_time (element);
|
||||||
if (start_time != GST_CLOCK_TIME_NONE)
|
if (start_time != GST_CLOCK_TIME_NONE)
|
||||||
start_time = gst_clock_get_time (GST_ELEMENT_CLOCK (self)) - start_time;
|
start_time = gst_clock_get_time (clock) - start_time;
|
||||||
|
|
||||||
// FIXME: This will probably not work
|
// FIXME: This will probably not work
|
||||||
if (start_time == GST_CLOCK_TIME_NONE)
|
if (start_time == GST_CLOCK_TIME_NONE)
|
||||||
|
@ -774,15 +782,14 @@ gst_decklink_video_sink_start_scheduled_playback (GstElement * element)
|
||||||
// because we might go to PLAYING later than the pipeline
|
// because we might go to PLAYING later than the pipeline
|
||||||
self->internal_base_time =
|
self->internal_base_time =
|
||||||
gst_clock_get_internal_time (self->output->clock);
|
gst_clock_get_internal_time (self->output->clock);
|
||||||
self->external_base_time =
|
self->external_base_time = gst_clock_get_internal_time (clock);
|
||||||
gst_clock_get_internal_time (GST_ELEMENT_CLOCK (self));
|
|
||||||
|
|
||||||
convert_to_internal_clock (self, &start_time, NULL);
|
convert_to_internal_clock (self, &start_time, NULL);
|
||||||
|
|
||||||
g_mutex_lock (&self->output->lock);
|
g_mutex_lock (&self->output->lock);
|
||||||
// Check if someone else started in the meantime
|
// Check if someone else started in the meantime
|
||||||
if (self->output->started)
|
if (self->output->started)
|
||||||
return;
|
goto done;
|
||||||
|
|
||||||
active = false;
|
active = false;
|
||||||
self->output->output->IsScheduledPlaybackRunning (&active);
|
self->output->output->IsScheduledPlaybackRunning (&active);
|
||||||
|
@ -795,7 +802,7 @@ gst_decklink_video_sink_start_scheduled_playback (GstElement * element)
|
||||||
if (res != S_OK) {
|
if (res != S_OK) {
|
||||||
GST_ELEMENT_ERROR (self, STREAM, FAILED,
|
GST_ELEMENT_ERROR (self, STREAM, FAILED,
|
||||||
(NULL), ("Failed to stop scheduled playback: 0x%08x", res));
|
(NULL), ("Failed to stop scheduled playback: 0x%08x", res));
|
||||||
return;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -809,7 +816,7 @@ gst_decklink_video_sink_start_scheduled_playback (GstElement * element)
|
||||||
if (res != S_OK) {
|
if (res != S_OK) {
|
||||||
GST_ELEMENT_ERROR (self, STREAM, FAILED,
|
GST_ELEMENT_ERROR (self, STREAM, FAILED,
|
||||||
(NULL), ("Failed to start scheduled playback: 0x%08x", res));
|
(NULL), ("Failed to start scheduled playback: 0x%08x", res));
|
||||||
return;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->output->started = TRUE;
|
self->output->started = TRUE;
|
||||||
|
@ -822,12 +829,14 @@ gst_decklink_video_sink_start_scheduled_playback (GstElement * element)
|
||||||
// after we started scheduled playback
|
// after we started scheduled playback
|
||||||
self->internal_base_time =
|
self->internal_base_time =
|
||||||
gst_clock_get_internal_time (self->output->clock);
|
gst_clock_get_internal_time (self->output->clock);
|
||||||
self->external_base_time =
|
self->external_base_time = gst_clock_get_internal_time (clock);
|
||||||
gst_clock_get_internal_time (GST_ELEMENT_CLOCK (self));
|
|
||||||
g_mutex_lock (&self->output->lock);
|
g_mutex_lock (&self->output->lock);
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG_OBJECT (self, "Not starting scheduled playback yet");
|
GST_DEBUG_OBJECT (self, "Not starting scheduled playback yet");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
gst_object_unref (clock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstStateChangeReturn
|
static GstStateChangeReturn
|
||||||
|
@ -853,14 +862,19 @@ gst_decklink_video_sink_change_state (GstElement * element,
|
||||||
GstClock *clock, *audio_clock;
|
GstClock *clock, *audio_clock;
|
||||||
|
|
||||||
clock = gst_element_get_clock (GST_ELEMENT_CAST (self));
|
clock = gst_element_get_clock (GST_ELEMENT_CAST (self));
|
||||||
audio_clock = gst_decklink_output_get_audio_clock (self->output);
|
if (clock) {
|
||||||
if (clock && clock != self->output->clock && clock != audio_clock) {
|
audio_clock = gst_decklink_output_get_audio_clock (self->output);
|
||||||
gst_clock_set_master (self->output->clock, clock);
|
if (clock && clock != self->output->clock && clock != audio_clock) {
|
||||||
}
|
gst_clock_set_master (self->output->clock, clock);
|
||||||
if (clock)
|
}
|
||||||
gst_object_unref (clock);
|
gst_object_unref (clock);
|
||||||
if (audio_clock)
|
if (audio_clock)
|
||||||
gst_object_unref (audio_clock);
|
gst_object_unref (audio_clock);
|
||||||
|
} else {
|
||||||
|
GST_ELEMENT_ERROR (self, STREAM, FAILED,
|
||||||
|
(NULL), ("Need a clock to go to PLAYING"));
|
||||||
|
ret = GST_STATE_CHANGE_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -868,6 +882,8 @@ gst_decklink_video_sink_change_state (GstElement * element,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret == GST_STATE_CHANGE_FAILURE)
|
||||||
|
return ret;
|
||||||
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
||||||
if (ret == GST_STATE_CHANGE_FAILURE)
|
if (ret == GST_STATE_CHANGE_FAILURE)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -891,21 +907,31 @@ gst_decklink_video_sink_change_state (GstElement * element,
|
||||||
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:{
|
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:{
|
||||||
GstClockTime start_time;
|
GstClockTime start_time;
|
||||||
HRESULT res;
|
HRESULT res;
|
||||||
|
GstClock *clock;
|
||||||
|
|
||||||
// FIXME: start time is the same for the complete pipeline,
|
clock = gst_element_get_clock (GST_ELEMENT_CAST (self));
|
||||||
// but what we need here is the start time of this element!
|
if (clock) {
|
||||||
start_time = gst_element_get_base_time (element);
|
// FIXME: start time is the same for the complete pipeline,
|
||||||
if (start_time != GST_CLOCK_TIME_NONE)
|
// but what we need here is the start time of this element!
|
||||||
start_time = gst_clock_get_time (GST_ELEMENT_CLOCK (self)) - start_time;
|
start_time = gst_element_get_base_time (element);
|
||||||
|
if (start_time != GST_CLOCK_TIME_NONE)
|
||||||
|
start_time = gst_clock_get_time (clock) - start_time;
|
||||||
|
|
||||||
// FIXME: This will probably not work
|
// FIXME: This will probably not work
|
||||||
if (start_time == GST_CLOCK_TIME_NONE)
|
if (start_time == GST_CLOCK_TIME_NONE)
|
||||||
|
start_time = 0;
|
||||||
|
|
||||||
|
convert_to_internal_clock (self, &start_time, NULL);
|
||||||
|
|
||||||
|
// The start time is now the running time when we stopped
|
||||||
|
// playback
|
||||||
|
|
||||||
|
gst_object_unref (clock);
|
||||||
|
} else {
|
||||||
|
GST_WARNING_OBJECT (self,
|
||||||
|
"No clock, stopping scheduled playback immediately");
|
||||||
start_time = 0;
|
start_time = 0;
|
||||||
|
}
|
||||||
convert_to_internal_clock (self, &start_time, NULL);
|
|
||||||
|
|
||||||
// The start time is now the running time when we stopped
|
|
||||||
// playback
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (self,
|
GST_DEBUG_OBJECT (self,
|
||||||
"Stopping scheduled playback at %" GST_TIME_FORMAT,
|
"Stopping scheduled playback at %" GST_TIME_FORMAT,
|
||||||
|
|
|
@ -812,6 +812,14 @@ gst_decklink_video_src_start_streams (GstElement * element)
|
||||||
{
|
{
|
||||||
GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (element);
|
GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (element);
|
||||||
HRESULT res;
|
HRESULT res;
|
||||||
|
GstClock *clock;
|
||||||
|
|
||||||
|
clock = gst_element_get_clock (element);
|
||||||
|
if (!clock) {
|
||||||
|
GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL),
|
||||||
|
("Streams supposed to start but we have no clock"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (self->input->video_enabled && (!self->input->audiosrc
|
if (self->input->video_enabled && (!self->input->audiosrc
|
||||||
|| self->input->audio_enabled)
|
|| self->input->audio_enabled)
|
||||||
|
@ -823,7 +831,7 @@ gst_decklink_video_src_start_streams (GstElement * element)
|
||||||
if (res != S_OK) {
|
if (res != S_OK) {
|
||||||
GST_ELEMENT_ERROR (self, STREAM, FAILED,
|
GST_ELEMENT_ERROR (self, STREAM, FAILED,
|
||||||
(NULL), ("Failed to start streams: 0x%08x", res));
|
(NULL), ("Failed to start streams: 0x%08x", res));
|
||||||
return;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->input->started = TRUE;
|
self->input->started = TRUE;
|
||||||
|
@ -839,13 +847,15 @@ gst_decklink_video_src_start_streams (GstElement * element)
|
||||||
// We can't use the normal base time for the external clock
|
// We can't use the normal base time for the external clock
|
||||||
// because we might go to PLAYING later than the pipeline
|
// because we might go to PLAYING later than the pipeline
|
||||||
self->internal_base_time = gst_clock_get_internal_time (self->input->clock);
|
self->internal_base_time = gst_clock_get_internal_time (self->input->clock);
|
||||||
self->external_base_time =
|
self->external_base_time = gst_clock_get_internal_time (clock);
|
||||||
gst_clock_get_internal_time (GST_ELEMENT_CLOCK (self));
|
|
||||||
|
|
||||||
g_mutex_lock (&self->input->lock);
|
g_mutex_lock (&self->input->lock);
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG_OBJECT (self, "Not starting streams yet");
|
GST_DEBUG_OBJECT (self, "Not starting streams yet");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
gst_object_unref (clock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstStateChangeReturn
|
static GstStateChangeReturn
|
||||||
|
@ -883,11 +893,17 @@ gst_decklink_video_src_change_state (GstElement * element,
|
||||||
GstClock *clock;
|
GstClock *clock;
|
||||||
|
|
||||||
clock = gst_element_get_clock (GST_ELEMENT_CAST (self));
|
clock = gst_element_get_clock (GST_ELEMENT_CAST (self));
|
||||||
if (clock && clock != self->input->clock) {
|
if (clock) {
|
||||||
gst_clock_set_master (self->input->clock, clock);
|
if (clock != self->input->clock) {
|
||||||
}
|
gst_clock_set_master (self->input->clock, clock);
|
||||||
if (clock)
|
}
|
||||||
|
|
||||||
gst_object_unref (clock);
|
gst_object_unref (clock);
|
||||||
|
} else {
|
||||||
|
GST_ELEMENT_ERROR (self, STREAM, FAILED,
|
||||||
|
(NULL), ("Need a clock to go to PLAYING"));
|
||||||
|
ret = GST_STATE_CHANGE_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -895,6 +911,8 @@ gst_decklink_video_src_change_state (GstElement * element,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret == GST_STATE_CHANGE_FAILURE)
|
||||||
|
return ret;
|
||||||
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
||||||
if (ret == GST_STATE_CHANGE_FAILURE)
|
if (ret == GST_STATE_CHANGE_FAILURE)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Reference in a new issue