gstreamer audiomixer 命令到代码转换

gstreamer audiomixer command to code converting

我想在我的应用程序中使用 audiomixer,它接收来自不同来源的音频并且应该在扬声器中一起播放它们。

我的最终应用程序应该执行如下命令:

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

我已经编写了使用 tee 和队列的代码,并且知道如何在基于 this code 的代码中使用 tee 和队列。但我不知道如何在我的代码中使用混音器。

所以为了简单起见,我只想编写一个代码来像这个命令一样工作:

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

我没有找到任何有用的例子来实现这个目标,我怎样才能写一个 C 代码来做到这一点?

第二部分:

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

此代码有效:

#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);
}