static void poll_func (GstBus * bus, GstMessage * message, GstBusPollData * poll_data) { GstMessageType type; if (!g_main_loop_is_running (poll_data->loop)) { GST_DEBUG ("mainloop %p not running", poll_data->loop); return; } type = GST_MESSAGE_TYPE (message); if (type & poll_data->events) { g_return_if_fail (poll_data->message == NULL); /* keep ref to message */ poll_data->message = gst_message_ref (message); GST_DEBUG ("mainloop %p quit", poll_data->loop); g_main_loop_quit (poll_data->loop); } else { GST_DEBUG ("type %08x does not match %08x", type, poll_data->events); } }
static gboolean play_bus_msg (GstBus * bus, GstMessage * msg, gpointer user_data) { GstPlay *play = user_data; switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_ASYNC_DONE: /* dump graph on preroll */ GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (play->playbin), GST_DEBUG_GRAPH_SHOW_ALL, "gst-play.async-done"); g_print ("Prerolled.\r"); if (play->missing != NULL && play_install_missing_plugins (play)) { g_print ("New plugins installed, trying again...\n"); --play->cur_idx; play_next (play); } break; case GST_MESSAGE_BUFFERING:{ gint percent; if (!play->buffering) g_print ("\n"); gst_message_parse_buffering (msg, &percent); g_print ("%s %d%% \r", _("Buffering..."), percent); if (percent == 100) { /* a 100% message means buffering is done */ if (play->buffering) { play->buffering = FALSE; /* no state management needed for live pipelines */ if (!play->is_live) gst_element_set_state (play->playbin, play->desired_state); } } else { /* buffering... */ if (!play->buffering) { if (!play->is_live) gst_element_set_state (play->playbin, GST_STATE_PAUSED); play->buffering = TRUE; } } break; } case GST_MESSAGE_CLOCK_LOST:{ g_print (_("Clock lost, selecting a new one\n")); gst_element_set_state (play->playbin, GST_STATE_PAUSED); gst_element_set_state (play->playbin, GST_STATE_PLAYING); break; } case GST_MESSAGE_LATENCY: g_print ("Redistribute latency...\n"); gst_bin_recalculate_latency (GST_BIN (play->playbin)); break; case GST_MESSAGE_REQUEST_STATE:{ GstState state; gchar *name; name = gst_object_get_path_string (GST_MESSAGE_SRC (msg)); gst_message_parse_request_state (msg, &state); g_print ("Setting state to %s as requested by %s...\n", gst_element_state_get_name (state), name); gst_element_set_state (play->playbin, state); g_free (name); break; } case GST_MESSAGE_EOS: /* print final position at end */ play_timeout (play); g_print ("\n"); /* and switch to next item in list */ if (!play_next (play)) { g_print ("%s\n", _("Reached end of play list.")); g_main_loop_quit (play->loop); } break; case GST_MESSAGE_WARNING:{ GError *err; gchar *dbg = NULL; /* dump graph on warning */ GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (play->playbin), GST_DEBUG_GRAPH_SHOW_ALL, "gst-play.warning"); gst_message_parse_warning (msg, &err, &dbg); g_printerr ("WARNING %s\n", err->message); if (dbg != NULL) g_printerr ("WARNING debug information: %s\n", dbg); g_clear_error (&err); g_free (dbg); break; } case GST_MESSAGE_ERROR:{ GError *err; gchar *dbg; /* dump graph on error */ GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (play->playbin), GST_DEBUG_GRAPH_SHOW_ALL, "gst-play.error"); gst_message_parse_error (msg, &err, &dbg); g_printerr ("ERROR %s for %s\n", err->message, play->uris[play->cur_idx]); if (dbg != NULL) g_printerr ("ERROR debug information: %s\n", dbg); g_clear_error (&err); g_free (dbg); /* flush any other error messages from the bus and clean up */ gst_element_set_state (play->playbin, GST_STATE_NULL); if (play->missing != NULL && play_install_missing_plugins (play)) { g_print ("New plugins installed, trying again...\n"); --play->cur_idx; play_next (play); break; } /* try next item in list then */ if (!play_next (play)) { g_print ("%s\n", _("Reached end of play list.")); g_main_loop_quit (play->loop); } break; } case GST_MESSAGE_ELEMENT: { GstNavigationMessageType mtype = gst_navigation_message_get_type (msg); if (mtype == GST_NAVIGATION_MESSAGE_EVENT) { GstEvent *ev = NULL; if (gst_navigation_message_parse_event (msg, &ev)) { GstNavigationEventType e_type = gst_navigation_event_get_type (ev); switch (e_type) { case GST_NAVIGATION_EVENT_KEY_PRESS: { const gchar *key; if (gst_navigation_event_parse_key_event (ev, &key)) { GST_INFO ("Key press: %s", key); if (strcmp (key, "Left") == 0) key = GST_PLAY_KB_ARROW_LEFT; else if (strcmp (key, "Right") == 0) key = GST_PLAY_KB_ARROW_RIGHT; else if (strcmp (key, "Up") == 0) key = GST_PLAY_KB_ARROW_UP; else if (strcmp (key, "Down") == 0) key = GST_PLAY_KB_ARROW_DOWN; else if (strcmp (key, "space") == 0) key = " "; else if (strlen (key) > 1) break; keyboard_cb (key, user_data); } break; } case GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS: { gint button; if (gst_navigation_event_parse_mouse_button_event (ev, &button, NULL, NULL)) { if (button == 4) { /* wheel up */ relative_seek (play, +0.08); } else if (button == 5) { /* wheel down */ relative_seek (play, -0.01); } } break; } default: break; } } if (ev) gst_event_unref (ev); } break; } default: if (gst_is_missing_plugin_message (msg)) { gchar *desc; desc = gst_missing_plugin_message_get_description (msg); g_print ("Missing plugin: %s\n", desc); g_free (desc); play->missing = g_list_append (play->missing, gst_message_ref (msg)); } break; } return TRUE; }
static gboolean play_bus_msg (GstBus * bus, GstMessage * msg, gpointer user_data) { GstPlay *play = user_data; switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_ASYNC_DONE: /* dump graph on preroll */ GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (play->playbin), GST_DEBUG_GRAPH_SHOW_ALL, "gst-play.async-done"); g_print ("Prerolled.\r"); if (play->missing != NULL && play_install_missing_plugins (play)) { g_print ("New plugins installed, trying again...\n"); --play->cur_idx; play_next (play); } break; case GST_MESSAGE_BUFFERING:{ gint percent; if (!play->buffering) g_print ("\n"); gst_message_parse_buffering (msg, &percent); g_print ("%s %d%% \r", _("Buffering..."), percent); if (percent == 100) { /* a 100% message means buffering is done */ if (play->buffering) { play->buffering = FALSE; /* no state management needed for live pipelines */ if (!play->is_live) gst_element_set_state (play->playbin, play->desired_state); } } else { /* buffering... */ if (!play->buffering) { if (!play->is_live) gst_element_set_state (play->playbin, GST_STATE_PAUSED); play->buffering = TRUE; } } break; } case GST_MESSAGE_CLOCK_LOST:{ g_print (_("Clock lost, selecting a new one\n")); gst_element_set_state (play->playbin, GST_STATE_PAUSED); gst_element_set_state (play->playbin, GST_STATE_PLAYING); break; } case GST_MESSAGE_LATENCY: g_print ("Redistribute latency...\n"); gst_bin_recalculate_latency (GST_BIN (play->playbin)); break; case GST_MESSAGE_REQUEST_STATE:{ GstState state; gchar *name; name = gst_object_get_path_string (GST_MESSAGE_SRC (msg)); gst_message_parse_request_state (msg, &state); g_print ("Setting state to %s as requested by %s...\n", gst_element_state_get_name (state), name); gst_element_set_state (play->playbin, state); g_free (name); break; } case GST_MESSAGE_EOS: /* print final position at end */ play_timeout (play); g_print ("\n"); /* and switch to next item in list */ if (!play_next (play)) { g_print ("Reached end of play list.\n"); g_main_loop_quit (play->loop); } break; case GST_MESSAGE_WARNING:{ GError *err; gchar *dbg = NULL; /* dump graph on warning */ GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (play->playbin), GST_DEBUG_GRAPH_SHOW_ALL, "gst-play.warning"); gst_message_parse_warning (msg, &err, &dbg); g_printerr ("WARNING %s\n", err->message); if (dbg != NULL) g_printerr ("WARNING debug information: %s\n", dbg); g_error_free (err); g_free (dbg); break; } case GST_MESSAGE_ERROR:{ GError *err; gchar *dbg; /* dump graph on error */ GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (play->playbin), GST_DEBUG_GRAPH_SHOW_ALL, "gst-play.error"); gst_message_parse_error (msg, &err, &dbg); g_printerr ("ERROR %s for %s\n", err->message, play->uris[play->cur_idx]); if (dbg != NULL) g_printerr ("ERROR debug information: %s\n", dbg); g_error_free (err); g_free (dbg); /* flush any other error messages from the bus and clean up */ gst_element_set_state (play->playbin, GST_STATE_NULL); if (play->missing != NULL && play_install_missing_plugins (play)) { g_print ("New plugins installed, trying again...\n"); --play->cur_idx; play_next (play); break; } /* try next item in list then */ if (!play_next (play)) { g_print ("Reached end of play list.\n"); g_main_loop_quit (play->loop); } break; } default: if (gst_is_missing_plugin_message (msg)) { gchar *desc; desc = gst_missing_plugin_message_get_description (msg); g_print ("Missing plugin: %s\n", desc); g_free (desc); play->missing = g_list_append (play->missing, gst_message_ref (msg)); } break; } return TRUE; }
QGstreamerMessage::QGstreamerMessage(QGstreamerMessage const& m): m_message(m.m_message) { gst_message_ref(m_message); }
QGstreamerMessage::QGstreamerMessage(GstMessage* message): m_message(message) { gst_message_ref(m_message); }
Message::Message(GstMessage* message): m_message(message) { gst_message_ref(m_message); }
Message::Message(Message const& m): m_message(m.m_message) { gst_message_ref(m_message); }
static GstElement * gst_auto_video_src_find_best (GstAutoVideoSrc * src) { GList *list, *item; GstElement *choice = NULL; GstMessage *message = NULL; GSList *errors = NULL; GstBus *bus = gst_bus_new (); GstPad *el_pad = NULL; GstCaps *el_caps = NULL, *intersect = NULL; gboolean no_match = TRUE; list = gst_registry_feature_filter (gst_registry_get_default (), (GstPluginFeatureFilter) gst_auto_video_src_factory_filter, FALSE, src); list = g_list_sort (list, (GCompareFunc) gst_auto_video_src_compare_ranks); GST_LOG_OBJECT (src, "Trying to find usable video devices ..."); for (item = list; item != NULL; item = item->next) { GstElementFactory *f = GST_ELEMENT_FACTORY (item->data); GstElement *el; if ((el = gst_auto_video_src_create_element_with_pretty_name (src, f))) { GstStateChangeReturn ret; GST_DEBUG_OBJECT (src, "Testing %s", GST_PLUGIN_FEATURE (f)->name); /* If AutoVideoSrc has been provided with filter caps, * accept only sources that match with the filter caps */ if (src->filter_caps) { el_pad = gst_element_get_static_pad (GST_ELEMENT (el), "src"); el_caps = gst_pad_get_caps (el_pad); gst_object_unref (el_pad); GST_DEBUG_OBJECT (src, "Checking caps: %" GST_PTR_FORMAT " vs. %" GST_PTR_FORMAT, src->filter_caps, el_caps); intersect = gst_caps_intersect (src->filter_caps, el_caps); no_match = gst_caps_is_empty (intersect); gst_caps_unref (el_caps); gst_caps_unref (intersect); if (no_match) { GST_DEBUG_OBJECT (src, "Incompatible caps"); gst_object_unref (el); continue; } else { GST_DEBUG_OBJECT (src, "Found compatible caps"); } } gst_element_set_bus (el, bus); ret = gst_element_set_state (el, GST_STATE_READY); if (ret == GST_STATE_CHANGE_SUCCESS) { GST_DEBUG_OBJECT (src, "This worked!"); choice = el; break; } /* collect all error messages */ while ((message = gst_bus_pop_filtered (bus, GST_MESSAGE_ERROR))) { GST_DEBUG_OBJECT (src, "error message %" GST_PTR_FORMAT, message); errors = g_slist_append (errors, message); } gst_element_set_state (el, GST_STATE_NULL); gst_object_unref (el); } } GST_DEBUG_OBJECT (src, "done trying"); if (!choice) { if (errors) { /* FIXME: we forward the first error for now; but later on it might make * sense to actually analyse them */ gst_message_ref (GST_MESSAGE (errors->data)); GST_DEBUG_OBJECT (src, "reposting message %p", errors->data); gst_element_post_message (GST_ELEMENT (src), GST_MESSAGE (errors->data)); } else { /* send warning message to application and use a fakesrc */ GST_ELEMENT_WARNING (src, RESOURCE, NOT_FOUND, (NULL), ("Failed to find a usable video source")); choice = gst_element_factory_make ("fakesrc", "fake-video-src"); if (g_object_class_find_property (G_OBJECT_GET_CLASS (choice), "sync")) g_object_set (choice, "sync", TRUE, NULL); gst_element_set_state (choice, GST_STATE_READY); } } gst_object_unref (bus); gst_plugin_feature_list_free (list); g_slist_foreach (errors, (GFunc) gst_mini_object_unref, NULL); g_slist_free (errors); return choice; }
Message::Message(const Message &other) { m_message = other.m_message; gst_message_ref(m_message); m_source = other.m_source; }
static gpointer _gst_message_ref0 (gpointer self) { return self ? gst_message_ref (self) : NULL; }
static void gst_net_client_internal_clock_observe_times (GstNetClientInternalClock * self, GstClockTime local_1, GstClockTime remote_1, GstClockTime remote_2, GstClockTime local_2) { GstClockTime current_timeout = 0; GstClockTime local_avg, remote_avg; gdouble r_squared; GstClock *clock; GstClockTime rtt, rtt_limit, min_update_interval; /* Use for discont tracking */ GstClockTime time_before = 0; GstClockTime min_guess = 0; GstClockTimeDiff time_discont = 0; gboolean synched, now_synched; GstClockTime internal_time, external_time, rate_num, rate_den; GstClockTime orig_internal_time, orig_external_time, orig_rate_num, orig_rate_den; GstClockTime max_discont; GstClockTime last_rtts[MEDIAN_PRE_FILTERING_WINDOW]; GstClockTime median; gint i; GST_OBJECT_LOCK (self); rtt_limit = self->roundtrip_limit; GST_LOG_OBJECT (self, "local1 %" G_GUINT64_FORMAT " remote1 %" G_GUINT64_FORMAT " remote2 %" G_GUINT64_FORMAT " local2 %" G_GUINT64_FORMAT, local_1, remote_1, remote_2, local_2); /* If the server told us a poll interval and it's bigger than the * one configured via the property, use the server's */ if (self->last_remote_poll_interval != GST_CLOCK_TIME_NONE && self->last_remote_poll_interval > self->minimum_update_interval) min_update_interval = self->last_remote_poll_interval; else min_update_interval = self->minimum_update_interval; GST_OBJECT_UNLOCK (self); if (local_2 < local_1) { GST_LOG_OBJECT (self, "Dropping observation: receive time %" GST_TIME_FORMAT " < send time %" GST_TIME_FORMAT, GST_TIME_ARGS (local_1), GST_TIME_ARGS (local_2)); goto bogus_observation; } if (remote_2 < remote_1) { GST_LOG_OBJECT (self, "Dropping observation: remote receive time %" GST_TIME_FORMAT " < send time %" GST_TIME_FORMAT, GST_TIME_ARGS (remote_1), GST_TIME_ARGS (remote_2)); goto bogus_observation; } /* The round trip time is (assuming symmetric path delays) * delta = (local_2 - local_1) - (remote_2 - remote_1) */ rtt = GST_CLOCK_DIFF (local_1, local_2) - GST_CLOCK_DIFF (remote_1, remote_2); if ((rtt_limit > 0) && (rtt > rtt_limit)) { GST_LOG_OBJECT (self, "Dropping observation: RTT %" GST_TIME_FORMAT " > limit %" GST_TIME_FORMAT, GST_TIME_ARGS (rtt), GST_TIME_ARGS (rtt_limit)); goto bogus_observation; } for (i = 1; i < MEDIAN_PRE_FILTERING_WINDOW; i++) self->last_rtts[i - 1] = self->last_rtts[i]; self->last_rtts[i - 1] = rtt; if (self->last_rtts_missing) { self->last_rtts_missing--; } else { memcpy (&last_rtts, &self->last_rtts, sizeof (last_rtts)); g_qsort_with_data (&last_rtts, MEDIAN_PRE_FILTERING_WINDOW, sizeof (GstClockTime), (GCompareDataFunc) compare_clock_time, NULL); median = last_rtts[MEDIAN_PRE_FILTERING_WINDOW / 2]; /* FIXME: We might want to use something else here, like only allowing * things in the interquartile range, or also filtering away delays that * are too small compared to the median. This here worked well enough * in tests so far. */ if (rtt > 2 * median) { GST_LOG_OBJECT (self, "Dropping observation, long RTT %" GST_TIME_FORMAT " > 2 * median %" GST_TIME_FORMAT, GST_TIME_ARGS (rtt), GST_TIME_ARGS (median)); goto bogus_observation; } } /* Track an average round trip time, for a bit of smoothing */ /* Always update before discarding a sample, so genuine changes in * the network get picked up, eventually */ if (self->rtt_avg == GST_CLOCK_TIME_NONE) self->rtt_avg = rtt; else if (rtt < self->rtt_avg) /* Shorter RTTs carry more weight than longer */ self->rtt_avg = (3 * self->rtt_avg + rtt) / 4; else self->rtt_avg = (15 * self->rtt_avg + rtt) / 16; if (rtt > 2 * self->rtt_avg) { GST_LOG_OBJECT (self, "Dropping observation, long RTT %" GST_TIME_FORMAT " > 2 * avg %" GST_TIME_FORMAT, GST_TIME_ARGS (rtt), GST_TIME_ARGS (self->rtt_avg)); goto bogus_observation; } /* The difference between the local and remote clock (again assuming * symmetric path delays): * * local_1 + delta / 2 - remote_1 = theta * or * local_2 - delta / 2 - remote_2 = theta * * which gives after some simple algebraic transformations: * * (remote_1 - local_1) + (remote_2 - local_2) * theta = ------------------------------------------- * 2 * * * Thus remote time at local_avg is equal to: * * local_avg + theta = * * local_1 + local_2 (remote_1 - local_1) + (remote_2 - local_2) * ----------------- + ------------------------------------------- * 2 2 * * = * * remote_1 + remote_2 * ------------------- = remote_avg * 2 * * We use this for our clock estimation, i.e. local_avg at remote clock * being the same as remote_avg. */ local_avg = (local_2 + local_1) / 2; remote_avg = (remote_2 + remote_1) / 2; GST_LOG_OBJECT (self, "remoteavg %" G_GUINT64_FORMAT " localavg %" G_GUINT64_FORMAT, remote_avg, local_avg); clock = GST_CLOCK_CAST (self); /* Store what the clock produced as 'now' before this update */ gst_clock_get_calibration (GST_CLOCK_CAST (self), &orig_internal_time, &orig_external_time, &orig_rate_num, &orig_rate_den); internal_time = orig_internal_time; external_time = orig_external_time; rate_num = orig_rate_num; rate_den = orig_rate_den; min_guess = gst_clock_adjust_with_calibration (GST_CLOCK_CAST (self), local_1, internal_time, external_time, rate_num, rate_den); time_before = gst_clock_adjust_with_calibration (GST_CLOCK_CAST (self), local_2, internal_time, external_time, rate_num, rate_den); /* Maximum discontinuity, when we're synched with the master. Could make this a property, * but this value seems to work fine */ max_discont = self->rtt_avg / 4; /* If the remote observation was within a max_discont window around our min/max estimates, we're synched */ synched = (GST_CLOCK_DIFF (remote_avg, min_guess) < (GstClockTimeDiff) (max_discont) && GST_CLOCK_DIFF (time_before, remote_avg) < (GstClockTimeDiff) (max_discont)); if (gst_clock_add_observation_unapplied (GST_CLOCK_CAST (self), local_avg, remote_avg, &r_squared, &internal_time, &external_time, &rate_num, &rate_den)) { /* Now compare the difference (discont) in the clock * after this observation */ time_discont = GST_CLOCK_DIFF (time_before, gst_clock_adjust_with_calibration (GST_CLOCK_CAST (self), local_2, internal_time, external_time, rate_num, rate_den)); /* If we were in sync with the remote clock, clamp the allowed * discontinuity to within quarter of one RTT. In sync means our send/receive estimates * of remote time correctly windowed the actual remote time observation */ if (synched && ABS (time_discont) > max_discont) { GstClockTimeDiff offset; GST_DEBUG_OBJECT (clock, "Too large a discont, clamping to 1/4 average RTT = %" GST_TIME_FORMAT, GST_TIME_ARGS (max_discont)); if (time_discont > 0) { /* Too large a forward step - add a -ve offset */ offset = max_discont - time_discont; if (-offset > external_time) external_time = 0; else external_time += offset; } else { /* Too large a backward step - add a +ve offset */ offset = -(max_discont + time_discont); external_time += offset; } time_discont += offset; } /* Check if the new clock params would have made our observation within range */ now_synched = (GST_CLOCK_DIFF (remote_avg, gst_clock_adjust_with_calibration (GST_CLOCK_CAST (self), local_1, internal_time, external_time, rate_num, rate_den)) < (GstClockTimeDiff) (max_discont)) && (GST_CLOCK_DIFF (gst_clock_adjust_with_calibration (GST_CLOCK_CAST (self), local_2, internal_time, external_time, rate_num, rate_den), remote_avg) < (GstClockTimeDiff) (max_discont)); /* Only update the clock if we had synch or just gained it */ if (synched || now_synched || self->skipped_updates > MAX_SKIPPED_UPDATES) { gst_clock_set_calibration (GST_CLOCK_CAST (self), internal_time, external_time, rate_num, rate_den); /* ghetto formula - shorter timeout for bad correlations */ current_timeout = (1e-3 / (1 - MIN (r_squared, 0.99999))) * GST_SECOND; current_timeout = MIN (current_timeout, gst_clock_get_timeout (GST_CLOCK_CAST (self))); self->skipped_updates = 0; /* FIXME: When do we consider the clock absolutely not synced anymore? */ gst_clock_set_synced (GST_CLOCK (self), TRUE); } else { /* Restore original calibration vars for the report, we're not changing the clock */ internal_time = orig_internal_time; external_time = orig_external_time; rate_num = orig_rate_num; rate_den = orig_rate_den; time_discont = 0; self->skipped_updates++; } } /* Limit the polling to at most one per minimum_update_interval */ if (rtt < min_update_interval) current_timeout = MAX (min_update_interval - rtt, current_timeout); GST_OBJECT_LOCK (self); if (self->busses) { GstStructure *s; GstMessage *msg; GList *l; /* Output a stats message, whether we updated the clock or not */ s = gst_structure_new ("gst-netclock-statistics", "synchronised", G_TYPE_BOOLEAN, synched, "rtt", G_TYPE_UINT64, rtt, "rtt-average", G_TYPE_UINT64, self->rtt_avg, "local", G_TYPE_UINT64, local_avg, "remote", G_TYPE_UINT64, remote_avg, "discontinuity", G_TYPE_INT64, time_discont, "remote-min-estimate", G_TYPE_UINT64, min_guess, "remote-max-estimate", G_TYPE_UINT64, time_before, "remote-min-error", G_TYPE_INT64, GST_CLOCK_DIFF (remote_avg, min_guess), "remote-max-error", G_TYPE_INT64, GST_CLOCK_DIFF (remote_avg, time_before), "request-send", G_TYPE_UINT64, local_1, "request-receive", G_TYPE_UINT64, local_2, "r-squared", G_TYPE_DOUBLE, r_squared, "timeout", G_TYPE_UINT64, current_timeout, "internal-time", G_TYPE_UINT64, internal_time, "external-time", G_TYPE_UINT64, external_time, "rate-num", G_TYPE_UINT64, rate_num, "rate-den", G_TYPE_UINT64, rate_den, "rate", G_TYPE_DOUBLE, (gdouble) (rate_num) / rate_den, "local-clock-offset", G_TYPE_INT64, GST_CLOCK_DIFF (internal_time, external_time), NULL); msg = gst_message_new_element (GST_OBJECT (self), s); for (l = self->busses; l; l = l->next) gst_bus_post (l->data, gst_message_ref (msg)); gst_message_unref (msg); } GST_OBJECT_UNLOCK (self); GST_INFO ("next timeout: %" GST_TIME_FORMAT, GST_TIME_ARGS (current_timeout)); self->timeout_expiration = gst_util_get_timestamp () + current_timeout; return; bogus_observation: /* Schedule a new packet again soon */ self->timeout_expiration = gst_util_get_timestamp () + (GST_SECOND / 4); return; }
static GstElement * gst_auto_audio_sink_find_best (GstAutoAudioSink * sink) { GList *list, *item; GstElement *choice = NULL; GstMessage *message = NULL; GSList *errors = NULL; GstBus *bus = gst_bus_new (); GstPad *el_pad = NULL; GstCaps *el_caps = NULL; gboolean no_match = TRUE; list = gst_registry_feature_filter (gst_registry_get (), (GstPluginFeatureFilter) gst_auto_audio_sink_factory_filter, FALSE, sink); list = g_list_sort (list, (GCompareFunc) gst_auto_audio_sink_compare_ranks); /* We don't treat sound server sinks special. Our policy is that sound * server sinks that have a rank must not auto-spawn a daemon under any * circumstances, so there's nothing for us to worry about here */ GST_LOG_OBJECT (sink, "Trying to find usable audio devices ..."); for (item = list; item != NULL; item = item->next) { GstElementFactory *f = GST_ELEMENT_FACTORY (item->data); GstElement *el; if ((el = gst_auto_audio_sink_create_element_with_pretty_name (sink, f))) { GstStateChangeReturn ret; GST_DEBUG_OBJECT (sink, "Testing %s", GST_OBJECT_NAME (f)); /* If autoaudiosink has been provided with filter caps, * accept only sinks that match with the filter caps */ if (sink->filter_caps) { el_pad = gst_element_get_static_pad (GST_ELEMENT (el), "sink"); el_caps = gst_pad_query_caps (el_pad, NULL); gst_object_unref (el_pad); GST_DEBUG_OBJECT (sink, "Checking caps: %" GST_PTR_FORMAT " vs. %" GST_PTR_FORMAT, sink->filter_caps, el_caps); no_match = !gst_caps_can_intersect (sink->filter_caps, el_caps); gst_caps_unref (el_caps); if (no_match) { GST_DEBUG_OBJECT (sink, "Incompatible caps"); gst_object_unref (el); continue; } else { GST_DEBUG_OBJECT (sink, "Found compatible caps"); } } gst_element_set_bus (el, bus); ret = gst_element_set_state (el, GST_STATE_READY); if (ret == GST_STATE_CHANGE_SUCCESS) { GST_DEBUG_OBJECT (sink, "This worked!"); choice = el; break; } /* collect all error messages */ while ((message = gst_bus_pop_filtered (bus, GST_MESSAGE_ERROR))) { GST_DEBUG_OBJECT (sink, "error message %" GST_PTR_FORMAT, message); errors = g_slist_append (errors, message); } gst_element_set_state (el, GST_STATE_NULL); gst_object_unref (el); } } GST_DEBUG_OBJECT (sink, "done trying"); if (!choice) { if (errors) { /* FIXME: we forward the first error for now; but later on it might make * sense to actually analyse them */ gst_message_ref (GST_MESSAGE (errors->data)); GST_DEBUG_OBJECT (sink, "reposting message %p", errors->data); gst_element_post_message (GST_ELEMENT (sink), GST_MESSAGE (errors->data)); } else { /* send warning message to application and use a fakesink */ GST_ELEMENT_WARNING (sink, RESOURCE, NOT_FOUND, (NULL), ("Failed to find a usable audio sink")); choice = gst_element_factory_make ("fakesink", "fake-audio-sink"); if (g_object_class_find_property (G_OBJECT_GET_CLASS (choice), "sync")) g_object_set (choice, "sync", TRUE, NULL); gst_element_set_state (choice, GST_STATE_READY); } } gst_object_unref (bus); gst_plugin_feature_list_free (list); g_slist_foreach (errors, (GFunc) gst_mini_object_unref, NULL); g_slist_free (errors); return choice; }