Video and Audio Recording and Muxing Issue in C++ GStreamer Pipeline
Sulthan Amanu via gstreamer-devel <[email protected]>
| Newsgroups | gmane.comp.video.gstreamer.devel |
|---|---|
| Message-ID | <CACnfP3XtuAoZQbXL3pWBNDWGyijyz_FyUbHL5pNbvv2VGmYfLw@mail.gmail.com> |
Dear Team, I have successfully implemented the GStreamer pipeline provided below in raw command-line form. The pipeline captures both audio and video correctly: **Pipeline** gst-launch-1.0 -e v4l2src device="/dev/video0" ! videoconvert ! queue ! x264enc tune=zerolatency ! h264parse config-interval=-1 ! mux. autoaudiosrc ! queue ! audioconvert ! audioresample ! volume volume=0.5 mute=false ! voaacenc ! aacparse ! qtmux name=mux ! filesink location=test-autoaudiosrc.mp4 sync=false However, when I converted this pipeline into C++ code, I encountered an issue where the audio is not recorded or muxed correctly. I have attempted to debug the problem using `GST_DEBUG=2`, and I've attached the error log below. **CODE FILE** = [my_gst_app.cpp](/uploads/0a048213b2125af003de6a6ac29cd290/my_gst_app.cpp) **Running Commend** = g++ -o my_gst_app my_gst_app.cpp `pkg-config --cflags --libs gstreamer-1.0` and GST_DEBUG=2 ./my_gst_app **Error Log:** GST_DEBUG=2 ./my_gst_app Audio Elements could linked. Video Elements could linked. 0:00:00.461866220 30618 0x7f464c0040f0 WARN audiosrc gstaudiosrc.c:197:audioringbuffer_thread_func:<audio-source-actual-src-puls> failed to set thread priority 0:00:06.889138959 30618 0x7f4658004c50 ERROR GST_PADS gstpad.c:3352:gst_pad_query_latency_default:<mux:src> minimum latency bigger than maximum latency 0:00:06.890978046 30618 0x55bacd3db630 WARN audiobasesrc gstaudiobasesrc.c:844:gst_audio_base_src_create:<audio-source-actual-src-puls> create DISCONT of 236817 samples at sample 282681 0:00:06.891032791 30618 0x55bacd3db630 WARN audiobasesrc gstaudiobasesrc.c:849:gst_audio_base_src_create:<audio-source-actual-src-puls> warning: Can't record audio fast enough 0:00:06.891049693 30618 0x55bacd3db630 WARN audiobasesrc gstaudiobasesrc.c:849:gst_audio_base_src_create:<audio-source-actual-src-puls> warning: Dropped 236817 samples. This is most likely because downstream can't keep up and is consuming samples too slowly. 0:00:07.281026296 30618 0x55bacd3db630 WARN audiobasesrc gstaudiobasesrc.c:844:gst_audio_base_src_create:<audio-source-actual-src-puls> create DISCONT of 16317 samples at sample 299880 0:00:07.281063662 30618 0x55bacd3db630 WARN audiobasesrc gstaudiobasesrc.c:849:gst_audio_base_src_create:<audio-source-actual-src-puls> warning: Can't record audio fast enough 0:00:07.281072629 30618 0x55bacd3db630 WARN audiobasesrc gstaudiobasesrc.c:849:gst_audio_base_src_create:<audio-source-actual-src-puls> warning: Dropped 16317 samples. This is most likely because downstream can't keep up and is consuming samples too slowly. I would like to request your assistance in fixing this bug and providing a proper C++ implementation of the pipeline that ensures both audio and video are recorded and muxed correctly. Your guidance and expertise would be greatly appreciated. Thank you for your help. Sincerely, Sulthan Amanau
my_gst_app.cpp
(text/x-c++src, 4.7 KB)
#include <gst/gst.h>
int main(int argc, char* argv[]) {
gst_init(&argc, &argv);
GstElement *pipeline, *src, *videoconvert, *x264enc, *h264parse, *mux, *audio_src, *queue, *video_queue, *audioconvert, *audioresample, *volume, *voaacenc, *aacparse, *filesink;
// Create a new pipeline
pipeline = gst_pipeline_new("my-pipeline");
// Create elements
src = gst_element_factory_make("v4l2src", "video-source");
videoconvert = gst_element_factory_make("videoconvert", "video-convert");
video_queue = gst_element_factory_make("queue", "video_queue");
x264enc = gst_element_factory_make("x264enc", "video-encoder");
h264parse = gst_element_factory_make("h264parse", "video-parser");
mux = gst_element_factory_make("mp4mux", "mux");
audio_src = gst_element_factory_make("autoaudiosrc", "audio-source");
queue = gst_element_factory_make("queue", "queue");
audioconvert = gst_element_factory_make("audioconvert", "audio-convert");
audioresample = gst_element_factory_make("audioresample", "audio-resample");
volume = gst_element_factory_make("volume", "audio-volume");
voaacenc = gst_element_factory_make("voaacenc", "audio-encoder");
aacparse = gst_element_factory_make("aacparse", "audio-parser");
filesink = gst_element_factory_make("filesink", "file-sink");
// Check if elements are created successfully
if (!pipeline || !src || !videoconvert || !video_queue || !x264enc || !h264parse || !mux || !audio_src || !queue || !audioconvert || !audioresample || !volume || !voaacenc || !aacparse || !filesink) {
g_printerr("One or more elements could not be created. Exiting.\n");
return -1;
}
// Set the device property of v4l2src
g_object_set(G_OBJECT(src), "device", "/dev/video0", NULL);
// Set the num-buffers property to limit the number of processed buffers
g_object_set(G_OBJECT(src), "num-buffers", 500, NULL);
// Set the volume property of the volume element
g_object_set(G_OBJECT(volume), "volume", 0.5, "mute", FALSE, NULL);
g_object_set(h264parse, "config-interval", -1, NULL);
// Set the latency settings for the mux element
//g_object_set(G_OBJECT(mux), "min-latency", 18009090, "max-latency", 100000, NULL);
g_object_set(mux, "fragment-duration", 2000, NULL);
// Set the location property of the filesink
g_object_set(G_OBJECT(filesink), "location", "test-autoaudiosrc.mp4","sync",FALSE, NULL);
// Add elements to the pipeline
gst_bin_add_many(GST_BIN(pipeline), src, videoconvert,video_queue, x264enc, h264parse, mux,audio_src,queue, audioconvert, audioresample, volume, voaacenc, aacparse,filesink, NULL);
// Link the elements together
if (!gst_element_link_many(audio_src,queue, audioconvert, volume, voaacenc, aacparse, mux, NULL)) {
g_printerr("audio_src,queue, audioconvert, audioresample, volume, voaacenc, aacparse, mux,. Not linked\n");
//return -1;
}
else
g_printerr("Audio Elements could linked. Exiting.\n");
// Link the elements together
if (!gst_element_link_many(src, videoconvert,video_queue, x264enc, h264parse, mux,filesink, NULL)) {
g_printerr("Elements could not be linked. Exiting.\n");
//return -1;
}
else
g_printerr("Video Elements could linked. Exiting.\n");
if(!gst_element_link(mux, filesink) != TRUE ) {
g_print("Elements could not be linked. Exiting.\n");
return -1;
}
// Set the pipeline state to playing
gst_element_set_state(pipeline, GST_STATE_PLAYING);
// Wait until error or EOS (End of Stream)
GstBus* bus = gst_element_get_bus(pipeline);
GstMessage* msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, static_cast<GstMessageType>(GST_MESSAGE_ERROR | GST_MESSAGE_EOS));
// Parse the message and handle it
if (msg != NULL) {
GError* err;
gchar* debug_info;
switch (GST_MESSAGE_TYPE(msg)) {
case GST_MESSAGE_ERROR:
gst_message_parse_error(msg, &err, &debug_info);
g_printerr("Error received from element %s: %s\n", GST_OBJECT_NAME(msg->src), err->message);
g_printerr("Debugging information: %s\n", debug_info ? debug_info : "none");
g_clear_error(&err);
g_free(debug_info);
break;
case GST_MESSAGE_EOS:
g_print("End-Of-Stream reached.\n");
break;
default:
g_printerr("Unexpected message received.\n");
break;
}
gst_message_unref(msg);
}
// Set the pipeline state to NULL (cleanup)
gst_element_set_state(pipeline, GST_STATE_NULL);
// Clean up and release resources
gst_object_unref(bus);
gst_object_unref(pipeline);
return 0;
}