static gboolean gst_timestampoverlay_set_clock (GstElement * element, GstClock * clock) { GstTimeStampOverlay *timestampoverlay = GST_TIMESTAMPOVERLAY (element); GST_DEBUG_OBJECT (timestampoverlay, "set_clock (%" GST_PTR_FORMAT ")", clock); if (gst_clock_set_master (timestampoverlay->realtime_clock, clock)) { if (clock) { /* gst_clock_set_master is asynchronous and may take some time to sync. * To give it a helping hand we'll initialise it here so we don't send * through spurious timings with the first buffer. */ gst_clock_set_calibration (timestampoverlay->realtime_clock, gst_clock_get_internal_time (timestampoverlay->realtime_clock), gst_clock_get_time (clock), 1, 1); } } else { GST_WARNING_OBJECT (element, "Failed to slave internal REALTIME clock %" GST_PTR_FORMAT " to master clock %" GST_PTR_FORMAT, timestampoverlay->realtime_clock, clock); } return GST_ELEMENT_CLASS (gst_timestampoverlay_parent_class)->set_clock (element, clock); }
static GstStateChangeReturn gst_decklink_video_src_change_state (GstElement * element, GstStateChange transition) { GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (element); GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: if (!gst_decklink_video_src_open (self)) { ret = GST_STATE_CHANGE_FAILURE; goto out; } if (self->mode == GST_DECKLINK_MODE_AUTO && self->video_format != GST_DECKLINK_VIDEO_FORMAT_AUTO) { GST_WARNING_OBJECT (self, "Warning: mode=auto and format!=auto may \ not work"); } break; case GST_STATE_CHANGE_READY_TO_PAUSED: g_mutex_lock (&self->input->lock); self->input->clock_start_time = GST_CLOCK_TIME_NONE; self->input->clock_epoch += self->input->clock_last_time; self->input->clock_last_time = 0; self->input->clock_offset = 0; g_mutex_unlock (&self->input->lock); gst_element_post_message (element, gst_message_new_clock_provide (GST_OBJECT_CAST (element), self->input->clock, TRUE)); self->flushing = FALSE; break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING:{ GstClock *clock; clock = gst_element_get_clock (GST_ELEMENT_CAST (self)); if (clock) { if (clock != self->input->clock) { gst_clock_set_master (self->input->clock, 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; } default: break; }
static GstStateChangeReturn gst_decklink_video_sink_change_state (GstElement * element, GstStateChange transition) { GstDecklinkVideoSink *self = GST_DECKLINK_VIDEO_SINK_CAST (element); GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: g_mutex_lock (&self->output->lock); self->output->clock_start_time = GST_CLOCK_TIME_NONE; self->output->clock_epoch += self->output->clock_last_time; self->output->clock_last_time = 0; self->output->clock_offset = 0; g_mutex_unlock (&self->output->lock); gst_element_post_message (element, gst_message_new_clock_provide (GST_OBJECT_CAST (element), self->output->clock, TRUE)); break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING:{ GstClock *clock, *audio_clock; clock = gst_element_get_clock (GST_ELEMENT_CAST (self)); if (clock) { audio_clock = gst_decklink_output_get_audio_clock (self->output); if (clock && clock != self->output->clock && clock != audio_clock) { gst_clock_set_master (self->output->clock, clock); } gst_object_unref (clock); if (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; } default: break; } if (ret == GST_STATE_CHANGE_FAILURE) return ret; ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); if (ret == GST_STATE_CHANGE_FAILURE) return ret; switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: gst_element_post_message (element, gst_message_new_clock_lost (GST_OBJECT_CAST (element), self->output->clock)); gst_clock_set_master (self->output->clock, NULL); // Reset calibration to make the clock reusable next time we use it gst_clock_set_calibration (self->output->clock, 0, 0, 1, 1); g_mutex_lock (&self->output->lock); self->output->clock_start_time = GST_CLOCK_TIME_NONE; self->output->clock_epoch += self->output->clock_last_time; self->output->clock_last_time = 0; self->output->clock_offset = 0; g_mutex_unlock (&self->output->lock); gst_decklink_video_sink_stop (self); break; case GST_STATE_CHANGE_PLAYING_TO_PAUSED:{ if (gst_decklink_video_sink_stop_scheduled_playback (self) == GST_STATE_CHANGE_FAILURE) ret = GST_STATE_CHANGE_FAILURE; break; } case GST_STATE_CHANGE_PAUSED_TO_PLAYING:{ g_mutex_lock (&self->output->lock); if (self->output->start_scheduled_playback) self->output->start_scheduled_playback (self->output->videosink); g_mutex_unlock (&self->output->lock); break; } default: break; } return ret; }
static GstStateChangeReturn gst_decklink_video_sink_change_state (GstElement * element, GstStateChange transition) { GstDecklinkVideoSink *self = GST_DECKLINK_VIDEO_SINK_CAST (element); GstStateChangeReturn ret; switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: g_mutex_lock (&self->output->lock); self->output->clock_start_time = GST_CLOCK_TIME_NONE; self->output->clock_last_time = 0; self->output->clock_offset = 0; g_mutex_unlock (&self->output->lock); gst_element_post_message (element, gst_message_new_clock_provide (GST_OBJECT_CAST (element), self->output->clock, TRUE)); self->last_render_time = GST_CLOCK_TIME_NONE; break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING:{ GstClock *clock, *audio_clock; clock = gst_element_get_clock (GST_ELEMENT_CAST (self)); audio_clock = gst_decklink_output_get_audio_clock (self->output); if (clock && clock != self->output->clock && clock != audio_clock) { gst_clock_set_master (self->output->clock, clock); } if (clock) gst_object_unref (clock); if (audio_clock) gst_object_unref (audio_clock); break; } default: break; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); if (ret == GST_STATE_CHANGE_FAILURE) return ret; switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: gst_element_post_message (element, gst_message_new_clock_lost (GST_OBJECT_CAST (element), self->output->clock)); gst_clock_set_master (self->output->clock, NULL); g_mutex_lock (&self->output->lock); self->output->clock_start_time = GST_CLOCK_TIME_NONE; self->output->clock_last_time = 0; self->output->clock_offset = 0; g_mutex_unlock (&self->output->lock); break; case GST_STATE_CHANGE_PLAYING_TO_PAUSED:{ GstClockTime start_time; HRESULT res; // FIXME: start time is the same for the complete pipeline, // but what we need here is the start time of this element! start_time = gst_element_get_base_time (element); if (start_time != GST_CLOCK_TIME_NONE) start_time = gst_clock_get_time (GST_ELEMENT_CLOCK (self)) - start_time; // FIXME: This will probably not work 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_DEBUG_OBJECT (self, "Stopping scheduled playback at %" GST_TIME_FORMAT, GST_TIME_ARGS (start_time)); g_mutex_lock (&self->output->lock); self->output->started = FALSE; g_mutex_unlock (&self->output->lock); res = self->output->output->StopScheduledPlayback (start_time, 0, GST_SECOND); if (res != S_OK) { GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL), ("Failed to stop scheduled playback: 0x%08x", res)); ret = GST_STATE_CHANGE_FAILURE; } self->internal_base_time = GST_CLOCK_TIME_NONE; self->external_base_time = GST_CLOCK_TIME_NONE; break; } case GST_STATE_CHANGE_PAUSED_TO_PLAYING:{ g_mutex_lock (&self->output->lock); if (self->output->start_scheduled_playback) self->output->start_scheduled_playback (self->output->videosink); g_mutex_unlock (&self->output->lock); break; } default: break; } return ret; }
static GstStateChangeReturn gst_decklink_video_src_change_state (GstElement * element, GstStateChange transition) { GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (element); GstStateChangeReturn ret; switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: if (!gst_decklink_video_src_open (self)) { ret = GST_STATE_CHANGE_FAILURE; goto out; } break; case GST_STATE_CHANGE_READY_TO_PAUSED: g_mutex_lock (&self->input->lock); self->input->clock_start_time = GST_CLOCK_TIME_NONE; self->input->clock_last_time = 0; self->input->clock_offset = 0; g_mutex_unlock (&self->input->lock); gst_element_post_message (element, gst_message_new_clock_provide (GST_OBJECT_CAST (element), self->input->clock, TRUE)); self->flushing = FALSE; break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING:{ GstClock *clock; clock = gst_element_get_clock (GST_ELEMENT_CAST (self)); if (clock && clock != self->input->clock) { gst_clock_set_master (self->input->clock, clock); } if (clock) gst_object_unref (clock); break; } default: break; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); if (ret == GST_STATE_CHANGE_FAILURE) return ret; switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: gst_element_post_message (element, gst_message_new_clock_lost (GST_OBJECT_CAST (element), self->input->clock)); gst_clock_set_master (self->input->clock, NULL); // Reset calibration to make the clock reusable next time we use it gst_clock_set_calibration (self->input->clock, 0, 0, 1, 1); g_mutex_lock (&self->input->lock); self->input->clock_start_time = GST_CLOCK_TIME_NONE; self->input->clock_last_time = 0; self->input->clock_offset = 0; g_mutex_unlock (&self->input->lock); g_queue_foreach (&self->current_frames, (GFunc) capture_frame_free, NULL); g_queue_clear (&self->current_frames); self->caps_mode = GST_DECKLINK_MODE_AUTO; break; case GST_STATE_CHANGE_PLAYING_TO_PAUSED:{ HRESULT res; GST_DEBUG_OBJECT (self, "Stopping streams"); g_mutex_lock (&self->input->lock); self->input->started = FALSE; g_mutex_unlock (&self->input->lock); res = self->input->input->StopStreams (); if (res != S_OK) { GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL), ("Failed to stop streams: 0x%08x", res)); ret = GST_STATE_CHANGE_FAILURE; } self->internal_base_time = GST_CLOCK_TIME_NONE; self->external_base_time = GST_CLOCK_TIME_NONE; break; } case GST_STATE_CHANGE_PAUSED_TO_PLAYING:{ g_mutex_lock (&self->input->lock); if (self->input->start_streams) self->input->start_streams (self->input->videosrc); g_mutex_unlock (&self->input->lock); break; } case GST_STATE_CHANGE_READY_TO_NULL: gst_decklink_video_src_close (self); break; default: break; } out: return ret; }