mirror of
https://github.com/badaix/snapcast.git
synced 2025-05-18 03:26:15 +02:00
seeking
git-svn-id: svn://elaine/murooma/trunk@209 d8a302eb-03bc-478d-80e4-98257eca68ef
This commit is contained in:
parent
10323c0485
commit
559baf31e3
6 changed files with 79 additions and 28 deletions
|
@ -22,6 +22,9 @@ void Player::start()
|
||||||
rate = stream_->format.rate;
|
rate = stream_->format.rate;
|
||||||
channels = stream_->format.channels;
|
channels = stream_->format.channels;
|
||||||
|
|
||||||
|
unsigned int buffer_time = 100 * 1000;
|
||||||
|
unsigned int period_time = buffer_time / 8;
|
||||||
|
|
||||||
|
|
||||||
/* Open the PCM device in playback mode */
|
/* Open the PCM device in playback mode */
|
||||||
if ((pcm = snd_pcm_open(&pcm_handle, PCM_DEVICE, SND_PCM_STREAM_PLAYBACK, 0)) < 0)
|
if ((pcm = snd_pcm_open(&pcm_handle, PCM_DEVICE, SND_PCM_STREAM_PLAYBACK, 0)) < 0)
|
||||||
|
@ -50,9 +53,12 @@ void Player::start()
|
||||||
if ((pcm = snd_pcm_hw_params_set_rate_near(pcm_handle, params, &rate, 0)) < 0)
|
if ((pcm = snd_pcm_hw_params_set_rate_near(pcm_handle, params, &rate, 0)) < 0)
|
||||||
cout << "ERROR: Can't set rate. " << snd_strerror(pcm) << "\n";
|
cout << "ERROR: Can't set rate. " << snd_strerror(pcm) << "\n";
|
||||||
|
|
||||||
long unsigned int periodsize = 2*rate/50;
|
snd_pcm_hw_params_set_period_time_near(pcm_handle, params, &period_time, 0);
|
||||||
if ((pcm = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, params, &periodsize)) < 0)
|
snd_pcm_hw_params_set_buffer_time_near(pcm_handle, params, &buffer_time, 0);
|
||||||
cout << "Unable to set buffer size " << (long int)periodsize << ": " << snd_strerror(pcm) << "\n";
|
|
||||||
|
// long unsigned int periodsize = stream_->format.msRate() * 50;//2*rate/50;
|
||||||
|
// if ((pcm = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, params, &periodsize)) < 0)
|
||||||
|
// cout << "Unable to set buffer size " << (long int)periodsize << ": " << snd_strerror(pcm) << "\n";
|
||||||
|
|
||||||
/* Write parameters */
|
/* Write parameters */
|
||||||
if ((pcm = snd_pcm_hw_params(pcm_handle, params)) < 0)
|
if ((pcm = snd_pcm_hw_params(pcm_handle, params)) < 0)
|
||||||
|
|
|
@ -6,13 +6,6 @@
|
||||||
// Olivier Chamoux <olivier.chamoux@fr.thalesgroup.com>
|
// Olivier Chamoux <olivier.chamoux@fr.thalesgroup.com>
|
||||||
//
|
//
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <deque>
|
|
||||||
#include <vector>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <thread>
|
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,20 @@ time_point_ms Stream::getSilentPlayerChunk(void* outputBuffer, unsigned long fra
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
time_point_ms Stream::seek(unsigned long ms)
|
||||||
|
{
|
||||||
|
if (!chunk)
|
||||||
|
chunk = chunks.pop();
|
||||||
|
// time_point_ms tp = chunk->timePoint();
|
||||||
|
while (ms > chunk->getDuration())
|
||||||
|
{
|
||||||
|
chunk = chunks.pop();
|
||||||
|
ms -= min(ms, (unsigned long)chunk->getDuration());
|
||||||
|
}
|
||||||
|
chunk->seek(ms * format.msRate());
|
||||||
|
return chunk->timePoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
time_point_ms Stream::getNextPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer, int correction)
|
time_point_ms Stream::getNextPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer, int correction)
|
||||||
{
|
{
|
||||||
|
@ -117,7 +131,7 @@ void Stream::resetBuffers()
|
||||||
void Stream::getPlayerChunk(void* outputBuffer, double outputBufferDacTime, unsigned long framesPerBuffer)
|
void Stream::getPlayerChunk(void* outputBuffer, double outputBufferDacTime, unsigned long framesPerBuffer)
|
||||||
{
|
{
|
||||||
//cout << "framesPerBuffer: " << framesPerBuffer << "\tms: " << framesPerBuffer*2 / PLAYER_CHUNK_MS_SIZE << "\t" << PLAYER_CHUNK_SIZE << "\n";
|
//cout << "framesPerBuffer: " << framesPerBuffer << "\tms: " << framesPerBuffer*2 / PLAYER_CHUNK_MS_SIZE << "\t" << PLAYER_CHUNK_SIZE << "\n";
|
||||||
//int msBuffer = framesPerBuffer / (format_.rate/1000);
|
int msBuffer = framesPerBuffer / format_.msRate();
|
||||||
//cout << msBuffer << " ms, " << framesPerBuffer << "\t" << format_.rate/1000 << "\n";
|
//cout << msBuffer << " ms, " << framesPerBuffer << "\t" << format_.rate/1000 << "\n";
|
||||||
int ticks = 0;
|
int ticks = 0;
|
||||||
long currentTick = getTickCount();
|
long currentTick = getTickCount();
|
||||||
|
@ -136,28 +150,43 @@ void Stream::getPlayerChunk(void* outputBuffer, double outputBufferDacTime, unsi
|
||||||
if (sleep != 0)
|
if (sleep != 0)
|
||||||
{
|
{
|
||||||
resetBuffers();
|
resetBuffers();
|
||||||
if (sleep < -10)
|
if (sleep < -msBuffer/2)
|
||||||
{
|
{
|
||||||
|
cout << "Sleep " << sleep;
|
||||||
sleep = Chunk::getAge(getSilentPlayerChunk(outputBuffer, framesPerBuffer)) - bufferMs + outputBufferDacTime;
|
sleep = Chunk::getAge(getSilentPlayerChunk(outputBuffer, framesPerBuffer)) - bufferMs + outputBufferDacTime;
|
||||||
std::cerr << "Sleep: " << sleep << ", chunks: " << chunks.size() << "\n";
|
std::cerr << " after: " << sleep << ", chunks: " << chunks.size() << "\n";
|
||||||
// std::clog << kLogNotice << "sleep: " << sleep << std::endl;
|
// std::clog << kLogNotice << "sleep: " << sleep << std::endl;
|
||||||
// if (sleep > -msBuffer/2)
|
// if (sleep > -msBuffer/2)
|
||||||
// sleep = 0;
|
// sleep = 0;
|
||||||
|
if (sleep < -msBuffer/2)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (sleep > 10)
|
else if (sleep > msBuffer/2)
|
||||||
{
|
{
|
||||||
|
cout << "Sleep " << sleep;
|
||||||
|
sleep = Chunk::getAge(seek(sleep)) - bufferMs + outputBufferDacTime;
|
||||||
|
cout << " after: " << sleep << "\n";
|
||||||
// std::clog << kLogNotice << "sleep: " << sleep << std::endl;
|
// std::clog << kLogNotice << "sleep: " << sleep << std::endl;
|
||||||
while (true)
|
// while (true)
|
||||||
|
// {
|
||||||
|
// if (!chunk)
|
||||||
|
// chunk = chunks.pop();
|
||||||
|
/* while (chunk->getAge() - bufferMs + outputBufferDacTime > chunk->getDuration())
|
||||||
{
|
{
|
||||||
sleep = Chunk::getAge(getNextPlayerChunk(outputBuffer, framesPerBuffer)) - bufferMs + outputBufferDacTime;
|
cout << "chunk->getAge() > chunk->getDuration(): " << chunk->getAge() - bufferMs + outputBufferDacTime << " > " << chunk->getDuration() << ", chunks: " << chunks.size() << ", out: " << outputBufferDacTime << ", needed: " << msBuffer << "\n";
|
||||||
usleep(100);
|
usleep(10);
|
||||||
// std::clog << kLogNotice << "age: " << age << std::endl;
|
chunk = chunks.pop();
|
||||||
if (sleep < 0)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
// while
|
||||||
|
// sleep = Chunk::getAge(getNextPlayerChunk(outputBuffer, framesPerBuffer)) - bufferMs + outputBufferDacTime;
|
||||||
|
// usleep(100);
|
||||||
|
// cout << "age: " << sleep << "\t out: " << outputBufferDacTime << "\t frames: " << framesPerBuffer << ", chunks: " << chunks.size() << "\n";
|
||||||
|
// if (sleep < 0)
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
// sleep = 0;
|
// sleep = 0;
|
||||||
return;
|
// return;
|
||||||
}
|
}
|
||||||
else if (sleep < 0)
|
else if (sleep < 0)
|
||||||
{
|
{
|
||||||
|
@ -179,7 +208,7 @@ void Stream::getPlayerChunk(void* outputBuffer, double outputBufferDacTime, unsi
|
||||||
// if (pCardBuffer->full())
|
// if (pCardBuffer->full())
|
||||||
// age += 4*cardBuffer;
|
// age += 4*cardBuffer;
|
||||||
|
|
||||||
// cout << age << "\t" << framesPerBuffer << "\t" << msBuffer << "\t" << ticks << "\t" << cardBuffer << "\t" << outputBufferDacTime*1000 << "\n";
|
// cout << age << "\t" << outputBufferDacTime << "\t";// << framesPerBuffer << "\t" << msBuffer << "\t" << ticks << "\t" << cardBuffer << "\t" << outputBufferDacTime << "\n";
|
||||||
|
|
||||||
|
|
||||||
if (sleep == 0)
|
if (sleep == 0)
|
||||||
|
@ -199,6 +228,11 @@ void Stream::getPlayerChunk(void* outputBuffer, double outputBufferDacTime, unsi
|
||||||
cout << "pMiniBuffer->full() && (abs(pMiniBuffer->mean()) > 50): " << pMiniBuffer->median() << "\n";
|
cout << "pMiniBuffer->full() && (abs(pMiniBuffer->mean()) > 50): " << pMiniBuffer->median() << "\n";
|
||||||
sleep = pMiniBuffer->mean();
|
sleep = pMiniBuffer->mean();
|
||||||
}
|
}
|
||||||
|
else if (abs(age) > 50)
|
||||||
|
{
|
||||||
|
cout << "age > 50): " << age << "\n";
|
||||||
|
sleep = age;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sleep != 0)
|
if (sleep != 0)
|
||||||
|
|
|
@ -27,6 +27,7 @@ public:
|
||||||
private:
|
private:
|
||||||
time_point_ms getNextPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer, int correction = 0);
|
time_point_ms getNextPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer, int correction = 0);
|
||||||
time_point_ms getSilentPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer);
|
time_point_ms getSilentPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer);
|
||||||
|
time_point_ms seek(unsigned long ms);
|
||||||
void updateBuffers(int age);
|
void updateBuffers(int age);
|
||||||
void resetBuffers();
|
void resetBuffers();
|
||||||
|
|
||||||
|
|
|
@ -27,18 +27,33 @@ Chunk::~Chunk()
|
||||||
|
|
||||||
bool Chunk::isEndOfChunk() const
|
bool Chunk::isEndOfChunk() const
|
||||||
{
|
{
|
||||||
return idx >= (wireChunk->length / format.frameSize);
|
return idx >= getFrameCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double Chunk::getFrameCount() const
|
||||||
|
{
|
||||||
|
return (wireChunk->length / format.frameSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
double Chunk::getDuration() const
|
double Chunk::getDuration() const
|
||||||
{
|
{
|
||||||
// std::cout << wireChunk->length << "\t" << format.frameSize << "\t" << (wireChunk->length / format.frameSize) << "\t" << ((double)format.rate / 1000.) << "\n";
|
return getFrameCount() / format.msRate();
|
||||||
return (wireChunk->length / format.frameSize) / ((double)format.rate / 1000.);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Chunk::seek(int frames)
|
||||||
|
{
|
||||||
|
idx += frames;
|
||||||
|
if (idx > getFrameCount())
|
||||||
|
idx = getFrameCount();
|
||||||
|
if (idx < 0)
|
||||||
|
idx = 0;
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int Chunk::read(void* outputBuffer, size_t frameCount)
|
int Chunk::read(void* outputBuffer, size_t frameCount)
|
||||||
{
|
{
|
||||||
|
|
|
@ -67,7 +67,9 @@ public:
|
||||||
return std::chrono::duration_cast<T>(std::chrono::high_resolution_clock::now() - time_point);
|
return std::chrono::duration_cast<T>(std::chrono::high_resolution_clock::now() - time_point);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int seek(int frames);
|
||||||
double getDuration() const;
|
double getDuration() const;
|
||||||
|
double getFrameCount() const;
|
||||||
|
|
||||||
WireChunk* wireChunk;
|
WireChunk* wireChunk;
|
||||||
SampleFormat format;
|
SampleFormat format;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue