static GstElement * default_create_pipeline (GstRTSPMediaFactory * factory, GstRTSPMedia * media) { GstElement *pipeline; pipeline = gst_pipeline_new ("media-pipeline"); gst_rtsp_media_take_pipeline (media, GST_PIPELINE_CAST (pipeline)); return pipeline; }
static GstElement * create_pipeline (GstRTSPMediaFactory * factory, GstRTSPMedia * media) { GstElement *pipeline; pipeline = gst_pipeline_new ("media-pipeline"); if (global_clock == NULL) { g_print ("No clock!!!!\n"); } else { gst_pipeline_use_clock (GST_PIPELINE (pipeline), global_clock); } gst_rtsp_media_take_pipeline (media, GST_PIPELINE_CAST (pipeline)); return pipeline; }
static GstElement * default_create_pipeline (GstRTSPMediaFactory * factory, GstRTSPMedia * media) { GstElement *pipeline; pipeline = gst_pipeline_new ("media-pipeline"); /* FIXME 2.0: This should be done by the caller, not the vfunc. Every * implementation of the vfunc has to call it otherwise at the end. * Also it does not allow use to add further behaviour here that could * be reused by subclasses that chain up */ gst_rtsp_media_take_pipeline (media, GST_PIPELINE_CAST (pipeline)); return pipeline; }
static int act_gstreamer_render (VisPluginData *plugin, VisVideo *video, VisAudio *audio) { GstreamerPrivate *priv = visual_object_get_private (VISUAL_OBJECT (plugin)); static int playing = 0; if (playing == 0) { char pipe[1024]; gst_init (NULL, NULL); /* snprintf(pipe, 1024, "filesrc location=%s ! decodebin ! ffmpegcolorspace ! " "videoscale ! video/x-raw-rgb,bpp=32,depth=32,width=%d,height=%d," "red_mask=0xff000000,green_mask=0x00ff0000,blue_mask=0x0000ff00 !" "fakesink name=sink sync=true", "test.mpg", video->width, video->height); */ snprintf(pipe, 1024, "filesrc location=%s ! decodebin ! ffmpegcolorspace ! " "video/x-raw-rgb,bpp=24,depth=24 ! " "fakesink name=sink signal-handoffs=true", "test.mpg"); GError *err = NULL; priv->pipe = GST_PIPELINE_CAST(gst_parse_launch (pipe, &err)); if (err) { visual_log (VISUAL_LOG_ERROR, "Failed to create pipeline", err->message); return; } gst_element_set_state (GST_ELEMENT (priv->pipe), GST_STATE_PLAYING); g_signal_connect (gst_bin_get_by_name_recurse_up (GST_BIN (priv->pipe), "sink"), "handoff", G_CALLBACK (have_data), video); playing = 1; } // g_signal_handlers_disconnect_by_func (gst_bin_get_by_name_recurse_up (GST_BIN (priv->pipe), "sink"), // G_CALLBACK (have_data), priv->old_video); gst_bin_iterate (GST_BIN (priv->pipe)); priv->old_video = video; return 0; }
/* takes a snapshot of the running_time of the pipeline and store this as the * element start_time. This is the time we will set as the running_time of the * pipeline when we go to PLAYING next. */ static void pipeline_update_start_time (GstElement * element) { GstPipeline *pipeline = GST_PIPELINE_CAST (element); GstClock *clock; GST_OBJECT_LOCK (element); if ((clock = element->clock)) { GstClockTime now; gst_object_ref (clock); GST_OBJECT_UNLOCK (element); /* calculate the time when we stopped */ now = gst_clock_get_time (clock); gst_object_unref (clock); GST_OBJECT_LOCK (element); /* store the current running time */ if (GST_ELEMENT_START_TIME (pipeline) != GST_CLOCK_TIME_NONE) { if (now != GST_CLOCK_TIME_NONE) GST_ELEMENT_START_TIME (pipeline) = now - element->base_time; else GST_WARNING_OBJECT (element, "Clock %s returned invalid time, can't calculate " "running_time when going to the PAUSED state", GST_OBJECT_NAME (clock)); /* we went to PAUSED, when going to PLAYING select clock and new * base_time */ pipeline->priv->update_clock = TRUE; } GST_DEBUG_OBJECT (element, "start_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT ", base_time %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_ELEMENT_START_TIME (pipeline)), GST_TIME_ARGS (now), GST_TIME_ARGS (element->base_time)); } GST_OBJECT_UNLOCK (element); }
/** * gst_validate_monitor_factory_create: * @target: The #GstObject to create a #GstValidateMonitor for * @runner: The #GstValidateRunner to use for the new monitor * @parent: (nullable): The parent of the new monitor * * Create a new monitor for @target and starts monitoring it. * * Returns: (transfer full): The newly created #GstValidateMonitor */ GstValidateMonitor * gst_validate_monitor_factory_create (GstObject * target, GstValidateRunner * runner, GstValidateMonitor * parent) { GstValidateMonitor *monitor = NULL; g_return_val_if_fail (target != NULL, NULL); monitor = g_object_get_data ((GObject *) target, "validate-monitor"); if (monitor) { GST_INFO_OBJECT (target, "Is already monitored by %" GST_PTR_FORMAT, monitor); return g_object_ref (monitor); } if (GST_IS_PAD (target)) { monitor = GST_VALIDATE_MONITOR_CAST (gst_validate_pad_monitor_new (GST_PAD_CAST (target), runner, GST_VALIDATE_ELEMENT_MONITOR_CAST (parent))); } else if (GST_IS_PIPELINE (target)) { monitor = GST_VALIDATE_MONITOR_CAST (gst_validate_pipeline_monitor_new (GST_PIPELINE_CAST (target), runner, parent)); } else if (GST_IS_BIN (target)) { monitor = GST_VALIDATE_MONITOR_CAST (gst_validate_bin_monitor_new (GST_BIN_CAST (target), runner, parent)); } else if (GST_IS_ELEMENT (target)) { monitor = GST_VALIDATE_MONITOR_CAST (gst_validate_element_monitor_new (GST_ELEMENT_CAST (target), runner, parent)); } else { g_assert_not_reached (); } return monitor; }
/* intercept the bus messages from our children. We watch for the ASYNC_START * message with is posted by the elements (sinks) that require a reset of the * running_time after a flush. ASYNC_START also brings the pipeline back into * the PAUSED, pending PAUSED state. When the ASYNC_DONE message is received the * pipeline will redistribute the new base_time and will bring the elements back * to the desired state of the pipeline. */ static void gst_pipeline_handle_message (GstBin * bin, GstMessage * message) { GstPipeline *pipeline = GST_PIPELINE_CAST (bin); switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_RESET_TIME: { GstClockTime running_time; gst_message_parse_reset_time (message, &running_time); /* reset our running time if we need to distribute a new base_time to the * children. */ reset_start_time (pipeline, running_time); break; } case GST_MESSAGE_CLOCK_LOST: { GstClock *clock; gst_message_parse_clock_lost (message, &clock); GST_OBJECT_LOCK (bin); if (clock == GST_ELEMENT_CAST (bin)->clock) { GST_DEBUG_OBJECT (bin, "Used clock '%s' got lost", GST_OBJECT_NAME (clock)); pipeline->priv->update_clock = TRUE; } GST_OBJECT_UNLOCK (bin); } default: break; } GST_BIN_CLASS (parent_class)->handle_message (bin, message); }
/* MT safe */ static GstStateChangeReturn gst_pipeline_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS; GstPipeline *pipeline = GST_PIPELINE_CAST (element); GstClock *clock; switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: GST_OBJECT_LOCK (element); if (element->bus) gst_bus_set_flushing (element->bus, FALSE); GST_OBJECT_UNLOCK (element); break; case GST_STATE_CHANGE_READY_TO_PAUSED: GST_OBJECT_LOCK (element); pipeline->priv->update_clock = TRUE; GST_OBJECT_UNLOCK (element); /* READY to PAUSED starts running_time from 0 */ reset_start_time (pipeline, 0); break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: { GstClockTime now, start_time, last_start_time, delay; gboolean update_clock; GstClock *cur_clock; GST_DEBUG_OBJECT (element, "selecting clock and base_time"); GST_OBJECT_LOCK (element); cur_clock = element->clock; if (cur_clock) gst_object_ref (cur_clock); /* get the desired running_time of the first buffer aka the start_time */ start_time = GST_ELEMENT_START_TIME (pipeline); last_start_time = pipeline->priv->last_start_time; pipeline->priv->last_start_time = start_time; /* see if we need to update the clock */ update_clock = pipeline->priv->update_clock; pipeline->priv->update_clock = FALSE; delay = pipeline->delay; GST_OBJECT_UNLOCK (element); /* running time changed, either with a PAUSED or a flush, we need to check * if there is a new clock & update the base time */ /* only do this for top-level, however */ if (GST_OBJECT_PARENT (element) == NULL && (update_clock || last_start_time != start_time)) { GST_DEBUG_OBJECT (pipeline, "Need to update start_time"); /* when going to PLAYING, select a clock when needed. If we just got * flushed, we don't reselect the clock. */ if (update_clock) { GST_DEBUG_OBJECT (pipeline, "Need to update clock."); clock = gst_element_provide_clock (element); } else { GST_DEBUG_OBJECT (pipeline, "Don't need to update clock, using old clock."); /* only try to ref if cur_clock is not NULL */ if (cur_clock) gst_object_ref (cur_clock); clock = cur_clock; } if (clock) { now = gst_clock_get_time (clock); } else { GST_DEBUG_OBJECT (pipeline, "no clock, using base time of NONE"); now = GST_CLOCK_TIME_NONE; } if (clock != cur_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 (clock) gst_object_unref (clock); if (start_time != GST_CLOCK_TIME_NONE && now != GST_CLOCK_TIME_NONE) { GstClockTime new_base_time = now - start_time + delay; GST_DEBUG_OBJECT (element, "start_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT ", base_time %" GST_TIME_FORMAT, GST_TIME_ARGS (start_time), GST_TIME_ARGS (now), GST_TIME_ARGS (new_base_time)); gst_element_set_base_time (element, new_base_time); } else { GST_DEBUG_OBJECT (pipeline, "NOT adjusting base_time because start_time is NONE"); } } else { GST_DEBUG_OBJECT (pipeline, "NOT adjusting base_time because we selected one before"); } if (cur_clock) gst_object_unref (cur_clock); break; } case GST_STATE_CHANGE_PLAYING_TO_PAUSED: { /* we take a start_time snapshot before calling the children state changes * so that they know about when the pipeline PAUSED. */ pipeline_update_start_time (element); break; } case GST_STATE_CHANGE_PAUSED_TO_READY: reset_start_time (pipeline, 0); break; case GST_STATE_CHANGE_READY_TO_NULL: break; } result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: break; case GST_STATE_CHANGE_READY_TO_PAUSED: break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: break; case GST_STATE_CHANGE_PLAYING_TO_PAUSED: { /* Take a new snapshot of the start_time after calling the state change on * all children. This will be the running_time of the pipeline when we go * back to PLAYING */ pipeline_update_start_time (element); break; } case GST_STATE_CHANGE_PAUSED_TO_READY: break; case GST_STATE_CHANGE_READY_TO_NULL: { GstBus *bus; gboolean auto_flush; /* grab some stuff before we release the lock to flush out the bus */ GST_OBJECT_LOCK (element); if ((bus = element->bus)) gst_object_ref (bus); auto_flush = pipeline->priv->auto_flush_bus; GST_OBJECT_UNLOCK (element); if (bus) { if (auto_flush) { gst_bus_set_flushing (bus, TRUE); } else { GST_INFO_OBJECT (element, "not flushing bus, auto-flushing disabled"); } gst_object_unref (bus); } break; } } return result; /* ERRORS */ invalid_clock: { /* we generate this error when the selected clock was not * accepted by some element */ GST_ELEMENT_ERROR (pipeline, CORE, CLOCK, (_("Selected clock cannot be used in pipeline.")), ("Pipeline cannot operate with selected clock")); GST_DEBUG_OBJECT (pipeline, "Pipeline cannot operate with selected clock %p", clock); if (clock) gst_object_unref (clock); return GST_STATE_CHANGE_FAILURE; } }