diff --git a/client/stream.cpp b/client/stream.cpp index bc52befd..3bd6b997 100644 --- a/client/stream.cpp +++ b/client/stream.cpp @@ -1,20 +1,20 @@ /*** - This file is part of snapcast - Copyright (C) 2014-2020 Johannes Pohl + This file is part of snapcast + Copyright (C) 2014-2020 Johannes Pohl - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program. If not, see . - ***/ + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***/ #include "stream.hpp" #include "common/aixlog.hpp" @@ -251,8 +251,9 @@ cs::time_point_clk Stream::getNextPlayerChunk(void* outputBuffer, unsigned long frame_delta_ -= framesCorrection; long toRead = frames + framesCorrection; - char* buffer = new char[toRead * format_.frameSize]; - cs::time_point_clk tp = getNextPlayerChunk(buffer, toRead); + if (toRead * format_.frameSize > read_buffer_.size()) + read_buffer_.resize(toRead * format_.frameSize); + cs::time_point_clk tp = getNextPlayerChunk(read_buffer_.data(), toRead); const auto max = framesCorrection < 0 ? frames : toRead; // Divide the buffer into one more slice than frames that need to be dropped. @@ -282,22 +283,19 @@ cs::time_point_clk Stream::getNextPlayerChunk(void* outputBuffer, unsigned long { // Read one frame less per slice from the input, but write a duplicated frame per slice to the output // LOG(TRACE, LOG_TAG) << "duplicate - requested: " << frames << ", read: " << toRead << ", slice: " << n << ", size: " << size << ", out pos: " << - // pos << ", - // source pos: " << pos - n << "\n"; - memcpy(static_cast(outputBuffer) + pos * format_.frameSize, buffer + (pos - n) * format_.frameSize, size * format_.frameSize); + // pos << ", source pos: " << pos - n << "\n"; + memcpy(static_cast(outputBuffer) + pos * format_.frameSize, read_buffer_.data() + (pos - n) * format_.frameSize, size * format_.frameSize); } else { // Read all input frames, but skip a frame per slice when writing to the output. // LOG(TRACE, LOG_TAG) << "remove - requested: " << frames << ", read: " << toRead << ", slice: " << n << ", size: " << size << ", out pos: " << pos - // - n << - // ", source pos: " << pos << "\n"; - memcpy(static_cast(outputBuffer) + (pos - n) * format_.frameSize, buffer + pos * format_.frameSize, size * format_.frameSize); + // - n << ", source pos: " << pos << "\n"; + memcpy(static_cast(outputBuffer) + (pos - n) * format_.frameSize, read_buffer_.data() + pos * format_.frameSize, size * format_.frameSize); } pos += size; } - delete[] buffer; return tp; } @@ -378,13 +376,18 @@ bool Stream::getPlayerChunk(void* outputBuffer, const cs::usec& outputBufferDacT // and the current chunk duration is 50ms, so we need to play 20ms silence (as we don't have data) // and can play 30ms of the stream size_t silent_frames = static_cast(-chunk_->format.nsRate() * std::chrono::duration_cast(age).count()); + bool result = (silent_frames <= frames); + silent_frames = std::min(silent_frames, frames); LOG(DEBUG, LOG_TAG) << "Silent frames: " << silent_frames << ", frames: " << frames << ", age: " << std::chrono::duration_cast(age).count() / 1000. << "\n"; getSilentPlayerChunk(outputBuffer, silent_frames); getNextPlayerChunk((char*)outputBuffer + (chunk_->format.frameSize * silent_frames), frames - silent_frames); - hard_sync_ = false; - resetBuffers(); + if (result) + { + hard_sync_ = false; + resetBuffers(); + } return true; } return false; @@ -472,6 +475,7 @@ bool Stream::getPlayerChunk(void* outputBuffer, const cs::usec& outputBufferDacT catch (int e) { LOG(INFO) << "Exception\n"; + hard_sync_ = true; return false; } } diff --git a/client/stream.hpp b/client/stream.hpp index 48429082..7b90f4ad 100644 --- a/client/stream.hpp +++ b/client/stream.hpp @@ -85,6 +85,7 @@ private: soxr_t soxr_; std::vector resample_buffer_; + std::vector read_buffer_; int frame_delta_; // int64_t next_us_;