GNOME Bugzilla – Bug 612915
streaming stopped for tcp interleaved communication:
Last modified: 2010-04-06 19:35:29 UTC
server : gst-rtsp-server client :quick time player When we opt the communication transport as TCP from client side, the streaming server is stopping just after one minute of playback. I found that , the VLC player is sending GET_PARAMETER (as a ping) in some intervals and there is no problem for streaming. But player like QuickTime is not sending this GET_PARAMETER request and stopping exactly after one minute of playback.(only for tcp communication). I found that the dispatch function in gstrtspconnection.c (gst-plubins-base/gst-libs/gst/rtsp) gst_rtsp_source_dispatch (GSource * source, GSourceFunc callback G_GNUC_UNUSED,gpointer user_data G_GNUC_UNUSED) is called in regular intervals ( because gst_rtsp_source_check returning TRUE for reafd) for VLC player and controll is entering into if (watch->readfd.events & READ_COND || watch->conn->initial_buffer != NULL) { .But for QT_player the control is not came to the "if (watch->readfd.events & READ_COND || watch->conn->initial_buffer != NULL)" And the connection is closed after one minute of playback.
And the control comes to "if (watch->readfd.events & READ_COND || watch->conn->initial_buffer !=NULL) " only after one minute.And at that time read socket returns 0 .
For VLC, server sends the rtcp packets but for qt not found the rtcp packet sending through gst_rtsp_media_stream_rtcp(). Is it because of tunnelling used by QT?
When I tried the following public link to stream the video from WAN using rtsp rtsp://tijuana.ucsd.edu/branson/physics130a/spring2003/040903_full.mp4 Itz worked fine for QT player also. But when we try with gst-rtsp-server and qtplayer, the problem of "closing after one minute" is persist for TCP interleaving.(tunnelling) So I think we have some issues in the gst-rtsp-server side. the handle_data() callback in rtsp-client.c is not calling for QT!!
if handle_data() is not called, that means that the client is not sending RTCP (correctly). I checked the server side in tunneled mode and it's sending RTCP fine too. So, no idea what's wrong yet.
even we try with vlc,(Tunnelling RTSP and RTP through HTTP) it will not work... only tcp interleaving is working .. QuickTime player does not support RTSP/RTP interleaving but only the HTTP-tunneled variant that Apple has implemented(Tunnelling RTSP and RTP through HTTP). VLC has both the 2 options 1) rtp over rtsp 2) tunnel rtsp and rtp over http. It seems that gst-rtsp-server is working fine for rtsp over tcp. And not working with the second option tunnel rtsp and rtp over http. (for both vlc and qt). It is always trying for tcp interleaving. And one more thing is that In any phase of the execution, the control is not reaching there in setup_tunneling() in gstrtspconnection.c !
I am pasting the gdb output here. The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /root/Source_March10/gst-rtsp-server_March25/examples/.libs/test-mp4 vi [Thread debugging using libthread_db enabled] [New Thread 0xb809a6c0 (LWP 17471)] [Switching to Thread 0xb809a6c0 (LWP 17471)] Breakpoint 1, main (argc=2, argv=0xbf8bb0b4) at test-mp4.c:32 32 gst_debug_set_default_threshold(GST_LEVEL_DEBUG); (gdb) n 33 gst_init (&argc, &argv); (gdb) n 35 if (argc < 2) { (gdb) n 40 loop = g_main_loop_new (NULL, FALSE); (gdb) n 43 server = gst_rtsp_server_new (); (gdb) n 47 mapping = gst_rtsp_server_get_media_mapping (server); (gdb) n 49 str = g_strdup_printf ( (gdb) n 47 mapping = gst_rtsp_server_get_media_mapping (server); (gdb) n 49 str = g_strdup_printf ( (gdb) n 59 factory = gst_rtsp_media_factory_new (); (gdb) n 60 gst_rtsp_media_factory_set_launch (factory, str); (gdb) n 59 factory = gst_rtsp_media_factory_new (); (gdb) n 60 gst_rtsp_media_factory_set_launch (factory, str); (gdb) n 61 g_free (str); (gdb) n 64 gst_rtsp_media_mapping_add_factory (mapping, "/test", factory); (gdb) n 67 g_object_unref (mapping); (gdb) n 70 gst_rtsp_server_attach (server, NULL); (gdb) n 73 g_main_loop_run (loop); (gdb) n [New Thread 0xb7e99b90 (LWP 17561)] [New Thread 0xb7498b90 (LWP 17562)] [New Thread 0xb6a97b90 (LWP 17563)] [New Thread 0xb6096b90 (LWP 17564)] [New Thread 0xb5695b90 (LWP 17565)] [New Thread 0xb4c94b90 (LWP 17566)] [New Thread 0xb4257b90 (LWP 17567)] [New Thread 0xb3856b90 (LWP 17568)] ^C Program received signal SIGINT, Interrupt. 0x00110416 in __kernel_vsyscall () (gdb) thread apply all bt
+ Trace 221085
Hi, I found one more strange thing. Please forgive me if it is because of my misunderstanding. Inside gst-plugins-base/gst-libs/gst/rtsp/gstrtspconnection.c ------------------------------------------------ I made the return value from static GstRTSPResult build_next (GstRTSPBuilder * builder, GstRTSPMessage * message,GstRTSPConnection * conn) as GST_RTSP_OK without considering the return value of read_bytes (conn, (guint8 *) builder->buffer, &builder->offset, 1); ( this returns 0,"controlled shut down" after one minute of play back) And now the video is playing . I tested it more than one hour. But the problem is that after this, the server will not accept any client request!
Hi, gst-plugins-base/gst-libs/gst/rtspgstrtspconneciton.c, -------------------------------------------------------------- Inside the function body gst_rtsp_source_dispatch (GSource * source, GSourceFuncallback G_GNUC_UNUSED,gpointer user_data G_GNUC_UNUSED) If build_next() returns EEOF, control goes to "goto eof;" and there the watchfuntion "closed" is initiating., so that the streaming is stopping . But for QuickTime player(in tunneling) , getting zero in the read socket function after one minute of streaming, and the build_next() returns EEOF after one minute. So the streaming stopped. But here actually the client is not closing ! If we remove the "watch->funcs.closed (watch, watch->user_data);" from "goto eof" and add " watch->funcs.message_received (watch, &watch->message, watch->user_data); return TRUE;" (so that write event occur without any problem). these to eof: then the streaming is not stopped .I checked it for two hours. One more problem still exist that, the server is not receiving further requests from client side player after this.
If we give a "PAUSE" after one minute of playback, we get " added new client 0x8b04fa8 ip 10.0.0.191:60168" in the server side stdout. and for getting the further playback, we needs to give the "PLAY" after some 30-45 seconds. A new session will be formed, but playback resumes from the previous "PAUSE" position. !
Created attachment 157558 [details] [review] patch1 (for gst-rtsp-server)
Created attachment 157559 [details] [review] patch2(gst-plugins-base)
If we opt streaming by Tunnelling RTSP and RTP through HTTP, In order to get through some proxies, a POST connection per RTSP request must be made instead of one POST connection per session.The client may at its option close the POST connection at any given time. The best time for this usually occurs after the PLAY request. When the client needs to communicate to the server again, it opens up another POST connection. Servers should be prepared to handle a series of POST connections. Found two issues in which one is in gst-rtsp-server and the other is in gst-plugins-base. bug in gst-rtsp-server ------------------------------ Inside tunnel_complete() funtion in rtsp-client.c, there is a line to remove the tunnel id from hash table. g_hash_table_remove (tunnels, tunnelid); This is wrong. Because initially the client create a full duplex connection with tunneling (having no problem there.).And after some time(approximately one minute) for sending an rtsp request ,client opens up another POST connection. (The POST request is never replied to by the server. ) . During this POST connection, this will get the same tunnel id which is previously created by, tunnelid = gst_rtsp_connection_get_tunnelid (client->connection); But it will not found the tunnel session in the hash table, because it is previously removed ! .I mean server is not handling the continuous POST connections after one GET connection. I am attaching a patch here to avoid this. bug in gst-plugins-base ------------------------------ Similarly , in gst-plugins-base, inside gst_rtsp_connection_do_tunnel() function, there is line g_return_val_if_fail (conn->tstate == TUNNEL_STATE_GET, GST_RTSP_EINVAL); This is wrong. Because tunnel state of connection is either TUNNEL_STATE_GET or TUNNEL_STATE_COMPLETE. Because after the PLAY request, When the client needs to communicate to the server again, it opens up another POST connection. In this case tunnel state of conn is TUNNEL_STATE_COMPLETE and conn2 is POST.
Ok, I see. Your patch does not seem to fix anything, the fundamental problem is in rtspconnection.c that returns EOF on one socket. We should probably only signal that the connection closed when both sockets are EOF.
Ya . Actually for my requirement i avoided that EOF, and make it as , returns GST_RTSP_OK for all times. We need to fix that in a proper way. But I think the previous two changes are needed together with that EOF handling. Presently I made all these 3 changes 1) avoid that EOF( it is not a proper way,so not submitted the patch-just done it for my requirement) 2) patch1 3) patch2 And worked with out any problem. So i think 2 and 3 are needed .
Player like QuickTime, uses Tunnelling RTSP and RTP through HTTP and in which they will send POST connections for each RTSP requests. So each POST connection needs to check whether a previous tunnel is there or not, so I think we should remove the line g_hash_table_remove (tunnels, tunnelid); Similar in case of patch2 also :) (even we handled the eof)
For avoiding the EOF , i used the following temporary setting.(diff file is pasted as the last part of this comment) Because after a few minutes playback, client will close the POST connection. (if we didn't give RTSP commands for a long time).Doing so frees socket and memory resources at the server that might otherwise be unused for a long time. But in gst-rtsp-server, it will accept as an eof, and closed the watch functions. So there will not be any further writing process. So client side won't get the stream there after. I avoided this watch funtion close() and initiate the message recive watch function(Inside the gst_rtsp_source_dispatch() function).So even the POST channel (client to server channel in full duplex mode) is closed, The Server to client channel will be there .And the server will continue the write process to the socket. So we will get the stream in client side . Whenever the client side wants to send an RTSP command ,it will create another POST channel through a new connection. For accepting that the previous two patches are needed I think. Presently all working fine in my system. :) diff --git a/gst-libs/gst/rtsp/gstrtspconnection.c b/gst-libs/gst/rtsp/gstrtspconnection.c index b2a30d8..2e77cdb 100644 --- a/gst-libs/gst/rtsp/gstrtspconnection.c +++ b/gst-libs/gst/rtsp/gstrtspconnection.c @@ -3213,9 +3213,10 @@ write_blocked: /* ERRORS */ eof: { - if (watch->funcs.closed) - watch->funcs.closed (watch, watch->user_data); - return FALSE; + + watch->funcs.message_received (watch, &watch->message, + watch->user_data); + return TRUE; } error: {
Wim: Expecting your comments as early as possible :)
I've got it working now, will push soon.
wow, nice :) . Without that two changes !. Waiting for the patch :)
commit 318fbf33102aa3c33194fa08aed38bc9e94e8642 Author: Wim Taymans <wim.taymans@collabora.co.uk> Date: Tue Apr 6 10:55:42 2010 +0200 rtspconnection: Handle closed POST socket in tunneling Catch more socket errors. Rework how sockets are managed in the GSource, wake up the maincontext instead of adding/removing the sockets from the source. Add callback for when the tunnel connection is lost. Some clients (Quicktime Player) close the POST connection in tunneled mode and reopen the socket when needed. See #612915 commit 30c31a65eb03873c00dc358a1a36bb67f881fb9b Author: Wim Taymans <wim.taymans@collabora.co.uk> Date: Tue Apr 6 11:13:51 2010 +0200 client: handle lost_tunnel callbacks Handle lost_tunnel callbacks and use it to store the tunnelid back into the hashtable so that we can reuse it for when the client reopens the POST socket. Close the connection after a TEARDOWN. Make sure or watchid is cleared when the watch is removed. Fixes #612915
one last thing: the server should keep the client session open for as long as the TCP connection is open because quicktime player does not seem to send RTCP reports back to the server.
commit 336ffc0941308597105f4cd3bc8c1cb497b38108 Author: Wim Taymans <wim.taymans@collabora.co.uk> Date: Tue Apr 6 17:08:40 2010 +0200 client: improve client cleanups Make sure the session does not timeout when using TCP. We need to do this because quicktime player does not send RTCP for some reason in tunneled mode. Refactor some cleanup code. Fixes #612915
Nice work ! Ok, I will check it.