GNOME Bugzilla – Bug 743834
tcpserversink: fails with html5 <video> client
Last modified: 2016-02-26 11:45:20 UTC
The problem is in use of the tcpserversink plug-in from gstreamer1.0 base set for translation a video stream from bin to html5 <video> element. Gstreamer pipeline: gst-launch-1.0 videotestsrc ! video/x-raw,width=1024,pixel-aspect-ratio=1/1 ! videoconvert ! theoraenc ! oggmux ! tcpserversink host=192.168.0.107 port=5454 sync=TRUE In the receiver web-page: <video src="http://192.168.0.107:5454" autoplay="autoplay" > Your browser does not support the VIDEO tag and/or RTP streams. </video> I found that problem occurs during gst_multi_socket_sink_handle_client_read() execution. Namely, any browser (instead of other client apps such as vlc or a gst client pipeline) falls into ... }else if(nread < 0) { ... (in current ver. is gstmultisocketsink.c, 593) and returns FALSE what cause client disconnect. I don't clearly understand full meaning of this code block, but I reached some results only when I modified it: I retained only WARNING about read error but cancelled the error generation and changed return to TRUE. After rebuild gst-plugins-base (v. 1.2.4, current in Ubuntu) web clients successfully connects to the pipeline and the video can be viewed. Is it may be possible to modify the content of this else {} block in master?
Part of the problem might be that browsers expect an http server at the other end of the connection, but tcpserversink doest not speak http. The nbytes == 0 case indicates that the client closed the connection, so I'm a bit puzzled why ignoring it would make things work, but if it works, it's hard to argue with that I guess. Someone just needs to investigate what's actually happening there then.
I guess we expect the client to only read, not write, and browsers will send http requests, so we should just ignore those and continue to send data instead of disconnecting the client entirely on our end.
Yes, it's really working! I'm stepping from fact that gstreamer-0.10 but not gstreamer-1.0 working normally with almost same pipeline (autovodeoconvert instead of videoconvert used). May be browser clients has adaptive routines which automatiacally detect content-type, etc.
(In reply to comment #2) > I guess we expect the client to only read, not write, and browsers will send > http requests, so we should just ignore those and continue to send data instead > of disconnecting the client entirely on our end. It looks good. The problem is also presented by several issues in web and it's resolving can make good news to some web applications developers.
(In reply to comment #1) > The nbytes == 0 case indicates that the client closed the connection Just in case, I told about case "nbytes < 0" (with "could not read" message) instead of "nbytes == 0" (with "client asked for close" message).
Tim-Philipp, what about the matter? Are you planning changes in gstmultisocketsink.c to avoid client disconnect in case of read error?
Related to this, see https://coaxion.net/blog/2013/10/streaming-gstreamer-pipelines-via-http/ That uses multisocketsink. tcpserversink by itself can't really do this like Tim says, you need something that speaks HTTP.
Ok, thank you! And sorry, I don't perfectly understand English and it seemed to me that he wants to change this place in the code despite mentioned reasons. > we should just ignore those and continue to send data instead of > disconnecting the client entirely on our end
Well, I think using tcpserversink for this purpose is not really entirely right, since it's not an http server. So it's not really a super-severe bug in my opinion, because tcpserversink was not meant to serve data to an http server. However, many browsers seem to just accept the data even if there's no http handshake, so if we can make that work with a trivial change that has no other negative side-effects, maybe we should do that. I have not yet looked further at the code to see what's happening.
Thank you.
I too found the difference between 0.10 and 1.0 pretty confusing and patched the "issue" in the same way as Dmitry. I would propose his fix as it does not seem to break anything downstream.
This should fix it: commit 6db2ee56b6e862f54c479e553f179daf2056da74 Author: Tim-Philipp Müller <tim@centricular.com> Date: Sat Apr 4 21:38:40 2015 +0100 tcpserversink: don't error out if clients send us something, just ignore it We don't expect clients to send us any data, but if they do, just ignore it. Web browsers might send us an HTTP request for example, but some will still be happy if we just send them data without a proper HTTP response. There was a bug in the reading code path. We only have a small read buffer and would provoke an EWOULDBLOCK trying to read because we don't bail out of the loop early enough. https://bugzilla.gnome.org/show_bug.cgi?id=743834
Dmitry, Arjen, it would be great if you could test the follow-up patch in bug #761257 to see if things still work properly for you then. (In retrospect my original patch doesn't seem quite right.)
@Tim: I no longer have the code lying around unfortunately so I am unable to test it. I'm sorry.