static gboolean gst_wildmidi_activate (GstPad * sinkpad, GstObject * parent) { GstQuery *query; gboolean pull_mode; query = gst_query_new_scheduling (); if (!gst_pad_peer_query (sinkpad, query)) { gst_query_unref (query); goto activate_push; } pull_mode = gst_query_has_scheduling_mode_with_flags (query, GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE); gst_query_unref (query); if (!pull_mode) goto activate_push; GST_DEBUG_OBJECT (sinkpad, "activating pull"); return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE); activate_push: { GST_DEBUG_OBJECT (sinkpad, "activating push"); return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE); } }
static void fake_demuxer_prepare_pads (GstBin * pipeline, GstElement * demux, GstValidateRunner * runner) { gint i = 0; GList *tmp; fail_unless (g_list_length (demux->srcpads), 3); for (tmp = demux->srcpads; tmp; tmp = tmp->next) { GstPad *new_peer; gchar *name = g_strdup_printf ("sink-%d", i++); GstElement *sink = gst_element_factory_make ("fakesink", name); gst_bin_add (pipeline, sink); new_peer = sink->sinkpads->data; gst_pad_link (tmp->data, new_peer); gst_element_set_state (sink, GST_STATE_PLAYING); gst_pad_activate_mode (tmp->data, GST_PAD_MODE_PUSH, TRUE); g_free (name); } fail_unless (gst_pad_activate_mode (demux->sinkpads->data, GST_PAD_MODE_PUSH, TRUE)); }
static gboolean gst_ghost_pad_internal_activate_pull_default (GstPad * pad, GstObject * parent, gboolean active) { gboolean ret; GstPad *other; GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad)); if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) { /* we are activated in pull mode by our peer element, which is a sinkpad * that wants to operate in pull mode. This activation has to propagate * upstream through the pipeline. We call the internal activation function, * which will trigger gst_ghost_pad_activate_pull_default, which propagates even * further upstream */ GST_LOG_OBJECT (pad, "pad is src, activate internal"); GST_PROXY_PAD_ACQUIRE_INTERNAL (pad, other, FALSE); ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active); GST_PROXY_PAD_RELEASE_INTERNAL (other); } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) { /* We are SINK, the ghostpad is SRC, we propagate the activation upstream * since we hold a pointer to the upstream peer. */ GST_LOG_OBJECT (pad, "activating peer"); ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active); gst_object_unref (other); } else { /* this is failure, we can't activate pull if there is no peer */ GST_LOG_OBJECT (pad, "not src and no peer, failing"); ret = FALSE; } return ret; }
static gboolean gst_ghost_pad_activate_pull_default (GstPad * pad, GstObject * parent, gboolean active) { gboolean ret; GstPad *other; GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad)); if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) { /* the ghostpad is SRC and activated in pull mode by its peer, call the * activation function of the internal pad to propagate the activation * upstream */ GST_LOG_OBJECT (pad, "pad is src, activate internal"); GST_PROXY_PAD_ACQUIRE_INTERNAL (pad, other, FALSE); ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active); GST_PROXY_PAD_RELEASE_INTERNAL (other); } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) { /* We are SINK and activated by the internal pad, propagate activation * upstream because we hold a ref to the upstream peer */ GST_LOG_OBJECT (pad, "activating peer"); ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active); gst_object_unref (other); } else { /* no peer, we fail */ GST_LOG_OBJECT (pad, "pad not src and no peer, failing"); ret = FALSE; } return ret; }
static gboolean gst_type_find_element_activate_sink (GstPad * pad, GstObject * parent) { GstQuery *query; gboolean pull_mode; query = gst_query_new_scheduling (); if (!gst_pad_peer_query (pad, query)) { gst_query_unref (query); goto typefind_push; } pull_mode = gst_query_has_scheduling_mode_with_flags (query, GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE); gst_query_unref (query); if (!pull_mode) goto typefind_push; if (!gst_pad_activate_mode (pad, GST_PAD_MODE_PULL, TRUE)) goto typefind_push; /* only start our task if we ourselves decide to start in pull mode */ return gst_pad_start_task (pad, (GstTaskFunction) gst_type_find_element_loop, pad, NULL); typefind_push: { return gst_pad_activate_mode (pad, GST_PAD_MODE_PUSH, TRUE); } }
static gboolean gst_asf_parse_sink_activate (GstPad * sinkpad, GstObject * parent) { GstQuery *query; gboolean pull_mode; query = gst_query_new_scheduling (); if (!gst_pad_peer_query (sinkpad, query)) { gst_query_unref (query); goto activate_push; } pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL); gst_query_unref (query); if (!pull_mode) goto activate_push; GST_DEBUG_OBJECT (sinkpad, "activating pull"); return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE); activate_push: { GST_DEBUG_OBJECT (sinkpad, "activating push"); return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE); } }
static void _test_flow_aggregation (GstFlowReturn flow, GstFlowReturn flow1, GstFlowReturn flow2, GstFlowReturn demux_flow, gboolean should_fail) { GstPad *srcpad; GstValidateReport *report; GstValidatePadMonitor *pmonitor, *pmonitor1, *pmonitor2; GstElement *demuxer = fake_demuxer_new (); GstBin *pipeline = GST_BIN (gst_pipeline_new ("validate-pipeline")); GList *reports; GstValidateRunner *runner; GstValidateMonitor *monitor; fail_unless (g_setenv ("GST_VALIDATE_REPORTING_DETAILS", "all", TRUE)); runner = gst_validate_runner_new (); monitor = gst_validate_monitor_factory_create (GST_OBJECT (pipeline), runner, NULL); gst_validate_reporter_set_handle_g_logs (GST_VALIDATE_REPORTER (monitor)); gst_bin_add (pipeline, demuxer); fake_demuxer_prepare_pads (pipeline, demuxer, runner); srcpad = gst_pad_new ("srcpad1", GST_PAD_SRC); gst_pad_link (srcpad, demuxer->sinkpads->data); fail_unless (gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, TRUE)); gst_check_setup_events_with_stream_id (srcpad, demuxer, NULL, GST_FORMAT_TIME, "the-stream"); pmonitor = _get_pad_monitor (gst_pad_get_peer (demuxer->srcpads->data)); pmonitor1 = _get_pad_monitor (gst_pad_get_peer (demuxer->srcpads->next->data)); pmonitor2 = _get_pad_monitor (gst_pad_get_peer (demuxer->srcpads->next->next->data)); pmonitor->last_flow_return = flow; pmonitor1->last_flow_return = flow1; pmonitor2->last_flow_return = flow2; FAKE_DEMUXER (demuxer)->return_value = demux_flow; fail_unless_equals_int (gst_pad_push (srcpad, gst_buffer_new ()), demux_flow); reports = gst_validate_runner_get_reports (runner); if (should_fail) { assert_equals_int (g_list_length (reports), 1); report = reports->data; fail_unless_equals_int (report->level, GST_VALIDATE_REPORT_LEVEL_CRITICAL); fail_unless_equals_int (report->issue->issue_id, WRONG_FLOW_RETURN); } else { assert_equals_int (g_list_length (reports), 0); } g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref); clean_bus (GST_ELEMENT (pipeline)); gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); ASSERT_OBJECT_REFCOUNT (pipeline, "ours", 1); check_destroyed (pipeline, demuxer, NULL); check_destroyed (monitor, pmonitor, NULL); }
static gboolean gst_type_find_element_activate_src_mode (GstPad * pad, GstObject * parent, GstPadMode mode, gboolean active) { gboolean res; GstTypeFindElement *typefind; typefind = GST_TYPE_FIND_ELEMENT (parent); switch (mode) { case GST_PAD_MODE_PULL: /* make sure our task stops pushing, we can't call _stop here because this * activation might happen from the streaming thread. */ gst_pad_pause_task (typefind->sink); res = gst_pad_activate_mode (typefind->sink, mode, active); if (active && res && typefind->caps) { GstCaps *caps; GST_OBJECT_LOCK (typefind); caps = gst_caps_ref (typefind->caps); GST_OBJECT_UNLOCK (typefind); res = gst_pad_set_caps (typefind->src, caps); gst_caps_unref (caps); } break; default: res = TRUE; break; } return res; }
static gboolean gst_rnd_buffer_size_activate (GstPad * pad, GstObject * parent) { GstQuery *query; gboolean pull_mode; query = gst_query_new_scheduling (); if (!gst_pad_peer_query (pad, query)) { gst_query_unref (query); goto no_pull; } pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL); gst_query_unref (query); if (!pull_mode) goto no_pull; GST_DEBUG_OBJECT (pad, "activating pull"); return gst_pad_activate_mode (pad, GST_PAD_MODE_PULL, TRUE); /* ERRORS */ no_pull: { GST_DEBUG_OBJECT (pad, "pull mode not supported"); return FALSE; } }
static gboolean gst_raw_parse_sink_activate (GstPad * sinkpad, GstObject * parent) { GstQuery *query; gboolean pull_mode = FALSE; query = gst_query_new_scheduling (); if (gst_pad_peer_query (sinkpad, query)) pull_mode = gst_query_has_scheduling_mode_with_flags (query, GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE); gst_query_unref (query); if (pull_mode) { GST_DEBUG ("going to pull mode"); return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE); } else { GST_DEBUG ("going to push (streaming) mode"); return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE); } }
static GstPad * gst_tcp_mix_src_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * unused, const GstCaps * caps) { GstTCPMixSrc *src = GST_TCP_MIX_SRC (element); GstPad *srcpad; gchar *name; gboolean res; int num; //g_print ("%s:%d: %s\n", __FILE__, __LINE__, __FUNCTION__); GST_INFO_OBJECT (src, "Requesting new pad %s.%s (caps: %s)", GST_ELEMENT_NAME (src), GST_PAD_TEMPLATE_NAME_TEMPLATE (templ), gst_caps_to_string (caps)); GST_OBJECT_LOCK (src); num = g_list_length (GST_ELEMENT_PADS (src)); name = g_strdup_printf ("src_%u", num); srcpad = GST_PAD_CAST (g_object_new (GST_TYPE_TCP_MIX_SRC_PAD, "name", name, "direction", templ->direction, "template", templ, NULL)); g_free (name); GST_OBJECT_UNLOCK (src); // see: gst_tcp_mix_src_activate_push gst_pad_set_active (srcpad, TRUE); gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, TRUE); gst_pad_set_activatemode_function (srcpad, (GstPadActivateModeFunction) gst_tcp_mix_src_activate_mode); gst_pad_set_query_function (srcpad, gst_tcp_mix_src_query); gst_pad_set_event_function (srcpad, gst_tcp_mix_src_event); gst_pad_set_getrange_function (srcpad, gst_tcp_mix_src_getrange); //GST_OBJECT_FLAG_SET (srcpad, GST_PAD_FLAG_PROXY_CAPS); //INFO ("add-pad: %s.%s", GST_ELEMENT_NAME (src), GST_PAD_NAME (srcpad)); res = gst_element_add_pad (GST_ELEMENT_CAST (src), srcpad); gst_tcp_mix_src_start (src, GST_TCP_MIX_SRC_PAD (srcpad)); if (G_UNLIKELY (!res)) { GST_ERROR_OBJECT (src, "Failed to add new pad"); } return srcpad; }
static gboolean gst_rnd_buffer_size_activate (GstPad * pad, GstObject * parent) { GstQuery *query; gboolean pull_mode; query = gst_query_new_scheduling (); if (gst_pad_peer_query (pad, query)) pull_mode = gst_query_has_scheduling_mode_with_flags (query, GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE); else pull_mode = FALSE; gst_query_unref (query); if (pull_mode) { GST_DEBUG_OBJECT (pad, "activating pull"); return gst_pad_activate_mode (pad, GST_PAD_MODE_PULL, TRUE); } else { GST_DEBUG_OBJECT (pad, "activating push"); return gst_pad_activate_mode (pad, GST_PAD_MODE_PUSH, TRUE); } }
static gboolean gst_ghost_pad_internal_activate_push_default (GstPad * pad, GstObject * parent, gboolean active) { gboolean ret; GstPad *other; GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, we're ok", (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad)); /* in both cases (SRC and SINK) we activate just the internal pad. The targets * will be activated later (or already in case of a ghost sinkpad). */ other = GST_PROXY_PAD_INTERNAL (pad); ret = gst_pad_activate_mode (other, GST_PAD_MODE_PUSH, active); return ret; }
static gboolean gst_ghost_pad_activate_push_default (GstPad * pad, GstObject * parent, gboolean active) { gboolean ret; GstPad *other; g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE); GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, proxy internal", (active ? "" : "de"), GST_DEBUG_PAD_NAME (pad)); /* just activate the internal pad */ other = GST_PROXY_PAD_INTERNAL (pad); ret = gst_pad_activate_mode (other, GST_PAD_MODE_PUSH, active); return ret; }
static gboolean on_activate(GstPad* pad, GstObject* parent) { gst_pad_activate_mode(pad,GST_PAD_MODE_PUSH,TRUE); GstTagList* list = gst_tag_list_new_empty(); GValue value; memset(&value,0,sizeof(value)); g_value_init(&value,G_TYPE_DOUBLE); fprintf(stderr,"bwub setting gain/peak %f %f %f\n", g_activate_gain.peak, g_activate_gain.gain, g_activate_gain.level); g_value_set_double(&value,g_activate_gain.gain*2); gst_tag_list_add_value(list, GST_TAG_MERGE_REPLACE, GST_TAG_TRACK_GAIN, &value); gst_tag_list_add_value(list, GST_TAG_MERGE_REPLACE, GST_TAG_ALBUM_GAIN, &value); g_value_set_double(&value,g_activate_gain.peak*2); gst_tag_list_add_value(list, GST_TAG_MERGE_REPLACE, GST_TAG_TRACK_PEAK, &value); gst_tag_list_add_value(list, GST_TAG_MERGE_REPLACE, GST_TAG_ALBUM_PEAK, &value); g_value_set_double(&value,g_activate_gain.level); gst_tag_list_add_value(list, GST_TAG_MERGE_REPLACE, GST_TAG_REFERENCE_LEVEL, &value); assert(TRUE==gst_pad_send_event(pad,gst_event_new_tag(list))); return TRUE; }
static void _check_media_info (GstSegment * segment, BufferDesc * bufs) { GList *reports; GstEvent *segev; GstBuffer *buffer; GstElement *decoder; GstPad *srcpad, *sinkpad; GstValidateReport *report; GstValidateMonitor *monitor; GstValidateRunner *runner; GstMediaDescriptor *mdesc; GError *err = NULL; gint i, num_issues = 0; fail_unless (g_setenv ("GST_VALIDATE_REPORTING_DETAILS", "all", TRUE)); runner = gst_validate_runner_new (); mdesc = (GstMediaDescriptor *) gst_media_descriptor_parser_new_from_xml (runner, media_info, &err); decoder = fake_decoder_new (); monitor = gst_validate_monitor_factory_create (GST_OBJECT (decoder), runner, NULL); gst_validate_monitor_set_media_descriptor (monitor, mdesc); srcpad = gst_pad_new ("src", GST_PAD_SRC); sinkpad = decoder->sinkpads->data; ASSERT_OBJECT_REFCOUNT (sinkpad, "decoder ref", 1); fail_unless (gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, TRUE)); fail_unless_equals_int (gst_element_set_state (decoder, GST_STATE_PLAYING), GST_STATE_CHANGE_SUCCESS); assert_equals_string (gst_pad_link_get_name (gst_pad_link (srcpad, sinkpad)), gst_pad_link_get_name (GST_PAD_LINK_OK)); gst_check_setup_events_with_stream_id (srcpad, decoder, gst_caps_from_string ("video/x-fake"), GST_FORMAT_TIME, "the-stream"); if (segment) { segev = gst_event_new_segment (segment); fail_unless (gst_pad_push_event (srcpad, segev)); } for (i = 0; bufs[i].content != NULL; i++) { BufferDesc *buf = &bufs[i]; buffer = _create_buffer (buf); assert_equals_string (gst_flow_get_name (gst_pad_push (srcpad, buffer)), gst_flow_get_name (GST_FLOW_OK)); reports = gst_validate_runner_get_reports (runner); num_issues += buf->num_issues; assert_equals_int (g_list_length (reports), num_issues); if (buf->num_issues) { GList *tmp = g_list_nth (reports, num_issues - buf->num_issues); while (tmp) { report = tmp->data; fail_unless_equals_int (report->level, GST_VALIDATE_REPORT_LEVEL_WARNING); fail_unless_equals_int (report->issue->issue_id, WRONG_BUFFER); tmp = tmp->next; } } } /* clean up */ fail_unless (gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, FALSE)); fail_unless_equals_int (gst_element_set_state (decoder, GST_STATE_NULL), GST_STATE_CHANGE_SUCCESS); gst_object_unref (srcpad); check_destroyed (decoder, sinkpad, NULL); check_destroyed (runner, NULL, NULL); }
static void _create_issues (GstValidateRunner * runner) { GstPad *srcpad1, *srcpad2, *sinkpad, *funnel_sink1, *funnel_sink2; GstElement *src1, *src2, *sink, *fakemixer; GstSegment segment; src1 = create_and_monitor_element ("fakesrc2", "fakesrc1", runner); src2 = create_and_monitor_element ("fakesrc2", "fakesrc2", runner); fakemixer = create_and_monitor_element ("fakemixer", "fakemixer", runner); sink = create_and_monitor_element ("fakesink", "fakesink", runner); srcpad1 = gst_element_get_static_pad (src1, "src"); srcpad2 = gst_element_get_static_pad (src2, "src"); funnel_sink1 = gst_element_get_request_pad (fakemixer, "sink_%u"); funnel_sink2 = gst_element_get_request_pad (fakemixer, "sink_%u"); sinkpad = gst_element_get_static_pad (sink, "sink"); fail_unless (gst_element_link (fakemixer, sink)); fail_unless (gst_pad_link (srcpad1, funnel_sink1) == GST_PAD_LINK_OK); fail_unless (gst_pad_link (srcpad2, funnel_sink2) == GST_PAD_LINK_OK); /* We want to handle the src behaviour ourselves */ fail_unless (gst_pad_activate_mode (srcpad1, GST_PAD_MODE_PUSH, TRUE)); fail_unless (gst_pad_activate_mode (srcpad2, GST_PAD_MODE_PUSH, TRUE)); /* Setup all needed events */ gst_segment_init (&segment, GST_FORMAT_TIME); segment.start = 0; segment.stop = GST_SECOND; fail_unless (gst_pad_push_event (srcpad1, gst_event_new_stream_start ("the-stream"))); fail_unless (gst_pad_push_event (srcpad1, gst_event_new_segment (&segment))); fail_unless (gst_pad_push_event (srcpad2, gst_event_new_stream_start ("the-stream"))); fail_unless (gst_pad_push_event (srcpad2, gst_event_new_segment (&segment))); fail_unless_equals_int (gst_element_set_state (fakemixer, GST_STATE_PLAYING), GST_STATE_CHANGE_SUCCESS); fail_unless_equals_int (gst_element_set_state (sink, GST_STATE_PLAYING), GST_STATE_CHANGE_ASYNC); /* Send an unexpected flush stop */ _gst_check_expecting_log = TRUE; fail_unless (gst_pad_push_event (srcpad1, gst_event_new_flush_stop (TRUE))); /* Once again but on the other fakemixer sink */ fail_unless (gst_pad_push_event (srcpad2, gst_event_new_flush_stop (TRUE))); /* clean up */ fail_unless (gst_pad_activate_mode (srcpad1, GST_PAD_MODE_PUSH, FALSE)); fail_unless (gst_pad_activate_mode (srcpad2, GST_PAD_MODE_PUSH, FALSE)); fail_unless_equals_int (gst_element_set_state (fakemixer, GST_STATE_NULL), GST_STATE_CHANGE_SUCCESS); fail_unless_equals_int (gst_element_set_state (sink, GST_STATE_NULL), GST_STATE_CHANGE_SUCCESS); gst_object_unref (srcpad1); gst_object_unref (srcpad2); gst_object_unref (sinkpad); gst_object_unref (funnel_sink1); gst_object_unref (funnel_sink2); gst_check_objects_destroyed_on_unref (fakemixer, funnel_sink1, funnel_sink2, NULL); gst_check_objects_destroyed_on_unref (src1, srcpad1, NULL); gst_check_objects_destroyed_on_unref (src2, srcpad2, NULL); gst_check_objects_destroyed_on_unref (sink, sinkpad, NULL); }
static GstPad * gst_tee_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * name_templ, const GstCaps * caps) { gchar *name; GstPad *srcpad; GstTee *tee; GstPadMode mode; gboolean res; guint index = 0; tee = GST_TEE (element); GST_DEBUG_OBJECT (tee, "requesting pad"); GST_OBJECT_LOCK (tee); if (name_templ) { sscanf (name_templ, "src_%u", &index); GST_LOG_OBJECT (element, "name: %s (index %d)", name_templ, index); if (g_hash_table_contains (tee->pad_indexes, GUINT_TO_POINTER (index))) { GST_ERROR_OBJECT (element, "pad name %s is not unique", name_templ); GST_OBJECT_UNLOCK (tee); return NULL; } if (index >= tee->next_pad_index) tee->next_pad_index = index + 1; } else { index = tee->next_pad_index; while (g_hash_table_contains (tee->pad_indexes, GUINT_TO_POINTER (index))) index++; tee->next_pad_index = index + 1; } g_hash_table_insert (tee->pad_indexes, GUINT_TO_POINTER (index), NULL); name = g_strdup_printf ("src_%u", index); srcpad = GST_PAD_CAST (g_object_new (GST_TYPE_TEE_PAD, "name", name, "direction", templ->direction, "template", templ, NULL)); GST_TEE_PAD_CAST (srcpad)->index = index; g_free (name); mode = tee->sink_mode; GST_OBJECT_UNLOCK (tee); switch (mode) { case GST_PAD_MODE_PULL: /* we already have a src pad in pull mode, and our pull mode can only be SINGLE, so fall through to activate this new pad in push mode */ case GST_PAD_MODE_PUSH: res = gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, TRUE); break; default: res = TRUE; break; } if (!res) goto activate_failed; gst_pad_set_activatemode_function (srcpad, GST_DEBUG_FUNCPTR (gst_tee_src_activate_mode)); gst_pad_set_query_function (srcpad, GST_DEBUG_FUNCPTR (gst_tee_src_query)); gst_pad_set_getrange_function (srcpad, GST_DEBUG_FUNCPTR (gst_tee_src_get_range)); /* Forward sticky events to the new srcpad */ gst_pad_sticky_events_foreach (tee->sinkpad, forward_sticky_events, srcpad); GST_OBJECT_FLAG_SET (srcpad, GST_PAD_FLAG_PROXY_CAPS); gst_element_add_pad (GST_ELEMENT_CAST (tee), srcpad); return srcpad; /* ERRORS */ activate_failed: { gboolean changed = FALSE; GST_OBJECT_LOCK (tee); GST_DEBUG_OBJECT (tee, "warning failed to activate request pad"); if (tee->allocpad == srcpad) { tee->allocpad = NULL; changed = TRUE; } GST_OBJECT_UNLOCK (tee); gst_object_unref (srcpad); if (changed) { gst_tee_notify_alloc_pad (tee); } return NULL; } }
static gboolean gst_tee_src_activate_mode (GstPad * pad, GstObject * parent, GstPadMode mode, gboolean active) { GstTee *tee; gboolean res; GstPad *sinkpad; tee = GST_TEE (parent); switch (mode) { case GST_PAD_MODE_PULL: { GST_OBJECT_LOCK (tee); if (tee->pull_mode == GST_TEE_PULL_MODE_NEVER) goto cannot_pull; if (tee->pull_mode == GST_TEE_PULL_MODE_SINGLE && active && tee->pull_pad) goto cannot_pull_multiple_srcs; sinkpad = gst_object_ref (tee->sinkpad); GST_OBJECT_UNLOCK (tee); res = gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, active); gst_object_unref (sinkpad); if (!res) goto sink_activate_failed; GST_OBJECT_LOCK (tee); if (active) { if (tee->pull_mode == GST_TEE_PULL_MODE_SINGLE) tee->pull_pad = pad; } else { if (pad == tee->pull_pad) tee->pull_pad = NULL; } tee->sink_mode = (active ? GST_PAD_MODE_PULL : GST_PAD_MODE_NONE); GST_OBJECT_UNLOCK (tee); break; } default: res = TRUE; break; } return res; /* ERRORS */ cannot_pull: { GST_OBJECT_UNLOCK (tee); GST_INFO_OBJECT (tee, "Cannot activate in pull mode, pull-mode " "set to NEVER"); return FALSE; } cannot_pull_multiple_srcs: { GST_OBJECT_UNLOCK (tee); GST_INFO_OBJECT (tee, "Cannot activate multiple src pads in pull mode, " "pull-mode set to SINGLE"); return FALSE; } sink_activate_failed: { GST_INFO_OBJECT (tee, "Failed to %sactivate sink pad in pull mode", active ? "" : "de"); return FALSE; } }
static gboolean gst_type_find_element_activate_sink (GstPad * pad, GstObject * parent) { GstTypeFindElement *typefind; GstQuery *query; gboolean pull_mode; GstCaps *found_caps = NULL; GstTypeFindProbability probability = GST_TYPE_FIND_NONE; GstSchedulingFlags sched_flags; typefind = GST_TYPE_FIND_ELEMENT (parent); /* if we have force caps, use those */ GST_OBJECT_LOCK (typefind); if (typefind->force_caps) { found_caps = gst_caps_ref (typefind->force_caps); probability = GST_TYPE_FIND_MAXIMUM; GST_OBJECT_UNLOCK (typefind); GST_DEBUG ("Emiting found caps %" GST_PTR_FORMAT, found_caps); g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0, probability, found_caps); typefind->mode = MODE_NORMAL; /* the signal above could have made a downstream element activate * the pad in pull mode, we check if the pad is already active now and if * so, we are done */ if (gst_pad_is_active (pad)) return TRUE; goto typefind_push; } GST_OBJECT_UNLOCK (typefind); query = gst_query_new_scheduling (); if (!gst_pad_peer_query (pad, query)) { gst_query_unref (query); goto typefind_push; } gst_query_parse_scheduling (query, &sched_flags, NULL, NULL, NULL); pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL) && ((sched_flags & GST_SCHEDULING_FLAG_SEEKABLE) != 0); gst_query_unref (query); if (!pull_mode) goto typefind_push; if (!gst_pad_activate_mode (pad, GST_PAD_MODE_PULL, TRUE)) goto typefind_push; /* only start our task if we ourselves decide to start in pull mode */ return gst_pad_start_task (pad, (GstTaskFunction) gst_type_find_element_loop, pad, NULL); typefind_push: { return gst_pad_activate_mode (pad, GST_PAD_MODE_PUSH, TRUE); } }