static GstPadLinkReturn gst_frame_store_link_src (GstPad *pad, GstPad *peer) { GstPadLinkReturn result = GST_PAD_LINK_OK; GstFrameStore *fs; fs = GST_FRAME_STORE(gst_pad_get_parent(pad)); if (GST_PAD_LINKFUNC (peer)) { result = GST_PAD_LINKFUNC(peer) (peer, pad); } if (GST_PAD_LINK_SUCCESSFUL (result)) { g_mutex_lock (fs->lock); fs->srcresult = GST_FLOW_OK; if (fs->srcresult == GST_FLOW_OK) { gst_pad_start_task (pad, (GstTaskFunction) gst_frame_store_task, pad); } else { GST_DEBUG("not starting task"); /* not starting task */ } g_mutex_unlock (fs->lock); } gst_object_unref (fs); return result; }
static void src_pad_added_cb (FsStream *stream, GstPad *pad, FsCodec *codec, gpointer user_data) { GstElement *pipeline = GST_ELEMENT_CAST (user_data); GstElement *sink = NULL; GError *error = NULL; GstPad *pad2; g_print ("Adding receive pipeline\n"); if (g_getenv ("AUDIOSINK")) sink = gst_parse_bin_from_description (g_getenv ("AUDIOSINK"), TRUE, &error); else sink = gst_parse_bin_from_description (DEFAULT_AUDIOSINK, TRUE, &error); print_error (error); g_assert (sink); g_assert (gst_bin_add (GST_BIN (pipeline), sink)); pad2 = gst_element_get_static_pad (sink, "sink"); g_assert (pad2); g_assert (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (pad, pad2))); g_assert (gst_element_set_state (sink, GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE); gst_object_unref (pad2); }
void MediaParserGst::link_to_fakesink(GstPad* pad) { GstElement* fakesink = gst_element_factory_make("fakesink", NULL); if (!fakesink) { throw MediaException(_("MediaParserGst Failed to create fakesink.")); } gboolean success = gst_bin_add(GST_BIN(_bin), fakesink); if (!success) { gst_object_unref(fakesink); throw MediaException(_("MediaParserGst Failed to create fakesink.")); } GstPad* sinkpad = gst_element_get_static_pad (fakesink, "sink"); if (!sinkpad) { gst_object_unref(fakesink); throw MediaException(_("MediaParserGst: couldn't get the fakesink " "src element.")); } GstPadLinkReturn ret = gst_pad_link(pad, sinkpad); if (!GST_PAD_LINK_SUCCESSFUL(ret)) { gst_object_unref(fakesink); gst_object_unref(sinkpad); throw MediaException(_("MediaParserGst: couln't link fakesink")); } if (!gst_element_set_state (_bin, GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS) { throw GnashException(_("MediaParserGst could not change element state")); } }
static void gst_mikmod_loop (GstElement * element) { GstMikMod *mikmod; GstBuffer *buffer_in; g_return_if_fail (element != NULL); g_return_if_fail (GST_IS_MIKMOD (element)); mikmod = GST_MIKMOD (element); srcpad = mikmod->srcpad; mikmod->Buffer = NULL; if (!mikmod->initialized) { while ((buffer_in = GST_BUFFER (gst_pad_pull (mikmod->sinkpad)))) { if (GST_IS_EVENT (buffer_in)) { GstEvent *event = GST_EVENT (buffer_in); if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) break; } else { if (mikmod->Buffer) { mikmod->Buffer = gst_buffer_append (mikmod->Buffer, buffer_in); } else { mikmod->Buffer = buffer_in; } } } if (!GST_PAD_CAPS (mikmod->srcpad)) { if (GST_PAD_LINK_SUCCESSFUL (gst_pad_renegotiate (mikmod->srcpad))) { GST_ELEMENT_ERROR (mikmod, CORE, NEGOTIATION, (NULL), (NULL)); return; } } MikMod_RegisterDriver (&drv_gst); MikMod_RegisterAllLoaders (); MikMod_Init (""); reader = GST_READER_new (mikmod); module = Player_LoadGeneric (reader, 64, 0); gst_buffer_unref (mikmod->Buffer); if (!Player_Active ()) Player_Start (module); mikmod->initialized = TRUE; } if (Player_Active ()) { timestamp = (module->sngtime / 1024.0) * GST_SECOND; drv_gst.Update (); } else { gst_element_set_eos (GST_ELEMENT (mikmod)); gst_pad_push (mikmod->srcpad, GST_DATA (gst_event_new (GST_EVENT_EOS))); } }
static void setup_test_objects (struct TestData *td, GstPadChainFunction chain_func, GstPadBufferAllocFunction alloc_func) { td->mycaps = gst_caps_new_simple ("test/test", NULL); td->funnel = gst_element_factory_make ("fsfunnel", NULL); td->funnelsrc = gst_element_get_static_pad (td->funnel, "src"); fail_unless (td->funnelsrc != NULL); td->funnelsink11 = gst_element_get_request_pad (td->funnel, "sink11"); fail_unless (td->funnelsink11 != NULL); fail_unless (!strcmp (GST_OBJECT_NAME (td->funnelsink11), "sink11")); td->funnelsink22 = gst_element_get_request_pad (td->funnel, "sink22"); fail_unless (td->funnelsink22 != NULL); fail_unless (!strcmp (GST_OBJECT_NAME (td->funnelsink22), "sink22")); fail_unless (gst_element_set_state (td->funnel, GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS); td->mysink = gst_pad_new ("sink", GST_PAD_SINK); gst_pad_set_chain_function (td->mysink, chain_func); gst_pad_set_bufferalloc_function (td->mysink, alloc_func); gst_pad_set_active (td->mysink, TRUE); gst_pad_set_caps (td->mysink, td->mycaps); td->mysrc1 = gst_pad_new ("src1", GST_PAD_SRC); gst_pad_set_active (td->mysrc1, TRUE); gst_pad_set_caps (td->mysrc1, td->mycaps); td->mysrc2 = gst_pad_new ("src2", GST_PAD_SRC); gst_pad_set_active (td->mysrc2, TRUE); gst_pad_set_caps (td->mysrc2, td->mycaps); fail_unless (GST_PAD_LINK_SUCCESSFUL( gst_pad_link (td->funnelsrc, td->mysink))); fail_unless (GST_PAD_LINK_SUCCESSFUL( gst_pad_link (td->mysrc1, td->funnelsink11))); fail_unless (GST_PAD_LINK_SUCCESSFUL( gst_pad_link (td->mysrc2, td->funnelsink22))); }
static void setup_test_objects (struct TestData *td, GstPadChainFunction chain_func) { td->mycaps = gst_caps_new_empty_simple ("test/test"); td->funnel = gst_element_factory_make ("funnel", NULL); td->funnelsrc = gst_element_get_static_pad (td->funnel, "src"); fail_unless (td->funnelsrc != NULL); td->funnelsink11 = gst_element_get_request_pad (td->funnel, "sink_11"); fail_unless (td->funnelsink11 != NULL); fail_unless (!strcmp (GST_OBJECT_NAME (td->funnelsink11), "sink_11")); td->funnelsink22 = gst_element_get_request_pad (td->funnel, "sink_22"); fail_unless (td->funnelsink22 != NULL); fail_unless (!strcmp (GST_OBJECT_NAME (td->funnelsink22), "sink_22")); fail_unless (gst_element_set_state (td->funnel, GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS); td->mysink = gst_pad_new ("sink", GST_PAD_SINK); gst_pad_set_chain_function (td->mysink, chain_func); gst_pad_set_active (td->mysink, TRUE); td->mysrc1 = gst_pad_new ("src1", GST_PAD_SRC); gst_pad_set_active (td->mysrc1, TRUE); gst_check_setup_events_with_stream_id (td->mysrc1, td->funnel, td->mycaps, GST_FORMAT_BYTES, "test1"); td->mysrc2 = gst_pad_new ("src2", GST_PAD_SRC); gst_pad_set_active (td->mysrc2, TRUE); gst_check_setup_events_with_stream_id (td->mysrc2, td->funnel, td->mycaps, GST_FORMAT_BYTES, "test2"); fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (td->funnelsrc, td->mysink))); fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (td->mysrc1, td->funnelsink11))); fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (td->mysrc2, td->funnelsink22))); }
static void pad_added_cb (GstElement * decodebin, GstPad * pad, PlayState * state) { GstPadLinkReturn ret; GstElement *fakesink; GstPad *fakesink_pad; StreamInfo *si; fakesink = gst_element_factory_make ("fakesink", NULL); #if 0 if (state->n_sinks == 1) g_object_set (fakesink, "silent", FALSE, NULL); #endif si = g_new0 (StreamInfo, 1); si->pad = g_object_ref (pad); si->state = state; si->fwd_times = g_array_new (FALSE, TRUE, sizeof (StreamTSRange)); si->bkwd_times = g_array_new (FALSE, TRUE, sizeof (StreamTSRange)); gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM, (GstPadProbeCallback) handle_output, si, (GDestroyNotify) _destroy_stream_info); state->n_sinks++; gst_bin_add (GST_BIN (state->pipe), fakesink); gst_element_sync_state_with_parent (fakesink); fakesink_pad = gst_element_get_static_pad (fakesink, "sink"); ret = gst_pad_link (pad, fakesink_pad); if (!GST_PAD_LINK_SUCCESSFUL (ret)) { g_printerr ("Failed to link %s:%s to %s:%s (ret = %d)\n", GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (fakesink_pad), ret); } else { GstCaps *caps = gst_pad_get_current_caps (pad); gchar *s = gst_caps_to_string (caps); g_print ("Linked %s:%s to %s:%s caps %s\n", GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (fakesink_pad), s); gst_caps_unref (caps); g_free (s); } gst_object_unref (fakesink_pad); }
static void test_pipeline (const char *pipeline) { GstElement *bin, *sink; GstPad *pad, *sinkpad; GstBus *bus; GError *error = NULL; GMainLoop *loop; GstPadLinkReturn linkret; bin = gst_parse_launch (pipeline, &error); fail_unless (bin != NULL, "Error parsing pipeline: %s", error ? error->message : "(invalid error)"); pad = gst_bin_find_unlinked_pad (GST_BIN (bin), GST_PAD_SRC); fail_unless (pad != NULL, "Could not locate free src pad"); /* connect the fake sink */ sink = gst_element_factory_make ("fakesink", "fake_sink"); fail_unless (sink != NULL, "Could create fakesink"); fail_unless (gst_bin_add (GST_BIN (bin), sink), "Could not insert fakesink"); sinkpad = gst_element_get_static_pad (sink, "sink"); fail_unless (sinkpad != NULL, "Could not get fakesink src pad"); linkret = gst_pad_link (pad, sinkpad); fail_unless (GST_PAD_LINK_SUCCESSFUL (linkret), "Could not link to fake sink"); gst_object_unref (sinkpad); /* run until we receive EOS */ loop = g_main_loop_new (NULL, FALSE); bus = gst_element_get_bus (bin); gst_bus_add_watch (bus, (GstBusFunc) eos_watch, loop); gst_object_unref (bus); start_pipeline (bin, pad); g_main_loop_run (loop); stop_pipeline (bin, pad); /* clean up */ g_main_loop_unref (loop); gst_object_unref (pad); gst_object_unref (bin); }
static void pad_added_cb (GstElement * timeline, GstPad * pad, GstElement * scale) { GstPad *sinkpad; GstPadLinkReturn ret; sinkpad = gst_element_get_static_pad (scale, "sink"); if (sinkpad) { GST_DEBUG ("got sink pad, trying to link"); ret = gst_pad_link (pad, sinkpad); gst_object_unref (sinkpad); if (GST_PAD_LINK_SUCCESSFUL (ret)) { GST_DEBUG ("linked ok, returning"); return; } } GST_DEBUG ("pad failed to link properly"); }
static gboolean gst_median_link (GstPad * pad, const GstCaps * caps) { GstMedian *filter = GST_MEDIAN (gst_pad_get_parent (pad)); GstPad *otherpad = (pad == filter->srcpad) ? filter->sinkpad : filter->srcpad; GstStructure *structure = gst_caps_get_structure (caps, 0); gint w, h; GstPadLinkReturn ret; gst_structure_get_int (structure, "width", &w); gst_structure_get_int (structure, "height", &h); ret = gst_pad_try_set_caps (otherpad, caps); if (GST_PAD_LINK_SUCCESSFUL (ret)) { filter->width = w; filter->height = h; } gst_object_unref (filter); return ret; }
static void pad_added_cb (GstElement * element, GstPad * pad, gint * n_added) { App *app = &s_app; GstPad *sinkpad = NULL; GstPad *target = NULL; if (app->fakesink[*n_added] != NULL) { sinkpad = gst_element_get_static_pad (app->fakesink[*n_added], "sink"); fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (pad, sinkpad))); gst_object_unref (sinkpad); target = gst_ghost_pad_get_target (GST_GHOST_PAD (pad)); fail_unless (target != NULL); gst_pad_add_probe (target, GST_PAD_PROBE_TYPE_EVENT_UPSTREAM, _appsrc_event_probe, GST_PAD_PARENT (target), NULL); gst_object_unref (target); } *n_added = *n_added + 1; }
static void src_pad_added_cb (FsStream *self, GstPad *pad, FsCodec *codec, GstElement *pipeline) { GstElement *sink; GstPad *sinkpad; sink = gst_element_factory_make ("fakesink", NULL); g_object_set (sink, "sync", TRUE, "signal-handoffs", TRUE, NULL); g_signal_connect (sink, "handoff", G_CALLBACK (handoff_handler), NULL); fail_unless (gst_bin_add (GST_BIN (pipeline), sink)); gst_element_set_state (sink, GST_STATE_PLAYING); sinkpad = gst_element_get_static_pad (sink, "sink"); fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (pad, sinkpad))); gst_object_unref (sinkpad); GST_DEBUG ("Pad added"); }
int configureAVElement (GstPad* pad, GstElement *element) { int linked = 0; GstPad* sinkpad = gst_element_get_static_pad (element, "sink"); if(!GST_PAD_IS_LINKED(sinkpad)) { linked = GST_PAD_LINK_SUCCESSFUL(gst_pad_link (pad, sinkpad)); if (!linked) { g_print ("Gstreamer: Failed to link demux and AV decoders\n"); } else { g_print("Configured Audio/Video \n"); } } else g_print("Already linked\n"); gst_object_unref (sinkpad); return linked; }
//static void MediaParserGst::cb_pad_added(GstElement* /* element */, GstPad* new_pad, gpointer data) { MediaParserGst* parser = static_cast<MediaParserGst*>(data); GstCaps* caps = gst_pad_get_caps(new_pad); print_caps(caps); GstStructure* str = gst_caps_get_structure (caps, 0); if (!str) { log_error(_("MediaParserGst: couldn't get structure name.")); parser->link_to_fakesink(new_pad); return; } const gchar* caps_name = gst_structure_get_name (str); bool media_type_audio; if (std::equal(caps_name, caps_name+5, "audio")) { media_type_audio = true; } else if (std::equal(caps_name, caps_name+5, "video")) { media_type_audio = false; } else { log_error(_("MediaParserGst: ignoring stream of type %s."), caps_name); parser->link_to_fakesink(new_pad); return; } gboolean parsed = false; gboolean framed = false; gst_structure_get_boolean(str, "parsed", &parsed); gst_structure_get_boolean(str, "framed", &framed); bool already_parsed = parsed || framed; GstPad* final_pad = 0; if (already_parsed) { final_pad = new_pad; } else { // We'll try to find a parser, so that we will eventually receive // timestamped buffers, on which the MediaParser system relies. GstElementFactory* parserfactory = swfdec_gst_get_parser_factory (caps); if (!parserfactory) { log_error(_("MediaParserGst: Failed to find a parser (media: %s)."), caps_name); parser->link_to_fakesink(new_pad); return; } GstElement* parserel = gst_element_factory_create (parserfactory, NULL); gst_object_unref (parserfactory); if (!parserel) { log_error(_("MediaParserGst: Failed to find a parser. We'll continue, " "but either audio or video will not work!")); parser->link_to_fakesink(new_pad); return; } gboolean success = gst_bin_add(GST_BIN(parser->_bin), parserel); if (!success) { gst_object_unref(parserel); log_error(_("MediaParserGst: couldn't add parser.")); parser->link_to_fakesink(new_pad); return; } GstPad* sinkpad = gst_element_get_static_pad (parserel, "sink"); assert(sinkpad); GstPadLinkReturn ret = gst_pad_link(new_pad, sinkpad); gst_object_unref(GST_OBJECT(sinkpad)); if (!GST_PAD_LINK_SUCCESSFUL(ret)) { log_error(_("MediaParserGst: couldn't link parser.")); parser->link_to_fakesink(new_pad); return; } final_pad = gst_element_get_static_pad (parserel, "src"); } if (media_type_audio) { parser->_audiosink = swfdec_gst_connect_sinkpad_by_pad (final_pad, caps); if (!parser->_audiosink) { log_error(_("MediaParserGst: couldn't link \"fake\" sink.")); return; } gst_pad_set_chain_function(parser->_audiosink, MediaParserGst::cb_chain_func_audio); g_object_set_data(G_OBJECT (parser->_audiosink), "mediaparser-obj", parser); LOG_ONCE( log_unimpl("MediaParserGst won't set codec, sampleRate, " "sampleSize, stereo and duration in AudioInfo"); ); AudioInfo* audioinfo = new AudioInfo(0, 0, 0, false, 0, CODEC_TYPE_CUSTOM); audioinfo->extra.reset(new ExtraInfoGst(caps)); parser->_audioInfo.reset(audioinfo); log_debug(_("MediaParserGst: Linked audio source (type: %s)"), caps_name); } else {
static gboolean gst_goo_encjpeg_setcaps (GstPad* pad, GstCaps* caps) { GstGooEncJpeg* self = GST_GOO_ENCJPEG (gst_pad_get_parent (pad)); GstGooEncJpegPrivate* priv = GST_GOO_ENCJPEG_GET_PRIVATE (self); GstStructure* structure; const GValue* framerate; guint32 fourcc; GstPad* otherpad; GstCaps* othercaps; gboolean ret; otherpad = (pad == self->srcpad) ? self->sinkpad : self->srcpad; othercaps = gst_caps_copy (gst_pad_get_pad_template_caps (otherpad)); structure = gst_caps_get_structure (caps, 0); gst_structure_get_int (structure, "width", &priv->width); gst_structure_get_int (structure, "height", &priv->height); gst_structure_get_fourcc (structure, "format", &fourcc); switch (fourcc) { case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'): priv->colorformat = OMX_COLOR_FormatCbYCrY; break; case GST_MAKE_FOURCC ('I', '4', '2', '0'): priv->colorformat = OMX_COLOR_FormatYUV420PackedPlanar; break; default: GST_ERROR ("format not supported"); return FALSE; } g_object_set (self->component, "width", priv->width, NULL); g_object_set (self->component, "height", priv->height, NULL); priv->omxbufsiz = (priv->colorformat == OMX_COLOR_FormatCbYCrY) ? priv->width * priv->height * 2 : priv->width * priv->height * 1.5; framerate = gst_structure_get_value (structure, "framerate"); if (G_LIKELY (framerate)) { gst_caps_set_simple (othercaps, "width", G_TYPE_INT, priv->width, "height", G_TYPE_INT, priv->height, "framerate", GST_TYPE_FRACTION, gst_value_get_fraction_numerator (framerate), gst_value_get_fraction_denominator (framerate), NULL); } else { gst_caps_set_simple (othercaps, "width", G_TYPE_INT, priv->width, "height", G_TYPE_INT, priv->height, NULL); } ret = gst_pad_set_caps (self->srcpad, othercaps); gst_caps_unref (othercaps); if (GST_PAD_LINK_SUCCESSFUL (ret) && goo_component_get_state (self->component) == OMX_StateLoaded) { omx_start (self); } gst_object_unref (self); return ret; }
static TestSession* add_audio_session (GstElement *pipeline, FsConference *conf, guint id, FsParticipant *part, gchar *send_socket, gchar *recv_socket) { TestSession *ses = g_slice_new0 (TestSession); GError *error = NULL; GstPad *pad = NULL, *pad2 = NULL; GstElement *src = NULL; GList *cands = NULL; GParameter param = {0}; gboolean res; FsCandidate *cand; GList *codecs = NULL; ses->send_socket = send_socket; ses->recv_socket = recv_socket; ses->session = fs_conference_new_session (conf, FS_MEDIA_TYPE_AUDIO, &error); print_error (error); g_assert (ses->session); g_object_get (ses->session, "sink-pad", &pad, NULL); if (g_getenv ("AUDIOSRC")) src = gst_parse_bin_from_description (g_getenv ("AUDIOSRC"), TRUE, &error); else src = gst_parse_bin_from_description (DEFAULT_AUDIOSRC, TRUE, &error); print_error (error); g_assert (src); g_assert (gst_bin_add (GST_BIN (pipeline), src)); pad2 = gst_element_get_static_pad (src, "src"); g_assert (pad2); g_assert (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (pad2, pad))); gst_object_unref (pad2); gst_object_unref (pad); ses->stream = fs_session_new_stream (ses->session, part, FS_DIRECTION_BOTH, &error); print_error (error); g_assert (ses->stream); cand = fs_candidate_new ("", FS_COMPONENT_RTP, FS_CANDIDATE_TYPE_HOST, FS_NETWORK_PROTOCOL_UDP, send_socket, 0); cands = g_list_prepend (NULL, cand); param.name = "preferred-local-candidates"; g_value_init (¶m.value, FS_TYPE_CANDIDATE_LIST); g_value_take_boxed (¶m.value, cands); res = fs_stream_set_transmitter (ses->stream, "shm", ¶m, 1, &error); print_error (error); g_value_unset (¶m.value); g_signal_connect (ses->stream, "src-pad-added", G_CALLBACK (src_pad_added_cb), pipeline); codecs = g_list_prepend (NULL, fs_codec_new (FS_CODEC_ID_ANY, "PCMA", FS_MEDIA_TYPE_AUDIO, 0)); codecs = g_list_prepend (codecs, fs_codec_new (FS_CODEC_ID_ANY, "PCMU", FS_MEDIA_TYPE_AUDIO, 0)); res = fs_session_set_codec_preferences (ses->session, codecs, &error); print_error (error); fs_codec_list_destroy (codecs); g_object_get (ses->session, "codecs-without-config", &codecs, NULL); res = fs_stream_set_remote_codecs (ses->stream, codecs, &error); print_error (error); g_assert (res); return ses; }
static void gst_insert_bin_do_change (GstInsertBin * self, GstPad * pad) { struct ChangeData *data; GST_OBJECT_LOCK (self); if (!is_right_direction_for_block (pad)) { GST_WARNING_OBJECT (self, "Block pad does not have the expected direction"); goto next; } while ((data = g_queue_pop_head (&self->priv->change_queue)) != NULL) { GstPad *peer = NULL; GstPad *other_peer = NULL; GST_OBJECT_UNLOCK (self); if (data->action == GST_INSERT_BIN_ACTION_ADD && !validate_element (self, data->element)) goto error; peer = gst_pad_get_peer (pad); if (peer == NULL) { GST_WARNING_OBJECT (self, "Blocked pad has no peer"); goto error; } if (data->action == GST_INSERT_BIN_ACTION_ADD) { GstPad *srcpad = NULL, *sinkpad = NULL; GstPad *peersrcpad, *peersinkpad; /* First let's make sure we have the right pad */ if (data->sibling) { GstElement *parent = NULL; GstPad *siblingpad; if ((gst_pad_get_direction (pad) == GST_PAD_SRC && data->direction == DIRECTION_BEFORE) || (gst_pad_get_direction (pad) == GST_PAD_SINK && data->direction == DIRECTION_AFTER)) siblingpad = peer; else siblingpad = pad; parent = gst_pad_get_parent_element (siblingpad); if (parent != NULL) gst_object_unref (parent); if (parent != data->sibling) goto retry; } else { GstObject *parent; GstPad *ghost; GstPad *proxypad; if (data->direction == DIRECTION_BEFORE) { ghost = self->priv->srcpad; if (gst_pad_get_direction (pad) == GST_PAD_SINK) proxypad = pad; else proxypad = peer; } else { ghost = self->priv->sinkpad; if (gst_pad_get_direction (pad) == GST_PAD_SINK) proxypad = peer; else proxypad = pad; } if (!GST_IS_PROXY_PAD (proxypad)) goto retry; parent = gst_pad_get_parent (proxypad); if (!parent) goto retry; gst_object_unref (parent); if (GST_PAD_CAST (parent) != ghost) goto retry; } if (gst_pad_get_direction (pad) == GST_PAD_SRC) { peersrcpad = pad; peersinkpad = peer; } else { peersrcpad = peer; peersinkpad = pad; } if (GST_IS_PROXY_PAD (peersrcpad)) { GstObject *parent = gst_pad_get_parent (peersrcpad); if (GST_PAD_CAST (parent) == self->priv->sinkpad) peersrcpad = NULL; if (parent) gst_object_unref (parent); } if (GST_IS_PROXY_PAD (peersinkpad)) { GstObject *parent = gst_pad_get_parent (peersinkpad); if (GST_PAD_CAST (parent) == self->priv->srcpad) peersinkpad = NULL; if (parent) gst_object_unref (parent); } if (peersinkpad && peersrcpad) { gst_pad_unlink (peersrcpad, peersinkpad); } else { if (!peersinkpad) gst_ghost_pad_set_target (GST_GHOST_PAD (self->priv->srcpad), NULL); if (!peersrcpad) gst_ghost_pad_set_target (GST_GHOST_PAD (self->priv->sinkpad), NULL); } srcpad = get_single_pad (data->element, GST_PAD_SRC); sinkpad = get_single_pad (data->element, GST_PAD_SINK); if (srcpad == NULL || sinkpad == NULL) { GST_WARNING_OBJECT (self, "Can not get element src or sink pad"); goto error; } if (!gst_bin_add (GST_BIN (self), data->element)) { GST_WARNING_OBJECT (self, "Can not add element to bin"); goto error; } if (peersrcpad) { if (GST_PAD_LINK_FAILED (gst_pad_link (peersrcpad, sinkpad))) { GST_WARNING_OBJECT (self, "Can not link sibling's %s:%s pad" " to element's %s:%s pad", GST_DEBUG_PAD_NAME (peersrcpad), GST_DEBUG_PAD_NAME (sinkpad)); goto error; } } else { if (!gst_ghost_pad_set_target (GST_GHOST_PAD (self->priv->sinkpad), sinkpad)) { GST_WARNING_OBJECT (self, "Can not set %s:%s as target for %s:%s", GST_DEBUG_PAD_NAME (sinkpad), GST_DEBUG_PAD_NAME (self->priv->sinkpad)); goto error; } } if (peersinkpad) { if (GST_PAD_LINK_FAILED (gst_pad_link (srcpad, peersinkpad))) { GST_WARNING_OBJECT (self, "Can not link element's %s:%s pad" " to sibling's %s:%s pad", GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (peersinkpad)); goto error; } } else { if (!gst_ghost_pad_set_target (GST_GHOST_PAD (self->priv->srcpad), srcpad)) { GST_WARNING_OBJECT (self, "Can not set %s:%s as target for %s:%s", GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (self->priv->srcpad)); goto error; } } gst_object_unref (srcpad); gst_object_unref (sinkpad); if (!gst_element_sync_state_with_parent (data->element)) { GST_WARNING_OBJECT (self, "Can not sync element's state with parent"); goto error; } } else { GstElement *parent = NULL; GstPad *other_pad; GstCaps *caps = NULL, *peercaps = NULL; gboolean can_intersect; gboolean success; parent = gst_pad_get_parent_element (peer); if (parent != NULL) gst_object_unref (parent); if (parent != data->element) goto retry; if (gst_pad_get_direction (peer) == GST_PAD_SRC) other_pad = get_single_pad (data->element, GST_PAD_SINK); else other_pad = get_single_pad (data->element, GST_PAD_SRC); if (!other_pad) { GST_WARNING_OBJECT (self, "Can not get element's other pad"); goto error; } other_peer = gst_pad_get_peer (other_pad); gst_object_unref (other_pad); if (!other_peer) { GST_WARNING_OBJECT (self, "Can not get element's other peer"); goto error; } /* Get the negotiated caps for the source pad peer, * because renegotiation while the pipeline is playing doesn't work * that fast. */ if (gst_pad_get_direction (pad) == GST_PAD_SRC) caps = gst_pad_get_current_caps (pad); else peercaps = gst_pad_get_current_caps (other_peer); if (!caps) caps = gst_pad_query_caps (pad, NULL); if (!peercaps) peercaps = gst_pad_query_caps (other_peer, NULL); can_intersect = gst_caps_can_intersect (caps, peercaps); gst_caps_unref (caps); gst_caps_unref (peercaps); if (!can_intersect) { GST_WARNING_OBJECT (self, "Pads are incompatible without the element"); goto error; } if (gst_pad_get_direction (other_peer) == GST_PAD_SRC && gst_pad_is_active (other_peer)) { gulong probe_id; probe_id = gst_pad_add_probe (other_peer, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, wait_and_drop_eos_cb, NULL, NULL); gst_pad_send_event (peer, gst_event_new_eos ()); gst_pad_remove_probe (other_peer, probe_id); } gst_element_set_locked_state (data->element, TRUE); gst_element_set_state (data->element, GST_STATE_NULL); if (!gst_bin_remove (GST_BIN (self), data->element)) { GST_WARNING_OBJECT (self, "Element removal rejected"); goto error; } gst_element_set_locked_state (data->element, FALSE); if (gst_pad_get_direction (pad) == GST_PAD_SRC) success = GST_PAD_LINK_SUCCESSFUL (gst_pad_link_full (pad, other_peer, GST_PAD_LINK_CHECK_HIERARCHY | GST_PAD_LINK_CHECK_TEMPLATE_CAPS)); else success = GST_PAD_LINK_SUCCESSFUL (gst_pad_link_full (other_peer, pad, GST_PAD_LINK_CHECK_HIERARCHY | GST_PAD_LINK_CHECK_TEMPLATE_CAPS)); gst_object_unref (other_peer); other_peer = NULL; if (!success) { GST_ERROR_OBJECT (self, "Could not re-link after the element's" " removal"); goto error; } } gst_insert_bin_change_data_complete (self, data, TRUE); gst_object_unref (peer); GST_OBJECT_LOCK (self); continue; done: if (other_peer != NULL) gst_object_unref (other_peer); if (peer != NULL) gst_object_unref (peer); break; retry: GST_OBJECT_LOCK (self); g_queue_push_head (&self->priv->change_queue, data); goto done; error: /* Handle error */ gst_insert_bin_change_data_complete (self, data, FALSE); GST_OBJECT_LOCK (self); goto done; } next: gst_insert_bin_block_pad_unlock (self); }
static void test_pipeline (const char *pipeline) { GstElement *bin, *sink; GstPad *pad, *sinkpad; GstBus *bus; GError *error = NULL; GMainLoop *loop; GstPadLinkReturn linkret; guint bus_watch = 0; bin = gst_parse_launch (pipeline, &error); fail_unless (bin != NULL, "Error parsing pipeline: %s", error ? error->message : "(invalid error)"); pad = gst_bin_find_unlinked_pad (GST_BIN (bin), GST_PAD_SRC); fail_unless (pad != NULL, "Could not locate free src pad"); /* connect the fake sink */ sink = gst_element_factory_make ("fakesink", "fake_sink"); fail_unless (sink != NULL, "Could create fakesink"); fail_unless (gst_bin_add (GST_BIN (bin), sink), "Could not insert fakesink"); sinkpad = gst_element_get_static_pad (sink, "sink"); fail_unless (sinkpad != NULL, "Could not get fakesink src pad"); linkret = gst_pad_link (pad, sinkpad); fail_unless (GST_PAD_LINK_SUCCESSFUL (linkret), "Could not link to fake sink"); gst_object_unref (sinkpad); /* run until we receive EOS */ loop = g_main_loop_new (NULL, FALSE); bus = gst_element_get_bus (bin); bus_watch = gst_bus_add_watch (bus, (GstBusFunc) eos_watch, loop); gst_object_unref (bus); start_pipeline (bin, pad); g_main_loop_run (loop); /* we're EOS now; make sure oggmux out caps have stream headers on them */ { GstStructure *s; GstCaps *muxcaps; muxcaps = gst_pad_get_negotiated_caps (sinkpad); fail_unless (muxcaps != NULL); s = gst_caps_get_structure (muxcaps, 0); fail_unless (gst_structure_has_name (s, "application/ogg")); fail_unless (gst_structure_has_field (s, "streamheader")); fail_unless (gst_structure_has_field_typed (s, "streamheader", GST_TYPE_ARRAY)); gst_caps_unref (muxcaps); } stop_pipeline (bin, pad); /* clean up */ g_main_loop_unref (loop); g_source_remove (bus_watch); gst_object_unref (pad); gst_object_unref (bin); }