From: Tiago K. <kat...@in...> - 2009-05-08 20:18:17
|
Im trying to do a rtp stream sending data and another side receiving the data, the part that sends the data is working fine, but the part that receives is giving me a lot of trouble. At http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-bad-plugins/html/gst-plugins-bad-plugins-gstrtpbin.htmli have read: "To use GstRtpBin<http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-bad-plugins/html/gst-plugins-bad-plugins-gstrtpbin.html#GstRtpBin>as an RTP receiver, request a recv_rtp_sink_% d pad. The session number must be specified in the pad name. Data received on the recv_rtp_sink_%d pad will be processed in the gstrtpsession manager and after being validated forwarded on GstRtpsSrcDemux element. Each RTP stream is demuxed based on the SSRC and send to a GstRtpJitterBuffer<http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-bad-plugins/html/gst-plugins-bad-plugins-gstrtpjitterbuffer.html#GstRtpJitterBuffer>. After the packets are released from the jitterbuffer, they will be forwarded to a GstRtpsSrcDemux element. The GstRtpsSrcDemux element will demux the packets based on the payload type and will create a unique pad recv_rtp_src_%d_%d_%d on gstrtpbin with the session number, SSRC and payload type respectively as the pad name. " on my application i cant get the recv_rtp_src_%d_%d_%d, i already tried on a lot of ways, my last shot was try to iterate over all the pads on the bin and try to conect, i discovered that the src pad never shows up. No error is given. I can get the on-new-ssrc signal...and other signals as on-ssrc-validated... but on all this signals the recv_rtp_src_%d_%d_%d is not created yet, i also tried to get the "on-pad-added" signal but this signal never happens. My problem is, when the recv_rtp_src_%d_%d_%d is created. When i iterate over the pads i always get a ** (teste_rtp:9516): DEBUG: GstRtpBin has [0] src pads here goes the source code, is a little messy because im all day trying a lot of different ways to do this. And i get no error message. #include <gst/gst.h> #include <glib.h> #define PORTA_UDP_ENTRADA 5000 static gboolean 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: g_print("Tipo da mensagem [%d], Nome da mensagem [%s]\n", GST_MESSAGE_TYPE (msg), GST_MESSAGE_TYPE_NAME(msg)); break; } return TRUE; } static void on_new_ssrc (GstElement* gstrtpbin, guint session, guint ssrc, gpointer data) { GstPad* sinkpad; GstPad* srcpad[1]; GstElement* decoder = (GstElement *) data; GstIterator* iter; gint done, linked, iter_count; g_print ("New session stabilished, linking gstrtpbin session src pad to the rtp_decoder\n"); sinkpad = gst_element_get_static_pad(decoder, "sink"); // TODO Esta dificil de pegar o pad src do gstrtpbin que eh criado ao iniciar uma sessao nova. if(!sinkpad){ g_warning("Error getting rtp_decoder sink pad"); return; } /* unique pad recv_rtp_src_%d_%d_%d on gstrtpbin with the session number, SSRC and payload type respectively as the pad name. http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-bad-plugins/html/gst-plugins-bad-plugins-gstrtpbin.html */ iter = gst_element_iterate_src_pads(gstrtpbin); if(!iter){ g_warning("Error getting gstrtpbin pads iterator"); return; } done = FALSE; linked = FALSE; iter_count = 0; while (!done) { switch (gst_iterator_next (iter, (gpointer *) srcpad)) { case GST_ITERATOR_OK: if(gst_pad_link (*srcpad, sinkpad) != GST_PAD_LINK_OK){ g_warning("Error linking gstrtpbin pad[%s] to rtp_decoder pad[%s]", gst_pad_get_name(*srcpad), gst_pad_get_name(sinkpad)); }else{ g_warning("Linked gstrtpbin pad[%s] to rtp_decoder pad[%s] with success", gst_pad_get_name(*srcpad), gst_pad_get_name(sinkpad)); linked = TRUE; } iter_count++; gst_object_unref (*srcpad); break; case GST_ITERATOR_RESYNC: gst_iterator_resync (iter); break; case GST_ITERATOR_ERROR: done = TRUE; break; case GST_ITERATOR_DONE: done = TRUE; break; } } if(!linked){ g_warning("failed to found a valid recv_src_pad on gstrtpbin"); } g_debug("GstRtpBin has [%d] src pads", iter_count); gst_iterator_free (iter); gst_object_unref (sinkpad); } static void on_pad_added (GstElement *element, GstPad *pad, gpointer data) { GstPad *sinkpad; GstElement *decoder = (GstElement *) data; /* We can now link this pad with the converter sink pad */ g_print ("Dynamic pad created, linking wavparser/converter\n"); sinkpad = gst_element_get_static_pad (decoder, "sink"); if(gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK){ g_warning("Error linking recv_rtp_src pad to sinkpad"); } gst_object_unref (sinkpad); } int main (int argc, char *argv[]) { GMainLoop *loop; GstElement *pipeline, *source, *rtp_bin, *rtp_decoder, *sink; GstPad *gstrtp_sink_pad; GstBus *bus; /* Initialisation */ gst_init (&argc, &argv); loop = g_main_loop_new (NULL, FALSE); /* Create gstreamer elements */ pipeline = gst_pipeline_new ("audio-player"); source = gst_element_factory_make ("udpsrc","udp-source"); rtp_bin = gst_element_factory_make ("gstrtpbin", "gst_rtpbin"); rtp_decoder = gst_element_factory_make ("rtpL16depay", "rtp_decoder"); sink = gst_element_factory_make ("filesink", "file-sink"); if (!pipeline || !source || !sink || !rtp_decoder || !rtp_bin) { g_printerr ("One element could not be created. Exiting.\n"); return -1; } gstrtp_sink_pad = gst_element_get_request_pad(rtp_bin, "recv_rtp_sink_0"); if (!gstrtp_sink_pad) { g_printerr ("Sink pad could not be created. Exiting.\n"); return -1; } /* Set up the pipeline */ g_object_set (G_OBJECT (source), "port", PORTA_UDP_ENTRADA , NULL); g_object_set (G_OBJECT (sink), "location", "dados_recebidos_rtp" , NULL); /* we add a message handler */ bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); gst_bus_add_watch (bus, bus_call, loop); gst_object_unref (bus); /* we add all elements into the pipeline */ /* file-source | ogg-demuxer | vorbis-decoder | converter | alsa-output */ gst_bin_add_many (GST_BIN (pipeline), source, sink, rtp_bin, rtp_decoder, NULL); /* we link the elements together */ if(gst_pad_link(gst_element_get_static_pad(source, "src"), gstrtp_sink_pad) != GST_PAD_LINK_OK){ g_warning("Error linking source to the gstrtp_sink_pad"); gst_object_unref (GST_OBJECT (pipeline)); return 0; } /* After the packets are released from the jitterbuffer, they will be forwarded to a GstRtpsSrcDemux element. The GstRtpsSrcDemux element will demux the packets based on the payload type and will create a unique pad recv_rtp_src_%d_%d_%d on gstrtpbin with the session number, SSRC and payload type respectively as the pad name. Because of that we have to dinamicaly link the src pads on runtime. */ g_signal_connect (rtp_bin, "pad-added", G_CALLBACK (on_pad_added), rtp_decoder); g_signal_connect (rtp_bin, "on-new-ssrc", G_CALLBACK (on_new_ssrc), rtp_decoder); if(!gst_element_link (rtp_decoder, sink)){ g_warning("Error linking the rtp_decoder to the sink"); gst_object_unref (GST_OBJECT (pipeline)); return -1; } /* Set the pipeline to "playing" state*/ g_print ("listening on port: %d\n", PORTA_UDP_ENTRADA); gst_element_set_state (pipeline, GST_STATE_PLAYING); /* Iterate */ g_print ("Running...\n"); g_main_loop_run (loop); /* Out of the main loop, clean up nicely */ g_print ("Returned, stopping listening on port\n"); gst_element_set_state (pipeline, GST_STATE_NULL); g_print ("Deleting pipeline\n"); gst_object_unref (GST_OBJECT (pipeline)); return 0; } |