diff options
author | Max Kellermann <max@musicpd.org> | 2017-11-05 17:48:41 +0100 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2017-11-05 17:48:41 +0100 |
commit | 523051132d77cb5da01847592c4c1e1faae93c6a (patch) | |
tree | b82c42d2638eb9e83715cac0ea9dc77c7797e798 /src | |
parent | 55e6629fb49187f90e3c8357cee16ab393f5667d (diff) | |
parent | b111a8fe8d64ee9584ffc63f648dc1bce7c670d6 (diff) |
Merge branch 'v0.20.x'
Diffstat (limited to 'src')
-rw-r--r-- | src/decoder/plugins/VorbisDecoderPlugin.cxx | 16 | ||||
-rw-r--r-- | src/input/plugins/CurlInputPlugin.cxx | 21 | ||||
-rw-r--r-- | src/output/Thread.cxx | 19 | ||||
-rw-r--r-- | src/player/Thread.cxx | 9 |
4 files changed, 53 insertions, 12 deletions
diff --git a/src/decoder/plugins/VorbisDecoderPlugin.cxx b/src/decoder/plugins/VorbisDecoderPlugin.cxx index be557a353..fbbc0264a 100644 --- a/src/decoder/plugins/VorbisDecoderPlugin.cxx +++ b/src/decoder/plugins/VorbisDecoderPlugin.cxx @@ -178,6 +178,20 @@ VorbisDecoder::SubmitInit() client.Ready(audio_format, eos_granulepos > 0, duration); } +#ifdef HAVE_TREMOR +static inline int16_t tremor_clip_sample(int32_t x) +{ + x >>= 9; + + if (x < INT16_MIN) + return INT16_MIN; + if (x > INT16_MAX) + return INT16_MAX; + + return x; +} +#endif + bool VorbisDecoder::SubmitSomePcm() { @@ -197,7 +211,7 @@ VorbisDecoder::SubmitSomePcm() auto *dest = &buffer[c]; for (size_t i = 0; i < n_frames; ++i) { - *dest = *src++; + *dest = tremor_clip_sample(*src++); dest += channels; } } diff --git a/src/input/plugins/CurlInputPlugin.cxx b/src/input/plugins/CurlInputPlugin.cxx index a1be25d90..6ab7e34ee 100644 --- a/src/input/plugins/CurlInputPlugin.cxx +++ b/src/input/plugins/CurlInputPlugin.cxx @@ -66,7 +66,6 @@ static const size_t CURL_RESUME_AT = 384 * 1024; struct CurlInputStream final : public AsyncInputStream, CurlResponseHandler { /* some buffers which were passed to libcurl, which we have too free */ - char range[32]; CurlSlist request_headers; CurlRequest *request = nullptr; @@ -89,9 +88,20 @@ struct CurlInputStream final : public AsyncInputStream, CurlResponseHandler { static InputStream *Open(const char *url, Mutex &mutex, Cond &cond); + /** + * Create and initialize a new #CurlRequest instance. After + * this, you may add more request headers and set options. To + * actually start the request, call StartRequest(). + */ void InitEasy(); /** + * Start the request after having called InitEasy(). After + * this, you must not set any CURL options. + */ + void StartRequest(); + + /** * Frees the current "libcurl easy" handle, and everything * associated with it. * @@ -365,6 +375,11 @@ CurlInputStream::InitEasy() request_headers.Clear(); request_headers.Append("Icy-Metadata: 1"); +} + +void +CurlInputStream::StartRequest() +{ request->SetOption(CURLOPT_HTTPHEADER, request_headers.Get()); request->Start(); @@ -391,6 +406,7 @@ CurlInputStream::SeekInternal(offset_type new_offset) /* send the "Range" header */ if (offset > 0) { + char range[32]; #ifdef WIN32 // TODO: what can we use on Windows to format 64 bit? sprintf(range, "%lu-", (long)offset); @@ -399,6 +415,8 @@ CurlInputStream::SeekInternal(offset_type new_offset) #endif request->SetOption(CURLOPT_RANGE, range); } + + StartRequest(); } void @@ -422,6 +440,7 @@ CurlInputStream::Open(const char *url, Mutex &mutex, Cond &cond) try { BlockingCall(c->GetEventLoop(), [c](){ c->InitEasy(); + c->StartRequest(); }); } catch (...) { delete c; diff --git a/src/output/Thread.cxx b/src/output/Thread.cxx index 5acf0da0b..ed2feac82 100644 --- a/src/output/Thread.cxx +++ b/src/output/Thread.cxx @@ -245,16 +245,15 @@ try { inline bool AudioOutputControl::PlayChunk() noexcept { - if (tags) { - const auto *tag = source.ReadTag(); - if (tag != nullptr) { - const ScopeUnlock unlock(mutex); - try { - output->SendTag(*tag); - } catch (const std::runtime_error &e) { - FormatError(e, "Failed to send tag to %s", - GetLogName()); - } + // ensure pending tags are flushed in all cases + const auto *tag = source.ReadTag(); + if (tags && tag != nullptr) { + const ScopeUnlock unlock(mutex); + try { + output->SendTag(*tag); + } catch (const std::runtime_error &e) { + FormatError(e, "Failed to send tag to %s", + GetLogName()); } } diff --git a/src/player/Thread.cxx b/src/player/Thread.cxx index a6d2b3d4b..90431ef90 100644 --- a/src/player/Thread.cxx +++ b/src/player/Thread.cxx @@ -32,6 +32,7 @@ #include "output/MultipleOutputs.hxx" #include "tag/Tag.hxx" #include "Idle.hxx" +#include "system/PeriodClock.hxx" #include "util/Domain.hxx" #include "thread/Name.hxx" #include "Log.hxx" @@ -146,6 +147,8 @@ class Player { */ SongTime elapsed_time; + PeriodClock throttle_silence_log; + public: Player(PlayerControl &_pc, DecoderControl &_dc, MusicBuffer &_buffer) @@ -934,6 +937,8 @@ Player::SongBorder() { FormatDefault(player_domain, "played \"%s\"", song->GetURI()); + throttle_silence_log.Reset(); + ReplacePipe(dc.pipe); pc.outputs.SongBorder(); @@ -1095,6 +1100,10 @@ Player::Run() /* the decoder is too busy and hasn't provided new PCM data in time: send silence (if the output pipe is empty) */ + + if (throttle_silence_log.CheckUpdate(std::chrono::seconds(5))) + FormatWarning(player_domain, "Decoder is too slow; playing silence to avoid xrun"); + if (!SendSilence()) break; } |