hzeller / gmrender-resurrect

Resource efficient UPnP/DLNA renderer, optimal for Raspberry Pi, CuBox or a general MediaServer. Fork of GMediaRenderer to add some features to make it usable.
GNU General Public License v2.0
851 stars 206 forks source link

Playback stutters when playing FLAC files due to buffering #182

Closed mill1000 closed 5 years ago

mill1000 commented 5 years ago

Issue

As of commit 4f221e6, playback of FLAC, and presumably other high quality files, stutters because playback is repeatedly paused for short durations in response to buffering messages from gstreamer. This occurs on both WiFi and Ethernet connections to the media server, and across multiple media servers implementations. Increasing the buffer duration can reduce the frequency of stutters but does not eliminate it.

A similar issue #169 exists, but was submitted before the buffering commit so I think it is unrelated.

This issue is more of a notice to others, as I'm nearly 100% certain the issue is within gstreamer.

Workaround

Disabling buffering with --gstout-buffer-duration=0 stops the stuttering.

Details

The issue can be seen outside of gmediarender by calling the gstreamer playbin with gst-launch like so

gst-launch-1.0 -v playbin uri=http://media_server_ip/uri_to_media_file.flac

and in the output multiple PAUSE, PLAY transitions can be seen.

Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
/GstPlayBin:playbin0/GstInputSelector:inputselector0.GstSelectorPad:sink_0: tags = taglist, title=(string)"Let\ It\ Go", artist=(string)22-20s, album=(string)Shake/Shiver/Moan, album-artist=(string)22-20s, track-number=(uint)9, audio-codec=(string)"Free\ Lossless\ Audio\ Codec\ \(FLAC\)", minimum-bitrate=(uint)541430, maximum-bitrate=(uint)629114, bitrate=(uint)521381;
New clock: GstAudioSinkClock
[Misc tag data removed]
Buffering, setting pipeline to PAUSED ...
Done buffering, setting pipeline to PLAYING ...
[Misc tag data removed]
Buffering, setting pipeline to PAUSED ...
Done buffering, setting pipeline to PLAYING ...
[Misc tag data removed]
Buffering, setting pipeline to PAUSED ...
Done buffering, setting pipeline to PLAYING ...
[Misc tag data removed]
Buffering, setting pipeline to PAUSED ...
Done buffering, setting pipeline to PLAYING ...

A user of gstreamer reported the same or a similar problem with FLAC files in 2016 (http://gstreamer-devel.966125.n4.nabble.com/Audio-dropouts-that-disappear-when-queue2-logging-is-enabled-td4679375.html), and some troubleshooting indicated it a problem between the souphttpsrc and queue2 elements within the uridecodebin, within playbin. Increasing the buffer size to 4 MB solved the users issue but this is an excessively large buffer for what is likely a 20-30 MB file.

An issue was created for this users report but is still open. https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/issues/253

At a high-level, it appears the source is pushing too much data into queue2, causing it to become full with only a single entry. When this entry is removed, the buffering level immediately drops to 0% and playback is paused. Then almost instantly the buffer is filled again and playback resumes.

The latest release of gstreamer (v1.16) hints that the issue is being worked on. The release notes (https://gstreamer.freedesktop.org/releases/1.16/) have the following note about queue2 behavior

queue2: avoid ping-pong between 0% and 100% buffering messages if upstream is pushing buffers larger than one of its limits, plus performance optimisations

I have compiled and tested against gstreamer v1.16 and, while possibly less frequent, the issue still remains.

newfaceinhell commented 5 years ago

I just came to say thank you mill1000. After rebuilding my Raspberry Pi the sound streamed by gmediarender stuttered. I spent two hours searching for the resolution for the issue until I found your entry. Thanks again, adding --gstout-buffer-duration=0 to ExecStart in gmediarender.service solved the issue.

hzeller commented 5 years ago

mmh, so maybe we should leave it off by default.

Did you try to also increase it with --gstout-buffer-duration ?

mill1000 commented 5 years ago

@hzeller I did try a larger buffer duration. I found it reduced the frequency of the stutter but could not eliminate it.

hzeller commented 5 years ago

Alright, I have now disabled the buffering by setting the default to zero to avoid unnecessary wasted debugging times.