Bug 65703

Summary: High latency in HTTP streaming
Product: PulseAudio Reporter: Arun Raghavan <arun>
Component: modulesAssignee: Wang Xingchao <wangxingchao2011>
Status: RESOLVED MOVED QA Contact: pulseaudio-bugs
Severity: normal    
Priority: medium CC: amar.akshat, lennart, wangxingchao2011
Version: unspecified   
Hardware: Other   
OS: All   
Whiteboard:
i915 platform: i915 features:
Attachments: patch to debug http latency issue
http-latency issue log
this is the correct/full log, ignore previous log
add missing rewind callback
0001-protocol-http-Add-missing-rewind-callback-for-source.patch
0002-protocol-http-Fix-assertion-in-do_write.patch

Description Arun Raghavan 2013-06-13 09:30:26 UTC
When streaming audio from the HTTP module, latency can go quite high (in the order of several seconds). This is particularly painful since Rygel depends on this functionality for exposing PA devices over UPnP.
Comment 1 Amar Akshat 2013-06-18 15:52:55 UTC
Trying to reproduce it.
How do we know that the latency increases in order of several seconds ?

Running rygel, and browsing from my Android device UPnP player and playing sound.
Executing from the master branch. Am I missing something here. ?
Comment 2 Arun Raghavan 2013-06-18 15:56:02 UTC
You're browsing the PulseAudio devices and not just the music files exported by Rygel, right?
Comment 3 Arun Raghavan 2013-06-18 16:00:09 UTC
p.s.: you'll need to manually load the module-http-protocol-tcp and module-rygel-media-server
Comment 4 Amar Akshat 2013-06-18 16:05:04 UTC
No, I was initially browsing just the files exported by Rygel, and was trying to use GstLaunch to browse media monitor source.

Thanks for the heads up, regarding loading the rygel module.
Comment 5 Amar Akshat 2013-06-19 01:50:13 UTC
So, I tried browsing pa devices as exposed by rygel,
And for some reason, I am receiving following error for every connect request from my UPnP browser.

(rygel:23376): Rygel-CRITICAL **: Error from pipeline RygelHTTPGstResponse: gstsouphttpsrc.c(922): gst_soup_http_src_finished_cb (): /GstPipeline:RygelHTTPGstResponse/GstBin:transcoder-source/GstSoupHTTPSrc:souphttpsrc1:

I am still investigating it, however if you any reflections.. could let me know!
Comment 6 Amar Akshat 2013-06-19 11:08:06 UTC
I was able to reproduce it, First I was assuming that client device buffering would have been issue, however the latency increases with time, it seems the bit rates are different.
Comment 7 Amar Akshat 2013-06-19 16:25:28 UTC
Hi Arun,

src/pulsecore/protocol-http.c

function: source_output_push_cb -- seems to be pushing the chunk into outq,
function: source_output_process_msg --seems to be fetching from out queue and doing a do_write for the chunk, into the stream for http.

Seems like atleast 2 threads. Suspecting that there might be sync issue, I put a counter in do write and source_output_push_cb,

At the start - 
do_write, counter = 1
source_output_push_cb, counter = 1

After some time, (around 3 minutes later)

do_write, counter = 6165
source_output_push_cb, counter = 6417
which suggests. that do_write has happened 6165 times, and push into the outq has happened 6417 times.

Clearly in the 2 threads, the sync is not happening, and the difference probably increases linear to time.

Any idea why this must be happening?
Comment 8 Arun Raghavan 2013-06-20 09:59:06 UTC
Are you counting the number of calls or the number of bytes read/written?
Comment 9 Amar Akshat 2013-06-20 10:56:43 UTC
Actually I am just counting the number of times the operation is happening, but thats a nice suggestion to count number of bytes.
Comment 10 Amar Akshat 2013-06-20 14:56:45 UTC
I think the total bytes pushed and written are pretty close and appear to be in sync.

At time 't'
Pushed => 184072960
do_write => 184421476

Do you think that is far apart ?
Comment 11 Amar Akshat 2013-06-21 15:54:10 UTC
So reducing the "Maximum hw buffer size" to minimal (~0), did bring down the latency by 2 seconds, however the effective latency is still around 16 seconds in my setup.
Comment 12 Tanu Kaskinen 2013-06-23 07:54:49 UTC
(In reply to comment #10)
> I think the total bytes pushed and written are pretty close and appear to be
> in sync.
> 
> At time 't'
> Pushed => 184072960
> do_write => 184421476
> 
> Do you think that is far apart ?

Assuming 44100 Hz 16-bit 2-channel audio, that's 2 seconds.
Comment 13 Amar Akshat 2013-06-23 08:41:50 UTC
Following up on this, I notice that http streamed audio being played at client at 1411Kbps, i.e. 1.4 Mbps, which I think is too high, atleast for Wifi networks. I am running the test on a plain Ad-hoc network, and streaming audio WITHOUT using rygel (direct PA source over http), Windows Media Player isn't able to play the stream over network without any buffering. Additionally if I increase buffering to 2 seconds at the WM Player, the sounds comes broken.

I think compressing the audio might be a solution to this.
Comment 14 Arun Raghavan 2013-06-23 13:27:13 UTC
There are a few points of latency in this. The first is in PulseAudio, there's some in the network itself (but this is relatively low), and then there's some in the UPnP client itself.

You could probably eliminate the client buffering (or at least make it deterministic) by just opening the HTTP stream directly (look at http://localhost:4714/).

I am able to reproduce some large latency with this as well on my laptop, so this eliminates both the network and the client to some extent, but is still in the "few seconds" range, which is not that great.

Now the latency in PulseAudio is basically caused by points where we are buffering data, so this should be something to look at.
Comment 15 Amar Akshat 2013-06-23 15:44:56 UTC
>You could probably eliminate the client buffering (or at least make it >deterministic) by just opening the HTTP stream directly (look at >http://localhost:4714/).
>

Yes, absolutely, so in my experiment described in Commend 13, I was accessing directly the sound cards as exposed by PA over HTTP, without Rygel. However, by setting the client buffering to 0 or as low as 2 seconds, I wasn't able to play the sound perfectly.
Moreover I found that my client (Windows Media Player), was playing the stream at 1411 Kbps, which is the bitrate for uncompressed sound.

Does this suggest that we should apply compression at PulseAudio..?
Comment 16 Arun Raghavan 2013-06-24 10:39:09 UTC
(In reply to comment #15)
> >You could probably eliminate the client buffering (or at least make it >deterministic) by just opening the HTTP stream directly (look at >http://localhost:4714/).
> >
> 
> Yes, absolutely, so in my experiment described in Commend 13, I was
> accessing directly the sound cards as exposed by PA over HTTP, without
> Rygel. However, by setting the client buffering to 0 or as low as 2 seconds,
> I wasn't able to play the sound perfectly.
> Moreover I found that my client (Windows Media Player), was playing the
> stream at 1411 Kbps, which is the bitrate for uncompressed sound.
> 
> Does this suggest that we should apply compression at PulseAudio..?

Your localhost network should easily cope with the 1.4 Mbps, so this is unlikely to be the culprit.

That's not to say comrpession is not desirable (although doing that in PA itself is not ideal), but the bandwidth problem should be orthogonal to the latency being this large.
Comment 17 Amar Akshat 2013-06-25 14:14:59 UTC
> 
> That's not to say comrpession is not desirable (although doing that in PA
> itself is not ideal), but the bandwidth problem should be orthogonal to the
> latency being this large.

However, the buffering is definitely at client end. Because I did the following.

a) Exposed sound cards using rygel, and also directly through http.
b) Connected from my Android device and started streaming, with around 16 second latency.
c) Simply power-offed the system, removing any trace of PA and rygel, however my Android device kept playing the sound, until 16 seconds, and then the stream just died.

So, the client essentially has the stream buffered for 16 seconds.
Comment 18 Wang Xingchao 2013-07-02 16:39:11 UTC
(In reply to comment #6)
> I was able to reproduce it, First I was assuming that client device
> buffering would have been issue, however the latency increases with time, it
> seems the bit rates are different.

Hi Amar Akshat,

please correct me if there's misunderstanding. I knew littlbe about uPnp and Rygel, even i donot setup the environment to reproduce this issue yet. After some google search and study, i assume the whole picture like below:

1) you're using some Andorid based uPnp player(like BubbleUPnP or other) as control point and player software.
2) Rygel was running and you could get exported media files from other uPnp devices through uPnp player.
3) Pa could export devices in the DLNA network, maybe local device or other uPnp deivce has audio playback capability.
4) uPnp player could see above PA devices through Rygel system.
5) uPnpn player could choose media files and play them through previous exported PA device.

In software level, i assume some operations like below:
1) Rygel get media data and send them to Gstreamer
2) Media data routed to Pulesaudio and send out to selected PA sink through
   http-protocol. The issue is high latency here.

Still i donot quite understand the role of module-rygel-media-server here.
i need some time to get things clear. please let me know whether something was wrong.

thanks
--xingchao
Comment 19 Wang Xingchao 2013-07-02 17:01:35 UTC
(In reply to comment #17)
> > 
> > That's not to say comrpession is not desirable (although doing that in PA
> > itself is not ideal), but the bandwidth problem should be orthogonal to the
> > latency being this large.
> 
> However, the buffering is definitely at client end. Because I did the
> following.
> 
> a) Exposed sound cards using rygel, and also directly through http.
> b) Connected from my Android device and started streaming, with around 16
> second latency.
> c) Simply power-offed the system, removing any trace of PA and rygel,
> however my Android device kept playing the sound, until 16 seconds, and then
> the stream just died.
> 
> So, the client essentially has the stream buffered for 16 seconds.

what's the expected behavior here after step c) ?
After power-offed, the connection died so if no buffering at client end user could hear nothing, right?
And now android device continue sending left buffering stream out for default device(andoird itself) until all buffering data empty.

So the issue is maybe PA blocked the transferring and caused the high latency.
I mean if PA is fast enough or ready to accept any buffering stream from client end, the buffering stream length in client end should be always 0. 

thanks
--xingchao
Comment 20 Wang Xingchao 2013-07-03 00:44:38 UTC
(In reply to comment #14)
> There are a few points of latency in this. The first is in PulseAudio,
> there's some in the network itself (but this is relatively low), and then
> there's some in the UPnP client itself.
> 
> You could probably eliminate the client buffering (or at least make it
> deterministic) by just opening the HTTP stream directly (look at
> http://localhost:4714/).
> 
> I am able to reproduce some large latency with this as well on my laptop, so
> this eliminates both the network and the client to some extent, but is still
> in the "few seconds" range, which is not that great.
> 
> Now the latency in PulseAudio is basically caused by points where we are
> buffering data, so this should be something to look at.

Hi Arun/Amar Akshat,

Do you have guide to reproduce this issue within a simple test environment?
I donot have uPnp devices and no Rygel setup yet. But i think if focus on Pa's 
http-module and module-rygel-media-server, maybe can find new clues. According to comment#17, sounds PA was blocked by something strange and client buffering increased to a high latency value. 

So if we can reproduce/test this issue within a simple model, it should be convenient to reproduce it.

--xingchao
Comment 21 Wang Xingchao 2013-07-03 00:47:01 UTC
(In reply to comment #14)
> There are a few points of latency in this. The first is in PulseAudio,
> there's some in the network itself (but this is relatively low), and then
> there's some in the UPnP client itself.
> 
> You could probably eliminate the client buffering (or at least make it
> deterministic) by just opening the HTTP stream directly (look at
> http://localhost:4714/).
> 
> I am able to reproduce some large latency with this as well on my laptop, so
> this eliminates both the network and the client to some extent, but is still
> in the "few seconds" range, which is not that great.
> 
> Now the latency in PulseAudio is basically caused by points where we are
> buffering data, so this should be something to look at.

Hi Arun/Amar Akshat,

Do you have guide to reproduce this issue within a simple test environment?
I donot have uPnp devices and no Rygel setup yet. But i think if focus on Pa's 
http-module and module-rygel-media-server, maybe can find new clues. According to comment#17, sounds PA was blocked by something strange and client buffering increased to a high latency value. 

So if we can reproduce/test this issue within a simple model, it should be convenient to reproduce it.

--xingchao
Comment 22 Amar Akshat 2013-07-03 02:30:22 UTC
Hi Xingchao,

Forget the rygel factor for a minute. Concentrate on http-module, and the delay due to that.

So, you need to, 
-- fetch the master branch
-- build the code, and run ./src/pulseaudio -vvvv
-- load http module, ./src/pactl load-module module-http-protocol-tcp
-- now make sure if the module is loaded by visiting, localhost:4714
-- If you see sources and sinks, you would be able to grab the http link to them by copying the link from the page.

Suppose you try sink(monitor), then you would you have something like

http://localhost:4714/listen/source/alsa_output.pci-0000_00_1b.0.analog-stereo.monitor

Now, you can play the above source on a VLC player, or using gstreamer tools like gst-launch.

I would suggest, try streaming on the local machine, to eliminate any latency caused due to network.

Hope this helps.

Amar
Comment 23 Amar Akshat 2013-07-03 02:32:34 UTC
(In reply to comment #19)
> (In reply to comment #17)
> > > 
> > > That's not to say comrpession is not desirable (although doing that in PA
> > > itself is not ideal), but the bandwidth problem should be orthogonal to the
> > > latency being this large.
> > 
> > However, the buffering is definitely at client end. Because I did the
> > following.
> > 
> > a) Exposed sound cards using rygel, and also directly through http.
> > b) Connected from my Android device and started streaming, with around 16
> > second latency.
> > c) Simply power-offed the system, removing any trace of PA and rygel,
> > however my Android device kept playing the sound, until 16 seconds, and then
> > the stream just died.
> > 
> > So, the client essentially has the stream buffered for 16 seconds.
> 
> what's the expected behavior here after step c) ?
If client had no buffering, and given the delay in PA, the sound would have immediately stopped at the client side (or maximum in 1-2 seconds).
The sound keeps playing for 16 seconds in the Client, suggests without reasonable doubt that client is buffering.
Comment 24 Amar Akshat 2013-07-03 02:42:39 UTC
(In reply to comment #18)
> (In reply to comment #6)
> > I was able to reproduce it, First I was assuming that client device
> > buffering would have been issue, however the latency increases with time, it
> > seems the bit rates are different.
> 
> Hi Amar Akshat,
> 
> please correct me if there's misunderstanding. I knew littlbe about uPnp and
> Rygel, even i donot setup the environment to reproduce this issue yet. After
> some google search and study, i assume the whole picture like below:
> 
> 1) you're using some Andorid based uPnp player(like BubbleUPnP or other) as
> control point and player software.

I was using, UPnP Play from Cybergarage.

> 2) Rygel was running and you could get exported media files from other uPnp
> devices through uPnp player.
> 3) Pa could export devices in the DLNA network, maybe local device or other
> uPnp deivce has audio playback capability.
> 4) uPnp player could see above PA devices through Rygel system.
> 5) uPnpn player could choose media files and play them through previous
> exported PA device.
> 
> In software level, i assume some operations like below:
> 1) Rygel get media data and send them to Gstreamer
> 2) Media data routed to Pulesaudio and send out to selected PA sink through
>    http-protocol. The issue is high latency here.
> 
> Still i donot quite understand the role of module-rygel-media-server here.
> i need some time to get things clear. please let me know whether something
> was wrong.

Yes, before the rygel factor we need to identify the latency due to the plain streaming over http.
So, you don't really need to use rygel module and any UPNP client to be able to reproduce it.
Comment 25 Wang Xingchao 2013-07-03 04:05:16 UTC
(In reply to comment #22)
> Hi Xingchao,
> 
> Forget the rygel factor for a minute. Concentrate on http-module, and the
> delay due to that.
> 
> So, you need to, 
> -- fetch the master branch
> -- build the code, and run ./src/pulseaudio -vvvv
> -- load http module, ./src/pactl load-module module-http-protocol-tcp
> -- now make sure if the module is loaded by visiting, localhost:4714
> -- If you see sources and sinks, you would be able to grab the http link to
> them by copying the link from the page.
> 
> Suppose you try sink(monitor), then you would you have something like
> 
> http://localhost:4714/listen/source/alsa_output.pci-0000_00_1b.0.analog-
> stereo.monitor
> 
> Now, you can play the above source on a VLC player, or using gstreamer tools
> like gst-launch.
> 
> I would suggest, try streaming on the local machine, to eliminate any
> latency caused due to network.
> 
> Hope this helps.
> 
> Amar

Hi Amar Akshat,

Thanks your guide.
Now i can see the sinks and source under "http://localhost:4714/listen".
i'm using Intel's ivybridge with codec "Realtek ALC889", also there's HDMI codec too.

The output info is like:
Sinks

Built-in Audio Analog Stereo

Sources

Built-in Audio Analog Stereo

And i think it's ready to use VLC player to play some mp3 files now.
I found VLC has network media option, and should i paste above sink link there?

The sink location is:
http://localhost:4714/listen/source/alsa_output.pci-0000_00_1b.0.analog-stereo.monitor

How did you continue test in your side?

thanks
--xingchao
Comment 26 Arun Raghavan 2013-07-03 04:13:00 UTC
gst-launch-1.0 souphttpsrc location=<uri> ! decodebin ! pulsesink

(gst-launch-0.10 and decodebin2 if you have gstreamer 0.10)
Comment 27 Wang Xingchao 2013-07-03 04:16:59 UTC
i add some configuration in VLC player:
1> open media file and choose one MP3 music file, configure it as stream.
2> in destination setup, choose "HTTP", and "NEXT", in the path field,
i should paste the sink location for PA, right?
What about the port number, should be changed to 4714?
3> goto next and start "stream".

please correct me if any step wrong.
Comment 28 Wang Xingchao 2013-07-03 05:36:33 UTC
(In reply to comment #26)
> gst-launch-1.0 souphttpsrc location=<uri> ! decodebin ! pulsesink
> 
> (gst-launch-0.10 and decodebin2 if you have gstreamer 0.10)

Thanks but seems this doesnot work well, i met some new errors;
gst-launch-0.10 -v souphttpsrc location=/home/xingchao/tmp/1299597316159.mp3 ! decodebin2 ! pulsesink
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
ERROR: from element /GstPipeline:pipeline0/GstSoupHTTPSrc:souphttpsrc0: Error parsing URL.
Additional debug info:
gstsouphttpsrc.c(1130): gst_soup_http_src_build_message (): /GstPipeline:pipeline0/GstSoupHTTPSrc:souphttpsrc0:
URL: /home/xingchao/tmp/1299597316159.mp3
ERROR: pipeline doesn't want to preroll.
Setting pipeline to NULL ...
Freeing pipeline ...

Please note it doesnot work either even i add "proxy" parameger for souphttpsrc.

thanks
--xingchao
Comment 29 Wang Xingchao 2013-07-03 05:41:58 UTC
(In reply to comment #28)
> (In reply to comment #26)
> > gst-launch-1.0 souphttpsrc location=<uri> ! decodebin ! pulsesink

meanwhile i found "souphttpsrc" works well with "filesink":

$ gst-launch-0.10 -v souphttpsrc location=https://bugs.freedesktop.org/show_bug.cgi?id=65703 ! filesink location=/home/xingchao/gst-launch-test.html
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
Got EOS from element "pipeline0".
Execution ended after 430978498 ns.
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...
$ ls gst-launch-test.html 
gst-launch-test.html

And it doesnot need "proxy" setting, it may use system proxy by default.
Comment 30 Arun Raghavan 2013-07-03 05:43:03 UTC
(In reply to comment #28)
> (In reply to comment #26)
> > gst-launch-1.0 souphttpsrc location=<uri> ! decodebin ! pulsesink
> > 
> > (gst-launch-0.10 and decodebin2 if you have gstreamer 0.10)
> 
> Thanks but seems this doesnot work well, i met some new errors;
> gst-launch-0.10 -v souphttpsrc location=/home/xingchao/tmp/1299597316159.mp3
> ! decodebin2 ! pulsesink

location needs to be an HTTP URI.
Comment 31 Wang Xingchao 2013-07-03 05:49:35 UTC
(In reply to comment #30)
> (In reply to comment #28)
> > (In reply to comment #26)
> > > gst-launch-1.0 souphttpsrc location=<uri> ! decodebin ! pulsesink
> > > 
> > > (gst-launch-0.10 and decodebin2 if you have gstreamer 0.10)
> > 
> > Thanks but seems this doesnot work well, i met some new errors;
> > gst-launch-0.10 -v souphttpsrc location=/home/xingchao/tmp/1299597316159.mp3
> > ! decodebin2 ! pulsesink
> 
> location needs to be an HTTP URI.

so if the location is "Source" exported by PA, could hear loopback audio, right?
The source location is "http://localhost:4714/listen/source/alsa_input.pci-0000_00_1b.0.analog-stereo".
Comment 32 Arun Raghavan 2013-07-03 05:51:20 UTC
(In reply to comment #31)
> so if the location is "Source" exported by PA, could hear loopback audio,
> right?
> The source location is
> "http://localhost:4714/listen/source/alsa_input.pci-0000_00_1b.0.analog-
> stereo".

Right.
Comment 33 Wang Xingchao 2013-07-03 06:43:00 UTC
(In reply to comment #32)
> (In reply to comment #31)
> > so if the location is "Source" exported by PA, could hear loopback audio,
> > right?
> > The source location is
> > "http://localhost:4714/listen/source/alsa_input.pci-0000_00_1b.0.analog-
> > stereo".
> 
> Right.

I used "arecord" to capture a piece of wav, it works well.
But when try to test the source, there's error, and cannot hear voice from Mic:

$gst-launch-0.10 -v souphttpsrc location=http://localhost:4714/listen/source/alsa_input.pci-0000_00_1b.0.analog-stereo ! decodebin2 ! pulsesink
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
ERROR: from element /GstPipeline:pipeline0/GstSoupHTTPSrc:souphttpsrc0: Service Unavailable
Additional debug info:
gstsouphttpsrc.c(1119): gst_soup_http_src_parse_status (): /GstPipeline:pipeline0/GstSoupHTTPSrc:souphttpsrc0:
Service Unavailable (503), URL: http://localhost:4714/listen/source/alsa_input.pci-0000_00_1b.0.analog-stereo
ERROR: pipeline doesn't want to preroll.
Setting pipeline to NULL ...
/GstPipeline:pipeline0/GstDecodeBin2:decodebin20/GstTypeFindElement:typefind.GstPad:src: caps = text/html
/GstPipeline:pipeline0/GstDecodeBin2:decodebin20/GstTypeFindElement:typefind.GstPad:src: caps = NULL
Freeing pipeline ...
Comment 34 Wang Xingchao 2013-07-03 07:34:50 UTC
Hi Akshat,

As i cannot reproduce the high latency issue atm, so would you share with me the pulseaudio infomathin when you do the test on your side?

pacmd--> info.

i wonder check the http-protocol client's status.

--xingchao
Comment 35 Wang Xingchao 2013-07-03 09:41:35 UTC
i would reproduce the issue on another machine later.
before that, i hope no misunderstanding from my side about the data path in below test command:
gst-launch-0.10 -v playbin uri=http://localhost:4714/listen/source/alsa_input.pci-0000_00_1b.0.analog-stereo

In such scenario, gst-launch would be the client for http_protocol, so the data path would be:
1> gst-launch try to read data from the exported source by PA, it's an http url.
2> pulseaudio regard gst-launch as the client connected to PA, also it's the target of source_out.
3> pulseaudio got data from Source and send to gst-launch
4> gst-launch buffer the data and send back to PA as the role of sink_input.
5> user hear captured audio from sink.

please correct me if any step wrong above.

--xingchao
Comment 36 Wang Xingchao 2013-07-03 11:05:56 UTC
(In reply to comment #35)
> i would reproduce the issue on another machine later.

I think i reproduced the issue now.
With same command on another laptop, i can long time delay after starting playing:

gst-launch playbin uri=http://localhost:4714/listen/source/alsa_input.pci-0000_00_1b.0.analog-stereo

$ gst-launch-0.10 playbin uri=http://localhost:4714/listen/source/alsa_input.pci-0000_00_1b.0.analog-stereo
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
buffering... 0%  
buffering... 0%  
...
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstPulseSinkClock
Buffering, setting pipeline to PAUSED ...
Done buffering, setting pipeline to PLAYING ...
...
Prerolled, waiting for buffering to finish...
Done buffering, setting pipeline to PLAYING ...
handling interrupt.
Interrupt: Stopping pipeline ...
Execution ended after 1254077037 ns.
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...


However the latency is larger than 16seconds here.
i would continue to investigate on that.
--xingchao
Comment 37 Arun Raghavan 2013-07-03 11:07:38 UTC
Note that playbin does buffering of its own, which is why I suggested the souphttpsrc + decodebin pipeline.
Comment 38 Wang Xingchao 2013-07-03 14:56:03 UTC
(In reply to comment #37)
> Note that playbin does buffering of its own, which is why I suggested the
> souphttpsrc + decodebin pipeline.

Oh good that explain much. :)
Comment 39 Wang Xingchao 2013-07-03 15:24:42 UTC
(In reply to comment #14)
> There are a few points of latency in this. The first is in PulseAudio,
> there's some in the network itself (but this is relatively low), and then
> there's some in the UPnP client itself.
> 
> You could probably eliminate the client buffering (or at least make it
> deterministic) by just opening the HTTP stream directly (look at
> http://localhost:4714/).
> 
> I am able to reproduce some large latency with this as well on my laptop, so
> this eliminates both the network and the client to some extent, but is still
> in the "few seconds" range, which is not that great.
> 
> Now the latency in PulseAudio is basically caused by points where we are
> buffering data, so this should be something to look at.

Arun, how did you reproduce this issue here? 
did you use command at comment #26?
gst-launch-1.0 souphttpsrc location=<uri> ! decodebin ! pulsesink

--xingchao
Comment 40 Wang Xingchao 2013-07-04 01:14:12 UTC
Arun,

could you try below command at your side?

gst-launch-0.10 souphttpsrc location=http://www.mediacollege.com/audio/tone/files/250Hz_44100Hz_16bit_30sec.wav ! decodebin ! pulsesink

I can hear sound at about ~2 seconds delay.

And compared with gst-launch, i used "mplayer" to repeat test, the delay is longer, ~4s.
That's caused by cache in mplayer:
"Cache size set to 320 KBytes
Cache fill: 12.62% (41368 bytes)   
"

So for me, this issue behavior is different:
1> with gst-launch playbin, comment #36.
gst-launch playbin uri=http://localhost:4714/listen/source/alsa_input.pci-0000_00_1b.0.analog-stereo
very long time delay. as your suggestion, switch to use souphttpsrc
2> with soupthttpsrc, the delay is ~2s, i think that's acceptable.

--xingchao
Comment 41 Wang Xingchao 2013-07-04 15:02:37 UTC
(In reply to comment #40)
> Arun,
> 
> could you try below command at your side?
> 
> gst-launch-0.10 souphttpsrc
> location=http://www.mediacollege.com/audio/tone/files/
> 250Hz_44100Hz_16bit_30sec.wav ! decodebin ! pulsesink
> 
> I can hear sound at about ~2 seconds delay.
> 
> And compared with gst-launch, i used "mplayer" to repeat test, the delay is
> longer, ~4s.
> That's caused by cache in mplayer:
> "Cache size set to 320 KBytes
> Cache fill: 12.62% (41368 bytes)   
> "
> 
> So for me, this issue behavior is different:
> 1> with gst-launch playbin, comment #36.
> gst-launch playbin
> uri=http://localhost:4714/listen/source/alsa_input.pci-0000_00_1b.0.analog-
> stereo
> very long time delay. as your suggestion, switch to use souphttpsrc
> 2> with soupthttpsrc, the delay is ~2s, i think that's acceptable.
> 
> --xingchao

As the playback has almost no latency, i suspect the latency coming from the capture routine:
gst-launch-0.10 souphttpsrc location=http://localhost:4714/listen/source/alsa_input.pci-0000_00_1b.0.analog-stereo ! decodebin ! pulsesink
(This test command doesnot work for me, there's error)
And in such scenario, the data path is like:

capture data-->PA Source-->http-protocol-->bin-->buffer?-->native-protocol-->PA-->Sink

currently i'm blocked by above test command, it doesnot work for me.

thanks
--xingchao
Comment 42 Wang Xingchao 2013-07-04 16:10:51 UTC
Amar,

did you tune the parameter of decodebin? i'm suspecting below parameters may has impact on the latency:
  "high-percent"            
  "low-percent"            
  "max-size-buffers"       
  "max-size-bytes"          
  "max-size-time"         

--xingchao
Comment 43 Wang Xingchao 2013-07-05 05:41:44 UTC
Created attachment 82062 [details] [review]
patch to debug http latency issue
Comment 44 Arun Raghavan 2013-07-05 05:50:05 UTC
The bug is about server side latency. Client side latency is something we don't have much control over. It is usually easy enough to generate additional latency by doing a few pause/resume cycles on the playback stream.
Comment 45 Arun Raghavan 2013-07-05 06:01:39 UTC
Also, I got something in the range of 5 seconds in my testing. 2 seconds is still not good - think of someone playing music from their laptop to a UPnP device. You don't want it to take 2s between hitting "next" and the track actually switching.
Comment 46 Wang Xingchao 2013-07-05 06:26:50 UTC
(In reply to comment #45)
> Also, I got something in the range of 5 seconds in my testing. 2 seconds is
> still not good - think of someone playing music from their laptop to a UPnP
> device. You don't want it to take 2s between hitting "next" and the track
> actually switching.

Yeah agree. 2 seconds is also long enough. Sometimes user may feel unacceptable.
i want to ensure the where the latency coming from. Maybe it's in http-protocol inside or from buffering in bin.
Comment 47 Wang Xingchao 2013-07-05 15:01:24 UTC
How to reproduce this issue in local machine-:

1. pulseaudio --k; pulseaudio -vvvv
2. pactl load-module module-http-protocol-tcp
3. browser sinks/sources in Fixfox, url is:
http://localhost:4714/listen
will show sinks and sources
As I enabled Rygel following this page(https://wiki.gnome.org/Rygel/Pulseaudio), so there're two Sinks:

Built-in Audio Analog Stereo
DLNA/UPnP Streaming

And one Sources

Built-in Audio Analog Stereo

4. The basic rule is, playback music on one sink 0, and featch stream from sink 0 and send back to sink 1. 
  Here's my test command:
  1) gst-launch-0.10 filesrc location=/home/tangtang/Downloads/b.mp3 ! mad ! audioconvert ! audioresample ! pulsesink device=upnp
  this would send mp3 stream to sink "upnp"
  2) gst-launch-0.10 souphttpsrc location=http://localhost:4714/listen/source/upnp.monitor ! decodebin2 ! pulsesink device=alsa_output.pci-0000_00_1b.0.analog-stereo
  this would featch stream from sink "upnp" and send data back to default sink(user could hear music)

it's better to start second command and you when you start first command, after some delay, you will hear the music playing.  If you stop first command, you will notice music continues playing for some time and stopped.

--xingchao
Comment 48 Wang Xingchao 2013-07-05 15:20:57 UTC
Created attachment 82081 [details]
http-latency issue log

This log starts from playing back on sink 0,  and stops on terminate playing back on sink 1.

So can continue to investigate the latency during the test.
Comment 49 Wang Xingchao 2013-07-05 15:27:32 UTC
Created attachment 82082 [details]
this is the correct/full log, ignore previous log
Comment 50 Wang Xingchao 2013-07-06 08:31:23 UTC
Created attachment 82117 [details] [review]
add missing rewind callback

seems the source_output donot take rewind callback, and this make connection's output_memblockq never stop sending out useless data. So if user press "pause" but the stream would still send out to client.
Comment 51 Wang Xingchao 2013-07-06 17:07:07 UTC
I have a new patch to fix the issue.
The rootcause is about rewind missing in protcol-http, that caused the memblockq always has old stream even sink/monitor_source have flushed their data.
And it would cause two obvious latency;
- when starting to playback stream.
The latency is "silence" before user hear the stream
- when cork or stop the stream
The latency is from old stream data in memblockq.

After adding rewind callback, both the latency reduced to acceptable range.

--xingchao
Comment 52 Wang Xingchao 2013-07-07 12:00:58 UTC
Created attachment 82132 [details] [review]
0001-protocol-http-Add-missing-rewind-callback-for-source.patch

first patch to add rewind callback
Comment 53 Wang Xingchao 2013-07-07 12:01:39 UTC
Created attachment 82133 [details] [review]
0002-protocol-http-Fix-assertion-in-do_write.patch

second patch to fix assertion error.
Comment 54 Wang Xingchao 2013-07-07 12:03:10 UTC
Arun/Amar,

The two patches could help reduce latency as my test shown in comment#47.
0001-protocol-http-Add-missing-rewind-callback-for-source.patch
0002-protocol-http-Fix-assertion-in-do_write.patch

Please let me know whether it works for you.

--xingchao
Comment 55 Amar Akshat 2013-07-09 06:18:11 UTC
I tested this on the release version of pulseaudio on Ubuntu 12.04 (wiz 1.0), and I noticed the latency dropped by almost 1 to 1.5 seconds. However, I guess, there is still some element of un-acceptability in the existing latency.

for some some reason, I am unable to test on master, and the latency is still the same. Will update, as soon as I have some success testing on master.

Please note that I am re-producing it as described in comment 47.
Comment 56 Tanu Kaskinen 2013-07-09 15:37:39 UTC
I very much doubt that adding a rewind callback is the correct fix. The reason is that nothing in the code base currently implements the source output process_rewind() callback, so it doesn't seem to be important (I don't fully understand how source rewinding works - it's quite different from sink rewinding).

Also, source outputs can be rewound only when connected to a monitor source. Are you using a monitor source for testing? If not, then the callback is never called. How can the patch then have any effect on the latency? It seems that pa_source_output_push() behaves differently if the process_rewind() callback is set (even if it's never called):

    limit = o->process_rewind ? 0 : o->source->thread_info.max_rewind;
Comment 57 Arun Raghavan 2013-07-09 15:52:17 UTC
Adding to what Tanu said, the latency really is much more likely to be in the HTTP module itself.
Comment 58 Wang Xingchao 2013-07-09 23:13:29 UTC
(In reply to comment #56)
> I very much doubt that adding a rewind callback is the correct fix. The
> reason is that nothing in the code base currently implements the source
> output process_rewind() callback, so it doesn't seem to be important (I
> don't fully understand how source rewinding works - it's quite different
> from sink rewinding).
> 
> Also, source outputs can be rewound only when connected to a monitor source.
> Are you using a monitor source for testing?

yes, the source outputs connected to the monitor source "upnp" in the test case. please look at comment #47.
And it's easy to reproduce the issue with comment#47, you can check from the log the callback was called, and the latency reduced effeciently.i.e. without the patch, when stop the first stream which rendering MP3 to monitor source, i still hear musck playing for almost ~2 seconds. With the patch applied, it would shtop playback immediately.


> If not, then the callback is
> never called. How can the patch then have any effect on the latency? It
> seems that pa_source_output_push() behaves differently if the
> process_rewind() callback is set (even if it's never called):
> 
>     limit = o->process_rewind ? 0 : o->source->thread_info.max_rewind;
Comment 59 Tanu Kaskinen 2013-07-10 09:06:26 UTC
Ok, I'll have a deeper look into the patch, and try to really understand what it does (I'm not very eager to work on this bug myself, but I try to review any patches that are sent).
Comment 60 Tanu Kaskinen 2013-09-09 08:50:24 UTC
I think I have now a bit better idea of how source rewinding works. I still don't think that setting a rewind callback for the source output implementation is a good idea. It does reduce the latency, because data doesn't get buffered in pa_source_output.thread_info.delay_memblock if the callback is set. However, the delay_memblockq exists for a reason: clients can't handle the stream time going backwards, which is what happens on rewinds, so there must be a buffer somewhere that hides the rewind events from clients. If you disable the buffer in pa_source_output, you should implement a similar buffer in protocol-http, but your patch doesn't implement that. The result is that your patch most likely causes non-continuities in the audio, when rewinds occur.

If the latency caused by the delay memblockq is too large, the solution is to request lower latency from the source output. This should reduce the maximum rewind size, and therefore also the size of the delay memblockq.
Comment 61 GitLab Migration User 2018-07-30 09:58:22 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/pulseaudio/pulseaudio/issues/139.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.