void AudioFileReader::handleNewDeinterleavePad(GstPad* pad) { // A new pad for a planar channel was added in deinterleave. Plug // in an appsink so we can pull the data from each // channel. Pipeline looks like: // ... deinterleave ! queue ! appsink. GstElement* queue = gst_element_factory_make("queue", 0); GstElement* sink = gst_element_factory_make("appsink", 0); GstAppSinkCallbacks callbacks; callbacks.eos = 0; callbacks.new_preroll = 0; #ifdef GST_API_VERSION_1 callbacks.new_sample = onAppsinkPullRequiredCallback; #else callbacks.new_buffer_list = 0; callbacks.new_buffer = onAppsinkPullRequiredCallback; #endif gst_app_sink_set_callbacks(GST_APP_SINK(sink), &callbacks, this, 0); g_object_set(sink, "sync", FALSE, NULL); gst_bin_add_many(GST_BIN(m_pipeline), queue, sink, NULL); GstPad* sinkPad = gst_element_get_static_pad(queue, "sink"); gst_pad_link_full(pad, sinkPad, GST_PAD_LINK_CHECK_NOTHING); gst_object_unref(GST_OBJECT(sinkPad)); gst_element_link_pads_full(queue, "src", sink, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_set_state(queue, GST_STATE_READY); gst_element_set_state(sink, GST_STATE_READY); }
void AudioFileReader::decodeAudioForBusCreation() { // Build the pipeline (giostreamsrc | filesrc) ! decodebin2 // A deinterleave element is added once a src pad becomes available in decodebin. m_pipeline = gst_pipeline_new(0); GRefPtr<GstBus> bus = webkitGstPipelineGetBus(GST_PIPELINE(m_pipeline)); ASSERT(bus); gst_bus_add_signal_watch(bus.get()); g_signal_connect(bus.get(), "message", G_CALLBACK(messageCallback), this); GstElement* source; if (m_data) { ASSERT(m_dataSize); source = gst_element_factory_make("giostreamsrc", 0); GRefPtr<GInputStream> memoryStream = adoptGRef(g_memory_input_stream_new_from_data(m_data, m_dataSize, 0)); g_object_set(source, "stream", memoryStream.get(), NULL); } else { source = gst_element_factory_make("filesrc", 0); g_object_set(source, "location", m_filePath, NULL); } m_decodebin = gst_element_factory_make(gDecodebinName, "decodebin"); g_signal_connect(m_decodebin.get(), "pad-added", G_CALLBACK(onGStreamerDecodebinPadAddedCallback), this); gst_bin_add_many(GST_BIN(m_pipeline), source, m_decodebin.get(), NULL); gst_element_link_pads_full(source, "src", m_decodebin.get(), "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_set_state(m_pipeline, GST_STATE_PAUSED); }
/** * gst_camerabin_try_add_element: * @bin: tries adding an element to this bin * @srcpad: src pad name, or NULL for any * @new_elem: new element to be added * @dstpad: dst pad name, or NULL for any * * Adds given element to given @bin. Looks for an unconnected src pad * (with name @srcpad, if specified) from the @bin and links the element to * it. * * Returns: %TRUE if adding and linking succeeded, %FALSE otherwise. */ gboolean gst_camerabin_try_add_element (GstBin * bin, const gchar * srcpad, GstElement * new_elem, const gchar * dstpad) { GstPad *bin_pad; GstElement *bin_elem; gboolean ret = TRUE; g_return_val_if_fail (bin, FALSE); g_return_val_if_fail (new_elem, FALSE); /* Get pads for linking */ bin_pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SRC); /* Add to bin */ gst_bin_add (GST_BIN (bin), new_elem); /* Link, if unconnected pad was found, otherwise just add it to bin */ if (bin_pad) { GST_DEBUG_OBJECT (bin, "linking %s to %s:%s", GST_OBJECT_NAME (new_elem), GST_DEBUG_PAD_NAME (bin_pad)); bin_elem = gst_pad_get_parent_element (bin_pad); gst_object_unref (bin_pad); if (!gst_element_link_pads_full (bin_elem, srcpad, new_elem, dstpad, GST_PAD_LINK_CHECK_CAPS)) { gst_object_ref (new_elem); gst_bin_remove (bin, new_elem); ret = FALSE; } gst_object_unref (bin_elem); } else { GST_INFO_OBJECT (bin, "no unlinked source pad in bin"); } return ret; }
void composition_pad_added_cb (GstElement * composition, GstPad * pad, CollectStructure * collect) { fail_if (!(gst_element_link_pads_full (composition, GST_OBJECT_NAME (pad), collect->sink, "sink", GST_PAD_LINK_CHECK_NOTHING))); }
void AudioDestinationGStreamer::finishBuildingPipelineAfterWavParserPadReady(GstPad* pad) { ASSERT(m_wavParserAvailable); GRefPtr<GstElement> audioSink = gst_element_factory_make("autoaudiosink", 0); m_audioSinkAvailable = audioSink; if (!audioSink) { LOG_ERROR("Failed to create GStreamer autoaudiosink element"); return; } // Autoaudiosink does the real sink detection in the GST_STATE_NULL->READY transition // so it's best to roll it to READY as soon as possible to ensure the underlying platform // audiosink was loaded correctly. GstStateChangeReturn stateChangeReturn = gst_element_set_state(audioSink.get(), GST_STATE_READY); if (stateChangeReturn == GST_STATE_CHANGE_FAILURE) { LOG_ERROR("Failed to change autoaudiosink element state"); gst_element_set_state(audioSink.get(), GST_STATE_NULL); m_audioSinkAvailable = false; return; } GstElement* audioConvert = gst_element_factory_make("audioconvert", 0); gst_bin_add_many(GST_BIN(m_pipeline), audioConvert, audioSink.get(), NULL); // Link wavparse's src pad to audioconvert sink pad. GRefPtr<GstPad> sinkPad = adoptGRef(gst_element_get_static_pad(audioConvert, "sink")); gst_pad_link_full(pad, sinkPad.get(), GST_PAD_LINK_CHECK_NOTHING); // Link audioconvert to audiosink and roll states. gst_element_link_pads_full(audioConvert, "src", audioSink.get(), "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_sync_state_with_parent(audioConvert); gst_element_sync_state_with_parent(audioSink.leakRef()); }
AudioDestinationGStreamer::AudioDestinationGStreamer(AudioIOCallback& callback, float sampleRate) : m_callback(callback) , m_renderBus(AudioBus::create(2, framesToPull, false)) , m_sampleRate(sampleRate) , m_isPlaying(false) { m_pipeline = gst_pipeline_new("play"); GRefPtr<GstBus> bus = adoptGRef(gst_pipeline_get_bus(GST_PIPELINE(m_pipeline))); ASSERT(bus); gst_bus_add_signal_watch(bus.get()); g_signal_connect(bus.get(), "message", G_CALLBACK(messageCallback), this); GstElement* webkitAudioSrc = reinterpret_cast<GstElement*>(g_object_new(WEBKIT_TYPE_WEB_AUDIO_SRC, "rate", sampleRate, "bus", m_renderBus.get(), "provider", &m_callback, "frames", framesToPull, NULL)); GRefPtr<GstElement> audioSink = gst_element_factory_make("autoaudiosink", 0); m_audioSinkAvailable = audioSink; if (!audioSink) { LOG_ERROR("Failed to create GStreamer autoaudiosink element"); return; } // Autoaudiosink does the real sink detection in the GST_STATE_NULL->READY transition // so it's best to roll it to READY as soon as possible to ensure the underlying platform // audiosink was loaded correctly. GstStateChangeReturn stateChangeReturn = gst_element_set_state(audioSink.get(), GST_STATE_READY); if (stateChangeReturn == GST_STATE_CHANGE_FAILURE) { LOG_ERROR("Failed to change autoaudiosink element state"); gst_element_set_state(audioSink.get(), GST_STATE_NULL); m_audioSinkAvailable = false; return; } GstElement* audioConvert = gst_element_factory_make("audioconvert", 0); GstElement* audioResample = gst_element_factory_make("audioresample", 0); gst_bin_add_many(GST_BIN(m_pipeline), webkitAudioSrc, audioConvert, audioResample, audioSink.get(), NULL); // Link src pads from webkitAudioSrc to audioConvert ! audioResample ! autoaudiosink. gst_element_link_pads_full(webkitAudioSrc, "src", audioConvert, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full(audioConvert, "src", audioResample, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full(audioResample, "src", audioSink.get(), "sink", GST_PAD_LINK_CHECK_NOTHING); }
static GstElement * ges_title_source_create_source (GESTrackElement * object) { GstElement *topbin, *background, *text; GstPad *src, *pad; GESTitleSource *self = GES_TITLE_SOURCE (object); GESTitleSourcePrivate *priv = self->priv; const gchar *bg_props[] = { "pattern", "foreground-color", NULL }; const gchar *text_props[] = { "text", "font-desc", "valignment", "halignment", "color", "xpos", "ypos", "outline-color", "shaded-background", NULL }; topbin = gst_bin_new ("titlesrc-bin"); background = gst_element_factory_make ("videotestsrc", "titlesrc-bg"); text = gst_element_factory_make ("textoverlay", "titlsrc-text"); if (priv->text) { g_object_set (text, "text", priv->text, NULL); } if (priv->font_desc) { g_object_set (text, "font-desc", priv->font_desc, NULL); } g_object_set (text, "valignment", (gint) priv->valign, "halignment", (gint) priv->halign, NULL); g_object_set (text, "color", (guint) self->priv->color, NULL); g_object_set (text, "xpos", (gdouble) self->priv->xpos, NULL); g_object_set (text, "ypos", (gdouble) self->priv->ypos, NULL); g_object_set (background, "pattern", (gint) GES_VIDEO_TEST_PATTERN_SOLID, NULL); g_object_set (background, "foreground-color", (guint) self->priv->background, NULL); gst_bin_add_many (GST_BIN (topbin), background, text, NULL); gst_element_link_pads_full (background, "src", text, "video_sink", GST_PAD_LINK_CHECK_NOTHING); pad = gst_element_get_static_pad (text, "src"); src = gst_ghost_pad_new ("src", pad); gst_object_unref (pad); gst_element_add_pad (topbin, src); gst_object_ref (text); gst_object_ref (background); priv->text_el = text; priv->background_el = background; ges_track_element_add_children_props (object, text, NULL, NULL, text_props); ges_track_element_add_children_props (object, background, NULL, NULL, bg_props); return topbin; }
static gboolean activate_vpp (GstVaapiDecodeBin * vaapidecbin) { GstElement *src; if (vaapidecbin->ghost_pad_src || vaapidecbin->postproc) return TRUE; if (!vaapidecbin->has_vpp || vaapidecbin->disable_vpp) { src = vaapidecbin->queue; goto connect_src_ghost_pad; } /* create the postproc */ vaapidecbin->postproc = gst_element_factory_make ("vaapipostproc", "vaapipostproc"); if (!vaapidecbin->postproc) goto error_element_missing; g_object_set (G_OBJECT (vaapidecbin->postproc), "deinterlace-method", vaapidecbin->deinterlace_method, NULL); gst_bin_add (GST_BIN (vaapidecbin), vaapidecbin->postproc); if (!gst_element_link_pads_full (vaapidecbin->queue, "src", vaapidecbin->postproc, "sink", GST_PAD_LINK_CHECK_NOTHING)) goto error_link_pad; GST_DEBUG_OBJECT (vaapidecbin, "Enabling VPP"); src = vaapidecbin->postproc; goto connect_src_ghost_pad; error_element_missing: { post_missing_element_message (vaapidecbin, "vaapipostproc"); return FALSE; } error_link_pad: { GST_ERROR_OBJECT (vaapidecbin, "Failed to link the child elements"); return FALSE; } connect_src_ghost_pad: { GstPad *srcpad, *ghostpad; srcpad = gst_element_get_static_pad (src, "src"); ghostpad = gst_ghost_pad_new ("src", srcpad); vaapidecbin->ghost_pad_src = ghostpad; gst_object_unref (srcpad); gst_element_add_pad (GST_ELEMENT (vaapidecbin), ghostpad); return TRUE; } }
void AudioFileReader::plugDeinterleave(GstPad* pad) { // Ignore any additional source pads just in case. if (m_deInterleave) return; // A decodebin pad was added, plug in a deinterleave element to // separate each planar channel. Sub pipeline looks like // ... decodebin2 ! audioconvert ! audioresample ! capsfilter ! deinterleave. GstElement* audioConvert = gst_element_factory_make("audioconvert", 0); GstElement* audioResample = gst_element_factory_make("audioresample", 0); GstElement* capsFilter = gst_element_factory_make("capsfilter", 0); m_deInterleave = gst_element_factory_make("deinterleave", "deinterleave"); g_object_set(m_deInterleave.get(), "keep-positions", TRUE, NULL); g_signal_connect(m_deInterleave.get(), "pad-added", G_CALLBACK(onGStreamerDeinterleavePadAddedCallback), this); g_signal_connect(m_deInterleave.get(), "no-more-pads", G_CALLBACK(onGStreamerDeinterleaveReadyCallback), this); GstCaps* caps = gst_caps_new_simple("audio/x-raw", "rate", G_TYPE_INT, static_cast<int>(m_sampleRate), "channels", G_TYPE_INT, m_channels, "format", G_TYPE_STRING, GST_AUDIO_NE(F32), "layout", G_TYPE_STRING, "interleaved", nullptr); g_object_set(capsFilter, "caps", caps, NULL); gst_caps_unref(caps); gst_bin_add_many(GST_BIN(m_pipeline), audioConvert, audioResample, capsFilter, m_deInterleave.get(), NULL); GstPad* sinkPad = gst_element_get_static_pad(audioConvert, "sink"); gst_pad_link_full(pad, sinkPad, GST_PAD_LINK_CHECK_NOTHING); gst_object_unref(GST_OBJECT(sinkPad)); gst_element_link_pads_full(audioConvert, "src", audioResample, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full(audioResample, "src", capsFilter, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full(capsFilter, "src", m_deInterleave.get(), "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_sync_state_with_parent(audioConvert); gst_element_sync_state_with_parent(audioResample); gst_element_sync_state_with_parent(capsFilter); gst_element_sync_state_with_parent(m_deInterleave.get()); }
static GstElement * ges_multi_file_source_create_source (GESTrackElement * track_element) { GESMultiFileSource *self; GstElement *bin, *src, *decodebin; GstCaps *disc_caps; GstDiscovererStreamInfo *stream_info; GValue fps = G_VALUE_INIT; GstCaps *caps; GESUriSourceAsset *asset; GESMultiFileURI *uri_data; self = (GESMultiFileSource *) track_element; asset = GES_URI_SOURCE_ASSET (ges_extractable_get_asset (GES_EXTRACTABLE (self))); if (asset != NULL) { stream_info = ges_uri_source_asset_get_stream_info (asset); g_assert (stream_info); disc_caps = gst_discoverer_stream_info_get_caps (stream_info); caps = gst_caps_copy (disc_caps); GST_DEBUG ("Got some nice caps %s", gst_caps_to_string (disc_caps)); gst_object_unref (stream_info); gst_caps_unref (disc_caps); } else { caps = gst_caps_new_empty (); GST_WARNING ("Could not extract asset."); } g_value_init (&fps, GST_TYPE_FRACTION); gst_value_set_fraction (&fps, 25, 1); gst_caps_set_value (caps, "framerate", &fps); bin = GST_ELEMENT (gst_bin_new ("multi-image-bin")); src = gst_element_factory_make ("multifilesrc", NULL); uri_data = ges_multi_file_uri_new (self->uri); g_object_set (src, "start-index", uri_data->start, "stop-index", uri_data->end, "caps", caps, "location", uri_data->location, NULL); g_free (uri_data); decodebin = gst_element_factory_make ("decodebin", NULL); gst_bin_add_many (GST_BIN (bin), src, decodebin, NULL); gst_element_link_pads_full (src, "src", decodebin, "sink", GST_PAD_LINK_CHECK_NOTHING); g_signal_connect (G_OBJECT (decodebin), "pad-added", G_CALLBACK (pad_added_cb), bin); return bin; }
static gboolean create_node (GstBin * bin, GstElement * sink, const gchar * sinkpadname, GstElement ** new_sink, gint children, gint flavour) { GstElement *mix, *proc, *conv; if (children >= 1) { mix = gst_element_factory_make (factories[flavour][ELEM_MIX], NULL); if (!mix) { GST_WARNING ("need element '%s'", factories[flavour][ELEM_MIX]); return FALSE; } } else { mix = gst_element_factory_make ("identity", NULL); } proc = gst_element_factory_make (factories[flavour][ELEM_PROC], NULL); if (!proc) { GST_WARNING ("need element '%s'", factories[flavour][ELEM_PROC]); return FALSE; } conv = gst_element_factory_make (factories[flavour][ELEM_CONV], NULL); if (!conv) { GST_WARNING ("need element '%s'", factories[flavour][ELEM_CONV]); return FALSE; } gst_bin_add_many (bin, mix, proc, conv, NULL); if (!gst_element_link_pads_full (mix, "src", proc, "sink", GST_PAD_LINK_CHECK_NOTHING) || !gst_element_link_pads_full (proc, "src", conv, "sink", GST_PAD_LINK_CHECK_NOTHING) || !gst_element_link_pads_full (conv, "src", sink, sinkpadname, GST_PAD_LINK_CHECK_NOTHING)) { GST_WARNING ("can't link elements"); return FALSE; } *new_sink = mix; return TRUE; }
static GstElement * ges_image_source_create_source (GESTrackElement * track_element) { GstElement *bin, *source, *scale, *freeze, *iconv; GstPad *src, *target; bin = GST_ELEMENT (gst_bin_new ("still-image-bin")); source = gst_element_factory_make ("uridecodebin", NULL); scale = gst_element_factory_make ("videoscale", NULL); freeze = gst_element_factory_make ("imagefreeze", NULL); iconv = gst_element_factory_make ("videoconvert", NULL); g_object_set (scale, "add-borders", TRUE, NULL); gst_bin_add_many (GST_BIN (bin), source, scale, freeze, iconv, NULL); gst_element_link_pads_full (scale, "src", iconv, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full (iconv, "src", freeze, "sink", GST_PAD_LINK_CHECK_NOTHING); /* FIXME: add capsfilter here with sink caps (see 626518) */ target = gst_element_get_static_pad (freeze, "src"); src = gst_ghost_pad_new ("src", target); gst_element_add_pad (bin, src); gst_object_unref (target); g_object_set (source, "uri", ((GESImageSource *) track_element)->uri, NULL); g_signal_connect (G_OBJECT (source), "pad-added", G_CALLBACK (pad_added_cb), scale); return bin; }
static gboolean gst_vaapi_decode_bin_configure (GstVaapiDecodeBin * vaapidecbin) { gchar *missing_factory = NULL; /* create the decoder */ vaapidecbin->decoder = gst_element_factory_make ("vaapidecode", "vaapidecode"); if (!vaapidecbin->decoder) { missing_factory = "vaapidecode"; goto error_element_missing; } /* create the queue */ vaapidecbin->queue = gst_element_factory_make ("queue", "queue"); if (!vaapidecbin->queue) { missing_factory = "queue"; goto error_element_missing; } g_object_set (G_OBJECT (vaapidecbin->queue), "max-size-bytes", vaapidecbin->max_size_bytes, "max-size-buffers", vaapidecbin->max_size_buffers, "max-size-time", vaapidecbin->max_size_time, NULL); gst_bin_add_many (GST_BIN (vaapidecbin), vaapidecbin->decoder, vaapidecbin->queue, NULL); if (!gst_element_link_pads_full (vaapidecbin->decoder, "src", vaapidecbin->queue, "sink", GST_PAD_LINK_CHECK_NOTHING)) goto error_link_pad; return TRUE; error_element_missing: { post_missing_element_message (vaapidecbin, missing_factory); return FALSE; } error_link_pad: { GST_ERROR_OBJECT (vaapidecbin, "Failed to link the child elements"); return FALSE; } }
static GstElement * ges_track_title_source_create_element (GESTrackObject * object) { GESTrackTitleSource *self = GES_TRACK_TITLE_SOURCE (object); GESTrackTitleSourcePrivate *priv = self->priv; GstElement *topbin, *background, *text; GstPad *src; topbin = gst_bin_new ("titlesrc-bin"); background = gst_element_factory_make ("videotestsrc", "titlesrc-bg"); text = gst_element_factory_make ("textoverlay", "titlsrc-text"); if (priv->text) { g_object_set (text, "text", priv->text, NULL); } if (priv->font_desc) { g_object_set (text, "font-desc", priv->font_desc, NULL); } g_object_set (text, "valignment", (gint) priv->valign, "halignment", (gint) priv->halign, NULL); g_object_set (background, "pattern", (gint) GES_VIDEO_TEST_PATTERN_BLACK, NULL); g_object_set (text, "color", (guint) self->priv->color, NULL); g_object_set (text, "xpos", (gdouble) self->priv->xpos, NULL); g_object_set (text, "ypos", (gdouble) self->priv->ypos, NULL); gst_bin_add_many (GST_BIN (topbin), background, text, NULL); gst_element_link_pads_full (background, "src", text, "video_sink", GST_PAD_LINK_CHECK_NOTHING); src = gst_ghost_pad_new ("src", gst_element_get_static_pad (text, "src")); gst_element_add_pad (topbin, src); g_object_ref (text); g_object_ref (background); priv->text_el = text; priv->background_el = background; return topbin; }
void AudioSourceProviderGStreamer::configureAudioBin(GstElement* audioBin, GstElement* teePredecessor) { m_audioSinkBin = audioBin; GstElement* audioTee = gst_element_factory_make("tee", "audioTee"); GstElement* audioQueue = gst_element_factory_make("queue", 0); GstElement* audioConvert = gst_element_factory_make("audioconvert", 0); GstElement* audioConvert2 = gst_element_factory_make("audioconvert", 0); GstElement* audioResample = gst_element_factory_make("audioresample", 0); GstElement* audioResample2 = gst_element_factory_make("audioresample", 0); GstElement* volumeElement = gst_element_factory_make("volume", "volume"); GstElement* audioSink = gst_element_factory_make("autoaudiosink", 0); gst_bin_add_many(GST_BIN(m_audioSinkBin.get()), audioTee, audioQueue, audioConvert, audioResample, volumeElement, audioConvert2, audioResample2, audioSink, nullptr); // In cases where the audio-sink needs elements before tee (such // as scaletempo) they need to be linked to tee which in this case // doesn't need a ghost pad. It is assumed that the teePredecessor // chain already configured a ghost pad. if (teePredecessor) gst_element_link_pads_full(teePredecessor, "src", audioTee, "sink", GST_PAD_LINK_CHECK_NOTHING); else { // Add a ghostpad to the bin so it can proxy to tee. GRefPtr<GstPad> audioTeeSinkPad = adoptGRef(gst_element_get_static_pad(audioTee, "sink")); gst_element_add_pad(m_audioSinkBin.get(), gst_ghost_pad_new("sink", audioTeeSinkPad.get())); } // Link a new src pad from tee to queue ! audioconvert ! // audioresample ! volume ! audioconvert ! audioresample ! // autoaudiosink. The audioresample and audioconvert are needed to // ensure the audio sink receives buffers in the correct format. gst_element_link_pads_full(audioTee, "src_%u", audioQueue, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full(audioQueue, "src", audioConvert, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full(audioConvert, "src", audioResample, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full(audioResample, "src", volumeElement, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full(volumeElement, "src", audioConvert2, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full(audioConvert2, "src", audioResample2, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full(audioResample2, "src", audioSink, "sink", GST_PAD_LINK_CHECK_NOTHING); }
void AudioLiveInputPipeline::handleNewDeinterleavePad(GstPad* pad) { // A new pad for a planar channel was added in deinterleave. // Plug in an appsink so we can pull the data from each channel. // Pipeline looks like: // ... deinterleave ! appsink. GstElement* queue = gst_element_factory_make("queue", nullptr); GstElement* sink = gst_element_factory_make("appsink", nullptr); gst_bin_add_many(GST_BIN(m_pipeline), queue, sink, nullptr); GstPad* sinkPad = gst_element_get_static_pad(queue, "sink"); gst_pad_link_full(pad, sinkPad, GST_PAD_LINK_CHECK_NOTHING); gst_object_unref(GST_OBJECT(sinkPad)); gst_element_link_pads_full(queue, "src", sink, "sink", GST_PAD_LINK_CHECK_NOTHING); m_sinkList = g_slist_prepend(m_sinkList, sink); gst_element_sync_state_with_parent(queue); gst_element_sync_state_with_parent(sink); }
GstElement * audiotest_bin_src (const gchar * name, guint64 start, gint64 duration, guint priority, gboolean intaudio) { GstElement *source = NULL; GstElement *identity = NULL; GstElement *audiotestsrc = NULL; GstElement *audioconvert = NULL; GstElement *bin = NULL; GstCaps *caps; GstPad *srcpad = NULL; audiotestsrc = gst_element_factory_make_or_warn ("audiotestsrc", NULL); identity = gst_element_factory_make_or_warn ("identity", NULL); bin = gst_bin_new (NULL); source = new_nle_src (name, start, duration, priority); audioconvert = gst_element_factory_make_or_warn ("audioconvert", NULL); if (intaudio) caps = gst_caps_from_string ("audio/x-raw,format=(string)S16LE"); else caps = gst_caps_from_string ("audio/x-raw,format=(string)F32LE"); gst_bin_add_many (GST_BIN (bin), audiotestsrc, audioconvert, identity, NULL); gst_element_link_pads_full (audiotestsrc, "src", audioconvert, "sink", GST_PAD_LINK_CHECK_NOTHING); fail_if ((gst_element_link_filtered (audioconvert, identity, caps)) != TRUE); gst_caps_unref (caps); gst_bin_add (GST_BIN (source), bin); srcpad = gst_element_get_static_pad (identity, "src"); gst_element_add_pad (bin, gst_ghost_pad_new ("src", srcpad)); gst_object_unref (srcpad); return source; }
AudioDestinationGStreamer::AudioDestinationGStreamer(AudioIOCallback& callback, float sampleRate) : m_callback(callback) , m_renderBus(2, framesToPull, false) , m_sampleRate(sampleRate) , m_isPlaying(false) { m_pipeline = gst_pipeline_new("play"); GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(m_pipeline)); ASSERT(bus); gst_bus_add_signal_watch(bus); g_signal_connect(bus, "message", G_CALLBACK(messageCallback), this); gst_object_unref(bus); GstElement* webkitAudioSrc = reinterpret_cast<GstElement*>(g_object_new(WEBKIT_TYPE_WEB_AUDIO_SRC, "rate", sampleRate, "bus", &m_renderBus, "provider", &m_callback, "frames", framesToPull, NULL)); GstElement* wavParser = gst_element_factory_make("wavparse", 0); m_wavParserAvailable = wavParser; ASSERT_WITH_MESSAGE(m_wavParserAvailable, "Failed to create GStreamer wavparse element"); if (!m_wavParserAvailable) return; #ifndef GST_API_VERSION_1 g_signal_connect(wavParser, "pad-added", G_CALLBACK(onGStreamerWavparsePadAddedCallback), this); #endif gst_bin_add_many(GST_BIN(m_pipeline), webkitAudioSrc, wavParser, NULL); gst_element_link_pads_full(webkitAudioSrc, "src", wavParser, "sink", GST_PAD_LINK_CHECK_NOTHING); #ifdef GST_API_VERSION_1 GRefPtr<GstPad> srcPad = adoptGRef(gst_element_get_static_pad(wavParser, "src")); finishBuildingPipelineAfterWavParserPadReady(srcPad.get()); #endif }
void AudioFileReader::decodeAudioForBusCreation() { // Build the pipeline (giostreamsrc | filesrc) ! decodebin2 // A deinterleave element is added once a src pad becomes available in decodebin. m_pipeline = gst_pipeline_new(0); GRefPtr<GstBus> bus = adoptGRef(gst_pipeline_get_bus(GST_PIPELINE(m_pipeline))); ASSERT(bus); gst_bus_add_signal_watch(bus.get()); g_signal_connect(bus.get(), "message", G_CALLBACK(messageCallback), this); GstElement* source; if (m_data) { ASSERT(m_dataSize); source = gst_element_factory_make("giostreamsrc", 0); GRefPtr<GInputStream> memoryStream = adoptGRef(g_memory_input_stream_new_from_data(m_data, m_dataSize, 0)); g_object_set(source, "stream", memoryStream.get(), NULL); } else { source = gst_element_factory_make("filesrc", 0); g_object_set(source, "location", m_filePath, NULL); } m_decodebin = gst_element_factory_make("decodebin", "decodebin"); g_signal_connect(m_decodebin.get(), "pad-added", G_CALLBACK(onGStreamerDecodebinPadAddedCallback), this); gst_bin_add_many(GST_BIN(m_pipeline), source, m_decodebin.get(), NULL); gst_element_link_pads_full(source, "src", m_decodebin.get(), "sink", GST_PAD_LINK_CHECK_NOTHING); // Catch errors here immediately, there might not be an error message if // we're unlucky. if (gst_element_set_state(m_pipeline, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) { g_warning("Error: Failed to set pipeline to PAUSED"); m_errorOccurred = true; g_main_loop_quit(m_loop.get()); } }
GstElement * videotest_in_bin_nle_src (const gchar * name, guint64 start, gint64 duration, gint pattern, guint priority) { GstElement *nlesource = NULL; GstElement *videotestsrc = NULL; GstElement *bin = NULL; GstElement *alpha = NULL; GstPad *srcpad = NULL; alpha = gst_element_factory_make ("alpha", NULL); if (alpha == NULL) return NULL; videotestsrc = gst_element_factory_make_or_warn ("videotestsrc", NULL); g_object_set (G_OBJECT (videotestsrc), "pattern", pattern, NULL); bin = gst_bin_new (NULL); nlesource = new_nle_src (name, start, duration, priority); gst_bin_add (GST_BIN (bin), videotestsrc); gst_bin_add (GST_BIN (bin), alpha); gst_element_link_pads_full (videotestsrc, "src", alpha, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_bin_add (GST_BIN (nlesource), bin); srcpad = gst_element_get_static_pad (alpha, "src"); gst_element_add_pad (bin, gst_ghost_pad_new ("src", srcpad)); gst_object_unref (srcpad); return nlesource; }
// This function creates and initializes some internal variables, and returns a // pointer to the element that should receive the data flow first GstElement* MediaPlayerPrivateGStreamerBase::createVideoSink(GstElement* pipeline) { if (!initializeGStreamer()) return 0; #if USE(NATIVE_FULLSCREEN_VIDEO) m_gstGWorld = GStreamerGWorld::createGWorld(pipeline); m_webkitVideoSink = webkitVideoSinkNew(m_gstGWorld.get()); #else UNUSED_PARAM(pipeline); m_webkitVideoSink = webkitVideoSinkNew(); #endif m_repaintHandler = g_signal_connect(m_webkitVideoSink.get(), "repaint-requested", G_CALLBACK(mediaPlayerPrivateRepaintCallback), this); #if USE(NATIVE_FULLSCREEN_VIDEO) // Build a new video sink consisting of a bin containing a tee // (meant to distribute data to multiple video sinks) and our // internal video sink. For fullscreen we create an autovideosink // and initially block the data flow towards it and configure it m_videoSinkBin = gst_bin_new("video-sink"); GstElement* videoTee = gst_element_factory_make("tee", "videoTee"); GstElement* queue = gst_element_factory_make("queue", 0); #ifdef GST_API_VERSION_1 GRefPtr<GstPad> sinkPad = adoptGRef(gst_element_get_static_pad(videoTee, "sink")); GST_OBJECT_FLAG_SET(GST_OBJECT(sinkPad.get()), GST_PAD_FLAG_PROXY_ALLOCATION); #endif gst_bin_add_many(GST_BIN(m_videoSinkBin.get()), videoTee, queue, NULL); // Link a new src pad from tee to queue1. gst_element_link_pads_full(videoTee, 0, queue, "sink", GST_PAD_LINK_CHECK_NOTHING); #endif GstElement* actualVideoSink = 0; m_fpsSink = gst_element_factory_make("fpsdisplaysink", "sink"); if (m_fpsSink) { // The verbose property has been added in -bad 0.10.22. Making // this whole code depend on it because we don't want // fpsdiplaysink to spit data on stdout. GstElementFactory* factory = GST_ELEMENT_FACTORY(GST_ELEMENT_GET_CLASS(m_fpsSink)->elementfactory); if (gst_plugin_feature_check_version(GST_PLUGIN_FEATURE(factory), 0, 10, 22)) { g_object_set(m_fpsSink, "silent", TRUE , NULL); // Turn off text overlay unless logging is enabled. #if LOG_DISABLED g_object_set(m_fpsSink, "text-overlay", FALSE , NULL); #else WTFLogChannel* channel = getChannelFromName("Media"); if (channel->state != WTFLogChannelOn) g_object_set(m_fpsSink, "text-overlay", FALSE , NULL); #endif // LOG_DISABLED if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_fpsSink), "video-sink")) { g_object_set(m_fpsSink, "video-sink", m_webkitVideoSink.get(), NULL); #if USE(NATIVE_FULLSCREEN_VIDEO) gst_bin_add(GST_BIN(m_videoSinkBin.get()), m_fpsSink); #endif actualVideoSink = m_fpsSink; } else m_fpsSink = 0; } else m_fpsSink = 0; } if (!m_fpsSink) { #if USE(NATIVE_FULLSCREEN_VIDEO) gst_bin_add(GST_BIN(m_videoSinkBin.get()), m_webkitVideoSink.get()); #endif actualVideoSink = m_webkitVideoSink.get(); } ASSERT(actualVideoSink); #if USE(NATIVE_FULLSCREEN_VIDEO) // Faster elements linking. gst_element_link_pads_full(queue, "src", actualVideoSink, "sink", GST_PAD_LINK_CHECK_NOTHING); // Add a ghostpad to the bin so it can proxy to tee. GRefPtr<GstPad> pad = adoptGRef(gst_element_get_static_pad(videoTee, "sink")); gst_element_add_pad(m_videoSinkBin.get(), gst_ghost_pad_new("sink", pad.get())); // Set the bin as video sink of playbin. return m_videoSinkBin.get(); #else return actualVideoSink; #endif }
static gboolean gst_viewfinder_bin_create_elements (GstViewfinderBin * vfbin) { GstElement *csp = NULL; GstElement *videoscale = NULL; GstPad *firstpad = NULL; const gchar *missing_element_name; gboolean newsink = FALSE; gboolean updated_converters = FALSE; GST_DEBUG_OBJECT (vfbin, "Creating internal elements"); /* First check if we need to add/replace the internal sink */ if (vfbin->video_sink) { if (vfbin->user_video_sink && vfbin->video_sink != vfbin->user_video_sink) { gst_bin_remove (GST_BIN_CAST (vfbin), vfbin->video_sink); gst_object_unref (vfbin->video_sink); vfbin->video_sink = NULL; } } if (!vfbin->video_sink) { if (vfbin->user_video_sink) vfbin->video_sink = gst_object_ref (vfbin->user_video_sink); else { vfbin->video_sink = gst_element_factory_make ("autovideosink", "vfbin-sink"); if (!vfbin->video_sink) { missing_element_name = "autovideosink"; goto missing_element; } } gst_bin_add (GST_BIN_CAST (vfbin), gst_object_ref (vfbin->video_sink)); newsink = TRUE; } /* check if we want add/remove the conversion elements */ if (vfbin->elements_created && vfbin->disable_converters) { /* remove the elements, user doesn't want them */ gst_ghost_pad_set_target (GST_GHOST_PAD (vfbin->ghostpad), NULL); csp = gst_bin_get_by_name (GST_BIN_CAST (vfbin), "vfbin-csp"); videoscale = gst_bin_get_by_name (GST_BIN_CAST (vfbin), "vfbin-videoscale"); gst_bin_remove (GST_BIN_CAST (vfbin), csp); gst_bin_remove (GST_BIN_CAST (vfbin), videoscale); gst_object_unref (csp); gst_object_unref (videoscale); updated_converters = TRUE; } else if (!vfbin->elements_created && !vfbin->disable_converters) { gst_ghost_pad_set_target (GST_GHOST_PAD (vfbin->ghostpad), NULL); /* add the elements, user wants them */ csp = gst_element_factory_make ("ffmpegcolorspace", "vfbin-csp"); if (!csp) { missing_element_name = "ffmpegcolorspace"; goto missing_element; } gst_bin_add (GST_BIN_CAST (vfbin), csp); videoscale = gst_element_factory_make ("videoscale", "vfbin->videoscale"); if (!videoscale) { missing_element_name = "videoscale"; goto missing_element; } gst_bin_add (GST_BIN_CAST (vfbin), videoscale); gst_element_link_pads_full (csp, "src", videoscale, "sink", GST_PAD_LINK_CHECK_NOTHING); vfbin->elements_created = TRUE; GST_DEBUG_OBJECT (vfbin, "Elements succesfully created and linked"); updated_converters = TRUE; } /* otherwise, just leave it as is */ /* if sink was replaced -> link it to the internal converters */ if (newsink && !vfbin->disable_converters) { gboolean unref = FALSE; if (!videoscale) { videoscale = gst_bin_get_by_name (GST_BIN_CAST (vfbin), "vfbin-videscale"); unref = TRUE; } if (!gst_element_link_pads_full (videoscale, "src", vfbin->video_sink, "sink", GST_PAD_LINK_CHECK_CAPS)) { GST_ELEMENT_ERROR (vfbin, CORE, NEGOTIATION, (NULL), ("linking videoscale and viewfindersink failed")); } if (unref) gst_object_unref (videoscale); videoscale = NULL; } /* Check if we need a new ghostpad target */ if (updated_converters || (newsink && vfbin->disable_converters)) { if (vfbin->disable_converters) { firstpad = gst_element_get_static_pad (vfbin->video_sink, "sink"); } else { /* csp should always exist at this point */ firstpad = gst_element_get_static_pad (csp, "sink"); } } /* need to change the ghostpad target if firstpad is set */ if (firstpad) { if (!gst_ghost_pad_set_target (GST_GHOST_PAD (vfbin->ghostpad), firstpad)) goto error; gst_object_unref (firstpad); firstpad = NULL; } return TRUE; missing_element: gst_element_post_message (GST_ELEMENT_CAST (vfbin), gst_missing_element_message_new (GST_ELEMENT_CAST (vfbin), missing_element_name)); GST_ELEMENT_ERROR (vfbin, CORE, MISSING_PLUGIN, (_("Missing element '%s' - check your GStreamer installation."), missing_element_name), (NULL)); goto error; error: GST_WARNING_OBJECT (vfbin, "Creating internal elements failed"); if (firstpad) gst_object_unref (firstpad); return FALSE; }
/** * ges_pipeline_set_mode: * @pipeline: a #GESPipeline * @mode: the #GESPipelineFlags to use * * switches the @pipeline to the specified @mode. The default mode when * creating a #GESPipeline is #GES_PIPELINE_MODE_PREVIEW. * * Note: The @pipeline will be set to #GST_STATE_NULL during this call due to * the internal changes that happen. The caller will therefore have to * set the @pipeline to the requested state after calling this method. * * Returns: %TRUE if the mode was properly set, else %FALSE. **/ gboolean ges_pipeline_set_mode (GESPipeline * pipeline, GESPipelineFlags mode) { GList *tmp; g_return_val_if_fail (GES_IS_PIPELINE (pipeline), FALSE); GST_DEBUG_OBJECT (pipeline, "current mode : %d, mode : %d", pipeline->priv->mode, mode); /* fast-path, nothing to change */ if (mode == pipeline->priv->mode) return TRUE; /* FIXME: It would be nice if we are only (de)activating preview * modes to not set the whole pipeline to NULL, but instead just * do the proper (un)linking to playsink. */ /* Switch pipeline to NULL since we're changing the configuration */ gst_element_set_state (GST_ELEMENT_CAST (pipeline), GST_STATE_NULL); if (pipeline->priv->timeline) { gboolean disabled = ! !(mode & (GES_PIPELINE_MODE_RENDER | GES_PIPELINE_MODE_SMART_RENDER)); for (tmp = pipeline->priv->timeline->tracks; tmp; tmp = tmp->next) track_disable_last_gap (GES_TRACK (tmp->data), disabled); } /* remove no-longer needed components */ if (pipeline->priv->mode & GES_PIPELINE_MODE_PREVIEW && !(mode & GES_PIPELINE_MODE_PREVIEW)) { /* Disable playsink */ GST_DEBUG ("Disabling playsink"); gst_object_ref (pipeline->priv->playsink); gst_bin_remove (GST_BIN_CAST (pipeline), pipeline->priv->playsink); } if ((pipeline->priv->mode & (GES_PIPELINE_MODE_RENDER | GES_PIPELINE_MODE_SMART_RENDER)) && !(mode & (GES_PIPELINE_MODE_RENDER | GES_PIPELINE_MODE_SMART_RENDER))) { GList *tmp; GstCaps *caps; for (tmp = pipeline->priv->timeline->tracks; tmp; tmp = tmp->next) { GESTrackType type = GES_TRACK (tmp->data)->type; if (type == GES_TRACK_TYPE_AUDIO) caps = gst_caps_new_empty_simple ("audio/x-raw"); else if (type == GES_TRACK_TYPE_VIDEO) caps = gst_caps_new_empty_simple ("video/x-raw"); else continue; ges_track_set_caps (GES_TRACK (tmp->data), caps); gst_caps_unref (caps); } /* Disable render bin */ GST_DEBUG ("Disabling rendering bin"); gst_object_ref (pipeline->priv->encodebin); gst_object_ref (pipeline->priv->urisink); gst_bin_remove_many (GST_BIN_CAST (pipeline), pipeline->priv->encodebin, pipeline->priv->urisink, NULL); } /* Add new elements */ if (!(pipeline->priv->mode & GES_PIPELINE_MODE_PREVIEW) && (mode & GES_PIPELINE_MODE_PREVIEW)) { /* Add playsink */ GST_DEBUG ("Adding playsink"); if (!gst_bin_add (GST_BIN_CAST (pipeline), pipeline->priv->playsink)) { GST_ERROR_OBJECT (pipeline, "Couldn't add playsink"); return FALSE; } } if (!(pipeline->priv->mode & (GES_PIPELINE_MODE_RENDER | GES_PIPELINE_MODE_SMART_RENDER)) && (mode & (GES_PIPELINE_MODE_RENDER | GES_PIPELINE_MODE_SMART_RENDER))) { /* Adding render bin */ GST_DEBUG ("Adding render bin"); if (G_UNLIKELY (pipeline->priv->urisink == NULL)) { GST_ERROR_OBJECT (pipeline, "Output URI not set !"); return FALSE; } if (!gst_bin_add (GST_BIN_CAST (pipeline), pipeline->priv->encodebin)) { GST_ERROR_OBJECT (pipeline, "Couldn't add encodebin"); return FALSE; } if (!gst_bin_add (GST_BIN_CAST (pipeline), pipeline->priv->urisink)) { GST_ERROR_OBJECT (pipeline, "Couldn't add URI sink"); return FALSE; } g_object_set (pipeline->priv->encodebin, "avoid-reencoding", !(!(mode & GES_PIPELINE_MODE_SMART_RENDER)), NULL); gst_element_link_pads_full (pipeline->priv->encodebin, "src", pipeline->priv->urisink, "sink", GST_PAD_LINK_CHECK_NOTHING); } /* FIXUPS */ /* FIXME * If we are rendering, set playsink to sync=False, * If we are NOT rendering, set playsink to sync=TRUE */ pipeline->priv->mode = mode; return TRUE; }
static void _test_negotiation (const gchar * src_templ, const gchar * sink_templ, gint width, gint height, gint par_n, gint par_d) { GstElement *pipeline; GstElement *src, *capsfilter1, *scale, *capsfilter2, *sink; GstBus *bus; GMainLoop *loop; GstCaps *caps; TestNegotiationData data = { 0, 0, 0, 0, FALSE, NULL }; GstPad *pad; GST_DEBUG ("Running test for src templ caps '%s' and sink templ caps '%s'", src_templ, sink_templ); pipeline = gst_element_factory_make ("pipeline", "pipeline"); fail_unless (pipeline != NULL); src = gst_element_factory_make ("videotestsrc", "src"); fail_unless (src != NULL); g_object_set (G_OBJECT (src), "num-buffers", 1, NULL); capsfilter1 = gst_element_factory_make ("capsfilter", "filter1"); fail_unless (capsfilter1 != NULL); caps = gst_caps_from_string (src_templ); fail_unless (caps != NULL); g_object_set (G_OBJECT (capsfilter1), "caps", caps, NULL); gst_caps_unref (caps); scale = gst_element_factory_make ("videoscale", "scale"); fail_unless (scale != NULL); capsfilter2 = gst_element_factory_make ("capsfilter", "filter2"); fail_unless (capsfilter2 != NULL); caps = gst_caps_from_string (sink_templ); fail_unless (caps != NULL); g_object_set (G_OBJECT (capsfilter2), "caps", caps, NULL); gst_caps_unref (caps); pad = gst_element_get_static_pad (capsfilter2, "sink"); fail_unless (pad != NULL); g_signal_connect (pad, "notify::caps", G_CALLBACK (_test_negotiation_notify_caps), &data); gst_object_unref (pad); sink = gst_element_factory_make ("fakesink", "sink"); fail_unless (sink != NULL); g_object_set (sink, "async", FALSE, NULL); gst_bin_add_many (GST_BIN (pipeline), src, capsfilter1, scale, capsfilter2, sink, NULL); fail_unless (gst_element_link_pads_full (src, "src", capsfilter1, "sink", LINK_CHECK_FLAGS)); fail_unless (gst_element_link_pads_full (capsfilter1, "src", scale, "sink", LINK_CHECK_FLAGS)); fail_unless (gst_element_link_pads_full (scale, "src", capsfilter2, "sink", LINK_CHECK_FLAGS)); fail_unless (gst_element_link_pads_full (capsfilter2, "src", sink, "sink", LINK_CHECK_FLAGS)); loop = g_main_loop_new (NULL, FALSE); bus = gst_element_get_bus (pipeline); fail_unless (bus != NULL); gst_bus_add_signal_watch (bus); data.loop = loop; data.width = width; data.height = height; data.par_n = par_n; data.par_d = par_d; data.ok = FALSE; g_signal_connect (bus, "message", G_CALLBACK (_test_negotiation_message), &data); gst_object_unref (bus); fail_unless (gst_element_set_state (pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS); g_main_loop_run (loop); fail_unless (data.ok == TRUE); fail_unless (gst_element_set_state (pipeline, GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS); gst_object_unref (pipeline); g_main_loop_unref (loop); }
static GstElement * ges_track_video_transition_create_element (GESTrackObject * object) { GstElement *topbin, *iconva, *iconvb, *scalea, *scaleb, *capsfilt, *oconv; GstObject *target = NULL; const gchar *propname = NULL; GstElement *mixer = NULL; GstPad *sinka_target, *sinkb_target, *src_target, *sinka, *sinkb, *src, *srca_pad; GESTrackVideoTransition *self; GESTrackVideoTransitionPrivate *priv; self = GES_TRACK_VIDEO_TRANSITION (object); priv = self->priv; GST_LOG ("creating a video bin"); topbin = gst_bin_new ("transition-bin"); iconva = gst_element_factory_make ("videoconvert", "tr-csp-a"); iconvb = gst_element_factory_make ("videoconvert", "tr-csp-b"); scalea = gst_element_factory_make ("videoscale", "vs-a"); scaleb = gst_element_factory_make ("videoscale", "vs-b"); capsfilt = gst_element_factory_make ("capsfilter", "capsfilt"); oconv = gst_element_factory_make ("videoconvert", "tr-csp-output"); gst_bin_add_many (GST_BIN (topbin), iconva, iconvb, scalea, scaleb, capsfilt, oconv, NULL); mixer = gst_element_factory_make ("videomixer", NULL); g_assert (mixer); g_object_set (G_OBJECT (mixer), "background", 1, NULL); gst_bin_add (GST_BIN (topbin), mixer); if (priv->pending_type != GES_VIDEO_STANDARD_TRANSITION_TYPE_CROSSFADE) { priv->sinka = (GstPad *) link_element_to_mixer_with_smpte (GST_BIN (topbin), iconva, mixer, priv->pending_type, NULL); priv->sinkb = (GstPad *) link_element_to_mixer_with_smpte (GST_BIN (topbin), iconvb, mixer, priv->pending_type, &priv->smpte); target = GST_OBJECT (priv->smpte); propname = "position"; priv->start_value = 1.0; priv->end_value = 0.0; } else { gst_element_link_pads_full (iconva, "src", scalea, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full (iconvb, "src", scaleb, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full (scaleb, "src", capsfilt, "sink", GST_PAD_LINK_CHECK_NOTHING); priv->sinka = (GstPad *) link_element_to_mixer (scalea, mixer); priv->sinkb = (GstPad *) link_element_to_mixer (capsfilt, mixer); target = GST_OBJECT (priv->sinkb); propname = "alpha"; priv->start_value = 0.0; priv->end_value = 1.0; } priv->mixer = gst_object_ref (mixer); fast_element_link (mixer, oconv); sinka_target = gst_element_get_static_pad (iconva, "sink"); sinkb_target = gst_element_get_static_pad (iconvb, "sink"); src_target = gst_element_get_static_pad (oconv, "src"); sinka = gst_ghost_pad_new ("sinka", sinka_target); sinkb = gst_ghost_pad_new ("sinkb", sinkb_target); src = gst_ghost_pad_new ("src", src_target); gst_element_add_pad (topbin, src); gst_element_add_pad (topbin, sinka); gst_element_add_pad (topbin, sinkb); srca_pad = gst_element_get_static_pad (scalea, "src"); g_signal_connect (srca_pad, "notify::caps", G_CALLBACK (on_caps_set), (GstElement *) capsfilt); gst_object_unref (sinka_target); gst_object_unref (sinkb_target); gst_object_unref (src_target); gst_object_unref (srca_pad); /* set up interpolation */ set_interpolation (target, priv, propname); priv->topbin = topbin; priv->type = priv->pending_type; return topbin; }
/** * ges_timeline_pipeline_set_mode: * @pipeline: a #GESTimelinePipeline * @mode: the #GESPipelineFlags to use * * switches the @pipeline to the specified @mode. The default mode when * creating a #GESTimelinePipeline is #TIMELINE_MODE_PREVIEW. * * Note: The @pipeline will be set to #GST_STATE_NULL during this call due to * the internal changes that happen. The caller will therefore have to * set the @pipeline to the requested state after calling this method. * * Returns: %TRUE if the mode was properly set, else %FALSE. **/ gboolean ges_timeline_pipeline_set_mode (GESTimelinePipeline * pipeline, GESPipelineFlags mode) { GST_DEBUG_OBJECT (pipeline, "current mode : %d, mode : %d", pipeline->priv->mode, mode); /* fast-path, nothing to change */ if (mode == pipeline->priv->mode) return TRUE; /* FIXME: It would be nice if we are only (de)activating preview * modes to not set the whole pipeline to NULL, but instead just * do the proper (un)linking to playsink. */ /* Switch pipeline to NULL since we're changing the configuration */ gst_element_set_state (GST_ELEMENT_CAST (pipeline), GST_STATE_NULL); /* remove no-longer needed components */ if (pipeline->priv->mode & TIMELINE_MODE_PREVIEW && !(mode & TIMELINE_MODE_PREVIEW)) { /* Disable playsink */ GST_DEBUG ("Disabling playsink"); g_object_ref (pipeline->priv->playsink); gst_bin_remove (GST_BIN_CAST (pipeline), pipeline->priv->playsink); } if ((pipeline->priv->mode & (TIMELINE_MODE_RENDER | TIMELINE_MODE_SMART_RENDER)) && !(mode & (TIMELINE_MODE_RENDER | TIMELINE_MODE_SMART_RENDER))) { /* Disable render bin */ GST_DEBUG ("Disabling rendering bin"); g_object_ref (pipeline->priv->encodebin); g_object_ref (pipeline->priv->urisink); gst_bin_remove_many (GST_BIN_CAST (pipeline), pipeline->priv->encodebin, pipeline->priv->urisink, NULL); } /* Add new elements */ if (!(pipeline->priv->mode & TIMELINE_MODE_PREVIEW) && (mode & TIMELINE_MODE_PREVIEW)) { /* Add playsink */ GST_DEBUG ("Adding playsink"); if (!gst_bin_add (GST_BIN_CAST (pipeline), pipeline->priv->playsink)) { GST_ERROR_OBJECT (pipeline, "Couldn't add playsink"); return FALSE; } } if (!(pipeline->priv->mode & (TIMELINE_MODE_RENDER | TIMELINE_MODE_SMART_RENDER)) && (mode & (TIMELINE_MODE_RENDER | TIMELINE_MODE_SMART_RENDER))) { /* Adding render bin */ GST_DEBUG ("Adding render bin"); if (G_UNLIKELY (pipeline->priv->urisink == NULL)) { GST_ERROR_OBJECT (pipeline, "Output URI not set !"); return FALSE; } if (!gst_bin_add (GST_BIN_CAST (pipeline), pipeline->priv->encodebin)) { GST_ERROR_OBJECT (pipeline, "Couldn't add encodebin"); return FALSE; } if (!gst_bin_add (GST_BIN_CAST (pipeline), pipeline->priv->urisink)) { GST_ERROR_OBJECT (pipeline, "Couldn't add URI sink"); return FALSE; } g_object_set (pipeline->priv->encodebin, "avoid-reencoding", !(!(mode & TIMELINE_MODE_SMART_RENDER)), NULL); gst_element_link_pads_full (pipeline->priv->encodebin, "src", pipeline->priv->urisink, "sink", GST_PAD_LINK_CHECK_NOTHING); } /* FIXUPS */ /* FIXME * If we are rendering, set playsink to sync=False, * If we are NOT rendering, set playsink to sync=TRUE */ pipeline->priv->mode = mode; return TRUE; }
bool GStreamerGWorld::enterFullscreen() { if (m_dynamicPadName) return false; if (!m_videoWindow) m_videoWindow = PlatformVideoWindow::createWindow(); GstElement* platformVideoSink = gst_element_factory_make("autovideosink", "platformVideoSink"); GstElement* colorspace = gst_element_factory_make(gVideoConvertName, "colorspace"); GstElement* queue = gst_element_factory_make("queue", "queue"); GstElement* videoScale = gst_element_factory_make("videoscale", "videoScale"); // Get video sink bin and the tee inside. GRefPtr<GstElement> videoSink; GstElement* sinkPtr = 0; g_object_get(m_pipeline, "video-sink", &sinkPtr, NULL); videoSink = adoptGRef(sinkPtr); GRefPtr<GstElement> tee = adoptGRef(gst_bin_get_by_name(GST_BIN(videoSink.get()), "videoTee")); gst_bin_add_many(GST_BIN(videoSink.get()), platformVideoSink, videoScale, colorspace, queue, NULL); // Faster elements linking. gst_element_link_pads_full(queue, "src", colorspace, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full(colorspace, "src", videoScale, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full(videoScale, "src", platformVideoSink, "sink", GST_PAD_LINK_CHECK_NOTHING); // Link a new src pad from tee to queue. #ifndef GST_API_VERSION_1 GRefPtr<GstPad> srcPad = adoptGRef(gst_element_get_request_pad(tee.get(), "src%d")); #else GRefPtr<GstPad> srcPad = adoptGRef(gst_element_get_request_pad(tee.get(), "src_%u")); #endif GRefPtr<GstPad> sinkPad = adoptGRef(gst_element_get_static_pad(queue, "sink")); gst_pad_link(srcPad.get(), sinkPad.get()); m_dynamicPadName.set(gst_pad_get_name(srcPad.get())); // Synchronize the new elements with pipeline state. If it's // paused limit the state change to pre-rolling. GstState state; gst_element_get_state(m_pipeline, &state, 0, 0); if (state < GST_STATE_PLAYING) state = GST_STATE_READY; gst_element_set_state(platformVideoSink, state); gst_element_set_state(videoScale, state); gst_element_set_state(colorspace, state); gst_element_set_state(queue, state); #ifndef GST_API_VERSION_1 // Query the current media segment informations and send them towards // the new tee branch downstream. GstQuery* query = gst_query_new_segment(GST_FORMAT_TIME); gboolean queryResult = gst_element_query(m_pipeline, query); if (!queryResult) { gst_query_unref(query); return true; } gint64 position; GstFormat format; if (!gst_element_query_position(m_pipeline, &format, &position)) position = 0; gdouble rate; gint64 startValue, stopValue; gst_query_parse_segment(query, &rate, &format, &startValue, &stopValue); GstEvent* event = gst_event_new_new_segment(FALSE, rate, format, startValue, stopValue, position); gst_pad_push_event(srcPad.get(), event); gst_query_unref(query); #endif return true; }
static void uridecodebin_pad_added_cb (GstElement * uridecodebin, GstPad * pad, GstDiscoverer * dc) { PrivateStream *ps; GstPad *sinkpad = NULL; GstCaps *caps; static GstCaps *subs_caps = NULL; if (!subs_caps) { subs_caps = gst_caps_from_string ("text/plain; text/x-pango-markup; " "subpicture/x-pgs; subpicture/x-dvb; application/x-subtitle-unknown; " "application/x-ssa; application/x-ass; subtitle/x-kate; " "video/x-dvd-subpicture; "); } GST_DEBUG_OBJECT (dc, "pad %s:%s", GST_DEBUG_PAD_NAME (pad)); ps = g_slice_new0 (PrivateStream); ps->dc = dc; ps->pad = pad; ps->queue = gst_element_factory_make ("queue", NULL); ps->sink = gst_element_factory_make ("fakesink", NULL); if (G_UNLIKELY (ps->queue == NULL || ps->sink == NULL)) goto error; g_object_set (ps->sink, "silent", TRUE, NULL); g_object_set (ps->queue, "max-size-buffers", 1, "silent", TRUE, NULL); caps = gst_pad_get_caps_reffed (pad); if (gst_caps_can_intersect (caps, subs_caps)) { /* Subtitle streams are sparse and don't provide any information - don't * wait for data to preroll */ g_object_set (ps->sink, "async", FALSE, NULL); } gst_caps_unref (caps); gst_bin_add_many (dc->priv->pipeline, ps->queue, ps->sink, NULL); if (!gst_element_link_pads_full (ps->queue, "src", ps->sink, "sink", GST_PAD_LINK_CHECK_NOTHING)) goto error; if (!gst_element_sync_state_with_parent (ps->sink)) goto error; if (!gst_element_sync_state_with_parent (ps->queue)) goto error; sinkpad = gst_element_get_static_pad (ps->queue, "sink"); if (sinkpad == NULL) goto error; if (gst_pad_link_full (pad, sinkpad, GST_PAD_LINK_CHECK_NOTHING) != GST_PAD_LINK_OK) goto error; gst_object_unref (sinkpad); /* Add an event probe */ gst_pad_add_event_probe (pad, G_CALLBACK (_event_probe), ps); DISCO_LOCK (dc); dc->priv->streams = g_list_append (dc->priv->streams, ps); DISCO_UNLOCK (dc); GST_DEBUG_OBJECT (dc, "Done handling pad"); return; error: GST_ERROR_OBJECT (dc, "Error while handling pad"); if (sinkpad) gst_object_unref (sinkpad); if (ps->queue) gst_object_unref (ps->queue); if (ps->sink) gst_object_unref (ps->sink); g_slice_free (PrivateStream, ps); return; }
static void pad_blocked_cb (GstPad * pad, gboolean blocked, GstPlaySinkVideoConvert * self) { GstPad *peer; GstCaps *caps; gboolean raw; GST_PLAY_SINK_VIDEO_CONVERT_LOCK (self); self->sink_proxypad_blocked = blocked; GST_DEBUG_OBJECT (self, "Pad blocked: %d", blocked); if (!blocked) goto done; /* There must be a peer at this point */ peer = gst_pad_get_peer (self->sinkpad); caps = gst_pad_get_negotiated_caps (peer); if (!caps) caps = gst_pad_get_caps_reffed (peer); gst_object_unref (peer); raw = is_raw_caps (caps); GST_DEBUG_OBJECT (self, "Caps %" GST_PTR_FORMAT " are raw: %d", caps, raw); gst_caps_unref (caps); if (raw == self->raw) goto unblock; self->raw = raw; if (raw) { GstBin *bin = GST_BIN_CAST (self); GstElement *head = NULL, *prev = NULL; GstPad *pad; GST_DEBUG_OBJECT (self, "Creating raw conversion pipeline"); gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->sinkpad), NULL); gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), NULL); self->conv = gst_element_factory_make ("ffmpegcolorspace", "conv"); if (self->conv == NULL) { post_missing_element_message (self, "ffmpegcolorspace"); GST_ELEMENT_WARNING (self, CORE, MISSING_PLUGIN, (_("Missing element '%s' - check your GStreamer installation."), "ffmpegcolorspace"), ("video rendering might fail")); } else { gst_bin_add (bin, self->conv); gst_element_sync_state_with_parent (self->conv); distribute_running_time (self->conv, &self->segment); prev = head = self->conv; } self->scale = gst_element_factory_make ("videoscale", "scale"); if (self->scale == NULL) { post_missing_element_message (self, "videoscale"); GST_ELEMENT_WARNING (self, CORE, MISSING_PLUGIN, (_("Missing element '%s' - check your GStreamer installation."), "videoscale"), ("possibly a liboil version mismatch?")); } else { /* Add black borders if necessary to keep the DAR */ g_object_set (self->scale, "add-borders", TRUE, NULL); gst_bin_add (bin, self->scale); gst_element_sync_state_with_parent (self->scale); distribute_running_time (self->scale, &self->segment); if (prev) { if (!gst_element_link_pads_full (prev, "src", self->scale, "sink", GST_PAD_LINK_CHECK_TEMPLATE_CAPS)) goto link_failed; } else { head = self->scale; } prev = self->scale; } if (head) { pad = gst_element_get_static_pad (head, "sink"); gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->sinkpad), pad); gst_object_unref (pad); } if (prev) { pad = gst_element_get_static_pad (prev, "src"); gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), pad); gst_object_unref (pad); } if (!head && !prev) { gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), self->sink_proxypad); } GST_DEBUG_OBJECT (self, "Raw conversion pipeline created"); } else { GstBin *bin = GST_BIN_CAST (self); GST_DEBUG_OBJECT (self, "Removing raw conversion pipeline"); gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->sinkpad), NULL); gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), NULL); if (self->conv) { gst_element_set_state (self->conv, GST_STATE_NULL); gst_bin_remove (bin, self->conv); self->conv = NULL; } if (self->scale) { gst_element_set_state (self->scale, GST_STATE_NULL); gst_bin_remove (bin, self->scale); self->scale = NULL; } gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), self->sink_proxypad); GST_DEBUG_OBJECT (self, "Raw conversion pipeline removed"); } unblock: gst_pad_set_blocked_async_full (self->sink_proxypad, FALSE, (GstPadBlockCallback) pad_blocked_cb, gst_object_ref (self), (GDestroyNotify) gst_object_unref); done: GST_PLAY_SINK_VIDEO_CONVERT_UNLOCK (self); return; link_failed: { GST_ELEMENT_ERROR (self, CORE, PAD, (NULL), ("Failed to configure the video converter.")); gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), self->sink_proxypad); gst_pad_set_blocked_async_full (self->sink_proxypad, FALSE, (GstPadBlockCallback) pad_blocked_cb, gst_object_ref (self), (GDestroyNotify) gst_object_unref); return; } }
static void run_test (const GstCaps * caps, gint src_width, gint src_height, gint dest_width, gint dest_height, gint method, GCallback src_handoff, gpointer src_handoff_user_data, GCallback sink_handoff, gpointer sink_handoff_user_data) { GstElement *pipeline; GstElement *src, *videoconvert, *capsfilter1, *identity, *scale, *capsfilter2, *sink; GstMessage *msg; GstBus *bus; GstCaps *copy; guint n_buffers = 0; /* skip formats that videoconvert can't handle */ if (!videoconvert_supports_caps (caps)) return; pipeline = gst_element_factory_make ("pipeline", "pipeline"); fail_unless (pipeline != NULL); src = gst_element_factory_make ("videotestsrc", "src"); fail_unless (src != NULL); g_object_set (G_OBJECT (src), "num-buffers", 1, NULL); videoconvert = gst_element_factory_make ("videoconvert", "csp"); fail_unless (videoconvert != NULL); capsfilter1 = gst_element_factory_make ("capsfilter", "filter1"); fail_unless (capsfilter1 != NULL); copy = gst_caps_copy (caps); gst_caps_set_simple (copy, "width", G_TYPE_INT, src_width, "height", G_TYPE_INT, src_height, "framerate", GST_TYPE_FRACTION, 30, 1, NULL); g_object_set (G_OBJECT (capsfilter1), "caps", copy, NULL); gst_caps_unref (copy); identity = gst_element_factory_make ("identity", "identity"); fail_unless (identity != NULL); if (src_handoff) { g_object_set (G_OBJECT (identity), "signal-handoffs", TRUE, NULL); g_signal_connect (identity, "handoff", G_CALLBACK (src_handoff), src_handoff_user_data); } scale = gst_element_factory_make ("videoscale", "scale"); fail_unless (scale != NULL); g_object_set (G_OBJECT (scale), "method", method, NULL); capsfilter2 = gst_element_factory_make ("capsfilter", "filter2"); fail_unless (capsfilter2 != NULL); copy = gst_caps_copy (caps); gst_caps_set_simple (copy, "width", G_TYPE_INT, dest_width, "height", G_TYPE_INT, dest_height, NULL); g_object_set (G_OBJECT (capsfilter2), "caps", copy, NULL); gst_caps_unref (copy); sink = gst_element_factory_make ("fakesink", "sink"); fail_unless (sink != NULL); g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, "async", FALSE, NULL); g_signal_connect (sink, "handoff", G_CALLBACK (on_sink_handoff), &n_buffers); if (sink_handoff) { g_signal_connect (sink, "handoff", G_CALLBACK (sink_handoff), sink_handoff_user_data); } gst_bin_add_many (GST_BIN (pipeline), src, videoconvert, capsfilter1, identity, scale, capsfilter2, sink, NULL); fail_unless (gst_element_link_pads_full (src, "src", videoconvert, "sink", LINK_CHECK_FLAGS)); fail_unless (gst_element_link_pads_full (videoconvert, "src", capsfilter1, "sink", LINK_CHECK_FLAGS)); fail_unless (gst_element_link_pads_full (capsfilter1, "src", identity, "sink", LINK_CHECK_FLAGS)); fail_unless (gst_element_link_pads_full (identity, "src", scale, "sink", LINK_CHECK_FLAGS)); fail_unless (gst_element_link_pads_full (scale, "src", capsfilter2, "sink", LINK_CHECK_FLAGS)); fail_unless (gst_element_link_pads_full (capsfilter2, "src", sink, "sink", LINK_CHECK_FLAGS)); bus = gst_element_get_bus (pipeline); fail_unless (bus != NULL); fail_unless (gst_element_set_state (pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS); msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_EOS | GST_MESSAGE_ERROR | GST_MESSAGE_WARNING); fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_EOS); fail_unless (gst_element_set_state (pipeline, GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS); fail_unless (n_buffers == 1); gst_object_unref (pipeline); gst_message_unref (msg); gst_object_unref (bus); }