#include #include "gst-pipeline.h" #include "audio-sources.h" static GstElement *pipeline_create_simple(gchar *audio_source, GList *dev_list, gchar *enc_pipeline, gchar *output_sink, gchar **err_msg); static GstElement *pipeline_create_complex(gchar *audio_source, GList *dev_list, gchar *enc_pipeline, gchar *output_sink, gchar **err_msg); GstElement *pipeline_create(gchar *audio_source, GList *dev_list, gchar *enc_pipeline, gchar *output_sink, gchar **err_msg) { // Create a GStreamer pipeline for audio recording or listening GstElement *pipeline = NULL; // Wash the device list. User may have disconnected microphones and webcams. // Invalid devices will crash the GStreamer pipeline. // Remove invalid devices. GList *new_list = audio_sources_wash_device_list(dev_list); // Zero or one device? if (g_list_length(new_list) < 2) { // Create a simple pipeline that can record from/listen to max 1 device pipeline = pipeline_create_simple(audio_source, new_list, enc_pipeline, output_sink, err_msg); } else { // Create a complex pipeline that can record from/listen to 2 or more devices pipeline = pipeline_create_complex(audio_source, new_list, enc_pipeline, output_sink, err_msg); } // Free new_list str_list_free(new_list); new_list = NULL; return pipeline; } GstElement *pipeline_create_simple(gchar *audio_source, GList *dev_list, gchar *enc_pipeline, gchar *output_sink, gchar **err_msg) { // Create a simple pipeline that can record from 1 device. // Ref: http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/section-intro-basics-bins.html // Typical pipeline is: // gst-launch pulsesrc name=source0 device=alsa_input.usb-046d_089d-01-U0x46d0x89d.analog-mono ! // level name=level ! queue ! audioconvert ! audio/x-raw-float,rate=44100,channels=2 ! // vorbisenc name=enc quality=0.5 ! oggmux ! filesink name=output-sink location=test1.oga // Other pipeline samples. // OGG audio output: // $ gst-launch pulsesrc ! queue ! audioconvert ! vorbisenc ! oggmux ! filesink location=test.oga // // FLAC: // $ gst-launch pulsesrc ! queue ! audioconvert ! flacenc ! filesink location=test.flac // // WAV: // $ gst-launch pulsesrc ! queue ! audioconvert ! wavenc ! filesink location=test.wav // // MP3: // $ gst-launch pulsesrc ! queue ! audioconvert ! lame ! filesink location=test.mp3 // // See also: gconf-editor, key: system -> gstreamer -> 0.10 -> audio -> profiles. GstElement *pipeline = NULL; // Build a pipeline string gchar *pipeline_cmd = g_strdup_printf ("%s name=source0" " ! level name=level" " ! queue" " ! audioconvert" " ! %s" " ! %s name=output-sink", audio_source, enc_pipeline, output_sink); LOG_DEBUG("\n\n"); LOG_DEBUG("Going to create pipeline:\ngst-launch %s\n\n", pipeline_cmd); GError *err = NULL; pipeline = gst_parse_launch(pipeline_cmd, &err); g_free(pipeline_cmd); if (err) { // Set err_msg *err_msg = g_strdup_printf(_("Cannot create audio pipeline. %s.\n"), err->message); g_error_free(err); goto LBL_1; } // Get the "source0" element GstElement *source = gst_bin_get_by_name(GST_BIN(pipeline), "source0"); if (!GST_IS_ELEMENT(source)) { // Set err_msg *err_msg = g_strdup_printf(_("Cannot find audio element %s.\n"), audio_source); goto LBL_1; } // Set audio device if (g_list_length(dev_list) > 0) { gchar *device = dev_list->data; g_object_set(G_OBJECT(source), "device", device, NULL); LOG_DEBUG("Setting device. %s device=%s\n", audio_source, device); } g_object_unref(source); // Ok return pipeline; LBL_1: // Got an error return NULL; } static GstElement *pipeline_create_complex(gchar *audio_source, GList *dev_list, gchar *enc_pipeline, gchar *output_sink, gchar **err_msg) { // Create a complex pipeline using the GstAdder element. // Ref: http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-plugins/html/gst-plugins-base-plugins-adder.html // This can record from 2, 3 or more devices. // Typical pipeline is: // $ gst-launch-0.10 adder name=mix ! audioconvert ! vorbisenc ! oggmux ! filesink location=test1.ogg { // pulsesrc device=alsa_output.pci-0000_04_02.0.analog-stereo.monitor ! queue ! mix. } { // pulsesrc device=alsa_input.pci_8086_24c5_alsa_capture_0 ! queue ! mix. } GstElement *pipeline = NULL; // Build a pipeline string GString *str = g_string_new(NULL); g_string_printf(str, "adder name=mix" " ! level name=level" " ! audioconvert" " ! %s" " ! %s name=output-sink" " ", enc_pipeline, output_sink); // Add all devices to the pipe: // { pulsesrc device=alsa_input.pci_8086_24c5_alsa_capture_0 ! queue ! mix. } { // pulsesrc device=alsa_output.pci_8086_24c5_alsa_playback_0.monitor ! queue ! mix. // } { etc.} // For all devices in dev_list GList *n = g_list_first(dev_list); gint i = 0; while (n) { gchar *device = (gchar*)n->data; g_string_append_printf(str, "{ %s name=source%d device=%s ! queue ! mix. }", audio_source, i++, device); n = g_list_next(n); } // Take pipeline string gchar *pipeline_cmd = g_string_free(str, FALSE); LOG_DEBUG("\n\n"); LOG_DEBUG("Going to create pipeline:\ngst-launch %s\n\n", pipeline_cmd); GError *err = NULL; pipeline = gst_parse_launch(pipeline_cmd, &err); g_free(pipeline_cmd); if (err) { *err_msg = g_strdup_printf(_("Cannot create audio pipeline. %s.\n"), err->message); g_error_free(err); goto LBL_1; } // Ok return pipeline; LBL_1: // Got an error return NULL; }