Hello all,
I am new to Gstreamer and c++ programming in linux. I am using Gstreamer to record audio from RTP stream from a voip call session. For some reason gst_bus_add_watch() is not working and EOS is not being received in the callback, so I have made the GMainLoop object global and used g_main_loop_quit(loop) to end the recording. But after every recording completes, one file is being left open. After there are several calls we receive an error "Too many files open" and the app stops working. Please let me know if making the GMainLoop object as a global object is a wrong practice, or if there is any incorrect thing in the program. On using the command after every call termination : ls -l /proc/<pid>/fd, it shows that there are 4 files that are not being closed after recording ends. FYI for every call session, there are 4 different streams so 4 recordings take place on different threads.(there are 4 different GMainLoop objects for the 4 threads) Below are some parts of the program : int startRecording() { GstElement *asource, *acapsfilter, *gdepay, *queue2, *gdppay; GstElement *sink; GstBus *bus; guint bus_watch_id; GstCaps *caps; loop = g_main_loop_new (g_main_context_new(), FALSE); /* Create gstreamer elements */ GstElement * pipeline = gst_pipeline_new ("av-recorder"); asource = gst_element_factory_make ("udpsrc", "aud-source"); acapsfilter = gst_element_factory_make ("capsfilter", "audio-caps"); gdepay = gst_element_factory_make ("rtppcmadepay", "artpdepay"); queue2 = gst_element_factory_make ("queue", "queue2"); sink = gst_element_factory_make ("filesink", "file-output"); if (!pipeline || !asource || !acapsfilter || !gdepay || /*!gdppay ||*/ !queue2 ||!sink) { g_printerr ("One element could not be created. Exiting.\n"); return -1; } g_object_set (G_OBJECT (asource), "port", port, NULL); string capstring = "application/x-rtp,channels=(int)1,media=(string)audio,payload=(int)"+ boost::lexical_cast<string>(payloadInt)+ ",clock-rate=(int)8000,encoding-name=(string)"+encodingname; caps = gst_caps_from_string(capstring.c_str()); g_object_set (G_OBJECT (acapsfilter), "caps", caps, NULL); gst_caps_unref (caps); bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); bus_watch_id = gst_bus_add_watch (bus, bus_call, loop); gst_object_unref (bus); gst_bin_add_many (GST_BIN (pipeline),asource, acapsfilter, gdepay, /*gdppay, queue2,*/ sink, NULL); gst_element_link_many (asource, acapsfilter, gdepay, /*gdppay, queue2,*/ sink, NULL); gst_element_set_state (pipeline, GST_STATE_PLAYING); g_print ("***Recording (or not!)...\n"); g_main_loop_run (loop); g_print ("Returned, stopping recording\n"); gst_element_set_state (pipeline, GST_STATE_NULL); g_print ("Deleting pipeline\n"); gst_object_unref (GST_OBJECT (pipeline)); g_source_remove (bus_watch_id); g_main_loop_unref (loop); } void stopRecording() { g_main_loop_quit (loop); } // this method is not being invoked in any case gboolean RTPRecorder::bus_call (GstBus *bus, GstMessage *msg, gpointer data) { GMainLoop *loop = (GMainLoop *) data; switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_EOS: g_print ("End of stream\n"); g_main_loop_quit (loop); break; case GST_MESSAGE_ERROR:{ gchar *debug; GError *error; gst_message_parse_error (msg, &error, &debug); g_free (debug); g_printerr ("Error: %s\n", error->message); g_error_free (error); g_main_loop_quit (loop); break; } default: break; } return TRUE; } Any help will be highly appreciated. Thanks! -- Sent from: http://gstreamer-devel.966125.n4.nabble.com/ _______________________________________________ gstreamer-devel mailing list [hidden email] https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel |
On Thu, May 31, 2018 at 11:20:01PM -0700, [hidden email] wrote:
> Hello all, > > I am new to Gstreamer and c++ programming in linux. I am using > Gstreamer to record audio from RTP stream from a voip call > session. For some reason gst_bus_add_watch() is not working and EOS > is not being received in the callback, To stop recording, send an EOS event into your source element, then wait for the EOS message from the bus, then set state to NULL. I couldn't see in your code any sending of EOS event, and forcing state to NULL will not send EOS. (I haven't used gst_bus_add_watch; my preference has been gst_bus_add_signal_watch and then connect to signal "message".) -- James Cameron http://quozl.netrek.org/ _______________________________________________ gstreamer-devel mailing list [hidden email] https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel |
Thank you so much James for your reply. I tried to send the EOS event using
this code: gst_element_send_event(pipeline, gst_event_new_eos()) This didn't work until I tried something like below: void worker(GstElement *pipeline) { gst_element_send_event(pipeline, gst_event_new_eos()); } void stopListening() { boost::thread *th = new boost::thread(worker,pipeline); } i.e. when EOS was sent from another thread and not from the same thread, then only the bus watched method was being invoked. And after that all files were being closed properly. I don't know why it didn't work from the same thread. It would be really helpful if you could explain this behavior and also tell if this way of doing it is okay or not. FYI the recording is not being done on the main thread as there are multiple calls. So each recording task is being done on a different new thread. Thanks again. -- Sent from: http://gstreamer-devel.966125.n4.nabble.com/ _______________________________________________ gstreamer-devel mailing list [hidden email] https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel |
Free forum by Nabble | Edit this page |