diff --git a/client/stream.cpp b/client/stream.cpp index 96db9351..40babc74 100644 --- a/client/stream.cpp +++ b/client/stream.cpp @@ -1,7 +1,6 @@ #include "stream.h" #include #include -#include #include "common/log.h" #include "timeProvider.h" @@ -14,7 +13,7 @@ Stream::Stream(const SampleFormat& sampleFormat) : format(format_), format_(samp buffer.setSize(500); shortBuffer.setSize(100); miniBuffer.setSize(20); - cardBuffer.setSize(50); +// cardBuffer.setSize(50); bufferMs = msec(500); } @@ -178,10 +177,10 @@ bool Stream::getPlayerChunk(void* outputBuffer, const chronos::usec& outputBuffe chronos::usec correction = chronos::usec(0); if (sleep.count() != 0) { -// cout << "Sleep " << sleep.count() << "\n"; resetBuffers(); if (sleep < -bufferDuration/2) { + // We're early: not enough chunks. play silence. Reference chunk is the oldest (front) one sleep = chrono::duration_cast(TimeProvider::serverNow() - getSilentPlayerChunk(outputBuffer, framesPerBuffer) - bufferMs + outputBufferDacTime); //cout << "-sleep: " << sleep.count() << " " << -bufferDuration.count() / 2000 << "\n"; if (sleep < -bufferDuration/2) @@ -189,17 +188,18 @@ bool Stream::getPlayerChunk(void* outputBuffer, const chronos::usec& outputBuffe } else if (sleep > bufferDuration/2) { + // We're late: discard oldest chunks while (sleep > chunk->duration()) { - cout << "sleep > chunk->getDuration(): " << sleep.count() << " > " << chunk->duration().count() << ", chunks: " << chunks.size() << ", out: " << outputBufferDacTime.count() << ", needed: " << bufferDuration.count() << "\n"; +// cout << "sleep > chunk->getDuration(): " << sleep.count() << " > " << chunk->duration().count() << ", chunks: " << chunks.size() << ", out: " << outputBufferDacTime.count() << ", needed: " << bufferDuration.count() << "\n"; if (!chunks.try_pop(chunk, outputBufferDacTime)) return false; sleep = std::chrono::duration_cast(TimeProvider::serverNow() - chunk->start() - bufferMs + outputBufferDacTime); - usleep(1000); } } - + + // out of sync, can be corrected by playing faster/slower if (sleep < -chronos::usec(100)) { sleep += chronos::usec(100); @@ -245,14 +245,14 @@ bool Stream::getPlayerChunk(void* outputBuffer, const chronos::usec& outputBuffe updateBuffers(age.count()); - // std::cerr << "Chunk: " << age << "\t" << outputBufferDacTime*1000 << "\n"; + // print sync stats time_t now = time(NULL); if (now != lastUpdate) { lastUpdate = now; median = buffer.median(); shortMedian = shortBuffer.median(); - std::cerr << "Chunk: " << age.count()/100 << "\t" << miniBuffer.median()/100 << "\t" << shortMedian/100 << "\t" << median/100 << "\t" << buffer.size() << "\t" << /*cardBuffer << "\t" <<*/ outputBufferDacTime.count() << "\n"; + std::cerr << "Chunk: " << age.count()/100 << "\t" << miniBuffer.median()/100 << "\t" << shortMedian/100 << "\t" << median/100 << "\t" << buffer.size() << "\t" << outputBufferDacTime.count() << "\n"; } return true; } diff --git a/client/stream.h b/client/stream.h index 889e5dcd..9db66abc 100644 --- a/client/stream.h +++ b/client/stream.h @@ -1,18 +1,18 @@ #ifndef STREAM_H #define STREAM_H +//#include +//#include +//#include +//#include +//#include "common/timeUtils.h" #include -#include -#include -#include #include -#include #include "doubleBuffer.h" #include "message/message.h" #include "message/pcmChunk.h" #include "message/sampleFormat.h" -#include "common/timeUtils.h" #include "common/queue.h" @@ -40,10 +40,10 @@ private: chronos::usec sleep; Queue> chunks; - DoubleBuffer cardBuffer; - DoubleBuffer miniBuffer; - DoubleBuffer buffer; - DoubleBuffer shortBuffer; +// DoubleBuffer cardBuffer; + DoubleBuffer miniBuffer; + DoubleBuffer buffer; + DoubleBuffer shortBuffer; std::shared_ptr chunk; int median; diff --git a/common/timeDefs.h b/common/timeDefs.h index 691da288..f5069597 100644 --- a/common/timeDefs.h +++ b/common/timeDefs.h @@ -2,22 +2,45 @@ #define TIME_DEFS_H #include +#include namespace chronos { - template - std::chrono::duration abs(std::chrono::duration d) - { - Rep x = d.count(); - return std::chrono::duration(x >= 0 ? x : -x); - } - typedef std::chrono::high_resolution_clock hrc; typedef std::chrono::time_point time_point_hrc; typedef std::chrono::seconds sec; typedef std::chrono::milliseconds msec; typedef std::chrono::microseconds usec; typedef std::chrono::nanoseconds nsec; + + static void addUs(timeval& tv, int us) + { + if (us < 0) + { + timeval t; + t.tv_sec = -us / 1000000; + t.tv_usec = (-us % 1000000); + timersub(&tv, &t, &tv); + return; + } + tv.tv_usec += us; + tv.tv_sec += (tv.tv_usec / 1000000); + tv.tv_usec %= 1000000; + } + + static long getTickCount() + { + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + return now.tv_sec*1000 + now.tv_nsec / 1000000; + } + + template + std::chrono::duration abs(std::chrono::duration d) + { + Rep x = d.count(); + return std::chrono::duration(x >= 0 ? x : -x); + } } diff --git a/common/timeUtils.h b/common/timeUtils.h index a86967f1..ef529486 100644 --- a/common/timeUtils.h +++ b/common/timeUtils.h @@ -45,7 +45,7 @@ inline static long getAge(const time_point_ms& time_point) } */ - +/* static void addMs(timeval& tv, int ms) { if (ms < 0) @@ -75,7 +75,7 @@ static void addUs(timeval& tv, int us) tv.tv_sec += (tv.tv_usec / 1000000); tv.tv_usec %= 1000000; } - +*/ /*static long diffMs(const timeval& t1, const timeval& t2) { @@ -84,21 +84,6 @@ static void addUs(timeval& tv, int us) }*/ -static long getTickCount() -{ - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - return now.tv_sec*1000 + now.tv_nsec / 1000000; -} - - -static long getuTickCount() -{ - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - return now.tv_sec*1000000 + now.tv_nsec / 1000; -} - diff --git a/server/snapServer.cpp b/server/snapServer.cpp index 8736bb1a..8731c0f4 100644 --- a/server/snapServer.cpp +++ b/server/snapServer.cpp @@ -65,7 +65,7 @@ int main(int argc, char* argv[]) timeval tvChunk; gettimeofday(&tvChunk, NULL); - long nextTick = getTickCount(); + long nextTick = chronos::getTickCount(); mkfifo(fifoName.c_str(), 0777); SampleFormat format(sampleFormat); @@ -122,9 +122,9 @@ int main(int argc, char* argv[]) controlServer->send(chunk); //cout << chunk->tv_sec << ", " << chunk->tv_usec / 1000 << "\n"; // addUs(tvChunk, 1000*chunk->getDuration()); - addUs(tvChunk, chunkDuration * 1000); + chronos::addUs(tvChunk, chunkDuration * 1000); nextTick += duration; - long currentTick = getTickCount(); + long currentTick = chronos::getTickCount(); if (nextTick > currentTick) { usleep((nextTick - currentTick) * 1000); @@ -132,7 +132,7 @@ int main(int argc, char* argv[]) else { gettimeofday(&tvChunk, NULL); - nextTick = getTickCount(); + nextTick = chronos::getTickCount(); } } }