Search code examples
c++cgstreamer-1.0

gstreamer audiomixer command to code converting


I want to use audiomixer in my application which receives audios from different sources and should play them together in speaker.

my final application should do something like this command:

gst-launch-1.0 audiomixer name=mix ! autoaudiosink autoaudiosrc ! \
audioconvert ! mix. udpsrc port=5001 caps="application/x-rtp" ! queue !\
rtppcmudepay ! mulawdec ! audioconvert ! audioresample ! mix.

I already wrote a code to use tee and queues and know how to work with tee and queues in code based on this code. but I don't know how to use mixer in my code.

so for simplicity I just want to write a code to work as this command does:

 gst-launch-1.0 audiotestsrc freq=100 ! audiomixer name=mix ! audioconvert ! autoaudiosink autoaudiosrc ! mix.

I didn't find any useful example to reach this goal, how can I write a C code to do this?


Solution

  • for the second part:

     gst-launch-1.0 audiotestsrc freq=100 ! audiomixer name=mix ! audioconvert ! autoaudiosink autoaudiosrc ! mix.
    

    this code works:

    #include <gst/gst.h>
    static GMainLoop *loop;
    int bus_callback (GstBus *bus, GstMessage *message, gpointer data)
    {
        g_print ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message));
        switch (GST_MESSAGE_TYPE (message)) {
        case GST_MESSAGE_ERROR: {
            GError *err;
            gchar *debug;
            gst_message_parse_error (message, &err, &debug);
            g_print ("Error: %s\n", err->message);
            g_error_free (err);
            g_free (debug);
            g_main_loop_quit (loop);
            break;
        }
        case GST_MESSAGE_EOS:
            /* end-of-stream */
            g_main_loop_quit (loop);
            break;
        default:
            /* unhandled message */
            break;
        }
        /* we want to be notified again the next time there is a message
        * on the bus, so returning TRUE (FALSE means we want to stop watching
        * for messages on the bus and our callback should not be called again)
        */
        return TRUE;
    }
    
    int main(int argc, char *argv[])
    {
        /* Initialize GStreamer */
        gst_init (nullptr, nullptr);
        GstElement *pipeline, *src1,*src2, *sink, *convert1,*convert2,*audiomixer;
        GstPad *conv_pad1, *conv_pad2, *mixer1_sinkpad,*mixer2_sinkpad;
        gint i;
        static GstBus *bus;
        static guint bus_watch_id;
        pipeline = gst_pipeline_new ("pipeline");
        audiomixer = gst_element_factory_make ("adder", "mixer");
    
        sink = gst_element_factory_make ("autoaudiosink", "sink");
        src1 = gst_element_factory_make ("audiotestsrc", "src1");
        convert1 = gst_element_factory_make ("audioconvert", "convert1");
        src2 = gst_element_factory_make ("autoaudiosrc", "src2");
        convert2 = gst_element_factory_make ("audioconvert", "convert2");
        //g_object_set (sink, "async-handling", TRUE, NULL);
    
    
        gst_bin_add_many (GST_BIN (pipeline), audiomixer ,sink, NULL);
        gst_bin_add_many (GST_BIN (pipeline), src1 , convert1 , NULL);
        gst_bin_add_many (GST_BIN (pipeline), src2 , convert2 , NULL);
        gst_element_link (src1, convert1 );
        gst_element_link (src2, convert2 );
        gst_element_link(audiomixer , sink);
    
        conv_pad1= gst_element_get_static_pad (convert1, "src");
        mixer1_sinkpad = gst_element_get_request_pad (audiomixer, "sink_%u");
        gst_pad_link (conv_pad1, mixer1_sinkpad);
        g_object_unref(mixer1_sinkpad);
    
        conv_pad2= gst_element_get_static_pad (convert2, "src");
        mixer2_sinkpad = gst_element_get_request_pad (audiomixer, "sink_%u");
        gst_pad_link (conv_pad2, mixer2_sinkpad);
        g_object_unref(mixer2_sinkpad);
    
        /* adds a watch for new message on our pipeline’s message bus to
        * the default GLib main context, which is the main context that our
        * GLib main loop is attached to below
        */
        bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
        bus_watch_id = gst_bus_add_watch (bus, bus_callback, NULL);
        gst_object_unref (bus);
    
        /* Start playing */
        gst_element_set_state (pipeline, GST_STATE_PLAYING);
    
    
        loop = g_main_loop_new (NULL, FALSE);
    
        g_main_loop_run (loop);
        g_object_unref(conv_pad1);
        g_object_unref(conv_pad2);
        gst_element_set_state (pipeline, GST_STATE_NULL);
        g_source_remove (bus_watch_id);
    }