I am experimenting with the GStreamer library and have created the following test pipeline. The objective is for the pipeline to transmit the same number of RTP packets as it receives. However, the issue is that as soon as it enters the playing state, it continuously sends empty RTP packets. I've added some probes to the pads, and it appears that the audio mixer is constantly creating empty buffers on the source pad. Why is this happening and how can I change it ?
Any help would be greatly appreciated!
void build_pipeline() {
GstElement *pipeline, *udpsrc, *rtpL16depay, *tee, *queue, *audiomixer, *capsfilter, *audioconvert, *rtpL16pay, *udpsink;
GstCaps *caps;
GstPad *tee_audio_pad, *queue_audio_pad;
GstPadTemplate *tee_src_pad_template;
GstBus *bus;
guint bus_watch_id;
GMainLoop *loop;
// Initialize GStreamer
gst_init(NULL, NULL);
// Create elements
pipeline = gst_pipeline_new("audio-pipeline");
udpsrc = gst_element_factory_make("udpsrc", "udpsrc");
constexpr const char *const default_caps_str =
"application/x-rtp,"
"media=(string)audio,"
"clock-rate=(int)16000,"
"encoding-name=(string)L16,"
"encoding-params=(string)1,"
"channels=(int)1,"
"payload=(int)96";
g_object_set(G_OBJECT(udpsrc), "caps", gst_caps_from_string(default_caps_str), "address", "127.0.0.1", "port", 5005,
NULL);
rtpL16depay = gst_element_factory_make("rtpL16depay", "rtpL16depay");
tee = gst_element_factory_make("tee", "tee");
queue = gst_element_factory_make("queue", "queue");
audiomixer = gst_element_factory_make("audiomixer", "audiomixer");
capsfilter = gst_element_factory_make("capsfilter", "capsfilter");
caps = gst_caps_new_simple("audio/x-raw",
"format", G_TYPE_STRING, "S16LE",
"rate", G_TYPE_INT, 16000,
"channels", G_TYPE_INT, 1,
NULL);
g_object_set(G_OBJECT(capsfilter), "caps", caps, NULL);
gst_caps_unref(caps);
audioconvert = gst_element_factory_make("audioconvert", "audioconvert");
rtpL16pay = gst_element_factory_make("rtpL16pay", "rtpL16pay");
udpsink = gst_element_factory_make("udpsink", "udpsink");
g_object_set(G_OBJECT(udpsink), "host", "127.0.0.1", "port", 3030, NULL);
// Check for creation failures
if (!pipeline || !udpsrc || !rtpL16depay || !tee || !queue || !audiomixer || !capsfilter || !audioconvert ||
!rtpL16pay || !udpsink) {
g_printerr("Not all elements could be created.\n");
return;
}
// Add elements to pipeline
gst_bin_add_many(GST_BIN(pipeline), udpsrc, rtpL16depay, tee, queue, audiomixer, capsfilter, audioconvert,
rtpL16pay, udpsink, NULL);
// Link elements
gst_element_link(udpsrc, rtpL16depay);
gst_element_link(rtpL16depay, tee);
tee_src_pad_template = gst_element_class_get_pad_template(GST_ELEMENT_GET_CLASS(tee), "src_%u");
tee_audio_pad = gst_element_request_pad(tee, tee_src_pad_template, NULL, NULL);
queue_audio_pad = gst_element_get_static_pad(queue, "sink");
gst_pad_link(tee_audio_pad, queue_audio_pad);
gst_element_link_many(queue, audiomixer, capsfilter, audioconvert, rtpL16pay, udpsink, NULL);
gst_object_unref(queue_audio_pad);
gst_object_unref(tee_audio_pad);
// Start playing
gst_element_set_state(pipeline, GST_STATE_PLAYING);
// ... (Add code to manage the pipeline, e.g., main loop, message handling)
// Create a GMainLoop
loop = g_main_loop_new(NULL, FALSE);
// Get a bus from the pipeline
bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
bus_watch_id = gst_bus_add_watch(bus, bus_call, loop);
gst_object_unref(bus);
// Set the pipeline to "playing" state
gst_element_set_state(pipeline, GST_STATE_PLAYING);
// Run the loop
g_main_loop_run(loop);
// Clean up
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(GST_OBJECT(pipeline));
g_source_remove(bus_watch_id);
g_main_loop_unref(loop);
}