player/Thread: calculate `buffered_before_play` based on a fixed duration
Previously, there was the setting `buffered_before_play` which specified a percentage of the audio buffer, defaulting to `10%`. That was working well enough for quite some time, until high-quality audio formats became common. At 44.1 kHz, 16 bit stereo, MPD collected 2.3 seconds worth of data in the buffer before starting playback. With the same default settings and 192 kHz, 24 bit stereo, that was only 0.27 seconds. Making this depend on the byte size only leads to high latency at low quality, and too little data at high quality. The natural choice would be to use a duration instead of a byte size, which should give the same good experience with all audio formats. Since the `buffered_before_play` configuration setting was not understood well by users and caused more harm than good, this commit deprecates it. It has now no effect.
This commit is contained in:
parent
c1600bcf3d
commit
5b2374b949
1
NEWS
1
NEWS
|
@ -14,6 +14,7 @@ ver 0.21 (not yet released)
|
|||
- proxy: require libmpdclient 2.9
|
||||
- proxy: forward `sort` and `window` to server
|
||||
* player
|
||||
- hard-code "buffer_before_play" to 1 second, independent of audio format
|
||||
- "one-shot" single mode
|
||||
* input
|
||||
- curl: download to buffer instead of throttling transfer
|
||||
|
|
|
@ -54,7 +54,7 @@ const ConfigTemplate config_param_templates[] = {
|
|||
{ "volume_normalization" },
|
||||
{ "samplerate_converter" },
|
||||
{ "audio_buffer_size" },
|
||||
{ "buffer_before_play" },
|
||||
{ "buffer_before_play", false, true },
|
||||
{ "http_proxy_host", false, true },
|
||||
{ "http_proxy_port", false, true },
|
||||
{ "http_proxy_user", false, true },
|
||||
|
|
|
@ -57,6 +57,12 @@
|
|||
|
||||
static constexpr Domain player_domain("player");
|
||||
|
||||
/**
|
||||
* Start playback as soon as enough data for this duration has been
|
||||
* pushed to the decoder pipe.
|
||||
*/
|
||||
static constexpr auto buffer_before_play_duration = std::chrono::seconds(1);
|
||||
|
||||
class Player {
|
||||
PlayerControl &pc;
|
||||
|
||||
|
@ -80,9 +86,10 @@ class Player {
|
|||
|
||||
/**
|
||||
* Start playback as soon as this number of chunks has been
|
||||
* pushed to the decoder pipe.
|
||||
* pushed to the decoder pipe. This is calculated based on
|
||||
* #buffer_before_play_duration.
|
||||
*/
|
||||
const unsigned buffer_before_play;
|
||||
unsigned buffer_before_play;
|
||||
|
||||
/**
|
||||
* If the decoder pipe gets consumed below this threshold,
|
||||
|
@ -191,7 +198,6 @@ public:
|
|||
Player(PlayerControl &_pc, DecoderControl &_dc,
|
||||
MusicBuffer &_buffer) noexcept
|
||||
:pc(_pc), dc(_dc), buffer(_buffer),
|
||||
buffer_before_play(pc.buffered_before_play),
|
||||
decoder_wakeup_threshold(buffer.GetSize() * 3 / 4)
|
||||
{
|
||||
}
|
||||
|
@ -517,6 +523,12 @@ Player::CheckDecoderStartup() noexcept
|
|||
play_audio_format = dc.out_audio_format;
|
||||
decoder_starting = false;
|
||||
|
||||
const size_t buffer_before_play_size =
|
||||
play_audio_format.TimeToSize(buffer_before_play_duration);
|
||||
buffer_before_play =
|
||||
(buffer_before_play_size + sizeof(MusicChunk::data) - 1)
|
||||
/ sizeof(MusicChunk::data);
|
||||
|
||||
idle_add(IDLE_PLAYER);
|
||||
|
||||
if (pending_seek > SongTime::zero()) {
|
||||
|
|
Loading…
Reference in New Issue