/** * ges_timeline_pipeline_set_render_settings: * @pipeline: a #GESTimelinePipeline * @output_uri: the URI to which the timeline will be rendered * @profile: the #GstEncodingProfile to use to render the timeline. * * Specify where the pipeline shall be rendered and with what settings. * * A copy of @profile and @output_uri will be done internally, the caller can * safely free those values afterwards. * * This method must be called before setting the pipeline mode to * #TIMELINE_MODE_RENDER * * Returns: %TRUE if the settings were aknowledged properly, else %FALSE */ gboolean ges_timeline_pipeline_set_render_settings (GESTimelinePipeline * pipeline, gchar * output_uri, GstEncodingProfile * profile) { /* Clear previous URI sink if it existed */ /* FIXME : We should figure out if it was added to the pipeline, * and if so, remove it. */ if (pipeline->priv->urisink) { g_object_unref (pipeline->priv->urisink); pipeline->priv->urisink = NULL; } pipeline->priv->urisink = gst_element_make_from_uri (GST_URI_SINK, output_uri, "urisink"); if (G_UNLIKELY (pipeline->priv->urisink == NULL)) { GST_ERROR_OBJECT (pipeline, "Couldn't not create sink for URI %s", output_uri); return FALSE; } if (pipeline->priv->profile) gst_encoding_profile_unref (pipeline->priv->profile); g_object_set (pipeline->priv->encodebin, "avoid-reencoding", !(!(pipeline->priv->mode & TIMELINE_MODE_SMART_RENDER)), NULL); g_object_set (pipeline->priv->encodebin, "profile", profile, NULL); pipeline->priv->profile = (GstEncodingProfile *) gst_encoding_profile_ref (profile); return TRUE; }
static gboolean gst_hls_demux_make_fetcher (GstHLSDemux * demux, const gchar * uri) { GstPad *pad; if (!gst_uri_is_valid (uri)) return FALSE; GST_DEBUG_OBJECT (demux, "Creating fetcher for the URI:%s", uri); demux->fetcher = gst_element_make_from_uri (GST_URI_SRC, uri, NULL); if (!demux->fetcher) return FALSE; demux->fetcher_error = FALSE; demux->stopping_fetcher = FALSE; gst_element_set_bus (GST_ELEMENT (demux->fetcher), demux->fetcher_bus); g_object_set (G_OBJECT (demux->fetcher), "location", uri, NULL); pad = gst_element_get_static_pad (demux->fetcher, "src"); if (pad) { gst_pad_link (pad, demux->fetcherpad); gst_object_unref (pad); } return TRUE; }
static gboolean gst_uri_downloader_set_uri (GstUriDownloader * downloader, const gchar * uri) { GstPad *pad; if (!gst_uri_is_valid (uri)) return FALSE; GST_DEBUG_OBJECT (downloader, "Creating source element for the URI:%s", uri); downloader->priv->urisrc = gst_element_make_from_uri (GST_URI_SRC, uri, NULL); if (!downloader->priv->urisrc) return FALSE; /* add a sync handler for the bus messages to detect errors in the download */ gst_element_set_bus (GST_ELEMENT (downloader->priv->urisrc), downloader->priv->bus); gst_bus_set_sync_handler (downloader->priv->bus, gst_uri_downloader_bus_handler, downloader); pad = gst_element_get_static_pad (downloader->priv->urisrc, "src"); if (!pad) return FALSE; gst_pad_link (pad, downloader->priv->pad); gst_object_unref (pad); return TRUE; }
static gboolean make_source (GstUriTranscodeBin * self) { GError *err = NULL; if (!gst_uri_is_valid (self->source_uri)) goto invalid_uri; self->src = gst_element_make_from_uri (GST_URI_SRC, self->source_uri, "src", &err); if (!self->src) goto no_sink; gst_bin_add (GST_BIN (self), self->src); if (!gst_element_link (self->src, self->transcodebin)) return FALSE; return TRUE; invalid_uri: { GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND, ("Invalid URI \"%s\".", self->source_uri), (NULL)); g_clear_error (&err); return FALSE; } no_sink: { /* whoops, could not create the source element, dig a little deeper to * figure out what might be wrong. */ if (err != NULL && err->code == GST_URI_ERROR_UNSUPPORTED_PROTOCOL) { gchar *prot; prot = gst_uri_get_protocol (self->source_uri); if (prot == NULL) goto invalid_uri; gst_element_post_message (GST_ELEMENT_CAST (self), gst_missing_uri_source_message_new (GST_ELEMENT (self), prot)); GST_ELEMENT_ERROR (self, CORE, MISSING_PLUGIN, ("No URI handler implemented for \"%s\".", prot), (NULL)); g_free (prot); } else { GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND, ("%s", (err) ? err->message : "URI was not accepted by any element"), ("No element accepted URI '%s'", self->dest_uri)); } g_clear_error (&err); return FALSE; } }
static gpointer rb_audiocd_load_songs (RBAudioCdSource *source) { RBAudioCdSourcePrivate *priv = AUDIOCD_SOURCE_GET_PRIVATE (source); RhythmDB *db; GVolume *volume; g_object_get (source, "volume", &volume, NULL); priv->device_path = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); g_object_unref (volume); db = get_db_for_source (source); rb_debug ("loading Audio CD from %s", priv->device_path); /* create a cdda gstreamer element, to get cd info from */ priv->cdda = gst_element_make_from_uri (GST_URI_SRC, "cdda://", NULL); if (!priv->cdda) { gdk_threads_enter (); rb_error_dialog (NULL, _("Couldn't load Audio CD"), _("Rhythmbox could not get access to the CD device.")); gdk_threads_leave (); goto error_out; } rb_debug ("cdda longname: %s", gst_element_factory_get_longname (gst_element_get_factory (priv->cdda))); g_object_set (G_OBJECT (priv->cdda), "device", priv->device_path, NULL); priv->pipeline = gst_pipeline_new ("pipeline"); priv->fakesink = gst_element_factory_make ("fakesink", "fakesink"); gst_bin_add_many (GST_BIN (priv->pipeline), priv->cdda, priv->fakesink, NULL); gst_element_link (priv->cdda, priv->fakesink); /* disable paranoia (if using cdparanoia) since we're only reading track information here. * this reduces cdparanoia's cache size, so the process is much faster. */ if (g_object_class_find_property (G_OBJECT_GET_CLASS (source), "paranoia-mode")) g_object_set (source, "paranoia-mode", 0, NULL); if (rb_audiocd_scan_songs (source, db)) rb_audiocd_load_metadata (source, db); error_out: g_object_unref (db); g_object_unref (source); return NULL; }
/** * ges_pipeline_set_render_settings: * @pipeline: a #GESPipeline * @output_uri: the URI to which the timeline will be rendered * @profile: the #GstEncodingProfile to use to render the timeline. * * Specify where the pipeline shall be rendered and with what settings. * * A copy of @profile and @output_uri will be done internally, the caller can * safely free those values afterwards. * * This method must be called before setting the pipeline mode to * #TIMELINE_MODE_RENDER * * Returns: %TRUE if the settings were aknowledged properly, else %FALSE */ gboolean ges_pipeline_set_render_settings (GESPipeline * pipeline, const gchar * output_uri, GstEncodingProfile * profile) { GError *err = NULL; GstEncodingProfile *set_profile; g_return_val_if_fail (GES_IS_PIPELINE (pipeline), FALSE); /* Clear previous URI sink if it existed */ /* FIXME : We should figure out if it was added to the pipeline, * and if so, remove it. */ if (pipeline->priv->urisink) { gst_object_unref (pipeline->priv->urisink); pipeline->priv->urisink = NULL; } pipeline->priv->urisink = gst_element_make_from_uri (GST_URI_SINK, output_uri, "urisink", &err); if (G_UNLIKELY (pipeline->priv->urisink == NULL)) { GST_ERROR_OBJECT (pipeline, "Couldn't not create sink for URI %s: '%s'", output_uri, ((err && err->message) ? err->message : "failed to create element")); g_clear_error (&err); return FALSE; } if (pipeline->priv->profile) gst_encoding_profile_unref (pipeline->priv->profile); g_object_set (pipeline->priv->encodebin, "avoid-reencoding", !(!(pipeline->priv->mode & TIMELINE_MODE_SMART_RENDER)), NULL); g_object_set (pipeline->priv->encodebin, "profile", profile, NULL); g_object_get (pipeline->priv->encodebin, "profile", &set_profile, NULL); if (set_profile == NULL) { GST_ERROR_OBJECT (pipeline, "Profile %" GST_PTR_FORMAT " could no be set", profile); return FALSE; } /* We got a referencer when getting back the profile */ pipeline->priv->profile = profile; return TRUE; }
static gboolean gst_uri_downloader_set_uri (GstUriDownloader * downloader, const gchar * uri) { GstPad *pad; if (!gst_uri_is_valid (uri)) return FALSE; if (downloader->urisrc) { GstURIHandler *uri_handler = GST_URI_HANDLER (downloader->urisrc); if (gst_uri_handler_set_uri (uri_handler, uri, NULL)) { GST_DEBUG_OBJECT (downloader, "reusing element %s to download URI %s", GST_ELEMENT_NAME (downloader->urisrc), uri); return TRUE; } gst_element_set_state (downloader->urisrc, GST_STATE_NULL); gst_object_unref (downloader->urisrc); } GST_DEBUG_OBJECT (downloader, "creating source element for URI %s", uri); downloader->urisrc = gst_element_make_from_uri (GST_URI_SRC, uri, NULL, NULL); if (!downloader->urisrc) { GST_ERROR_OBJECT (downloader, "no element can handle URI %s", uri); return FALSE; } /* add a sync handler for the bus messages to detect errors */ gst_element_set_bus (downloader->urisrc, downloader->bus); gst_bus_set_sync_handler (downloader->bus, gst_uri_downloader_bus_handler, downloader, NULL); pad = gst_element_get_static_pad (downloader->urisrc, "src"); gst_pad_link_full (pad, downloader->pad, GST_PAD_LINK_CHECK_NOTHING); gst_object_unref (pad); return TRUE; }
gboolean sj_extractor_supports_encoding (GError **error) { GstElement *element = NULL; element = gst_element_make_from_uri (GST_URI_SRC, "cdda://1", "test", NULL); if (element == NULL) { g_set_error (error, SJ_ERROR, SJ_ERROR_INTERNAL_ERROR, _("The plugin necessary for CD access was not found")); return FALSE; } g_object_unref (element); element = gst_element_factory_make (FILE_SINK, "test"); if (element == NULL) { g_set_error (error, SJ_ERROR, SJ_ERROR_INTERNAL_ERROR, _("The plugin necessary for file access was not found")); return FALSE; } g_object_unref (element); return TRUE; }
GstElement * rygel_gst_utils_create_source_for_uri (const gchar *uri) { GstElement *src; g_return_val_if_fail (uri != NULL, NULL); src = gst_element_make_from_uri (GST_URI_SRC, uri, NULL); if (src) { if (GST_OBJECT_IS_FLOATING (GST_OBJECT (src))) { gst_object_ref_sink (src); } if (g_object_class_find_property (G_OBJECT_GET_CLASS (src), "blocksize")) { g_object_set (src, "blocksize", (glong) 65536, NULL); } if (g_object_class_find_property (G_OBJECT_GET_CLASS (src), "tcp-timeout")) { g_object_set (src, "tcp-timeout", (gint64) 60000000, NULL); } } return src; }
static GstElement * kms_recorder_endpoint_get_sink (KmsRecorderEndpoint * self) { GObjectClass *sink_class; GstElement *sink = NULL; GParamSpec *pspec; GError *err = NULL; KMS_ELEMENT_LOCK (KMS_ELEMENT (self)); if (KMS_URI_ENDPOINT (self)->uri == NULL) goto no_uri; if (!gst_uri_is_valid (KMS_URI_ENDPOINT (self)->uri)) goto invalid_uri; sink = gst_element_make_from_uri (GST_URI_SINK, KMS_URI_ENDPOINT (self)->uri, NULL, &err); if (sink == NULL) { /* Some elements have no URI handling capabilities though they can */ /* handle them. We try to find such element before failing to attend */ /* this request */ sink = kms_recorder_endpoint_get_sink_fallback (self); if (sink == NULL) goto no_sink; g_clear_error (&err); } /* Try to configure the sink element */ sink_class = G_OBJECT_GET_CLASS (sink); pspec = g_object_class_find_property (sink_class, "location"); if (pspec != NULL && G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_STRING) { if (g_strcmp0 (GST_OBJECT_NAME (gst_element_get_factory (sink)), "filesink") == 0) { /* Work around for filesink elements */ gchar *location = gst_uri_get_location (KMS_URI_ENDPOINT (self)->uri); GST_DEBUG_OBJECT (sink, "filesink location=%s", location); g_object_set (sink, "location", location, NULL); g_free (location); } else { GST_DEBUG_OBJECT (sink, "configuring location=%s", KMS_URI_ENDPOINT (self)->uri); g_object_set (sink, "location", KMS_URI_ENDPOINT (self)->uri, NULL); } } goto end; no_uri: { GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS, ("No URI specified to record to."), GST_ERROR_SYSTEM); goto end; } invalid_uri: { GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS, ("Invalid URI \"%s\".", KMS_URI_ENDPOINT (self)->uri), GST_ERROR_SYSTEM); g_clear_error (&err); goto end; } no_sink: { /* whoops, could not create the sink element, dig a little deeper to * figure out what might be wrong. */ if (err != NULL && err->code == GST_URI_ERROR_UNSUPPORTED_PROTOCOL) { gchar *prot; prot = gst_uri_get_protocol (KMS_URI_ENDPOINT (self)->uri); if (prot == NULL) goto invalid_uri; GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS, ("No URI handler implemented for \"%s\".", prot), GST_ERROR_SYSTEM); g_free (prot); } else { GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS, ("%s", (err) ? err->message : "URI was not accepted by any element"), GST_ERROR_SYSTEM); } g_clear_error (&err); goto end; } end: KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self)); return sink; }
static void build_pipeline (SjExtractor *extractor) { SjExtractorPrivate *priv; GstBus *bus; g_return_if_fail (SJ_IS_EXTRACTOR (extractor)); priv = extractor->priv; if (priv->pipeline != NULL) { gst_object_unref (GST_OBJECT (priv->pipeline)); } priv->pipeline = gst_pipeline_new ("pipeline"); bus = gst_element_get_bus (priv->pipeline); gst_bus_add_signal_watch (bus); g_signal_connect (G_OBJECT (bus), "message::error", G_CALLBACK (error_cb), extractor); /* Read from CD */ priv->cdsrc = gst_element_make_from_uri (GST_URI_SRC, "cdda://1", "cd_src", NULL); if (priv->cdsrc == NULL) { g_set_error (&priv->construct_error, SJ_ERROR, SJ_ERROR_INTERNAL_ERROR, _("Could not create GStreamer CD reader")); return; } g_object_set (G_OBJECT (priv->cdsrc), "device", priv->device_path, NULL); if (g_object_class_find_property (G_OBJECT_GET_CLASS (priv->cdsrc), "paranoia-mode")) { g_object_set (G_OBJECT (priv->cdsrc), "paranoia-mode", priv->paranoia_mode, NULL); } /* Get the track format for seeking later */ priv->track_format = gst_format_get_by_nick ("track"); g_assert (priv->track_format != 0); /* Encode */ priv->encodebin = build_encoder (extractor); if (priv->encodebin == NULL) { g_set_error (&priv->construct_error, SJ_ERROR, SJ_ERROR_INTERNAL_ERROR, _("Could not create GStreamer encoders for %s"), gst_encoding_profile_get_name (priv->profile)); return; } /* Connect to the eos so we know when its finished */ g_signal_connect (bus, "message::eos", G_CALLBACK (eos_cb), extractor); /* Write to disk */ priv->filesink = gst_element_factory_make (FILE_SINK, "file_sink"); if (priv->filesink == NULL) { g_set_error (&priv->construct_error, SJ_ERROR, SJ_ERROR_INTERNAL_ERROR, _("Could not create GStreamer file output")); return; } #if 0 g_signal_connect (G_OBJECT (priv->filesink), "allow-overwrite", G_CALLBACK (just_say_yes), extractor); #endif /* Add the elements to the pipeline */ gst_bin_add_many (GST_BIN (priv->pipeline), priv->cdsrc, priv->encodebin, priv->filesink, NULL); /* Link it all together */ if (!gst_element_link_many (priv->cdsrc, priv->encodebin, priv->filesink, NULL)) { g_set_error (&priv->construct_error, SJ_ERROR, SJ_ERROR_INTERNAL_ERROR, _("Could not link pipeline")); return; } priv->rebuild_pipeline = FALSE; }
static gboolean gst_ss_demux_create_download_pipe (GstSSDemux * demux, GstSSDemuxStream *stream, const gchar * uri, guint64 start_ts) { gchar *name = NULL; GstCaps *caps = NULL; if (!gst_uri_is_valid (uri)) return FALSE; name = g_strdup_printf("%s-%s", stream->name, "downloader"); stream->pipe = gst_pipeline_new (name); if (!stream->pipe) { GST_ERROR_OBJECT (demux, "failed to create pipeline"); return FALSE; } g_free(name); name = g_strdup_printf("%s-%s", stream->name, "httpsrc"); GST_DEBUG ("Creating source element for the URI:%s", uri); stream->urisrc = gst_element_make_from_uri (GST_URI_SRC, uri, name); if (!stream->urisrc) { GST_ERROR_OBJECT (demux, "failed to create urisrc"); return FALSE; } g_free(name); if (GST_SSM_PARSE_IS_LIVE_PRESENTATION(demux->parser)) g_object_set (G_OBJECT (stream->urisrc), "is-live", TRUE, NULL); else g_object_set (G_OBJECT (stream->urisrc), "is-live", FALSE, NULL); name = g_strdup_printf("%s-%s", stream->name, "parser"); stream->parser = gst_element_factory_make ("piffdemux", name); if (!stream->parser) { GST_ERROR_OBJECT (demux, "failed to create piffdemux element"); return FALSE; } caps = ssm_parse_get_stream_caps (demux->parser, stream->type); GST_INFO_OBJECT (stream->pad, "prepare caps = %s", gst_caps_to_string(caps)); g_object_set (G_OBJECT (stream->parser), "caps", caps, NULL); g_object_set (G_OBJECT (stream->parser), "start-ts", start_ts, NULL); g_object_set (G_OBJECT (stream->parser), "duration", GST_SSM_PARSE_GET_DURATION(demux->parser), NULL); g_object_set (G_OBJECT (stream->parser), "is-live", GST_SSM_PARSE_IS_LIVE_PRESENTATION(demux->parser), NULL); g_object_set (G_OBJECT (stream->parser), "lookahead-count", GST_SSM_PARSE_LOOKAHEAD_COUNT(demux->parser), NULL); g_signal_connect (stream->parser, "live-param", G_CALLBACK (gst_ss_demux_append_live_params), stream); g_free(name); name = g_strdup_printf("%s-%s", stream->name, "sink"); stream->sink = gst_element_factory_make ("appsink", name); if (!stream->sink) { GST_ERROR_OBJECT (demux, "failed to create appsink element"); return FALSE; } g_object_set (G_OBJECT (stream->sink), "emit-signals", TRUE, "sync", FALSE, NULL); g_signal_connect (stream->sink, "new-buffer", G_CALLBACK (gst_ssm_demux_on_new_buffer), stream); g_free(name); gst_bin_add_many (GST_BIN (stream->pipe), stream->urisrc, stream->parser, stream->sink, NULL); if (!gst_element_link_many (stream->urisrc, stream->parser, stream->sink, NULL)) { GST_ERROR ("failed to link elements..."); return FALSE; } stream->bus = gst_pipeline_get_bus (GST_PIPELINE (stream->pipe)); gst_bus_add_watch (stream->bus, (GstBusFunc)gst_ss_demux_download_bus_cb, stream); gst_object_unref (stream->bus); return TRUE; }
static gboolean brasero_normalize_build_pipeline (BraseroNormalize *normalize, const gchar *uri, GstElement *analysis, GError **error) { GstBus *bus = NULL; GstElement *source; GstElement *decode; GstElement *pipeline; GstElement *sink = NULL; GstElement *convert = NULL; GstElement *resample = NULL; BraseroNormalizePrivate *priv; priv = BRASERO_NORMALIZE_PRIVATE (normalize); BRASERO_JOB_LOG (normalize, "Creating new pipeline"); /* create filesrc ! decodebin ! audioresample ! audioconvert ! rganalysis ! fakesink */ pipeline = gst_pipeline_new (NULL); priv->pipeline = pipeline; /* a new source is created */ source = gst_element_make_from_uri (GST_URI_SRC, uri, NULL, NULL); if (source == NULL) { g_set_error (error, BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("%s element could not be created"), "\"Source\""); goto error; } gst_bin_add (GST_BIN (priv->pipeline), source); g_object_set (source, "typefind", FALSE, NULL); /* decode */ decode = gst_element_factory_make ("decodebin", NULL); if (decode == NULL) { g_set_error (error, BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("%s element could not be created"), "\"Decodebin\""); goto error; } gst_bin_add (GST_BIN (pipeline), decode); priv->decode = decode; if (!gst_element_link (source, decode)) { BRASERO_JOB_LOG (normalize, "Elements could not be linked"); g_set_error (error, BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("Impossible to link plugin pads")); goto error; } /* audioconvert */ convert = gst_element_factory_make ("audioconvert", NULL); if (convert == NULL) { g_set_error (error, BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("%s element could not be created"), "\"Audioconvert\""); goto error; } gst_bin_add (GST_BIN (pipeline), convert); /* audioresample */ resample = gst_element_factory_make ("audioresample", NULL); if (resample == NULL) { g_set_error (error, BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("%s element could not be created"), "\"Audioresample\""); goto error; } gst_bin_add (GST_BIN (pipeline), resample); priv->resample = resample; /* rganalysis: set the number of tracks to be expected */ priv->analysis = analysis; gst_bin_add (GST_BIN (pipeline), analysis); /* sink */ sink = gst_element_factory_make ("fakesink", NULL); if (!sink) { g_set_error (error, BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("%s element could not be created"), "\"Fakesink\""); goto error; } gst_bin_add (GST_BIN (pipeline), sink); g_object_set (sink, "sync", FALSE, NULL); /* link everything */ g_signal_connect (G_OBJECT (decode), "pad-added", G_CALLBACK (brasero_normalize_new_decoded_pad_cb), normalize); if (!gst_element_link_many (resample, convert, analysis, sink, NULL)) { g_set_error (error, BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("Impossible to link plugin pads")); } /* connect to the bus */ bus = gst_pipeline_get_bus (GST_PIPELINE (priv->pipeline)); gst_bus_add_watch (bus, (GstBusFunc) brasero_normalize_bus_messages, normalize); gst_object_unref (bus); gst_element_set_state (priv->pipeline, GST_STATE_PLAYING); return TRUE; error: if (error && (*error)) BRASERO_JOB_LOG (normalize, "can't create object : %s \n", (*error)->message); gst_object_unref (GST_OBJECT (pipeline)); return FALSE; }
SongLoader::Result SongLoader::LoadAudioCD() { #ifdef HAVE_AUDIOCD // Create gstreamer cdda element GstElement* cdda = gst_element_make_from_uri (GST_URI_SRC, "cdda://", NULL); if (cdda == NULL) { qLog(Error) << "Error while creating CDDA GstElement"; return Error; } // Change the element's state to ready and paused, to be able to query it if (gst_element_set_state(cdda, GST_STATE_READY) == GST_STATE_CHANGE_FAILURE || gst_element_set_state(cdda, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) { qLog(Error) << "Error while changing CDDA GstElement's state"; gst_element_set_state(cdda, GST_STATE_NULL); gst_object_unref(GST_OBJECT(cdda)); return Error; } // Get number of tracks GstFormat fmt = gst_format_get_by_nick ("track"); GstFormat out_fmt = fmt; gint64 num_tracks = 0; if (!gst_element_query_duration (cdda, &out_fmt, &num_tracks) || out_fmt != fmt) { qLog(Error) << "Error while querying cdda GstElement"; gst_object_unref(GST_OBJECT(cdda)); return Error; } for (int track_number = 1; track_number <= num_tracks; track_number++) { // Init song Song song; guint64 duration = 0; // quint64 == ulonglong and guint64 == ulong, therefore we must cast if (gst_tag_list_get_uint64 (GST_CDDA_BASE_SRC(cdda)->tracks[track_number-1].tags, GST_TAG_DURATION, &duration)) { song.set_length_nanosec((quint64)duration); } song.set_valid(true); song.set_filetype(Song::Type_Cdda); song.set_url(QUrl(QString("cdda://%1").arg(track_number))); song.set_title(QString("Track %1").arg(track_number)); song.set_track(track_number); songs_ << song; } // Generate MusicBrainz DiscId gst_tag_register_musicbrainz_tags(); GstElement *pipe = gst_pipeline_new ("pipeline"); gst_bin_add (GST_BIN (pipe), cdda); gst_element_set_state (pipe, GST_STATE_READY); gst_element_set_state (pipe, GST_STATE_PAUSED); GstMessage *msg = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipe), GST_CLOCK_TIME_NONE, GST_MESSAGE_TAG); GstTagList *tags = NULL; gst_message_parse_tag (msg, &tags); char *string_mb = NULL; if (gst_tag_list_get_string (tags, GST_TAG_CDDA_MUSICBRAINZ_DISCID, &string_mb)) { QString musicbrainz_discid(string_mb); qLog(Info) << "MusicBrainz discid: " << musicbrainz_discid; MusicBrainzClient *musicbrainz_client = new MusicBrainzClient(this); connect(musicbrainz_client, SIGNAL(Finished(const QString&, const QString&, MusicBrainzClient::ResultList)), SLOT(AudioCDTagsLoaded(const QString&, const QString&, MusicBrainzClient::ResultList))); musicbrainz_client->StartDiscIdRequest(musicbrainz_discid); g_free(string_mb); } // Clean all the Gstreamer objects we have used: we don't need them anymore gst_object_unref(GST_OBJECT(cdda)); gst_element_set_state (pipe, GST_STATE_NULL); gst_object_unref(GST_OBJECT(pipe)); gst_object_unref(GST_OBJECT(msg)); gst_object_unref(GST_OBJECT(tags)); return Success; #else // HAVE_AUDIOCD return Error; #endif }
/** * ges_pipeline_set_render_settings: * @pipeline: a #GESPipeline * @output_uri: the URI to which the timeline will be rendered * @profile: the #GstEncodingProfile to use to render the timeline. * * Specify where the pipeline shall be rendered and with what settings. * * A copy of @profile and @output_uri will be done internally, the caller can * safely free those values afterwards. * * This method must be called before setting the pipeline mode to * #GES_PIPELINE_MODE_RENDER * * Returns: %TRUE if the settings were aknowledged properly, else %FALSE */ gboolean ges_pipeline_set_render_settings (GESPipeline * pipeline, const gchar * output_uri, GstEncodingProfile * profile) { GError *err = NULL; GstEncodingProfile *set_profile; g_return_val_if_fail (GES_IS_PIPELINE (pipeline), FALSE); /* FIXME Properly handle multi track, for now GESPipeline * only hanles single track per type, so we should just set the * presence to 1. */ if (GST_IS_ENCODING_CONTAINER_PROFILE (profile)) { const GList *tmpprofiles = gst_encoding_container_profile_get_profiles (GST_ENCODING_CONTAINER_PROFILE (profile)); GList *tmptrack, *tracks = ges_timeline_get_tracks (pipeline->priv->timeline); for (; tmpprofiles; tmpprofiles = tmpprofiles->next) { for (tmptrack = tracks; tmptrack; tmptrack = tmptrack->next) { if ((GST_IS_ENCODING_AUDIO_PROFILE (tmpprofiles->data) && GES_IS_AUDIO_TRACK (tmptrack->data)) || (GST_IS_ENCODING_VIDEO_PROFILE (tmpprofiles->data) && GES_IS_VIDEO_TRACK (tmptrack->data))) { GST_DEBUG_OBJECT (pipeline, "Setting presence to 1!"); gst_encoding_profile_set_presence (tmpprofiles->data, 1); gst_encoding_profile_set_allow_dynamic_output (tmpprofiles->data, FALSE); } } } g_list_free_full (tracks, gst_object_unref); } /* Clear previous URI sink if it existed */ /* FIXME : We should figure out if it was added to the pipeline, * and if so, remove it. */ if (pipeline->priv->urisink) { gst_object_unref (pipeline->priv->urisink); pipeline->priv->urisink = NULL; } pipeline->priv->urisink = gst_element_make_from_uri (GST_URI_SINK, output_uri, "urisink", &err); if (G_UNLIKELY (pipeline->priv->urisink == NULL)) { GST_ERROR_OBJECT (pipeline, "Couldn't not create sink for URI %s: '%s'", output_uri, ((err && err->message) ? err->message : "failed to create element")); g_clear_error (&err); return FALSE; } if (pipeline->priv->profile) gst_encoding_profile_unref (pipeline->priv->profile); g_object_set (pipeline->priv->encodebin, "avoid-reencoding", !(!(pipeline->priv->mode & GES_PIPELINE_MODE_SMART_RENDER)), NULL); g_object_set (pipeline->priv->encodebin, "profile", profile, NULL); g_object_get (pipeline->priv->encodebin, "profile", &set_profile, NULL); if (set_profile == NULL) { GST_ERROR_OBJECT (pipeline, "Profile %" GST_PTR_FORMAT " could no be set", profile); return FALSE; } /* We got a referencer when getting back the profile */ pipeline->priv->profile = profile; return TRUE; }
/*! * \brief CvCapture_GStreamer::open Open the given file with gstreamer * \param type CvCapture type. One of CV_CAP_GSTREAMER_* * \param filename Filename to open in case of CV_CAP_GSTREAMER_FILE * \return boolean. Specifies if opening was succesful. * * In case of CV_CAP_GSTREAMER_V4L(2), a pipelin is constructed as follows: * v4l2src ! autoconvert ! appsink * * * The 'filename' parameter is not limited to filesystem paths, and may be one of the following: * * - a normal filesystem path: * e.g. video.avi or /path/to/video.avi or C:\\video.avi * - an uri: * e.g. file:///path/to/video.avi or rtsp:///path/to/stream.asf * - a gstreamer pipeline description: * e.g. videotestsrc ! videoconvert ! appsink * the appsink name should be either 'appsink0' (the default) or 'opencvsink' * * When dealing with a file, CvCapture_GStreamer will not drop frames if the grabbing interval * larger than the framerate period. (Unlike the uri or manual pipeline description, which assume * a live source) * * The pipeline will only be started whenever the first frame is grabbed. Setting pipeline properties * is really slow if we need to restart the pipeline over and over again. * * TODO: the 'type' parameter is imo unneeded. for v4l2, filename 'v4l2:///dev/video0' can be used. * I expect this to be the same for CV_CAP_GSTREAMER_1394. Is anyone actually still using v4l (v1)? * */ bool CvCapture_GStreamer::open( int type, const char* filename ) { CV_FUNCNAME("cvCaptureFromCAM_GStreamer"); __BEGIN__; gst_initializer::init(); bool file = false; bool stream = false; bool manualpipeline = false; char *uri = NULL; uridecodebin = NULL; GstElementFactory * testfac; GstStateChangeReturn status; if (type == CV_CAP_GSTREAMER_V4L){ testfac = gst_element_factory_find("v4lsrc"); if (!testfac){ return false; } g_object_unref(G_OBJECT(testfac)); filename = "v4lsrc ! "COLOR_ELEM" ! appsink"; } if (type == CV_CAP_GSTREAMER_V4L2){ testfac = gst_element_factory_find("v4l2src"); if (!testfac){ return false; } g_object_unref(G_OBJECT(testfac)); filename = "v4l2src ! "COLOR_ELEM" ! appsink"; } // test if we have a valid uri. If so, open it with an uridecodebin // else, we might have a file or a manual pipeline. // if gstreamer cannot parse the manual pipeline, we assume we were given and // ordinary file path. if(!gst_uri_is_valid(filename)) { uri = realpath(filename, NULL); stream = false; if(uri) { uri = g_filename_to_uri(uri, NULL, NULL); if(uri) { file = true; } else { CV_WARN("GStreamer: Error opening file\n"); close(); return false; } } else { GError *err = NULL; uridecodebin = gst_parse_launch(filename, &err); if(!uridecodebin) { fprintf(stderr, "GStreamer: Error opening bin: %s\n", err->message); return false; } stream = true; manualpipeline = true; } } else { stream = true; uri = g_strdup(filename); } bool element_from_uri = false; if(!uridecodebin) { // At this writing, the v4l2 element (and maybe others too) does not support caps renegotiation. // This means that we cannot use an uridecodebin when dealing with v4l2, since setting // capture properties will not work. // The solution (probably only until gstreamer 1.2) is to make an element from uri when dealing with v4l2. gchar * protocol = gst_uri_get_protocol(uri); if (!strcasecmp(protocol , "v4l2")) { #if GST_VERSION_MAJOR == 0 uridecodebin = gst_element_make_from_uri(GST_URI_SRC, uri, "src"); #else uridecodebin = gst_element_make_from_uri(GST_URI_SRC, uri, "src", NULL); #endif element_from_uri = true; }else{ uridecodebin = gst_element_factory_make("uridecodebin", NULL); g_object_set(G_OBJECT(uridecodebin), "uri", uri, NULL); } g_free(protocol); if(!uridecodebin) { //fprintf(stderr, "GStreamer: Error opening bin: %s\n", err->message); close(); return false; } } if(manualpipeline) { GstIterator *it = NULL; #if GST_VERSION_MAJOR == 0 it = gst_bin_iterate_sinks(GST_BIN(uridecodebin)); if(gst_iterator_next(it, (gpointer *)&sink) != GST_ITERATOR_OK) { CV_ERROR(CV_StsError, "GStreamer: cannot find appsink in manual pipeline\n"); return false; } #else it = gst_bin_iterate_sinks (GST_BIN(uridecodebin)); gboolean done = FALSE; GstElement *element = NULL; gchar* name = NULL; GValue value = G_VALUE_INIT; while (!done) { switch (gst_iterator_next (it, &value)) { case GST_ITERATOR_OK: element = GST_ELEMENT (g_value_get_object (&value)); name = gst_element_get_name(element); if (name){ if(strstr(name, "opencvsink") != NULL || strstr(name, "appsink") != NULL) { sink = GST_ELEMENT ( gst_object_ref (element) ); done = TRUE; } g_free(name); } g_value_unset (&value); break; case GST_ITERATOR_RESYNC: gst_iterator_resync (it); break; case GST_ITERATOR_ERROR: case GST_ITERATOR_DONE: done = TRUE; break; } } gst_iterator_free (it); if (!sink){ CV_ERROR(CV_StsError, "GStreamer: cannot find appsink in manual pipeline\n"); return false; } #endif pipeline = uridecodebin; } else { pipeline = gst_pipeline_new(NULL); // videoconvert (in 0.10: ffmpegcolorspace, in 1.x autovideoconvert) //automatically selects the correct colorspace conversion based on caps. color = gst_element_factory_make(COLOR_ELEM, NULL); sink = gst_element_factory_make("appsink", NULL); gst_bin_add_many(GST_BIN(pipeline), uridecodebin, color, sink, NULL); if(element_from_uri) { if(!gst_element_link(uridecodebin, color)) { CV_ERROR(CV_StsError, "GStreamer: cannot link color -> sink\n"); gst_object_unref(pipeline); pipeline = NULL; return false; } }else{ g_signal_connect(uridecodebin, "pad-added", G_CALLBACK(newPad), color); } if(!gst_element_link(color, sink)) { CV_ERROR(CV_StsError, "GStreamer: cannot link color -> sink\n"); gst_object_unref(pipeline); pipeline = NULL; return false; } } //TODO: is 1 single buffer really high enough? gst_app_sink_set_max_buffers (GST_APP_SINK(sink), 1); gst_app_sink_set_drop (GST_APP_SINK(sink), stream); //do not emit signals: all calls will be synchronous and blocking gst_app_sink_set_emit_signals (GST_APP_SINK(sink), 0); #if GST_VERSION_MAJOR == 0 caps = gst_caps_new_simple("video/x-raw-rgb", "bpp", G_TYPE_INT, 24, "red_mask", G_TYPE_INT, 0x0000FF, "green_mask", G_TYPE_INT, 0x00FF00, "blue_mask", G_TYPE_INT, 0xFF0000, NULL); #else // support 1 and 3 channel 8 bit data, as well as bayer (also 1 channel, 8bit) caps = gst_caps_from_string("video/x-raw, format=(string){BGR, GRAY8}; video/x-bayer,format=(string){rggb,bggr,grbg,gbrg}"); #endif gst_app_sink_set_caps(GST_APP_SINK(sink), caps); gst_caps_unref(caps); // For video files only: set pipeline to PAUSED state to get its duration if (file) { status = gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PAUSED); if (status == GST_STATE_CHANGE_ASYNC) { // wait for status update GstState st1; GstState st2; status = gst_element_get_state(pipeline, &st1, &st2, GST_CLOCK_TIME_NONE); } if (status == GST_STATE_CHANGE_FAILURE) { handleMessage(pipeline); gst_object_unref(pipeline); pipeline = NULL; CV_ERROR(CV_StsError, "GStreamer: unable to start pipeline\n"); return false; } GstFormat format; format = GST_FORMAT_DEFAULT; #if GST_VERSION_MAJOR == 0 if(!gst_element_query_duration(sink, &format, &duration)) #else if(!gst_element_query_duration(sink, format, &duration)) #endif { handleMessage(pipeline); CV_WARN("GStreamer: unable to query duration of stream"); duration = -1; return true; } } else { duration = -1; } __END__; return true; }
void CddaSongLoader::LoadSongsFromCdda() { QMutexLocker locker(&mutex_load_); cdio_ = cdio_open(url_.path().toLocal8Bit().constData(), DRIVER_DEVICE); if (cdio_ == nullptr) { return; } // Create gstreamer cdda element GError* error = nullptr; cdda_ = gst_element_make_from_uri(GST_URI_SRC, "cdda://", nullptr, &error); if (error) { qLog(Error) << error->code << QString::fromLocal8Bit(error->message); } if (cdda_ == nullptr) { return; } if (!url_.isEmpty()) { g_object_set(cdda_, "device", g_strdup(url_.path().toLocal8Bit().constData()), nullptr); } if (g_object_class_find_property (G_OBJECT_GET_CLASS (cdda_), "paranoia-mode")) { g_object_set (cdda_, "paranoia-mode", 0, NULL); } // Change the element's state to ready and paused, to be able to query it if (gst_element_set_state(cdda_, GST_STATE_READY) == GST_STATE_CHANGE_FAILURE || gst_element_set_state(cdda_, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) { gst_element_set_state(cdda_, GST_STATE_NULL); gst_object_unref(GST_OBJECT(cdda_)); return; } // Get number of tracks GstFormat fmt = gst_format_get_by_nick("track"); GstFormat out_fmt = fmt; gint64 num_tracks = 0; if (!gst_element_query_duration(cdda_, out_fmt, &num_tracks) || out_fmt != fmt) { qLog(Error) << "Error while querying cdda GstElement"; gst_object_unref(GST_OBJECT(cdda_)); return; } SongList songs; for (int track_number = 1; track_number <= num_tracks; track_number++) { // Init song Song song; song.set_id(track_number); song.set_valid(true); song.set_filetype(Song::Type_Cdda); song.set_url( GetUrlFromTrack(track_number)); song.set_title(QString("Track %1").arg(track_number)); song.set_track(track_number); songs << song; } emit SongsLoaded(songs); gst_tag_register_musicbrainz_tags(); GstElement* pipeline = gst_pipeline_new("pipeline"); GstElement* sink = gst_element_factory_make ("fakesink", NULL); gst_bin_add_many (GST_BIN (pipeline), cdda_, sink, NULL); gst_element_link (cdda_, sink); gst_element_set_state(pipeline, GST_STATE_READY); gst_element_set_state(pipeline, GST_STATE_PAUSED); // Get TOC and TAG messages GstMessage* msg = nullptr; GstMessage* msg_toc = nullptr; GstMessage* msg_tag = nullptr; while ((msg = gst_bus_timed_pop_filtered( GST_ELEMENT_BUS(pipeline), 2 * GST_SECOND, (GstMessageType)(GST_MESSAGE_TOC | GST_MESSAGE_TAG)))) { if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_TOC) { if (msg_toc) gst_message_unref(msg_toc); // Shouldn't happen, but just in case msg_toc = msg; } else if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_TAG) { if (msg_tag) gst_message_unref(msg_tag); msg_tag = msg; } } // Handle TOC message: get tracks duration if (msg_toc) { GstToc* toc; gst_message_parse_toc (msg_toc, &toc, nullptr); if (toc) { GList* entries = gst_toc_get_entries(toc); if (entries && songs.size() <= g_list_length (entries)) { int i = 0; for (GList* node = entries; node != nullptr; node = node->next) { GstTocEntry *entry = static_cast<GstTocEntry*>(node->data); quint64 duration = 0; gint64 start, stop; if (gst_toc_entry_get_start_stop_times (entry, &start, &stop)) duration = stop - start; songs[i++].set_length_nanosec(duration); } } } gst_message_unref(msg_toc); } emit SongsDurationLoaded(songs); // Handle TAG message: generate MusicBrainz DiscId if (msg_tag) { GstTagList* tags = nullptr; gst_message_parse_tag(msg_tag, &tags); char* string_mb = nullptr; if (gst_tag_list_get_string(tags, GST_TAG_CDDA_MUSICBRAINZ_DISCID, &string_mb)) { QString musicbrainz_discid(string_mb); qLog(Info) << "MusicBrainz discid: " << musicbrainz_discid; emit MusicBrainzDiscIdLoaded(musicbrainz_discid); g_free(string_mb); gst_message_unref(msg_tag); gst_tag_list_free(tags); } } gst_element_set_state(pipeline, GST_STATE_NULL); // This will also cause cdda_ to be unref'd. gst_object_unref(pipeline); }
/* * bt_wave_load_from_uri: * @self: the wave to load * @uri: the location to load from * * Load the wavedata from the @uri. * * Returns: %TRUE if the wavedata could be loaded */ static gboolean bt_wave_load_from_uri (const BtWave * const self, const gchar * const uri) { gboolean res = TRUE, done = FALSE; GstElement *pipeline; GstElement *src, *dec, *conv, *fmt, *sink; GstBus *bus = NULL; GstCaps *caps; GstMessage *msg; GstBtNote root_note = BT_WAVELEVEL_DEFAULT_ROOT_NOTE; GST_INFO ("about to load sample %s / %s", self->priv->uri, uri); // this leaks! //GST_INFO("current dir is %s", g_get_current_dir()); // check if the url is valid // if(!uri) goto invalid_uri; // create loader pipeline pipeline = gst_pipeline_new ("wave-loader"); src = gst_element_make_from_uri (GST_URI_SRC, uri, NULL, NULL); dec = gst_element_factory_make ("decodebin", NULL); conv = gst_element_factory_make ("audioconvert", NULL); fmt = gst_element_factory_make ("capsfilter", NULL); sink = gst_element_factory_make ("fdsink", NULL); // configure elements caps = gst_caps_new_simple ("audio/x-raw", "format", G_TYPE_STRING, GST_AUDIO_NE (S16), "layout", G_TYPE_STRING, "interleaved", "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL); g_object_set (fmt, "caps", caps, NULL); gst_caps_unref (caps); if ((self->priv->fd = g_file_open_tmp (NULL, NULL, NULL)) == -1) { res = FALSE; GST_WARNING ("Can't create tempfile."); goto Error; } g_object_set (sink, "fd", self->priv->fd, "sync", FALSE, NULL); // add and link gst_bin_add_many (GST_BIN (pipeline), src, dec, conv, fmt, sink, NULL); res = gst_element_link (src, dec); if (!res) { GST_WARNING_OBJECT (pipeline, "Can't link wave loader pipeline (src ! dec ! conv ! fmt ! sink)."); goto Error; } res = gst_element_link_many (conv, fmt, sink, NULL); if (!res) { GST_WARNING_OBJECT (pipeline, "Can't link wave loader pipeline (conf ! fmt ! sink)."); goto Error; } g_signal_connect (dec, "pad-added", G_CALLBACK (on_wave_loader_new_pad), (gpointer) conv); /* TODO(ensonic): during loading wave-data (into wavelevels) * - use statusbar for loader progress ("status" property like in song_io) * - should we do some size checks to avoid unpacking the audio track of a full * video on a machine with low memory * - if so, how to get real/virtual memory sizes? * mallinfo() not enough, sysconf()? */ bus = gst_element_get_bus (pipeline); // play and wait for EOS if (gst_element_set_state (pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { GST_WARNING_OBJECT (pipeline, "Can't set wave loader pipeline for %s / %s to playing", self->priv->uri, uri); gst_element_set_state (pipeline, GST_STATE_NULL); res = FALSE; goto Error; } else { GST_INFO_OBJECT (pipeline, "loading sample ..."); } /* load wave in sync mode, loading them async causes troubles in the * persistence code and makes testing complicated */ while (!done) { msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR | GST_MESSAGE_TAG, GST_CLOCK_TIME_NONE); if (!msg) break; switch (msg->type) { case GST_MESSAGE_EOS: res = done = TRUE; break; case GST_MESSAGE_ERROR: BT_GST_LOG_MESSAGE_ERROR (msg, NULL, NULL); res = FALSE; done = TRUE; break; case GST_MESSAGE_TAG:{ GstTagList *tags; #if GST_CHECK_VERSION(1,3,0) guint base_note; #endif gst_message_parse_tag (msg, &tags); #if GST_CHECK_VERSION(1,3,0) if (gst_tag_list_get_uint (tags, GST_TAG_MIDI_BASE_NOTE, &base_note)) { // map midi note -> BtNote gint octave = base_note / 12; gint tone = base_note - (octave * 12); root_note = GSTBT_NOTE_C_0 + (octave * 16) + tone; GST_INFO_OBJECT (GST_MESSAGE_SRC (msg), "root_note: %d (base_note: %u = oct: %d + tone: %d", root_note, base_note, octave, tone); } #endif gst_tag_list_unref (tags); break; } default: break; } gst_message_unref (msg); } if (res) { GstPad *pad; gint64 duration; guint64 length = 0; gint channels = 1, rate = GST_AUDIO_DEF_RATE; gpointer data = NULL; struct stat buf; res = FALSE; GST_INFO ("sample loaded"); // query length and convert to samples if (!gst_element_query_duration (pipeline, GST_FORMAT_TIME, &duration)) { GST_WARNING ("getting sample duration failed"); } // get caps for sample rate and channels if ((pad = gst_element_get_static_pad (fmt, "src"))) { GstCaps *caps = gst_pad_get_current_caps (pad); if (caps && GST_CAPS_IS_SIMPLE (caps)) { GstStructure *structure = gst_caps_get_structure (caps, 0); gst_structure_get_int (structure, "channels", &channels); gst_structure_get_int (structure, "rate", &rate); length = gst_util_uint64_scale (duration, (guint64) rate, GST_SECOND); } else { GST_WARNING ("No caps or format has not been fixed."); } if (caps) gst_caps_unref (caps); gst_object_unref (pad); } GST_INFO ("sample decoded: channels=%d, rate=%d, length=%" GST_TIME_FORMAT, channels, rate, GST_TIME_ARGS (duration)); if (!(fstat (self->priv->fd, &buf))) { if (lseek (self->priv->fd, 0, SEEK_SET) == 0) { if ((data = g_try_malloc (buf.st_size))) { /* mmap is unsave for removable drives :( * gpointer data=mmap(void *start, buf->st_size, PROT_READ, MAP_SHARED, self->priv->fd, 0); */ BtWavelevel *wavelevel; ssize_t bytes = read (self->priv->fd, data, buf.st_size); self->priv->channels = channels; g_object_notify (G_OBJECT (self), "channels"); wavelevel = bt_wavelevel_new (self->priv->song, self, root_note, (gulong) length, 0, length, rate, (gconstpointer) data); g_object_unref (wavelevel); GST_INFO ("sample loaded (%" G_GSSIZE_FORMAT "/%ld bytes)", bytes, buf.st_size); res = TRUE; } else { GST_WARNING ("sample is too long or empty (%ld bytes), not trying to load", buf.st_size); } } else { GST_WARNING ("can't seek to start of sample data"); } } else { GST_WARNING ("can't stat() sample"); } } Error: if (bus) gst_object_unref (bus); if (pipeline) { gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (pipeline); } if (!res) wave_io_free (self); return res; }
RCMusicMetaData *rc_tag_read_metadata(const gchar *uri) { GstElement *pipeline; GstElement *urisrc; GstElement *decodebin; GstElement *fakesink; GstPad *sink_pad; GstCaps *caps; GstStructure *structure; gint64 dura = 0; GstStateChangeReturn state_ret; GstMessage *msg; GstFormat fmt = GST_FORMAT_TIME; RCMusicMetaData *mmd; RCTagDecodedPadData decoded_pad_data; GstTagList *tags = NULL; gchar *encoding; const gchar *locale; if(uri==NULL) { return NULL; } if(rc_set_get_boolean("Metadata", "AutoEncodingDetect", NULL)) { locale = rc_player_get_locale(); if(strncmp(locale, "zh_CN", 5)==0) { g_setenv("GST_ID3_TAG_ENCODING", "GB18030:UTF-8", TRUE); g_setenv("GST_ID3V2_TAG_ENCODING", "GB18030:UTF-8", TRUE); rc_set_set_string("Metadata", "TagExEncoding", "GB18030:UTF-8"); } else if(strncmp(locale, "zh_TW", 5)==0) { g_setenv("GST_ID3_TAG_ENCODING", "BIG5:UTF-8", TRUE); g_setenv("GST_ID3V2_TAG_ENCODING", "BIG5:UTF-8", TRUE); rc_set_set_string("Metadata", "TagExEncoding", "BIG5:UTF-8"); } else if(strncmp(locale, "ja_JP", 5)==0) { g_setenv("GST_ID3_TAG_ENCODING", "ShiftJIS:UTF-8", TRUE); g_setenv("GST_ID3V2_TAG_ENCODING", "ShiftJIS:UTF-8", TRUE); rc_set_set_string("Metadata", "TagExEncoding", "ShiftJIS:UTF-8"); } } else { encoding = rc_set_get_string("Metadata", "TagExEncoding", NULL); if(encoding!=NULL && strlen(encoding)>0) { g_setenv("GST_ID3_TAG_ENCODING", encoding, TRUE); g_setenv("GST_ID3V2_TAG_ENCODING", encoding, TRUE); g_free(encoding); } } mmd = g_new0(RCMusicMetaData, 1); mmd->uri = g_strdup(uri); urisrc = gst_element_make_from_uri(GST_URI_SRC, mmd->uri, "urisrc"); if(urisrc==NULL) { rc_debug_module_perror(module_name, "Cannot load urisrc from " "given URI!"); g_free(mmd); return NULL; } pipeline = gst_pipeline_new("pipeline"); decodebin = gst_element_factory_make("decodebin2", NULL); if(decodebin==NULL) decodebin = gst_element_factory_make("decodebin", NULL); fakesink = gst_element_factory_make("fakesink", NULL); decoded_pad_data.pipeline = pipeline; decoded_pad_data.fakesink = fakesink; gst_bin_add_many(GST_BIN(pipeline), urisrc, decodebin, fakesink, NULL); gst_element_link(urisrc, decodebin); g_signal_connect(decodebin, "new-decoded-pad", G_CALLBACK(rc_tag_gst_new_decoded_pad_cb), &decoded_pad_data); gst_element_set_state(pipeline, GST_STATE_NULL); state_ret = gst_element_set_state(pipeline, GST_STATE_PAUSED); if(!state_ret) { if(pipeline!=NULL) gst_object_unref(GST_OBJECT(pipeline)); g_free(mmd); return NULL; } while(1) { msg = gst_bus_timed_pop_filtered(GST_ELEMENT_BUS(pipeline), GST_CLOCK_TIME_NONE, GST_MESSAGE_ASYNC_DONE | GST_MESSAGE_TAG | GST_MESSAGE_ERROR); if(GST_MESSAGE_TYPE(msg)!=GST_MESSAGE_TAG) break; gst_message_parse_tag(msg, &tags); rc_tag_get_tag(tags, mmd); gst_tag_list_free(tags); gst_message_unref(msg); } if(GST_MESSAGE_TYPE(msg)==GST_MESSAGE_ERROR) rc_debug_module_perror(module_name, "Cannot get tag!"); gst_message_unref(msg); gst_element_query_duration(pipeline, &fmt, &dura); sink_pad = gst_element_get_static_pad(fakesink, "sink"); if(sink_pad!=NULL) { caps = gst_pad_get_negotiated_caps(sink_pad); if(caps!=NULL) { structure = gst_caps_get_structure(caps, 0); gst_structure_get_int(structure, "rate", &mmd->samplerate); gst_structure_get_int(structure, "channels", &mmd->channels); gst_caps_unref(caps); } gst_object_unref(sink_pad); } mmd->length = dura; mmd->audio_flag = decoded_pad_data.audio_flag; mmd->video_flag = decoded_pad_data.video_flag; state_ret = gst_element_set_state(pipeline, GST_STATE_NULL); if(pipeline!=NULL) gst_object_unref(GST_OBJECT(pipeline)); return mmd; }
static gboolean gst_uri_downloader_set_uri (GstUriDownloader * downloader, const gchar * uri, const gchar * referer, gboolean compress, gboolean refresh, gboolean allow_cache) { GstPad *pad; GObjectClass *gobject_class; if (!gst_uri_is_valid (uri)) return FALSE; if (downloader->priv->urisrc) { gchar *old_protocol, *new_protocol; gchar *old_uri; old_uri = gst_uri_handler_get_uri (GST_URI_HANDLER (downloader->priv->urisrc)); old_protocol = gst_uri_get_protocol (old_uri); new_protocol = gst_uri_get_protocol (uri); if (!g_str_equal (old_protocol, new_protocol)) { gst_element_set_state (downloader->priv->urisrc, GST_STATE_NULL); gst_object_unref (downloader->priv->urisrc); downloader->priv->urisrc = NULL; GST_DEBUG_OBJECT (downloader, "Can't re-use old source element"); } else { GError *err = NULL; GST_DEBUG_OBJECT (downloader, "Re-using old source element"); if (!gst_uri_handler_set_uri (GST_URI_HANDLER (downloader->priv->urisrc), uri, &err)) { GST_DEBUG_OBJECT (downloader, "Failed to re-use old source element: %s", err->message); g_clear_error (&err); gst_element_set_state (downloader->priv->urisrc, GST_STATE_NULL); gst_object_unref (downloader->priv->urisrc); downloader->priv->urisrc = NULL; } } g_free (old_uri); g_free (old_protocol); g_free (new_protocol); } if (!downloader->priv->urisrc) { GST_DEBUG_OBJECT (downloader, "Creating source element for the URI:%s", uri); downloader->priv->urisrc = gst_element_make_from_uri (GST_URI_SRC, uri, NULL, NULL); if (!downloader->priv->urisrc) return FALSE; } gobject_class = G_OBJECT_GET_CLASS (downloader->priv->urisrc); if (g_object_class_find_property (gobject_class, "compress")) g_object_set (downloader->priv->urisrc, "compress", compress, NULL); if (g_object_class_find_property (gobject_class, "keep-alive")) g_object_set (downloader->priv->urisrc, "keep-alive", TRUE, NULL); if (g_object_class_find_property (gobject_class, "extra-headers")) { if (referer || refresh || !allow_cache) { GstStructure *extra_headers = gst_structure_new_empty ("headers"); if (referer) gst_structure_set (extra_headers, "Referer", G_TYPE_STRING, referer, NULL); if (!allow_cache) gst_structure_set (extra_headers, "Cache-Control", G_TYPE_STRING, "no-cache", NULL); else if (refresh) gst_structure_set (extra_headers, "Cache-Control", G_TYPE_STRING, "max-age=0", NULL); g_object_set (downloader->priv->urisrc, "extra-headers", extra_headers, NULL); gst_structure_free (extra_headers); } else { g_object_set (downloader->priv->urisrc, "extra-headers", NULL, NULL); } } /* add a sync handler for the bus messages to detect errors in the download */ gst_element_set_bus (GST_ELEMENT (downloader->priv->urisrc), downloader->priv->bus); gst_bus_set_sync_handler (downloader->priv->bus, gst_uri_downloader_bus_handler, downloader, NULL); pad = gst_element_get_static_pad (downloader->priv->urisrc, "src"); if (!pad) return FALSE; gst_pad_link (pad, downloader->priv->pad); gst_object_unref (pad); return TRUE; }
/* * Create a demux element, run a test using the input data and check * the output data */ void gst_adaptive_demux_test_run (const gchar * element_name, const gchar * manifest_uri, const GstAdaptiveDemuxTestCallbacks * callbacks, gpointer user_data) { GstBus *bus; GstElement *demux; GstElement *manifest_source; gboolean ret; GstStateChangeReturn stateChange; GstAdaptiveDemuxTestEnginePrivate *priv; priv = g_slice_new0 (GstAdaptiveDemuxTestEnginePrivate); priv->engine.output_streams = g_ptr_array_new_with_free_func (adaptive_demux_engine_stream_state_finalize); g_mutex_init (&priv->engine.lock); priv->callbacks = callbacks; priv->user_data = user_data; priv->engine.loop = g_main_loop_new (NULL, TRUE); fail_unless (priv->engine.loop != NULL); GST_TEST_LOCK (priv); priv->engine.pipeline = gst_pipeline_new ("pipeline"); fail_unless (priv->engine.pipeline != NULL); GST_DEBUG ("created pipeline %" GST_PTR_FORMAT, priv->engine.pipeline); /* register a callback to listen for error messages */ bus = gst_pipeline_get_bus (GST_PIPELINE (priv->engine.pipeline)); gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH); g_signal_connect (bus, "message::error", G_CALLBACK (on_ErrorMessageOnBus), priv); manifest_source = gst_element_make_from_uri (GST_URI_SRC, manifest_uri, NULL, NULL); fail_unless (manifest_source != NULL); priv->engine.manifest_source = manifest_source; demux = gst_check_setup_element (element_name); fail_unless (demux != NULL); priv->engine.demux = demux; GST_DEBUG ("created demux %" GST_PTR_FORMAT, demux); g_signal_connect (demux, "element-added", G_CALLBACK (on_demuxElementAdded), priv); g_signal_connect (demux, "pad-added", G_CALLBACK (on_demuxNewPad), priv); g_signal_connect (demux, "pad-removed", G_CALLBACK (on_demuxPadRemoved), priv); gst_bin_add_many (GST_BIN (priv->engine.pipeline), manifest_source, demux, NULL); ASSERT_OBJECT_REFCOUNT (manifest_source, element_name, 1); ASSERT_OBJECT_REFCOUNT (demux, element_name, 1); ret = gst_element_link (manifest_source, demux); fail_unless_equals_int (ret, TRUE); priv->engine.clock = gst_system_clock_obtain (); if (GST_IS_TEST_CLOCK (priv->engine.clock)) { /* * live tests will want to manipulate the clock, so they will register a * gst_test_clock as the system clock. * The on demand tests do not care about the clock, so they will let the * system clock to the default one. * If a gst_test_clock was installed as system clock, we register a * periodic callback to update its value. */ priv->clock_update_id = g_timeout_add (100, gst_adaptive_demux_update_test_clock, priv); } /* call a test callback before we start the pipeline */ if (callbacks->pre_test) (*callbacks->pre_test) (&priv->engine, priv->user_data); GST_TEST_UNLOCK (priv); GST_DEBUG ("Starting pipeline"); stateChange = gst_element_set_state (priv->engine.pipeline, GST_STATE_PAUSED); fail_unless (stateChange != GST_STATE_CHANGE_FAILURE); /* wait for completion of the move to PAUSED */ stateChange = gst_element_get_state (priv->engine.pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); fail_unless (stateChange != GST_STATE_CHANGE_FAILURE); g_idle_add ((GSourceFunc) start_pipeline_playing, priv); /* block until a callback calls g_main_loop_quit (engine.loop) */ GST_DEBUG ("main thread waiting for streams to finish"); g_main_loop_run (priv->engine.loop); GST_DEBUG ("main thread finished. Stopping pipeline"); /* no need to use gst_element_get_state as the move the GST_STATE_NULL is always synchronous */ stateChange = gst_element_set_state (priv->engine.pipeline, GST_STATE_NULL); fail_unless (stateChange != GST_STATE_CHANGE_FAILURE); GST_TEST_LOCK (priv); /* call a test callback after the stop of the pipeline */ if (callbacks->post_test) (*callbacks->post_test) (&priv->engine, priv->user_data); g_signal_handlers_disconnect_by_func (bus, G_CALLBACK (on_ErrorMessageOnBus), priv); gst_bus_remove_signal_watch (bus); g_signal_handlers_disconnect_by_func (demux, G_CALLBACK (on_demuxNewPad), priv); g_signal_handlers_disconnect_by_func (demux, G_CALLBACK (on_demuxPadRemoved), priv); GST_DEBUG ("main thread pipeline stopped"); if (priv->clock_update_id != 0) g_source_remove (priv->clock_update_id); gst_object_unref (priv->engine.clock); gst_object_unref (priv->engine.pipeline); priv->engine.pipeline = NULL; g_main_loop_unref (priv->engine.loop); g_ptr_array_unref (priv->engine.output_streams); gst_object_unref (bus); GST_TEST_UNLOCK (priv); g_mutex_clear (&priv->engine.lock); g_slice_free (GstAdaptiveDemuxTestEnginePrivate, priv); }
static gboolean brasero_transcode_create_pipeline (BraseroTranscode *transcode, GError **error) { gchar *uri; gboolean keep_dts; GstElement *decode; GstElement *source; GstBus *bus = NULL; GstCaps *filtercaps; GValue *value = NULL; GstElement *pipeline; GstElement *sink = NULL; BraseroJobAction action; GstElement *filter = NULL; GstElement *volume = NULL; GstElement *convert = NULL; BraseroTrack *track = NULL; GstElement *resample = NULL; BraseroTranscodePrivate *priv; priv = BRASERO_TRANSCODE_PRIVATE (transcode); BRASERO_JOB_LOG (transcode, "Creating new pipeline"); priv->set_active_state = 0; /* free the possible current pipeline and create a new one */ if (priv->pipeline) { gst_element_set_state (priv->pipeline, GST_STATE_NULL); gst_object_unref (G_OBJECT (priv->pipeline)); priv->link = NULL; priv->sink = NULL; priv->source = NULL; priv->convert = NULL; priv->pipeline = NULL; } /* create three types of pipeline according to the needs: (possibly adding grvolume) * - filesrc ! decodebin ! audioconvert ! fakesink (find size) and filesrc!mp3parse!fakesink for mp3s * - filesrc ! decodebin ! audioresample ! audioconvert ! audio/x-raw,format=S16BE,rate=44100 ! filesink * - filesrc ! decodebin ! audioresample ! audioconvert ! audio/x-raw,format=S16BE,rate=44100 ! fdsink */ pipeline = gst_pipeline_new (NULL); bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); gst_bus_add_watch (bus, (GstBusFunc) brasero_transcode_bus_messages, transcode); gst_object_unref (bus); /* source */ brasero_job_get_current_track (BRASERO_JOB (transcode), &track); uri = brasero_track_stream_get_source (BRASERO_TRACK_STREAM (track), TRUE); source = gst_element_make_from_uri (GST_URI_SRC, uri, NULL, NULL); g_free (uri); if (source == NULL) { g_set_error (error, BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, /* Translators: %s is the name of the object (as in * GObject) from the Gstreamer library that could * not be created */ _("%s element could not be created"), "\"Source\""); goto error; } gst_bin_add (GST_BIN (pipeline), source); g_object_set (source, "typefind", FALSE, NULL); /* sink */ brasero_job_get_action (BRASERO_JOB (transcode), &action); switch (action) { case BRASERO_JOB_ACTION_SIZE: if (priv->mp3_size_pipeline) return brasero_transcode_create_pipeline_size_mp3 (transcode, pipeline, source, error); sink = gst_element_factory_make ("fakesink", NULL); break; case BRASERO_JOB_ACTION_IMAGE: volume = brasero_transcode_create_volume (transcode, track); if (brasero_job_get_fd_out (BRASERO_JOB (transcode), NULL) != BRASERO_BURN_OK) { gchar *output; brasero_job_get_image_output (BRASERO_JOB (transcode), &output, NULL); sink = gst_element_factory_make ("filesink", NULL); g_object_set (sink, "location", output, NULL); g_free (output); } else { int fd; brasero_job_get_fd_out (BRASERO_JOB (transcode), &fd); sink = gst_element_factory_make ("fdsink", NULL); g_object_set (sink, "fd", fd, NULL); } break; default: goto error; } if (!sink) { g_set_error (error, BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("%s element could not be created"), "\"Sink\""); goto error; } gst_bin_add (GST_BIN (pipeline), sink); g_object_set (sink, "sync", FALSE, NULL); brasero_job_tag_lookup (BRASERO_JOB (transcode), BRASERO_SESSION_STREAM_AUDIO_FORMAT, &value); if (value) keep_dts = (g_value_get_int (value) & BRASERO_AUDIO_FORMAT_DTS) != 0; else keep_dts = FALSE; if (keep_dts && action == BRASERO_JOB_ACTION_IMAGE && (brasero_track_stream_get_format (BRASERO_TRACK_STREAM (track)) & BRASERO_AUDIO_FORMAT_DTS) != 0) { GstElement *wavparse; GstPad *sinkpad; BRASERO_JOB_LOG (transcode, "DTS wav pipeline"); /* FIXME: volume normalization won't work here. We'd need to * reencode it afterwards otherwise. */ /* This is a special case. This is DTS wav. So we only decode wav. */ wavparse = gst_element_factory_make ("wavparse", NULL); if (wavparse == NULL) { g_set_error (error, BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("%s element could not be created"), "\"Wavparse\""); goto error; } gst_bin_add (GST_BIN (pipeline), wavparse); if (!gst_element_link_many (source, wavparse, sink, NULL)) { g_set_error (error, BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("Impossible to link plugin pads")); goto error; } /* This is an ugly workaround for the lack of accuracy with * gstreamer. Yet this is unfortunately a necessary evil. */ /* FIXME: this does not look like it makes sense... (tpm) */ priv->pos = 0; priv->size = 0; sinkpad = gst_element_get_static_pad (sink, "sink"); priv->probe = gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_BUFFER, brasero_transcode_buffer_handler, transcode, NULL); gst_object_unref (sinkpad); priv->link = NULL; priv->sink = sink; priv->decode = NULL; priv->source = source; priv->convert = NULL; priv->pipeline = pipeline; gst_element_set_state (pipeline, GST_STATE_PLAYING); return TRUE; } /* audioconvert */ convert = gst_element_factory_make ("audioconvert", NULL); if (convert == NULL) { g_set_error (error, BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("%s element could not be created"), "\"Audioconvert\""); goto error; } gst_bin_add (GST_BIN (pipeline), convert); if (action == BRASERO_JOB_ACTION_IMAGE) { BraseroStreamFormat session_format; BraseroTrackType *output_type; output_type = brasero_track_type_new (); brasero_job_get_output_type (BRASERO_JOB (transcode), output_type); session_format = brasero_track_type_get_stream_format (output_type); brasero_track_type_free (output_type); /* audioresample */ resample = gst_element_factory_make ("audioresample", NULL); if (resample == NULL) { g_set_error (error, BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("%s element could not be created"), "\"Audioresample\""); goto error; } gst_bin_add (GST_BIN (pipeline), resample); /* filter */ filter = gst_element_factory_make ("capsfilter", NULL); if (!filter) { g_set_error (error, BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("%s element could not be created"), "\"Filter\""); goto error; } gst_bin_add (GST_BIN (pipeline), filter); filtercaps = gst_caps_new_full (gst_structure_new ("audio/x-raw", /* NOTE: we use little endianness only for libburn which requires little */ "format", G_TYPE_STRING, (session_format & BRASERO_AUDIO_FORMAT_RAW_LITTLE_ENDIAN) != 0 ? "S16LE" : "S16BE", "channels", G_TYPE_INT, 2, "rate", G_TYPE_INT, 44100, NULL), NULL); g_object_set (GST_OBJECT (filter), "caps", filtercaps, NULL); gst_caps_unref (filtercaps); } /* decode */ decode = gst_element_factory_make ("decodebin", NULL); if (decode == NULL) { g_set_error (error, BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("%s element could not be created"), "\"Decodebin\""); goto error; } gst_bin_add (GST_BIN (pipeline), decode); if (action == BRASERO_JOB_ACTION_IMAGE) { GstPad *sinkpad; gboolean res; if (!gst_element_link (source, decode)) { BRASERO_JOB_LOG (transcode, "Impossible to link plugin pads"); g_set_error (error, BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("Impossible to link plugin pads")); goto error; } priv->link = resample; g_signal_connect (G_OBJECT (decode), "pad-added", G_CALLBACK (brasero_transcode_new_decoded_pad_cb), transcode); if (volume) { gst_bin_add (GST_BIN (pipeline), volume); res = gst_element_link_many (resample, volume, convert, filter, sink, NULL); } else res = gst_element_link_many (resample, convert, filter, sink, NULL); if (!res) { BRASERO_JOB_LOG (transcode, "Impossible to link plugin pads"); g_set_error (error, BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("Impossible to link plugin pads")); goto error; } /* This is an ugly workaround for the lack of accuracy with * gstreamer. Yet this is unfortunately a necessary evil. */ /* FIXME: this does not look like it makes sense... (tpm) */ priv->pos = 0; priv->size = 0; sinkpad = gst_element_get_static_pad (sink, "sink"); priv->probe = gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_BUFFER, brasero_transcode_buffer_handler, transcode, NULL); gst_object_unref (sinkpad); } else { if (!gst_element_link (source, decode) || !gst_element_link (convert, sink)) { BRASERO_JOB_LOG (transcode, "Impossible to link plugin pads"); g_set_error (error, BRASERO_BURN_ERROR, BRASERO_BURN_ERROR_GENERAL, _("Impossible to link plugin pads")); goto error; } priv->link = convert; g_signal_connect (G_OBJECT (decode), "pad-added", G_CALLBACK (brasero_transcode_new_decoded_pad_cb), transcode); } priv->sink = sink; priv->decode = decode; priv->source = source; priv->convert = convert; priv->pipeline = pipeline; gst_element_set_state (pipeline, GST_STATE_PLAYING); return TRUE; error: if (error && (*error)) BRASERO_JOB_LOG (transcode, "can't create object : %s \n", (*error)->message); gst_object_unref (GST_OBJECT (pipeline)); return FALSE; }
void CddaDevice::Init() { QMutexLocker locker(&mutex_init_); song_count_ = 0; // Reset song count, in case it was already set cdio_ = cdio_open (url_.path().toLocal8Bit().constData(), DRIVER_DEVICE); if (cdio_ == NULL) { return; } // Create gstreamer cdda element cdda_ = gst_element_make_from_uri (GST_URI_SRC, "cdda://", NULL); if (cdda_ == NULL) { model_->Reset(); return; } GST_CDDA_BASE_SRC(cdda_)->device = g_strdup (url_.path().toLocal8Bit().constData()); // Change the element's state to ready and paused, to be able to query it if (gst_element_set_state(cdda_, GST_STATE_READY) == GST_STATE_CHANGE_FAILURE || gst_element_set_state(cdda_, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) { model_->Reset(); gst_element_set_state(cdda_, GST_STATE_NULL); gst_object_unref(GST_OBJECT(cdda_)); return; } // Get number of tracks GstFormat fmt = gst_format_get_by_nick ("track"); GstFormat out_fmt = fmt; gint64 num_tracks = 0; if (!gst_element_query_duration (cdda_, &out_fmt, &num_tracks) || out_fmt != fmt) { qLog(Error) << "Error while querying cdda GstElement"; model_->Reset(); gst_object_unref(GST_OBJECT(cdda_)); return; } SongList songs; for (int track_number = 1; track_number <= num_tracks; track_number++) { // Init song Song song; guint64 duration = 0; // quint64 == ulonglong and guint64 == ulong, therefore we must cast if (gst_tag_list_get_uint64 (GST_CDDA_BASE_SRC(cdda_)->tracks[track_number-1].tags, GST_TAG_DURATION, &duration)) { song.set_length_nanosec((quint64)duration); } song.set_id(track_number); song.set_valid(true); song.set_filetype(Song::Type_Cdda); song.set_url(QUrl(QString("cdda://%1/%2").arg(url_.path()).arg(track_number))); song.set_title(QString("Track %1").arg(track_number)); song.set_track(track_number); songs << song; } song_count_ = num_tracks; connect(this, SIGNAL(SongsDiscovered(const SongList&)), model_, SLOT(SongsDiscovered(const SongList&))); emit SongsDiscovered(songs); // Generate MusicBrainz DiscId gst_tag_register_musicbrainz_tags(); GstElement *pipe = gst_pipeline_new ("pipeline"); gst_bin_add (GST_BIN (pipe), cdda_); gst_element_set_state (pipe, GST_STATE_READY); gst_element_set_state (pipe, GST_STATE_PAUSED); GstMessage *msg = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipe), GST_CLOCK_TIME_NONE, GST_MESSAGE_TAG); GstTagList *tags = NULL; gst_message_parse_tag (msg, &tags); char *string_mb = NULL; if (gst_tag_list_get_string (tags, GST_TAG_CDDA_MUSICBRAINZ_DISCID, &string_mb)) { QString musicbrainz_discid(string_mb); qLog(Info) << "MusicBrainz discid: " << musicbrainz_discid; MusicBrainzClient *musicbrainz_client = new MusicBrainzClient(this); connect(musicbrainz_client, SIGNAL(Finished(const QString&, const QString&, MusicBrainzClient::ResultList)), SLOT(AudioCDTagsLoaded(const QString&, const QString&, MusicBrainzClient::ResultList))); musicbrainz_client->StartDiscIdRequest(musicbrainz_discid); g_free(string_mb); } // Clean all the Gstreamer objects we have used: we don't need them anymore gst_element_set_state (pipe, GST_STATE_NULL); // This will also cause cdda_ to be unref'd. gst_object_unref(GST_OBJECT(pipe)); gst_object_unref(GST_OBJECT(msg)); gst_tag_list_free(tags); }
static gboolean gst_transcoder_create_pipeline(GstTranscoder *transcoder, const char *input_uri, const char *output_uri, const gchar *encoder_pipeline) { GstElement *source_elem; GstElement *decoder_elem; GstElement *encoder_elem; GstElement *sink_elem; GstElement *conv_elem; GstPad *encoder_pad; if(transcoder == NULL) { return FALSE; } transcoder->pipeline = gst_pipeline_new("pipeline"); source_elem = gst_element_make_from_uri(GST_URI_SRC, input_uri, "source"); if(source_elem == NULL) { gst_transcoder_raise_error(transcoder, _("Could not create source element"), NULL); return FALSE; } decoder_elem = gst_element_factory_make("decodebin2", "decodebin2"); if(decoder_elem == NULL) { gst_transcoder_raise_error(transcoder, _("Could not create 'decodebin2' plugin"), NULL); return FALSE; } sink_elem = gst_element_make_from_uri(GST_URI_SINK, output_uri, "sink"); if(sink_elem == NULL) { gst_transcoder_raise_error(transcoder, _("Could not create sink element"), NULL); return FALSE; } transcoder->sink_bin = gst_bin_new("sinkbin"); if(transcoder->sink_bin == NULL) { gst_transcoder_raise_error(transcoder, _("Could not create 'sinkben' plugin"), NULL); return FALSE; } conv_elem = gst_element_factory_make("audioconvert", "audioconvert"); if(conv_elem == NULL) { gst_transcoder_raise_error(transcoder, _("Could not create 'audioconvert' plugin"), NULL); return FALSE; } encoder_elem = gst_transcoder_build_encoder(encoder_pipeline); if(encoder_elem == NULL) { gst_transcoder_raise_error(transcoder, _("Could not create encoding pipeline"), encoder_pipeline); return FALSE; } encoder_pad = gst_element_get_pad(conv_elem, "sink"); if(encoder_pad == NULL) { gst_transcoder_raise_error(transcoder, _("Could not get sink pad from encoder"), NULL); return FALSE; } gst_bin_add_many(GST_BIN(transcoder->sink_bin), conv_elem, encoder_elem, sink_elem, NULL); gst_element_link_many(conv_elem, encoder_elem, sink_elem, NULL); gst_element_add_pad(transcoder->sink_bin, gst_ghost_pad_new("sink", encoder_pad)); gst_object_unref(encoder_pad); gst_bin_add_many(GST_BIN(transcoder->pipeline), source_elem, decoder_elem, transcoder->sink_bin, NULL); gst_element_link(source_elem, decoder_elem); g_signal_connect(decoder_elem, "new-decoded-pad", G_CALLBACK(gst_transcoder_new_decoded_pad), transcoder); gst_bus_add_watch(gst_pipeline_get_bus(GST_PIPELINE(transcoder->pipeline)), gst_transcoder_bus_callback, transcoder); transcoder->conv_elem = conv_elem; return TRUE; }
static void transcode_file (gchar * uri, gchar * outputuri, GstEncodingProfile * prof) { GstElement *pipeline; GstElement *src; GstElement *ebin; GstElement *sink; GstBus *bus; GstCaps *profilecaps, *rescaps; GMainLoop *mainloop; g_print (" Input URI : %s\n", uri); g_print (" Output URI : %s\n", outputuri); sink = gst_element_make_from_uri (GST_URI_SINK, outputuri, "sink", NULL); if (G_UNLIKELY (sink == NULL)) { g_print ("Can't create output sink, most likely invalid output URI !\n"); return; } src = gst_element_factory_make ("uridecodebin", NULL); if (G_UNLIKELY (src == NULL)) { g_print ("Can't create uridecodebin for input URI, aborting!\n"); return; } /* Figure out the streams that can be passed as-is to encodebin */ g_object_get (src, "caps", &rescaps, NULL); rescaps = gst_caps_copy (rescaps); profilecaps = gst_encoding_profile_get_input_caps (prof); gst_caps_append (rescaps, profilecaps); /* Set properties */ g_object_set (src, "uri", uri, "caps", rescaps, NULL); ebin = gst_element_factory_make ("encodebin", NULL); g_object_set (ebin, "profile", prof, NULL); g_signal_connect (src, "autoplug-continue", G_CALLBACK (autoplug_continue_cb), ebin); g_signal_connect (src, "pad-added", G_CALLBACK (pad_added_cb), ebin); pipeline = gst_pipeline_new ("encoding-pipeline"); gst_bin_add_many (GST_BIN (pipeline), src, ebin, sink, NULL); gst_element_link (ebin, sink); mainloop = g_main_loop_new (NULL, FALSE); bus = gst_pipeline_get_bus ((GstPipeline *) pipeline); gst_bus_add_signal_watch (bus); g_signal_connect (bus, "message", G_CALLBACK (bus_message_cb), mainloop); if (gst_element_set_state (pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { g_print ("Failed to start the encoding\n"); return; } g_main_loop_run (mainloop); gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (pipeline); }
/*! * \brief OpenIMAJCapGStreamer::open Open the given file with gstreamer * \param type CvCapture type. One of CAP_GSTREAMER_* * \param filename Filename to open in case of CAP_GSTREAMER_FILE * \return boolean. Specifies if opening was succesful. * * In case of CAP_GSTREAMER_V4L(2), a pipelin is constructed as follows: * v4l2src ! autoconvert ! appsink * * * The 'filename' parameter is not limited to filesystem paths, and may be one of the following: * * - a normal filesystem path: * e.g. video.avi or /path/to/video.avi or C:\\video.avi * - an uri: * e.g. file:///path/to/video.avi or rtsp:///path/to/stream.asf * - a gstreamer pipeline description: * e.g. videotestsrc ! videoconvert ! appsink * the appsink name should be either 'appsink0' (the default) or 'opencvsink' * * When dealing with a file, OpenIMAJCapGStreamer will not drop frames if the grabbing interval * larger than the framerate period. (Unlike the uri or manual pipeline description, which assume * a live source) * * The pipeline will only be started whenever the first frame is grabbed. Setting pipeline properties * is really slow if we need to restart the pipeline over and over again. * */ bool OpenIMAJCapGStreamer::open(const char* filename ) { if(!isInited) { //FIXME: threadsafety gst_init (NULL, NULL); isInited = true; } bool stream = false; bool manualpipeline = false; char *uri = NULL; uridecodebin = NULL; // test if we have a valid uri. If so, open it with an uridecodebin // else, we might have a file or a manual pipeline. // if gstreamer cannot parse the manual pipeline, we assume we were given and // ordinary file path. if(!gst_uri_is_valid(filename)) { uri = realpath(filename, NULL); stream = false; if(uri) { uri = g_filename_to_uri(uri, NULL, NULL); if(!uri) { WARN("GStreamer: Error opening file\n"); close(); return false; } } else { GError *err = NULL; uridecodebin = gst_parse_launch(filename, &err); if(!uridecodebin) { //fprintf(stderr, "GStreamer: Error opening bin: %s\n", err->message); //close(); return false; } stream = true; manualpipeline = true; } } else { stream = true; uri = g_strdup(filename); } bool element_from_uri = false; if(!uridecodebin) { // At this writing, the v4l2 element (and maybe others too) does not support caps renegotiation. // This means that we cannot use an uridecodebin when dealing with v4l2, since setting // capture properties will not work. // The solution (probably only until gstreamer 1.2) is to make an element from uri when dealing with v4l2. gchar * protocol = gst_uri_get_protocol(uri); if (!strcasecmp(protocol , "v4l2")) { uridecodebin = gst_element_make_from_uri(GST_URI_SRC, uri, "src", NULL); element_from_uri = true; }else{ uridecodebin = gst_element_factory_make ("uridecodebin", NULL); g_object_set(G_OBJECT(uridecodebin),"uri",uri, NULL); } g_free(protocol); if(!uridecodebin) { //fprintf(stderr, "GStreamer: Error opening bin: %s\n", err->message); close(); return false; } } if(manualpipeline) { GstIterator *it = NULL; it = gst_bin_iterate_sinks (GST_BIN(uridecodebin)); gboolean done = FALSE; GstElement *element = NULL; gchar* name = NULL; GValue value = G_VALUE_INIT; while (!done) { switch (gst_iterator_next (it, &value)) { case GST_ITERATOR_OK: element = GST_ELEMENT (g_value_get_object (&value)); name = gst_element_get_name(element); if (name){ if(strstr(name, "opencvsink") != NULL || strstr(name, "appsink") != NULL) { sink = GST_ELEMENT ( gst_object_ref (element) ); done = TRUE; } g_free(name); } g_value_unset (&value); break; case GST_ITERATOR_RESYNC: gst_iterator_resync (it); break; case GST_ITERATOR_ERROR: case GST_ITERATOR_DONE: done = TRUE; break; } } gst_iterator_free (it); if (!sink){ //ERROR(1, "GStreamer: cannot find appsink in manual pipeline\n"); return false; } pipeline = uridecodebin; } else { pipeline = gst_pipeline_new (NULL); // videoconvert (in 0.10: ffmpegcolorspace) automatically selects the correct colorspace // conversion based on caps. color = gst_element_factory_make(COLOR_ELEM, NULL); sink = gst_element_factory_make("appsink", NULL); gst_bin_add_many(GST_BIN(pipeline), uridecodebin, color, sink, NULL); if(element_from_uri) { if(!gst_element_link(uridecodebin, color)) { //ERROR(1, "GStreamer: cannot link color -> sink\n"); gst_object_unref(pipeline); return false; } }else{ g_signal_connect(uridecodebin, "pad-added", G_CALLBACK(newPad), color); } if(!gst_element_link(color, sink)) { //ERROR(1, "GStreamer: cannot link color -> sink\n"); gst_object_unref(pipeline); return false; } } //TODO: is 1 single buffer really high enough? gst_app_sink_set_max_buffers (GST_APP_SINK(sink), 1); gst_app_sink_set_drop (GST_APP_SINK(sink), stream); //do not emit signals: all calls will be synchronous and blocking gst_app_sink_set_emit_signals (GST_APP_SINK(sink), 0); // support 1 and 3 channel 8 bit data, as well as bayer (also 1 channel, 8bit) caps = gst_caps_from_string("video/x-raw, format=(string){BGR, GRAY8}; video/x-bayer,format=(string){rggb,bggr,grbg,gbrg}"); gst_app_sink_set_caps(GST_APP_SINK(sink), caps); gst_caps_unref(caps); //we do not start recording here just yet. // the user probably wants to set capture properties first, so start recording whenever the first frame is requested return true; }
/** * ly_gla_fina: * * Create a new allocate LyMdhMetadata type structure based on a uri. It fills * all fields in metadata struct. * * Returns: a newly allocated metadata struct. */ LyMdhMetadata* ly_mdh_new_with_uri_full (char *uri) { /* * test file */ char *prefix=ly_gla_uri_get_prefix(uri); char *path=ly_gla_uri_get_path(uri); if(!g_str_equal(prefix, "file://")) { g_free(prefix); ly_log_put_with_flag(G_LOG_LEVEL_DEBUG, _("Cannot open file: %s. unsupported protocol!"), uri); return NULL; } g_free(prefix); if(!g_file_test(path, G_FILE_TEST_EXISTS)) { g_free(path); ly_log_put_with_flag(G_LOG_LEVEL_DEBUG, _("Cannot open file: %s. file not found!"), uri); return NULL; } g_free(path); ly_mdh_pipeline=NULL; ly_mdh_md_eos=FALSE; /* * create and initial metadata */ LyMdhMetadata *metadata=ly_mdh_new(); g_strlcpy(metadata->uri, uri, sizeof(metadata->uri)); /* * build the pipeline */ GstFormat fmt=GST_FORMAT_TIME; GstElement *urisrc; GstElement *decodebin; GstElement *fakesink; GstBus *bus=NULL; gint changeTimeout = 0; GstStateChangeReturn rt; GstMessage *msg; ly_mdh_pipeline=gst_pipeline_new("pipeline"); urisrc=gst_element_make_from_uri(GST_URI_SRC,metadata->uri,"urisrc"); decodebin=gst_element_factory_make("decodebin","decodebin"); fakesink=gst_element_factory_make("fakesink","fakesink"); gst_bin_add_many(GST_BIN(ly_mdh_pipeline),urisrc,decodebin,fakesink,NULL); gst_element_link(urisrc,decodebin); g_signal_connect_object(G_OBJECT(decodebin),"new-decoded-pad",G_CALLBACK(ly_mdh_new_with_uri_pipe_cb),fakesink,0); bus = gst_pipeline_get_bus(GST_PIPELINE(ly_mdh_pipeline)); gst_element_set_state(ly_mdh_pipeline,GST_STATE_NULL); gst_element_set_state(ly_mdh_pipeline,GST_STATE_READY); rt = gst_element_set_state(ly_mdh_pipeline,GST_STATE_PAUSED); if(!rt) { if(ly_mdh_pipeline!=NULL) gst_object_unref(GST_OBJECT(ly_mdh_pipeline)); ly_mdh_md_eos=FALSE; ly_mdh_pipeline=NULL; return FALSE; } while(rt==GST_STATE_CHANGE_ASYNC && !ly_mdh_md_eos && changeTimeout < 5) { msg = gst_bus_timed_pop(bus, 1 * GST_SECOND); if(msg!=NULL) { ly_mdh_new_with_uri_full_bus_cb(bus, msg, metadata); gst_message_unref(msg); changeTimeout = 0; } else changeTimeout++; rt = gst_element_get_state(ly_mdh_pipeline, NULL, NULL, 0); } gst_object_unref(bus); ly_mdh_new_with_uri_full_loop_cb(metadata, ly_mdh_pipeline, FALSE); if(rt!=GST_STATE_CHANGE_SUCCESS) { gst_element_set_state(ly_mdh_pipeline,GST_STATE_NULL); if(ly_mdh_pipeline!=NULL) gst_object_unref(GST_OBJECT(ly_mdh_pipeline)); return FALSE; } /* * get duration */ gint64 dura=0; gst_element_query_duration(ly_mdh_pipeline,&fmt,&dura); char *duration=ly_mdh_time_int2str(dura); g_strlcpy(metadata->duration,duration,sizeof(metadata->duration)); g_free(duration); rt = gst_element_set_state(ly_mdh_pipeline,GST_STATE_NULL); gst_object_unref(ly_mdh_pipeline); char *str; if(g_str_equal(metadata->title,"")||g_str_equal(metadata->title,"unknown")) { str=ly_gla_uri_get_filename(uri); g_strlcpy(metadata->title,str,sizeof(metadata->title)); g_free(str); } ly_mdh_pipeline=NULL; ly_mdh_md_eos=FALSE; return metadata; }