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 641072 - [baseaudiosink] Improve latency-time handling and optionally aggregate buffers until latency-time is reached
[baseaudiosink] Improve latency-time handling and optionally aggregate buffer...
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gst-plugins-base
0.10.x
Other Linux
: Normal enhancement
: 0.10.31
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2011-01-31 20:00 UTC by David Henningsson
Modified: 2014-10-13 11:08 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Patch against git head (2.29 KB, patch)
2011-01-31 20:00 UTC, David Henningsson
committed Details | Review
Patch v2 - allow bigger writes (2.75 KB, patch)
2011-08-18 13:30 UTC, David Henningsson
committed Details | Review

Description David Henningsson 2011-01-31 20:00:54 UTC
Created attachment 179744 [details] [review]
Patch against git head

On low-end machines, PulseAudio can crash due to spending too much time in RT prio, and with the PulseAudio debug log is filled with rewinds. One way to counteract this, and improve performance in general, is to send fewer bigger packets instead of many small ones. 

I'm attaching a patch that removes a strange limit of packet size to GStreamer's "segment size", which have been reported by more than one user, to fix the problem of PulseAudio crashing.
Comment 1 Stefan Sauer (gstreamer, gtkdoc dev) 2011-02-02 07:59:37 UTC
Comment on attachment 179744 [details] [review]
Patch against git head

Thanks for the patch!
Comment 2 Tim-Philipp Müller 2011-02-02 09:04:27 UTC
commit 1e2c1467ae042a3c6bb1a6bc0c07aeff13ec5edb
Author: David Henningsson <david.henningsson@canonical.com>
Date:   Mon Jan 31 05:58:36 2011 +0100

    Pulsesink: Allow chunks up to bufsize instead of segsize
    
    By allowing larger chunks to be sent, PulseAudio will have a
    lower CPU usage. This is especially important on low-end machines,
    where PulseAudio can crash if packets are coming in at a higher
    rate than PulseAudio can process them.
    
    Signed-off-by: David Henningsson <david.henningsson@canonical.com>
Comment 3 Sebastian Dröge (slomo) 2011-02-02 18:32:57 UTC
Doesn't this change make pulsesink ignore the "latency-time" property of baseaudiosink? Just choosing a higher value for latency-time would fix this bug too
Comment 4 Stefan Sauer (gstreamer, gtkdoc dev) 2011-02-03 10:41:32 UTC
(In reply to comment #3)
> Doesn't this change make pulsesink ignore the "latency-time" property of
> baseaudiosink? Just choosing a higher value for latency-time would fix this bug
> too

Yes, you are absolutely right. That was not visible from the patch (lack of context), but
  bufsize = buf->spec.segsize * buf->spec.segtotal;

What we should do instead is to configure the buffer- and latency-time from the high-level bins (and obviously revert the patch):
- playbin2 can set long buffer-time (1 sec) and use low number of segments (2-4).
- rtpbin would consigure a low-latency time and use 2 segments (buffer-time=2*latency-time)

I mark this as a blocker in oder to get consensus before next release.
Comment 5 David Henningsson 2011-02-03 11:07:04 UTC
Hrmm. I don't know GStreamer internals that well, but still, we never send more than has been created by the caller to gst_pulseringbuffer_commit. And if that is more than "latency-time", the caller has obviously already ignored latency-time. 

There is no gain in not sending what we already have created, right? So we shouldn't care about latency-time here, but earlier in the chain. 

Btw, I do agree that 10 ms is terribly low for a music player and that 1 sec or so would be more appropriate.
Comment 6 Sebastian Dröge (slomo) 2011-02-03 11:11:56 UTC
Collecting multiple buffers and only sending them to PA all together decreases the number of context switches
Comment 7 Sebastian Dröge (slomo) 2011-04-08 12:37:39 UTC
I'm going to revert the patch for this release. What should be done is what Stefan said, set the buffer/latency times on the elements. And maybe baseaudiosink/audiosink could have another property to always collect latency-time samples before pushing them to the sink and aggregate buffers if upstream provided smaller buffers.

I'll reassign this bug to -base and let's continue discussion then.
Comment 8 Pierre Bossart 2011-04-11 15:58:07 UTC
FYI, this bug is related to the changes I suggested in #641544.
I think we all agree that the default buffer sizes aren't great for music playback and could be increased.
However as Arun pointed out, increasing buffer sizes up to the default pulseaudio 2s has pretty nasty side effects on existing applications. Totem takes forever to pause and Rhythmbox ends-up crapping out... Instead of forcing a large buffer in playbin2 we may want the application to use a profile to indirectly set theses values.
Comment 9 David Henningsson 2011-08-18 13:30:11 UTC
The previous patch (posted several months ago) for improving pulsesink writes was rejected, due to causing underruns when playing wma files. I've been able to reproduce that error here, and have come up with a new version of the patch which does not underruns in that case.

In short, the behavioural difference is
 - without the patch, waiting and write size were both never above segsize
 - with the old patch, both waiting and write size could grow up to bufsize.
 - with the new patch, waiting is done up to segsize. However when waiting is done, it writes as much as it can.

Also, the previous patch was blamed to "ignore the latency-time" of the sink. This statement is false, at least for the new version of the patch. The latency is controlled by setting tlength and minreq parameters of pa_buffer_attr, which in turn controls the behaviour of pa_stream_writable_size.

Let me go through the patch quickly for you:

> diff --git a/ext/pulse/pulsesink.c b/ext/pulse/pulsesink.c
> index c9f0b58..b90ebe3 100644
> --- a/ext/pulse/pulsesink.c
> +++ b/ext/pulse/pulsesink.c
> @@ -1430,9 +1430,7 @@ gst_pulseringbuffer_commit (GstRingBuffer * buf, guint64 * sample,
>
>      towrite = out_samples * bps;
>
> -    /* Only ever write segsize bytes at once. This will
> -     * also limit the PA shm buffer to segsize
> -     */
> +    /* Wait for at least segsize bytes to become available */
>      if (towrite > buf->spec.segsize)
>        towrite = buf->spec.segsize;

Just change the comment to adhere to the new behaviour.

> @@ -1481,7 +1479,7 @@ gst_pulseringbuffer_commit (GstRingBuffer * buf, guint64 * sample,
>             goto uncork_failed;
>         }
>
> -        /* we can't write a single byte, wait a bit */
> +        /* we can't write segsize bytes, wait a bit */
>          GST_LOG_OBJECT (psink, "waiting for free space");
>          pa_threaded_mainloop_wait (mainloop);

Comment clarification.

> @@ -1489,14 +1487,10 @@ gst_pulseringbuffer_commit (GstRingBuffer * buf, guint64 * sample,
>            goto was_paused;
>        }
>
> -      /* make sure we only buffer up latency-time samples */
> -      if (pbuf->m_writable > buf->spec.segsize) {
> -        /* limit buffering to latency-time value */
> -        pbuf->m_writable = buf->spec.segsize;
> -
> -        GST_LOG_OBJECT (psink, "Limiting buffering to %" > G_GSIZE_FORMAT,
> -            pbuf->m_writable);
> -      }

So this is what's essentially wrong - there is no extra "buffering" being done here (despite the comment), as the samples are already in a buffer when they're coming into this function. This limit is what worsens performance, so remove it.

> +      /* Recalculate what we can write in the next chunk */
> +      towrite = out_samples * bps;
> +      if (pbuf->m_writable > towrite)
> +          pbuf->m_writable = towrite;
>
>        GST_LOG_OBJECT (psink, "requesting %" G_GSIZE_FORMAT " bytes of "
>            "shared memory", pbuf->m_writable);

Instead limit what we write to what's left to write in this round.

> @@ -1510,14 +1504,9 @@ gst_pulseringbuffer_commit (GstRingBuffer * buf, guint64 * sample,
>        GST_LOG_OBJECT (psink, "got %" G_GSIZE_FORMAT " bytes of shared memory",
>            pbuf->m_writable);
>
> -      /* Just to make sure that we didn't get more than requested */
> -      if (pbuf->m_writable > buf->spec.segsize) {
> -        /* limit buffering to latency-time value */
> -        pbuf->m_writable = buf->spec.segsize;
> -      }
>      }

The same write limit stuff is being done twice, remove it here as well.

>
> -    if (pbuf->m_writable < towrite)
> +    if (towrite > pbuf->m_writable)
>        towrite = pbuf->m_writable;
>      avail = towrite / bps;

Just more readable/common semantic IMO.
Comment 10 David Henningsson 2011-08-18 13:30:55 UTC
Created attachment 194130 [details] [review]
Patch v2 - allow bigger writes
Comment 11 Sebastian Dröge (slomo) 2011-08-19 07:49:06 UTC
commit e70020b45630d99132a99892ecc6e1dcd1ce6f8a
Author: David Henningsson <david.henningsson@canonical.com>
Date:   Thu Aug 18 13:37:39 2011 +0200

    pulsesink: Allow writes in bigger chunks
    
    There's no use in splitting the incoming data down to the segsize
    limit - by writing as much as possible in one chunk, we increase
    performance and avoid PulseAudio unnecessary rewinds.
    
    Signed-off-by: David Henningsson <david.henningsson@canonical.com>
Comment 12 Sebastian Dröge (slomo) 2011-08-19 08:08:29 UTC
I think there's still something to do with this bug in baseaudiosink, right?
Comment 13 David Henningsson 2011-08-19 08:30:35 UTC
I think this is really two separate bugs in one:

1) The pulsesink writing is inoptimal in that it splits packets when it's not needed, which is now fixed in my patch

2) The default buffer sizes for music playback should be larger, for better performance in general.
Comment 14 David Henningsson 2011-08-19 08:32:58 UTC
(In reply to comment #13)
> I think this is really two separate bugs in one:
> 
> 1) The pulsesink writing is inoptimal in that it splits packets when it's not
> needed, which is now fixed in my patch
> 
> 2) The default buffer sizes for music playback should be larger, for better
> performance in general.

*bashes at bugzilla for making some strange unintended hyperlink*
Comment 15 Edward Hervey 2013-08-23 12:00:09 UTC
Is this still an issue with current git ? If so maybe Arun could have a look ?
Comment 16 Arun Raghavan 2014-10-13 11:08:29 UTC
This can be closed now. David's aggregation patch has been merged a while back, and the larger latency handling is discussed under bug #641544.