mirror of
https://github.com/badaix/snapcast.git
synced 2025-07-19 17:37:45 +02:00
xxx
git-svn-id: svn://elaine/murooma/trunk@70 d8a302eb-03bc-478d-80e4-98257eca68ef
This commit is contained in:
parent
071405049e
commit
858e49a3ed
4 changed files with 117 additions and 61 deletions
4
chunk.h
4
chunk.h
|
@ -16,6 +16,10 @@
|
||||||
template <size_t T>
|
template <size_t T>
|
||||||
struct ChunkT
|
struct ChunkT
|
||||||
{
|
{
|
||||||
|
// ChunkT()
|
||||||
|
// {
|
||||||
|
// memset(&payload[0], 0, T);
|
||||||
|
// }
|
||||||
int32_t tv_sec;
|
int32_t tv_sec;
|
||||||
int32_t tv_usec;
|
int32_t tv_usec;
|
||||||
int32_t idx;
|
int32_t idx;
|
||||||
|
|
|
@ -50,14 +50,14 @@ static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
||||||
(void) statusFlags;
|
(void) statusFlags;
|
||||||
(void) inputBuffer;
|
(void) inputBuffer;
|
||||||
|
|
||||||
std::vector<short> s = stream->getChunk(timeInfo->outputBufferDacTime, framesPerBuffer);
|
PlayerChunk* playerChunk = stream->getChunk(timeInfo->outputBufferDacTime, framesPerBuffer);
|
||||||
|
|
||||||
for (size_t n=0; n<framesPerBuffer; n++)
|
for (size_t n=0; n<framesPerBuffer; n++)
|
||||||
{
|
{
|
||||||
*out++ = s[2*n];
|
*out++ = playerChunk->payload[2*n];
|
||||||
*out++ = s[2*n+1];
|
*out++ = playerChunk->payload[2*n+1];
|
||||||
}
|
}
|
||||||
// delete chunk;
|
delete playerChunk;
|
||||||
|
|
||||||
return paContinue;
|
return paContinue;
|
||||||
}
|
}
|
||||||
|
|
146
stream.h
146
stream.h
|
@ -15,8 +15,9 @@
|
||||||
class Stream
|
class Stream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Stream() : median(0), shortMedian(0), lastUpdate(0), skip(0), idx(0)
|
Stream() : lastPlayerChunk(NULL), median(0), shortMedian(0), lastUpdate(0), skip(0), idx(0)
|
||||||
{
|
{
|
||||||
|
silentPlayerChunk = new PlayerChunk();
|
||||||
pBuffer = new DoubleBuffer<int>(30000 / PLAYER_CHUNK_MS);
|
pBuffer = new DoubleBuffer<int>(30000 / PLAYER_CHUNK_MS);
|
||||||
pShortBuffer = new DoubleBuffer<int>(5000 / PLAYER_CHUNK_MS);
|
pShortBuffer = new DoubleBuffer<int>(5000 / PLAYER_CHUNK_MS);
|
||||||
pLock = new std::unique_lock<std::mutex>(mtx);
|
pLock = new std::unique_lock<std::mutex>(mtx);
|
||||||
|
@ -33,24 +34,73 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Chunk* getNextChunk()
|
||||||
|
|
||||||
|
|
||||||
std::vector<short> getChunk(double outputBufferDacTime, unsigned long framesPerBuffer)
|
|
||||||
{
|
{
|
||||||
Chunk* chunk = NULL;
|
Chunk* chunk = NULL;
|
||||||
if (chunks.empty())
|
if (chunks.empty())
|
||||||
cv.wait(*pLock);
|
cv.wait(*pLock);
|
||||||
|
|
||||||
int age(0);
|
|
||||||
int chunkCount(0);
|
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
chunk = chunks.front();
|
chunk = chunks.front();
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
age = getAge(*chunk) + outputBufferDacTime*1000 - bufferMs;
|
PlayerChunk* getNextPlayerChunk()
|
||||||
if (age < -500)
|
{
|
||||||
|
Chunk* chunk = getNextChunk();
|
||||||
|
// int age(0);
|
||||||
|
// age = getAge(*chunk) + outputBufferDacTime*1000 - bufferMs;
|
||||||
|
// std::cerr << "age: " << age << " \tidx: " << chunk->idx << "\n";
|
||||||
|
PlayerChunk* playerChunk = new PlayerChunk();
|
||||||
|
playerChunk->tv_sec = chunk->tv_sec;
|
||||||
|
playerChunk->tv_usec = chunk->tv_usec;
|
||||||
|
playerChunk->idx = 0;
|
||||||
|
|
||||||
|
size_t missing = PLAYER_CHUNK_SIZE;
|
||||||
|
if (chunk->idx + PLAYER_CHUNK_SIZE > WIRE_CHUNK_SIZE)
|
||||||
|
{
|
||||||
|
std::cerr << "chunk->idx + PLAYER_CHUNK_SIZE >= WIRE_CHUNK_SIZE: " << chunk->idx + PLAYER_CHUNK_SIZE << " >= " << WIRE_CHUNK_SIZE << "\n";
|
||||||
|
memcpy(&(playerChunk->payload[0]), &chunk->payload[chunk->idx], sizeof(int16_t)*(WIRE_CHUNK_SIZE - chunk->idx));
|
||||||
|
missing = chunk->idx + PLAYER_CHUNK_SIZE - WIRE_CHUNK_SIZE;
|
||||||
|
chunks.pop_front();
|
||||||
|
delete chunk;
|
||||||
|
|
||||||
|
chunk = getNextChunk();
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&(playerChunk->payload[0]), &chunk->payload[chunk->idx], sizeof(int16_t)*missing);
|
||||||
|
|
||||||
|
addMs(chunk, -PLAYER_CHUNK_MS);
|
||||||
|
chunk->idx += missing;
|
||||||
|
if (chunk->idx >= WIRE_CHUNK_SIZE)
|
||||||
|
{
|
||||||
|
chunks.pop_front();
|
||||||
|
delete chunk;
|
||||||
|
}
|
||||||
|
return playerChunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PlayerChunk* getChunk(double outputBufferDacTime, unsigned long framesPerBuffer)
|
||||||
|
{
|
||||||
|
PlayerChunk* playerChunk = getNextPlayerChunk();
|
||||||
|
int age = getAge(playerChunk) + outputBufferDacTime*1000 - bufferMs;
|
||||||
|
// std::cerr << "Chunk: " << age << "\t" << outputBufferDacTime*1000 << "\n";
|
||||||
|
if (age < -100)
|
||||||
|
{
|
||||||
|
std::cerr << "Playing silence, age: " << age << "\n";
|
||||||
|
sleepMs(-age);
|
||||||
|
// *playerChunk = new PlayerChunk();
|
||||||
|
// return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// int age = getAge(*lastPlayerChunk) + outputBufferDacTime*1000 - bufferMs;
|
||||||
|
return playerChunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if (age < -500)
|
||||||
{
|
{
|
||||||
std::vector<short> v;
|
std::vector<short> v;
|
||||||
if (skip < 0)
|
if (skip < 0)
|
||||||
|
@ -68,51 +118,50 @@ public:
|
||||||
|
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
|
|
||||||
if (skip == 0)
|
if (skip == 0)
|
||||||
|
{
|
||||||
|
if (now != lastUpdate)
|
||||||
{
|
{
|
||||||
if (now != lastUpdate)
|
lastUpdate = now;
|
||||||
{
|
median = pBuffer->median();
|
||||||
lastUpdate = now;
|
shortMedian = pShortBuffer->median();
|
||||||
median = pBuffer->median();
|
if (abs(age) > 500)
|
||||||
shortMedian = pShortBuffer->median();
|
skip = age / PLAYER_CHUNK_SIZE;
|
||||||
if (abs(age) > 500)
|
if (pShortBuffer->full() && (abs(shortMedian) > WIRE_CHUNK_MS))
|
||||||
skip = age / PLAYER_CHUNK_SIZE;
|
skip = shortMedian / PLAYER_CHUNK_SIZE;
|
||||||
if (pShortBuffer->full() && (abs(shortMedian) > WIRE_CHUNK_MS))
|
if (pBuffer->full() && (abs(median) > WIRE_CHUNK_MS))
|
||||||
skip = shortMedian / PLAYER_CHUNK_SIZE;
|
skip = median / PLAYER_CHUNK_SIZE;
|
||||||
if (pBuffer->full() && (abs(median) > WIRE_CHUNK_MS))
|
|
||||||
skip = median / PLAYER_CHUNK_SIZE;
|
|
||||||
}
|
|
||||||
std::cerr << "Chunk: " << age << /*" \tidx: " << chunk->idx <<*/ "\t" << shortMedian << "\t" << median << "\t" << pBuffer->size() << "\t" << chunkCount << "\t" << outputBufferDacTime*1000 << "\n";
|
|
||||||
}
|
}
|
||||||
|
std::cerr << "Chunk: " << age << "\t" << shortMedian << "\t" << median << "\t" << pBuffer->size() << "\t" << chunkCount << "\t" << outputBufferDacTime*1000 << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<short> v;
|
std::vector<short> v;
|
||||||
if (skip < 0)
|
if (skip < 0)
|
||||||
{
|
{
|
||||||
++skip;
|
++skip;
|
||||||
std::cerr << "chunk too new, sleeping\n";//age > WIRE_CHUNK_MS (" << age << " ms)\n";
|
std::cerr << "chunk too new, sleeping\n";//age > WIRE_CHUNK_MS (" << age << " ms)\n";
|
||||||
for (size_t n=0; n<(size_t)PLAYER_CHUNK_SIZE; ++n)
|
for (size_t n=0; n<(size_t)PLAYER_CHUNK_SIZE; ++n)
|
||||||
v.push_back(chunk->payload[n]);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t n=chunk->idx; n<chunk->idx + (size_t)PLAYER_CHUNK_SIZE; ++n)
|
|
||||||
{
|
|
||||||
v.push_back(chunk->payload[n]);
|
v.push_back(chunk->payload[n]);
|
||||||
}
|
|
||||||
//std::cerr << "before: " << chunkTime(*chunk) << ", after: ";
|
|
||||||
addMs(*chunk, -PLAYER_CHUNK_MS);
|
|
||||||
//std::cerr << chunkTime(*chunk) << "\n";
|
|
||||||
chunk->idx += PLAYER_CHUNK_SIZE;
|
|
||||||
if (chunk->idx >= WIRE_CHUNK_SIZE)
|
|
||||||
{
|
|
||||||
//std::cerr << "Chunk played out, deleting\n";
|
|
||||||
chunks.pop_front();
|
|
||||||
delete chunk;
|
|
||||||
}
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
for (size_t n=chunk->idx; n<chunk->idx + (size_t)PLAYER_CHUNK_SIZE; ++n)
|
||||||
|
{
|
||||||
|
v.push_back(chunk->payload[n]);
|
||||||
|
}
|
||||||
|
//std::cerr << "before: " << chunkTime(*chunk) << ", after: ";
|
||||||
|
addMs(*chunk, -PLAYER_CHUNK_MS);
|
||||||
|
//std::cerr << chunkTime(*chunk) << "\n";
|
||||||
|
chunk->idx += PLAYER_CHUNK_SIZE;
|
||||||
|
if (chunk->idx >= WIRE_CHUNK_SIZE)
|
||||||
|
{
|
||||||
|
//std::cerr << "Chunk played out, deleting\n";
|
||||||
|
chunks.pop_front();
|
||||||
|
delete chunk;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -304,6 +353,9 @@ private:
|
||||||
DoubleBuffer<int>* pBuffer;
|
DoubleBuffer<int>* pBuffer;
|
||||||
DoubleBuffer<int>* pShortBuffer;
|
DoubleBuffer<int>* pShortBuffer;
|
||||||
|
|
||||||
|
PlayerChunk* lastPlayerChunk;
|
||||||
|
PlayerChunk* silentPlayerChunk;
|
||||||
|
|
||||||
int median;
|
int median;
|
||||||
int shortMedian;
|
int shortMedian;
|
||||||
time_t lastUpdate;
|
time_t lastUpdate;
|
||||||
|
|
16
timeUtils.h
16
timeUtils.h
|
@ -34,13 +34,13 @@ long diff_ms(const timeval& t1, const timeval& t2)
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
long getAge(const T& chunk)
|
long getAge(const T* chunk)
|
||||||
{
|
{
|
||||||
timeval now;
|
timeval now;
|
||||||
gettimeofday(&now, NULL);
|
gettimeofday(&now, NULL);
|
||||||
timeval ts;
|
timeval ts;
|
||||||
ts.tv_sec = chunk.tv_sec;
|
ts.tv_sec = chunk->tv_sec;
|
||||||
ts.tv_usec = chunk.tv_usec;
|
ts.tv_usec = chunk->tv_usec;
|
||||||
return diff_ms(now, ts);
|
return diff_ms(now, ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,14 +69,14 @@ inline void addMs(timeval& tv, int ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void addMs(T& chunk, int ms)
|
void addMs(T* chunk, int ms)
|
||||||
{
|
{
|
||||||
timeval tv;
|
timeval tv;
|
||||||
tv.tv_sec = chunk.tv_sec;
|
tv.tv_sec = chunk->tv_sec;
|
||||||
tv.tv_usec = chunk.tv_usec;
|
tv.tv_usec = chunk->tv_usec;
|
||||||
addMs(tv, ms);
|
addMs(tv, ms);
|
||||||
chunk.tv_sec = tv.tv_sec;
|
chunk->tv_sec = tv.tv_sec;
|
||||||
chunk.tv_usec = tv.tv_usec;
|
chunk->tv_usec = tv.tv_usec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue