/* Data probe cb to drop everything but count buffers and events */ static GstPadProbeReturn probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) { gint count = 0; const gchar *count_type = NULL; GstMiniObject *obj = GST_PAD_PROBE_INFO_DATA (info); GST_LOG_OBJECT (pad, "got data"); if (GST_IS_BUFFER (obj)) { count_type = "buffer_count"; } else if (GST_IS_EVENT (obj)) { count_type = "event_count"; } else { g_assert_not_reached (); } /* increment and store count */ count = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (pad), count_type)); count++; g_object_set_data (G_OBJECT (pad), count_type, GINT_TO_POINTER (count)); /* drop every buffer */ return GST_IS_BUFFER (obj) ? GST_PAD_PROBE_DROP : GST_PAD_PROBE_PASS; }
static GstPadProbeReturn event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer udata) { GstPadProbeReturn ret = GST_PAD_PROBE_OK; GstEvent *event = GST_PAD_PROBE_INFO_DATA (info); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_STREAM_START:{ guint group_id; g_mutex_lock (&test_mutex); fail_unless (gst_event_parse_group_id (event, &group_id)); if (have_group_id) { if (group_id_pre != group_id) { event = gst_event_copy (event); gst_event_set_group_id (event, group_id_pre); gst_event_replace ((GstEvent **) & info->data, event); gst_event_unref (event); } } else { group_id_pre = group_id; have_group_id = TRUE; } g_mutex_unlock (&test_mutex); break; } default: break; } return ret; }
static GstPadProbeReturn on_video_sink_data_flow (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) { GstMiniObject *mini_obj = GST_PAD_PROBE_INFO_DATA (info); GstFPSDisplaySink *self = GST_FPS_DISPLAY_SINK (user_data); if (GST_IS_BUFFER (mini_obj)) { GstClockTime ts; /* assume the frame is going to be rendered. If it isnt', we'll get a qos * message and reset ->frames_rendered from there. */ g_atomic_int_inc (&self->frames_rendered); ts = gst_util_get_timestamp (); if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (self->start_ts))) { self->interval_ts = self->last_ts = self->start_ts = ts; } if (GST_CLOCK_DIFF (self->interval_ts, ts) > self->fps_update_interval) { display_current_fps (self); self->interval_ts = ts; } } return GST_PAD_PROBE_OK; }
/* reconfiguration is not supported by all sources and can be disruptive * we will handle reconfiguration manually * FIXME: implement source reconfiguration support :) */ static GstPadProbeReturn drop_reconfigure_cb(GstPad *pad, GstPadProbeInfo *info, gpointer user_data) { OWR_UNUSED(pad); OWR_UNUSED(user_data); if (GST_IS_EVENT(GST_PAD_PROBE_INFO_DATA(info)) && GST_EVENT_TYPE(GST_PAD_PROBE_INFO_EVENT(info)) == GST_EVENT_RECONFIGURE) { GST_DEBUG("Dropping reconfigure event"); return GST_PAD_PROBE_DROP; } return GST_PAD_PROBE_OK; }
static GstPadProbeReturn stop_notification_cb (GstPad * srcpad, GstPadProbeInfo * info, gpointer user_data) { KmsRecorderEndpoint *recorder = KMS_RECORDER_ENDPOINT (user_data); if (GST_EVENT_TYPE (GST_PAD_PROBE_INFO_DATA (info)) != GST_EVENT_EOS) return GST_PAD_PROBE_OK; kms_loop_idle_add_full (recorder->priv->loop, G_PRIORITY_HIGH_IDLE, set_to_null_state_on_EOS, g_object_ref (recorder), g_object_unref); return GST_PAD_PROBE_OK; }
static GstPadProbeReturn pay_event_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) { rtp_pipeline *p = (rtp_pipeline *) user_data; GstEvent *event = GST_PAD_PROBE_INFO_DATA (info); if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM) { const GstStructure *s0 = gst_event_get_structure (p->custom_event); const GstStructure *s1 = gst_event_get_structure (event); if (gst_structure_is_equal (s0, s1)) { return GST_PAD_PROBE_DROP; } } return GST_PAD_PROBE_OK; }
GstPadProbeReturn eos_event_cb (GstPad *pad, GstPadProbeInfo *info, gpointer data) { if (GST_EVENT_TYPE (GST_PAD_PROBE_INFO_DATA (info)) == GST_EVENT_EOS) { GstElement *bin = NULL; GstMessage *message = NULL; GstStructure *msg_struct = NULL; MbMedia *media; gchar *uri = NULL; int pads = 0; media = (MbMedia *) data; bin = gst_bin_get_by_name (GST_BIN(_mb_global_data.pipeline), media->name); g_assert(bin); g_mutex_lock (&(media->mutex)); pads = --media->valid_pads; g_mutex_unlock (&(media->mutex)); g_object_get (media->decoder, "uri", &uri, NULL); g_debug ("EOS received (%s): %s.\n", media->name, uri); g_debug ("%s still has %d valid pad(s).\n", media->name, pads); if (pads == 0) { MbEvent *event = create_state_change_event (MB_END, media->name); notify_handler (event); free (event); g_hash_table_remove (_mb_global_data.media_table, media->name); msg_struct = gst_structure_new ("end-media", "event_type", G_TYPE_INT, APP_EVT_MEDIA_END, "data", G_TYPE_POINTER, media, /* FILL ME IF NECESSARY */ NULL); message = gst_message_new_application (GST_OBJECT(bin), msg_struct); g_debug ("Posting event\n"); gst_bus_post (_mb_global_data.bus, message); } g_free (uri); } return GST_PAD_PROBE_OK; }
static GstPadProbeReturn event_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) { GMainLoop *loop = user_data; GstElement *next; if (GST_EVENT_TYPE (GST_PAD_PROBE_INFO_DATA (info)) != GST_EVENT_EOS) return GST_PAD_PROBE_OK; gst_pad_remove_probe (pad, GST_PAD_PROBE_INFO_ID (info)); /* push current event back into the queue */ g_queue_push_tail (&effects, gst_object_ref (cur_effect)); /* take next effect from the queue */ next = g_queue_pop_head (&effects); if (next == NULL) { GST_DEBUG_OBJECT (pad, "no more effects"); g_main_loop_quit (loop); return GST_PAD_PROBE_DROP; } g_print ("Switching from '%s' to '%s'..\n", GST_OBJECT_NAME (cur_effect), GST_OBJECT_NAME (next)); gst_element_set_state (cur_effect, GST_STATE_NULL); /* remove unlinks automatically */ GST_DEBUG_OBJECT (pipeline, "removing %" GST_PTR_FORMAT, cur_effect); gst_bin_remove (GST_BIN (pipeline), cur_effect); GST_DEBUG_OBJECT (pipeline, "adding %" GST_PTR_FORMAT, next); gst_bin_add (GST_BIN (pipeline), next); GST_DEBUG_OBJECT (pipeline, "linking.."); gst_element_link_many (conv_before, next, conv_after, NULL); gst_element_set_state (next, GST_STATE_PLAYING); cur_effect = next; GST_DEBUG_OBJECT (pipeline, "done"); return GST_PAD_PROBE_DROP; }
static GstPadProbeReturn event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) { GstMiniObject *data = GST_PAD_PROBE_INFO_DATA (info); gboolean before_q = (gboolean) GPOINTER_TO_INT (user_data); GST_DEBUG ("event probe called %p", data); fail_unless (GST_IS_EVENT (data)); if (before_q) { switch (GST_EVENT_TYPE (GST_EVENT (data))) { case GST_EVENT_CUSTOM_UPSTREAM: case GST_EVENT_CUSTOM_BOTH: case GST_EVENT_CUSTOM_BOTH_OOB: if (got_event_before_q != NULL) break; gst_event_ref ((GstEvent *) data); g_get_current_time (&got_event_time); got_event_before_q = GST_EVENT (data); break; default: break; } } else { switch (GST_EVENT_TYPE (GST_EVENT (data))) { case GST_EVENT_CUSTOM_DOWNSTREAM: case GST_EVENT_CUSTOM_DOWNSTREAM_OOB: case GST_EVENT_CUSTOM_BOTH: case GST_EVENT_CUSTOM_BOTH_OOB: if (got_event_after_q != NULL) break; gst_event_ref ((GstEvent *) data); g_get_current_time (&got_event_time); got_event_after_q = GST_EVENT (data); break; default: break; } } return GST_PAD_PROBE_OK; }
static GstPadProbeReturn _appsrc_event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer udata) { GstEvent *event = GST_PAD_PROBE_INFO_DATA (info); GstElement *appsrc = udata; const GstStructure *s; gchar *sstr; App *app = &s_app; GST_DEBUG ("element:%s got an event:%s", GST_ELEMENT_NAME (appsrc), GST_EVENT_TYPE_NAME (event)); if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_UPSTREAM) { s = gst_event_get_structure (event); sstr = gst_structure_to_string (s); if (g_str_equal (sstr, "application/x-custom;")) app->nb_received_event++; g_free (sstr); } else if (GST_EVENT_TYPE (event) == GST_EVENT_SEEK) { app->nb_received_event++; } return GST_PAD_PROBE_OK; }
/* Probe on the output of a parser chain (the last * src pad) */ static GstPadProbeReturn parse_chain_output_probe (GstPad * pad, GstPadProbeInfo * info, DecodebinInputStream * input) { GstPadProbeReturn ret = GST_PAD_PROBE_OK; if (GST_IS_EVENT (GST_PAD_PROBE_INFO_DATA (info))) { GstEvent *ev = GST_PAD_PROBE_INFO_EVENT (info); GST_DEBUG_OBJECT (pad, "Got event %s", GST_EVENT_TYPE_NAME (ev)); switch (GST_EVENT_TYPE (ev)) { case GST_EVENT_STREAM_START: { GstStream *stream = NULL; guint group_id = G_MAXUINT32; gst_event_parse_group_id (ev, &group_id); GST_DEBUG_OBJECT (pad, "Got stream-start, group_id:%d, input %p", group_id, input->input); if (set_input_group_id (input->input, &group_id)) { ev = gst_event_make_writable (ev); gst_event_set_group_id (ev, group_id); GST_PAD_PROBE_INFO_DATA (info) = ev; } input->saw_eos = FALSE; gst_event_parse_stream (ev, &stream); /* FIXME : Would we ever end up with a stream already set on the input ?? */ if (stream) { if (input->active_stream != stream) { MultiQueueSlot *slot; if (input->active_stream) gst_object_unref (input->active_stream); input->active_stream = stream; /* We have the beginning of a stream, get a multiqueue slot and link to it */ g_mutex_lock (&input->dbin->selection_lock); slot = get_slot_for_input (input->dbin, input); link_input_to_slot (input, slot); g_mutex_unlock (&input->dbin->selection_lock); } else gst_object_unref (stream); } } break; case GST_EVENT_CAPS: { GstCaps *caps = NULL; gst_event_parse_caps (ev, &caps); GST_DEBUG_OBJECT (pad, "caps %" GST_PTR_FORMAT, caps); if (caps && input->active_stream) gst_stream_set_caps (input->active_stream, caps); } break; case GST_EVENT_EOS: input->saw_eos = TRUE; if (all_inputs_are_eos (input->dbin)) { GST_DEBUG_OBJECT (pad, "real input pad, marking as EOS"); check_all_streams_for_eos (input->dbin); } else { GstPad *peer = gst_pad_get_peer (input->srcpad); if (peer) { /* Send custom-eos event to multiqueue slot */ GstStructure *s; GstEvent *event; GST_DEBUG_OBJECT (pad, "Got EOS end of input stream, post custom-eos"); s = gst_structure_new_empty ("decodebin3-custom-eos"); event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s); gst_pad_send_event (peer, event); gst_object_unref (peer); } else { GST_FIXME_OBJECT (pad, "No peer, what should we do ?"); } } ret = GST_PAD_PROBE_DROP; break; case GST_EVENT_FLUSH_STOP: GST_DEBUG_OBJECT (pad, "Clear saw_eos flag"); input->saw_eos = FALSE; default: break; } } else if (GST_IS_QUERY (GST_PAD_PROBE_INFO_DATA (info))) { GstQuery *q = GST_PAD_PROBE_INFO_QUERY (info); GST_DEBUG_OBJECT (pad, "Seeing query %s", GST_QUERY_TYPE_NAME (q)); /* If we have a parser, we want to reply to the caps query */ /* FIXME: Set a flag when the input stream is created for * streams where we shouldn't reply to these queries */ if (GST_QUERY_TYPE (q) == GST_QUERY_CAPS && (info->type & GST_PAD_PROBE_TYPE_PULL)) { GstCaps *filter = NULL; GstCaps *allowed; gst_query_parse_caps (q, &filter); allowed = get_parser_caps_filter (input->dbin, filter); GST_DEBUG_OBJECT (pad, "Intercepting caps query, setting %" GST_PTR_FORMAT, allowed); gst_query_set_caps_result (q, allowed); gst_caps_unref (allowed); ret = GST_PAD_PROBE_HANDLED; } else if (GST_QUERY_TYPE (q) == GST_QUERY_ACCEPT_CAPS) { GstCaps *prop = NULL; gst_query_parse_accept_caps (q, &prop); /* Fast check against target caps */ if (gst_caps_can_intersect (prop, input->dbin->caps)) gst_query_set_accept_caps_result (q, TRUE); else { gboolean accepted = check_parser_caps_filter (input->dbin, prop); /* check against caps filter */ gst_query_set_accept_caps_result (q, accepted); GST_DEBUG_OBJECT (pad, "ACCEPT_CAPS query, returning %d", accepted); } ret = GST_PAD_PROBE_HANDLED; } } return ret; }