mirror of
https://github.com/badaix/snapcast.git
synced 2025-06-10 23:01:45 +02:00
Fix deadlock and segfault in stream
This commit is contained in:
parent
99e147c5aa
commit
fd862f1bd6
2 changed files with 29 additions and 24 deletions
|
@ -251,8 +251,9 @@ cs::time_point_clk Stream::getNextPlayerChunk(void* outputBuffer, unsigned long
|
||||||
frame_delta_ -= framesCorrection;
|
frame_delta_ -= framesCorrection;
|
||||||
|
|
||||||
long toRead = frames + framesCorrection;
|
long toRead = frames + framesCorrection;
|
||||||
char* buffer = new char[toRead * format_.frameSize];
|
if (toRead * format_.frameSize > read_buffer_.size())
|
||||||
cs::time_point_clk tp = getNextPlayerChunk(buffer, toRead);
|
read_buffer_.resize(toRead * format_.frameSize);
|
||||||
|
cs::time_point_clk tp = getNextPlayerChunk(read_buffer_.data(), toRead);
|
||||||
|
|
||||||
const auto max = framesCorrection < 0 ? frames : toRead;
|
const auto max = framesCorrection < 0 ? frames : toRead;
|
||||||
// Divide the buffer into one more slice than frames that need to be dropped.
|
// 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
|
// 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: " <<
|
// LOG(TRACE, LOG_TAG) << "duplicate - requested: " << frames << ", read: " << toRead << ", slice: " << n << ", size: " << size << ", out pos: " <<
|
||||||
// pos << ",
|
// pos << ", source pos: " << pos - n << "\n";
|
||||||
// source pos: " << pos - n << "\n";
|
memcpy(static_cast<char*>(outputBuffer) + pos * format_.frameSize, read_buffer_.data() + (pos - n) * format_.frameSize, size * format_.frameSize);
|
||||||
memcpy(static_cast<char*>(outputBuffer) + pos * format_.frameSize, buffer + (pos - n) * format_.frameSize, size * format_.frameSize);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Read all input frames, but skip a frame per slice when writing to the output.
|
// 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
|
// LOG(TRACE, LOG_TAG) << "remove - requested: " << frames << ", read: " << toRead << ", slice: " << n << ", size: " << size << ", out pos: " << pos
|
||||||
// - n <<
|
// - n << ", source pos: " << pos << "\n";
|
||||||
// ", source pos: " << pos << "\n";
|
memcpy(static_cast<char*>(outputBuffer) + (pos - n) * format_.frameSize, read_buffer_.data() + pos * format_.frameSize, size * format_.frameSize);
|
||||||
memcpy(static_cast<char*>(outputBuffer) + (pos - n) * format_.frameSize, buffer + pos * format_.frameSize, size * format_.frameSize);
|
|
||||||
}
|
}
|
||||||
pos += size;
|
pos += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] buffer;
|
|
||||||
return tp;
|
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 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
|
// and can play 30ms of the stream
|
||||||
size_t silent_frames = static_cast<size_t>(-chunk_->format.nsRate() * std::chrono::duration_cast<cs::nsec>(age).count());
|
size_t silent_frames = static_cast<size_t>(-chunk_->format.nsRate() * std::chrono::duration_cast<cs::nsec>(age).count());
|
||||||
|
bool result = (silent_frames <= frames);
|
||||||
|
silent_frames = std::min(silent_frames, frames);
|
||||||
LOG(DEBUG, LOG_TAG) << "Silent frames: " << silent_frames << ", frames: " << frames
|
LOG(DEBUG, LOG_TAG) << "Silent frames: " << silent_frames << ", frames: " << frames
|
||||||
<< ", age: " << std::chrono::duration_cast<cs::usec>(age).count() / 1000. << "\n";
|
<< ", age: " << std::chrono::duration_cast<cs::usec>(age).count() / 1000. << "\n";
|
||||||
getSilentPlayerChunk(outputBuffer, silent_frames);
|
getSilentPlayerChunk(outputBuffer, silent_frames);
|
||||||
getNextPlayerChunk((char*)outputBuffer + (chunk_->format.frameSize * silent_frames), frames - silent_frames);
|
getNextPlayerChunk((char*)outputBuffer + (chunk_->format.frameSize * silent_frames), frames - silent_frames);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
hard_sync_ = false;
|
hard_sync_ = false;
|
||||||
resetBuffers();
|
resetBuffers();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -472,6 +475,7 @@ bool Stream::getPlayerChunk(void* outputBuffer, const cs::usec& outputBufferDacT
|
||||||
catch (int e)
|
catch (int e)
|
||||||
{
|
{
|
||||||
LOG(INFO) << "Exception\n";
|
LOG(INFO) << "Exception\n";
|
||||||
|
hard_sync_ = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,7 @@ private:
|
||||||
|
|
||||||
soxr_t soxr_;
|
soxr_t soxr_;
|
||||||
std::vector<char> resample_buffer_;
|
std::vector<char> resample_buffer_;
|
||||||
|
std::vector<char> read_buffer_;
|
||||||
int frame_delta_;
|
int frame_delta_;
|
||||||
// int64_t next_us_;
|
// int64_t next_us_;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue