diff --git a/client/controller.cpp b/client/controller.cpp index b8d46f3f..646a8e8e 100644 --- a/client/controller.cpp +++ b/client/controller.cpp @@ -101,6 +101,10 @@ void Controller::worker() { double latency = (reply->received.sec - reply->sent.sec) + (reply->received.usec - reply->sent.usec) / 1000000.; TimeProvider::getInstance().setDiffToServer((reply->latency - latency) * 1000 / 2); +cout << TimeProvider::sinceEpoche(chronos::hrc::now()).count() << "\n"; +cout << TimeProvider::sinceEpoche(TimeProvider::now()).count() << "\n"; +cout << TimeProvider::sinceEpoche(TimeProvider::serverNow()).count() << "\n"; +cout << "Received: " << TimeProvider::sinceEpoche(TimeProvider::toTimePoint(reply->received)).count() << "\n\n"; usleep(1000); } } diff --git a/client/player.cpp b/client/player.cpp index 650cb07d..cebc9a97 100644 --- a/client/player.cpp +++ b/client/player.cpp @@ -129,7 +129,7 @@ void Player::worker() { snd_pcm_avail_delay(pcm_handle, &avail, &delay); - if (stream_->getPlayerChunk(buff, (float)delay / stream_->format.msRate(), frames, 500)) + if (stream_->getPlayerChunk(buff, chronos::usec((chronos::usec::rep)(1000 * (double)delay / stream_->format.msRate())), frames, 500)) { if ((pcm = snd_pcm_writei(pcm_handle, buff, frames)) == -EPIPE) { diff --git a/client/stream.cpp b/client/stream.cpp index d3d92f86..bdd4e52e 100644 --- a/client/stream.cpp +++ b/client/stream.cpp @@ -6,6 +6,8 @@ #include "timeProvider.h" using namespace std; +using namespace chronos; + Stream::Stream(const SampleFormat& sampleFormat) : format(format_), format_(sampleFormat), sleep(0), median(0), shortMedian(0), lastUpdate(0) { @@ -13,14 +15,14 @@ Stream::Stream(const SampleFormat& sampleFormat) : format(format_), format_(samp shortBuffer.setSize(100); miniBuffer.setSize(20); cardBuffer.setSize(50); - bufferMs = 500; + bufferMs = msec(500); } void Stream::setBufferLen(size_t bufferLenMs) { - bufferMs = bufferLenMs; + bufferMs = msec(bufferLenMs); } @@ -42,11 +44,11 @@ void Stream::addChunk(PcmChunk* chunk) -time_point_ms Stream::getSilentPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer) +time_point_hrc Stream::getSilentPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer) { if (!chunk) chunk = chunks.pop(); - time_point_ms tp = chunk->timePoint(); + time_point_hrc tp = chunk->timePoint(); memset(outputBuffer, 0, framesPerBuffer * format.frameSize); return tp; } @@ -70,7 +72,7 @@ time_point_ms Stream::seekTo(const time_point_ms& to) */ -time_point_ms Stream::seek(long ms) +time_point_hrc Stream::seek(long ms) { if (!chunk) chunk = chunks.pop(); @@ -89,13 +91,13 @@ time_point_ms Stream::seek(long ms) } -time_point_ms Stream::getNextPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer, size_t timeout, int correction) +time_point_hrc Stream::getNextPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer, size_t timeout, int correction) { if (!chunk) - if (!chunks.try_pop(chunk, std::chrono::milliseconds(timeout))) + if (!chunks.try_pop(chunk, chronos::msec(timeout))) throw 0; - time_point_ms tp = chunk->timePoint(); + time_point_hrc tp = chunk->timePoint(); int read = 0; int toRead = framesPerBuffer + correction*format.msRate(); char* buffer; @@ -153,7 +155,7 @@ void Stream::resetBuffers() } -bool Stream::getPlayerChunk(void* outputBuffer, double outputBufferDacTime, unsigned long framesPerBuffer, size_t timeout) +bool Stream::getPlayerChunk(void* outputBuffer, chronos::usec outputBufferDacTime, unsigned long framesPerBuffer, size_t timeout) { try { @@ -174,7 +176,9 @@ bool Stream::getPlayerChunk(void* outputBuffer, double outputBufferDacTime, unsi if (sleep < -msBuffer/2) { cout << "Sleep " << sleep; - sleep = PcmChunk::getAge(getSilentPlayerChunk(outputBuffer, framesPerBuffer)) - bufferMs + outputBufferDacTime + TimeProvider::getInstance().getDiffToServerMs(); + msec age = chrono::duration_cast(TimeProvider::serverNow() - getSilentPlayerChunk(outputBuffer, framesPerBuffer) - bufferMs + outputBufferDacTime); + sleep = age.count(); +// sleep = PcmChunk::getAge(getSilentPlayerChunk(outputBuffer, framesPerBuffer)) - bufferMs + outputBufferDacTime + TimeProvider::getInstance().getDiffToServerMs(); std::cerr << " after: " << sleep << ", chunks: " << chunks.size() << "\n"; // std::clog << kLogNotice << "sleep: " << sleep << std::endl; // if (sleep > -msBuffer/2) @@ -192,17 +196,18 @@ bool Stream::getPlayerChunk(void* outputBuffer, double outputBufferDacTime, unsi cout << " after: " << sleep << "\n"; */ if (!chunk) - if (!chunks.try_pop(chunk, std::chrono::milliseconds(timeout))) + if (!chunks.try_pop(chunk, chronos::msec(timeout))) throw 0; while (sleep > chunk->getDuration()) { - if (!chunks.try_pop(chunk, std::chrono::milliseconds(timeout))) + if (!chunks.try_pop(chunk, chronos::msec(timeout))) throw 0; - sleep = chunk->getAge() - bufferMs + outputBufferDacTime + TimeProvider::getInstance().getDiffToServerMs(); - // cout << "chunk->getAge() > chunk->getDuration(): " << chunk->getAge() - bufferMs + outputBufferDacTime << " > " << chunk->getDuration() << ", chunks: " << chunks.size() << ", out: " << outputBufferDacTime << ", needed: " << msBuffer << ", sleep: " << sleep << "\n"; + msec age = std::chrono::duration_cast(TimeProvider::serverNow() - chunk->timePoint() - bufferMs + outputBufferDacTime); + sleep = age.count(); +// cout << "chunk->getAge() > chunk->getDuration(): " << chunk->getAge() - bufferMs + outputBufferDacTime << " > " << chunk->getDuration() << ", chunks: " << chunks.size() << ", out: " << outputBufferDacTime << ", needed: " << msBuffer << ", sleep: " << sleep << "\n"; usleep(1000); } - cout << "seek: " << PcmChunk::getAge(seek(sleep)) - bufferMs + outputBufferDacTime << "\n"; +// cout << "seek: " << PcmChunk::getAge(seek(sleep)) - bufferMs + outputBufferDacTime << "\n"; sleep = 0; } else if (sleep < 0) @@ -219,7 +224,7 @@ bool Stream::getPlayerChunk(void* outputBuffer, double outputBufferDacTime, unsi long age(0); - age = PcmChunk::getAge(getNextPlayerChunk(outputBuffer, framesPerBuffer, timeout, correction)) - bufferMs + outputBufferDacTime + TimeProvider::getInstance().getDiffToServerMs(); + age = std::chrono::duration_cast(TimeProvider::serverNow() - getNextPlayerChunk(outputBuffer, framesPerBuffer, timeout, correction) - bufferMs + outputBufferDacTime).count(); if (sleep == 0) @@ -262,7 +267,7 @@ bool Stream::getPlayerChunk(void* outputBuffer, double outputBufferDacTime, unsi lastUpdate = now; median = buffer.median(); shortMedian = shortBuffer.median(); - std::cerr << "Chunk: " << age << "\t" << miniBuffer.median() << "\t" << shortMedian << "\t" << median << "\t" << buffer.size() << "\t" << /*cardBuffer << "\t" <<*/ outputBufferDacTime << "\n"; + std::cerr << "Chunk: " << age << "\t" << miniBuffer.median() << "\t" << shortMedian << "\t" << median << "\t" << buffer.size() << "\t" << /*cardBuffer << "\t" <<*/ outputBufferDacTime.count() << "\n"; } return true; } diff --git a/client/stream.h b/client/stream.h index df5c9d91..13adb6de 100644 --- a/client/stream.h +++ b/client/stream.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "doubleBuffer.h" #include "message/message.h" #include "message/pcmChunk.h" @@ -21,14 +22,14 @@ public: Stream(const SampleFormat& format); void addChunk(PcmChunk* chunk); void clearChunks(); - bool getPlayerChunk(void* outputBuffer, double outputBufferDacTime, unsigned long framesPerBuffer, size_t timeout); + bool getPlayerChunk(void* outputBuffer, chronos::usec outputBufferDacTime, unsigned long framesPerBuffer, size_t timeout); void setBufferLen(size_t bufferLenMs); const SampleFormat& format; private: - time_point_ms getNextPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer, size_t timeout, int correction = 0); - time_point_ms getSilentPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer); - time_point_ms seek(long ms); + chronos::time_point_hrc getNextPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer, size_t timeout, int correction = 0); + chronos::time_point_hrc getSilentPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer); + chronos::time_point_hrc seek(long ms); // time_point_ms seekTo(const time_point_ms& to); void updateBuffers(int age); void resetBuffers(); @@ -48,7 +49,7 @@ private: int median; int shortMedian; time_t lastUpdate; - int bufferMs; + chronos::msec bufferMs; }; diff --git a/client/timeProvider.h b/client/timeProvider.h index f86d3d43..4fb27f62 100644 --- a/client/timeProvider.h +++ b/client/timeProvider.h @@ -2,7 +2,11 @@ #define TIME_PROVIDER_H #include +#include #include "doubleBuffer.h" +#include "message/message.h" +#include "common/timeDefs.h" + class TimeProvider { @@ -18,6 +22,28 @@ public: long getPercentileDiffToServer(size_t percentile); long getDiffToServerMs(); + + template + static T sinceEpoche(const chronos::time_point_hrc& point) + { + return std::chrono::duration_cast(point.time_since_epoch()); + } + + static chronos::time_point_hrc toTimePoint(const tv& timeval) + { + return chronos::time_point_hrc(chronos::usec(timeval.usec) + chronos::sec(timeval.sec)); + } + + inline static chronos::time_point_hrc now() + { + return chronos::hrc::now(); + } + + inline static chronos::time_point_hrc serverNow() + { + return chronos::hrc::now() + chronos::usec(TimeProvider::getInstance().getDiffToServer()); + } + private: TimeProvider(); TimeProvider(TimeProvider const&); // Don't Implement diff --git a/common/timeDefs.h b/common/timeDefs.h new file mode 100644 index 00000000..eacf0139 --- /dev/null +++ b/common/timeDefs.h @@ -0,0 +1,18 @@ +#ifndef TIME_DEFS_H +#define TIME_DEFS_H + +#include + +namespace chronos +{ + using hrc = std::chrono::high_resolution_clock; + using time_point_hrc = std::chrono::time_point; + using sec = std::chrono::seconds; + using msec = std::chrono::milliseconds; + using usec = std::chrono::microseconds; +} + + +#endif + + diff --git a/message/pcmChunk.h b/message/pcmChunk.h index 07c85064..04df7c87 100644 --- a/message/pcmChunk.h +++ b/message/pcmChunk.h @@ -1,12 +1,11 @@ #ifndef PCM_CHUNK_H #define PCM_CHUNK_H +#include #include "message.h" #include "wireChunk.h" #include "sampleFormat.h" - - -typedef std::chrono::time_point time_point_ms; +#include "common/timeDefs.h" @@ -20,6 +19,15 @@ public: int readFrames(void* outputBuffer, size_t frameCount); bool isEndOfChunk() const; + inline chronos::time_point_hrc timePoint() const + { + return chronos::time_point_hrc( + chronos::sec(timestamp.sec) + + chronos::usec(timestamp.usec) + + chronos::usec((chronos::usec::rep)(1000000. * ((double)idx / (double)format.rate))) + ); + } +/* inline time_point_ms timePoint() const { time_point_ms tp; @@ -52,7 +60,7 @@ public: { return std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - time_point); } - +*/ int seek(int frames); double getDuration() const; double getDurationUs() const; diff --git a/message/sampleFormat.h b/message/sampleFormat.h index c1977097..5370f0b5 100644 --- a/message/sampleFormat.h +++ b/message/sampleFormat.h @@ -22,9 +22,9 @@ public: uint16_t sampleSize; uint16_t frameSize; - float msRate() const + double msRate() const { - return (float)rate/1000.f; + return (double)rate/1000.f; } virtual void read(std::istream& stream)