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 795176 - souphttpsrc: Reading in too big blocksizes can cause the connection to time out
souphttpsrc: Reading in too big blocksizes can cause the connection to time out
Status: RESOLVED OBSOLETE
Product: GStreamer
Classification: Platform
Component: gst-plugins-good
git master
Other Linux
: Normal normal
: git master
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2018-04-11 22:54 UTC by Nicola
Modified: 2018-11-03 15:28 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
proof of concept patch (3.28 KB, patch)
2018-04-16 07:40 UTC, Nicola
reviewed Details | Review

Description Nicola 2018-04-11 22:54:18 UTC
please try this pipeline:

gst-launch-1.0 -v souphttpsrc location="http://root:prassel1@93.63.189.11:56182/axis-cgi/record/export/exportrecording.cgi?schemaversion=1&recordingid=20180411_132332_237E_ACCC8E5CE596&exportformat=matroska&diskid=SD_DISK&starttime=2018-04-11T11:23:32Z&stoptime=2018-04-11T11:29:47Z" ! matroskademux ! fakesink silent=false sync=false

the last buffer pts will be 0:06:13.674000000

now change sync=false to sync=true

the last buffer pts will vary every time and it never reachs 0:06:13.674000000

the server is ok, using curl, wget ecc.. and limit-rate option the problem does not happen.

I tested also with a custom element based on ffmpeg (avsrc, bug 788583) and it works the same way with sync=true and sync=false

so the problem is in souphttpsrc or libsoup and it is probably related to the missing Content-Length header
Comment 1 Nicola 2018-04-12 22:21:20 UTC
the problem is that g_input_stream_read here:

https://cgit.freedesktop.org/gstreamer/gst-plugins-good/tree/ext/soup/gstsouphttpsrc.c#n1710

return 0 but we are not really at the end of the file since other implementations work as expected, could be a glib bug?

According to the docs here:

https://developer.gnome.org/gio/stable/GInputStream.html#g-input-stream-read

"""
Zero is returned on end of file (or if count is zero), but never otherwise.
"""

this not seems the case, thanks
Comment 2 Nicola 2018-04-12 22:25:01 UTC
I tested with:

- glib 2.56.1, gstreamer 1.14.0, libsoup 2.62.1
- glib 2.50.3, gstreamer 1.12.3, libsoup 2.56.0

both these combinations shows the problem
Comment 3 Claudio Saavedra 2018-04-13 07:17:43 UTC
If you think this is a glib bug why did you move it to libsoup?
Comment 4 Sebastian Dröge (slomo) 2018-04-13 11:48:01 UTC
It's most likely the *implementation* in libsoup for GInputStream. It returns 0 bytes before the whole response body is returned (i.e. later calls would probably give the remainder).
Comment 5 Nicola 2018-04-13 12:51:54 UTC
Claudio, when using sync=true GStreamer asks to libsoup to download the file at a speed slower than the available network bandwidth, the problem does not happen when using sync=false that means download as fast as possibile,

curl or wget work as expected both at full speed than at a slower speed with the given http server (a network camera) and this exclude a server side problem

even my proof of concept GStreamer plugin based on libav (bug 788583) works as expected in both use cases
Comment 6 Claudio Saavedra 2018-04-13 15:09:28 UTC
It's going to take a while for me to try to debug this; also I'm not familiar at all with how gstreamer works. Is there any chance you could write a minimal test case using libsoup's relevant input stream implementation that can reproduce this issue? It would help narrow it down.
Comment 7 Nicola 2018-04-13 15:29:13 UTC
well, I can try in my spare time, but I'm not familiar with libsoup, I'll try to copy libsoup relevant code from souphttpsrc's GStreamer plugin.

Sebastian, I think that a good test case to simulate sync=true outside GStreamer is a timer that read for example 8KB (or something lesser than the available bandwidth) from libsoup's GInputStream every seconds until g_input_stream_read returns 0 and then check if the received bytes are lesser than the expected ones, do you agree?
Comment 8 Dan Winship 2018-04-13 15:45:36 UTC
(In reply to Nicola from comment #0)
> so the problem is in souphttpsrc or libsoup and it is probably related to
> the missing Content-Length header

(In reply to Nicola from comment #5)
> when using sync=true GStreamer asks to libsoup to download the file
> at a speed slower than the available network bandwidth

Are you sure the server isn't just timing out on you and closing the connection?
Comment 9 Nicola 2018-04-13 17:12:44 UTC
Thanks Dan,

you are right,

please take a look at these wireshark dumps here:

http://94.177.162.225/temp/795176.7z

the video file duration is 5 minutes and 18 seconds, avsrc read from the server all the time, while souphttpsrc read for about 125 seconds and 90 seconds after the last read the server close the connection.

Sebastian, there is no bug in libsoup, I think the problem is in souphttpsrc, specifically here:

https://cgit.freedesktop.org/gstreamer/gst-plugins-good/tree/ext/soup/gstsouphttpsrc.c#n1628

I see logs such as this one

souphttpsrc gstsouphttpsrc.c:1642:gst_soup_http_src_check_update_blocksize:<souphttpsrc0> Increased blocksize to 4194304

increasing the blocksize is a problem when you read high compressed streams and you play them synced on the clock, how do you propose to solve this, a property to limit tha max blocksize? an hardcoded limit? thanks
Comment 10 Sebastian Dröge (slomo) 2018-04-14 14:51:54 UTC
You could use libsoup's get.c, move it to use the GInputStream, read in chunks and add a sleep in the read-loop. That should reproduce the problem from what I understand
Comment 11 Sebastian Dröge (slomo) 2018-04-14 14:54:51 UTC
Ah nevermind, missed the last comment. Yeah so on the GStreamer side it should not just read 0 but also get an GError that the connection was closed, or not?

For the solution, I don't really know. Limiting the block-size is an option of course, but there's always a trade-off here. Lower block-sizes have lower latency and higher overhead, and the opposite for bigger block-sizes.

A property could make sense, but ideally we could solve this without requiring any settings.
Comment 12 Nicola 2018-04-14 15:12:55 UTC
(In reply to Sebastian Dröge (slomo) from comment #11)
> Ah nevermind, missed the last comment. Yeah so on the GStreamer side it
> should not just read 0 but also get an GError that the connection was
> closed, or not?


I think the current behaviour is correct here, the server can close the connection at the end of the file too

> 
> For the solution, I don't really know. Limiting the block-size is an option
> of course, but there's always a trade-off here. Lower block-sizes have lower
> latency and higher overhead, and the opposite for bigger block-sizes.
> 
> A property could make sense, but ideally we could solve this without
> requiring any settings.

probably we should increase block size if bytes_read >= blocksize * GROW_BLOCKSIZE_LIMIT and the difference in time between the current socket read and the previous one is <= 1 second or even a smaller value. This way we increase the block size only if the pipeline is really consuming all these bytes. 

If the pipeline does not consume the readed bytes quick enough I think that increasing the blocksize is useless.

If you agree I can work on a patch that implements this but I'm really busy at the moment and I don't know when I'll have an hour to do this. 

Thanks for your support,

Nicola
Comment 13 Nicola 2018-04-16 07:40:42 UTC
Created attachment 370975 [details] [review]
proof of concept patch

with this patch the issue is fixed, you can easily test with any large enough file served using an http server on localhost, when using sync=false the blocksize is increased as before, with sync=true the blocksize remains small enough to avoid the connection to time out
Comment 14 Sebastian Dröge (slomo) 2018-04-16 08:05:06 UTC
The approach makes sense to me. Thiago, you added this code. What do you think?
Comment 15 Sebastian Dröge (slomo) 2018-04-18 11:39:47 UTC
Comment on attachment 370975 [details] [review]
proof of concept patch

Looks good to me
Comment 16 GStreamer system administrator 2018-11-03 15:28:59 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/issues/463.