After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 612915 - streaming stopped for tcp interleaved communication:
streaming stopped for tcp interleaved communication:
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gst-rtsp-server
git master
Other Linux
: Normal major
: 0.10.6
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2010-03-15 05:44 UTC by sreerenj
Modified: 2010-04-06 19:35 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
patch1 (for gst-rtsp-server) (537 bytes, patch)
2010-03-31 07:02 UTC, sreerenj
none Details | Review
patch2(gst-plugins-base) (766 bytes, patch)
2010-03-31 07:03 UTC, sreerenj
none Details | Review

Description sreerenj 2010-03-15 05:44:51 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.
Comment 1 sreerenj 2010-03-15 18:25:46 UTC
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 .
Comment 2 sreerenj 2010-03-24 06:38:00 UTC
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?
Comment 3 sreerenj 2010-03-24 07:53:22 UTC
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!!
Comment 4 Wim Taymans 2010-03-24 11:53:22 UTC
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.
Comment 5 sreerenj 2010-03-24 12:59:34 UTC
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 !
Comment 6 sreerenj 2010-03-25 08:58:06 UTC
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


Comment 7 sreerenj 2010-03-26 13:34:46 UTC
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!
Comment 8 sreerenj 2010-03-29 11:52:01 UTC
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.
Comment 9 sreerenj 2010-03-29 12:58:29 UTC
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. !
Comment 10 sreerenj 2010-03-31 07:02:58 UTC
Created attachment 157558 [details] [review]
patch1 (for gst-rtsp-server)
Comment 11 sreerenj 2010-03-31 07:03:45 UTC
Created attachment 157559 [details] [review]
patch2(gst-plugins-base)
Comment 12 sreerenj 2010-03-31 07:04:37 UTC

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.
Comment 13 Wim Taymans 2010-03-31 17:52:04 UTC
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.
Comment 14 sreerenj 2010-03-31 18:37:09 UTC
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 .
Comment 15 sreerenj 2010-03-31 19:13:24 UTC
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)
Comment 16 sreerenj 2010-04-01 06:06:48 UTC
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:
   {
Comment 17 sreerenj 2010-04-01 18:42:31 UTC
Wim: Expecting your comments as early as possible :)
Comment 18 Wim Taymans 2010-04-05 12:35:06 UTC
I've got it working now, will push soon.
Comment 19 sreerenj 2010-04-05 12:42:25 UTC
wow, nice :) . Without that two changes !. Waiting for the patch :)
Comment 20 Wim Taymans 2010-04-06 09:16:30 UTC
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
Comment 21 Wim Taymans 2010-04-06 09:17:25 UTC
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.
Comment 22 Wim Taymans 2010-04-06 15:10:36 UTC
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
Comment 23 sreerenj 2010-04-06 19:35:29 UTC
Nice work ! Ok, I will check it.