git-svn-id: svn://elaine/murooma/trunk@290 d8a302eb-03bc-478d-80e4-98257eca68ef
This commit is contained in:
(no author) 2014-09-24 19:32:50 +00:00
parent 31ce469c35
commit 07fcca06ca
8 changed files with 91 additions and 29 deletions

View file

@ -101,6 +101,10 @@ void Controller::worker()
{ {
double latency = (reply->received.sec - reply->sent.sec) + (reply->received.usec - reply->sent.usec) / 1000000.; double latency = (reply->received.sec - reply->sent.sec) + (reply->received.usec - reply->sent.usec) / 1000000.;
TimeProvider::getInstance().setDiffToServer((reply->latency - latency) * 1000 / 2); TimeProvider::getInstance().setDiffToServer((reply->latency - latency) * 1000 / 2);
cout << TimeProvider::sinceEpoche<chronos::usec>(chronos::hrc::now()).count() << "\n";
cout << TimeProvider::sinceEpoche<chronos::msec>(TimeProvider::now()).count() << "\n";
cout << TimeProvider::sinceEpoche<chronos::msec>(TimeProvider::serverNow()).count() << "\n";
cout << "Received: " << TimeProvider::sinceEpoche<chronos::msec>(TimeProvider::toTimePoint(reply->received)).count() << "\n\n";
usleep(1000); usleep(1000);
} }
} }

View file

@ -129,7 +129,7 @@ void Player::worker()
{ {
snd_pcm_avail_delay(pcm_handle, &avail, &delay); 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) if ((pcm = snd_pcm_writei(pcm_handle, buff, frames)) == -EPIPE)
{ {

View file

@ -6,6 +6,8 @@
#include "timeProvider.h" #include "timeProvider.h"
using namespace std; using namespace std;
using namespace chronos;
Stream::Stream(const SampleFormat& sampleFormat) : format(format_), format_(sampleFormat), sleep(0), median(0), shortMedian(0), lastUpdate(0) 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); shortBuffer.setSize(100);
miniBuffer.setSize(20); miniBuffer.setSize(20);
cardBuffer.setSize(50); cardBuffer.setSize(50);
bufferMs = 500; bufferMs = msec(500);
} }
void Stream::setBufferLen(size_t bufferLenMs) 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) if (!chunk)
chunk = chunks.pop(); chunk = chunks.pop();
time_point_ms tp = chunk->timePoint(); time_point_hrc tp = chunk->timePoint();
memset(outputBuffer, 0, framesPerBuffer * format.frameSize); memset(outputBuffer, 0, framesPerBuffer * format.frameSize);
return tp; 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) if (!chunk)
chunk = chunks.pop(); 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 (!chunk)
if (!chunks.try_pop(chunk, std::chrono::milliseconds(timeout))) if (!chunks.try_pop(chunk, chronos::msec(timeout)))
throw 0; throw 0;
time_point_ms tp = chunk->timePoint(); time_point_hrc tp = chunk->timePoint();
int read = 0; int read = 0;
int toRead = framesPerBuffer + correction*format.msRate(); int toRead = framesPerBuffer + correction*format.msRate();
char* buffer; 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 try
{ {
@ -174,7 +176,9 @@ bool Stream::getPlayerChunk(void* outputBuffer, double outputBufferDacTime, unsi
if (sleep < -msBuffer/2) if (sleep < -msBuffer/2)
{ {
cout << "Sleep " << sleep; cout << "Sleep " << sleep;
sleep = PcmChunk::getAge(getSilentPlayerChunk(outputBuffer, framesPerBuffer)) - bufferMs + outputBufferDacTime + TimeProvider::getInstance().getDiffToServerMs(); msec age = chrono::duration_cast<msec>(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::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)
@ -192,17 +196,18 @@ bool Stream::getPlayerChunk(void* outputBuffer, double outputBufferDacTime, unsi
cout << " after: " << sleep << "\n"; cout << " after: " << sleep << "\n";
*/ */
if (!chunk) if (!chunk)
if (!chunks.try_pop(chunk, std::chrono::milliseconds(timeout))) if (!chunks.try_pop(chunk, chronos::msec(timeout)))
throw 0; throw 0;
while (sleep > chunk->getDuration()) while (sleep > chunk->getDuration())
{ {
if (!chunks.try_pop(chunk, std::chrono::milliseconds(timeout))) if (!chunks.try_pop(chunk, chronos::msec(timeout)))
throw 0; throw 0;
sleep = chunk->getAge() - bufferMs + outputBufferDacTime + TimeProvider::getInstance().getDiffToServerMs(); msec age = std::chrono::duration_cast<msec>(TimeProvider::serverNow() - chunk->timePoint() - bufferMs + outputBufferDacTime);
// cout << "chunk->getAge() > chunk->getDuration(): " << chunk->getAge() - bufferMs + outputBufferDacTime << " > " << chunk->getDuration() << ", chunks: " << chunks.size() << ", out: " << outputBufferDacTime << ", needed: " << msBuffer << ", sleep: " << sleep << "\n"; 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); usleep(1000);
} }
cout << "seek: " << PcmChunk::getAge(seek(sleep)) - bufferMs + outputBufferDacTime << "\n"; // cout << "seek: " << PcmChunk::getAge(seek(sleep)) - bufferMs + outputBufferDacTime << "\n";
sleep = 0; sleep = 0;
} }
else if (sleep < 0) else if (sleep < 0)
@ -219,7 +224,7 @@ bool Stream::getPlayerChunk(void* outputBuffer, double outputBufferDacTime, unsi
long age(0); long age(0);
age = PcmChunk::getAge(getNextPlayerChunk(outputBuffer, framesPerBuffer, timeout, correction)) - bufferMs + outputBufferDacTime + TimeProvider::getInstance().getDiffToServerMs(); age = std::chrono::duration_cast<msec>(TimeProvider::serverNow() - getNextPlayerChunk(outputBuffer, framesPerBuffer, timeout, correction) - bufferMs + outputBufferDacTime).count();
if (sleep == 0) if (sleep == 0)
@ -262,7 +267,7 @@ bool Stream::getPlayerChunk(void* outputBuffer, double outputBufferDacTime, unsi
lastUpdate = now; lastUpdate = now;
median = buffer.median(); median = buffer.median();
shortMedian = shortBuffer.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; return true;
} }

View file

@ -7,6 +7,7 @@
#include <condition_variable> #include <condition_variable>
#include <vector> #include <vector>
#include <memory> #include <memory>
#include <chrono>
#include "doubleBuffer.h" #include "doubleBuffer.h"
#include "message/message.h" #include "message/message.h"
#include "message/pcmChunk.h" #include "message/pcmChunk.h"
@ -21,14 +22,14 @@ public:
Stream(const SampleFormat& format); Stream(const SampleFormat& format);
void addChunk(PcmChunk* chunk); void addChunk(PcmChunk* chunk);
void clearChunks(); 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); void setBufferLen(size_t bufferLenMs);
const SampleFormat& format; const SampleFormat& format;
private: private:
time_point_ms getNextPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer, size_t timeout, int correction = 0); chronos::time_point_hrc getNextPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer, size_t timeout, int correction = 0);
time_point_ms getSilentPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer); chronos::time_point_hrc getSilentPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer);
time_point_ms seek(long ms); chronos::time_point_hrc seek(long ms);
// time_point_ms seekTo(const time_point_ms& to); // time_point_ms seekTo(const time_point_ms& to);
void updateBuffers(int age); void updateBuffers(int age);
void resetBuffers(); void resetBuffers();
@ -48,7 +49,7 @@ private:
int median; int median;
int shortMedian; int shortMedian;
time_t lastUpdate; time_t lastUpdate;
int bufferMs; chronos::msec bufferMs;
}; };

View file

@ -2,7 +2,11 @@
#define TIME_PROVIDER_H #define TIME_PROVIDER_H
#include <atomic> #include <atomic>
#include <chrono>
#include "doubleBuffer.h" #include "doubleBuffer.h"
#include "message/message.h"
#include "common/timeDefs.h"
class TimeProvider class TimeProvider
{ {
@ -18,6 +22,28 @@ public:
long getPercentileDiffToServer(size_t percentile); long getPercentileDiffToServer(size_t percentile);
long getDiffToServerMs(); long getDiffToServerMs();
template<typename T>
static T sinceEpoche(const chronos::time_point_hrc& point)
{
return std::chrono::duration_cast<T>(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: private:
TimeProvider(); TimeProvider();
TimeProvider(TimeProvider const&); // Don't Implement TimeProvider(TimeProvider const&); // Don't Implement

18
common/timeDefs.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef TIME_DEFS_H
#define TIME_DEFS_H
#include <chrono>
namespace chronos
{
using hrc = std::chrono::high_resolution_clock;
using time_point_hrc = std::chrono::time_point<hrc>;
using sec = std::chrono::seconds;
using msec = std::chrono::milliseconds;
using usec = std::chrono::microseconds;
}
#endif

View file

@ -1,12 +1,11 @@
#ifndef PCM_CHUNK_H #ifndef PCM_CHUNK_H
#define PCM_CHUNK_H #define PCM_CHUNK_H
#include <chrono>
#include "message.h" #include "message.h"
#include "wireChunk.h" #include "wireChunk.h"
#include "sampleFormat.h" #include "sampleFormat.h"
#include "common/timeDefs.h"
typedef std::chrono::time_point<std::chrono::high_resolution_clock, std::chrono::milliseconds> time_point_ms;
@ -20,6 +19,15 @@ public:
int readFrames(void* outputBuffer, size_t frameCount); int readFrames(void* outputBuffer, size_t frameCount);
bool isEndOfChunk() const; 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 inline time_point_ms timePoint() const
{ {
time_point_ms tp; time_point_ms tp;
@ -52,7 +60,7 @@ 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); int seek(int frames);
double getDuration() const; double getDuration() const;
double getDurationUs() const; double getDurationUs() const;

View file

@ -22,9 +22,9 @@ public:
uint16_t sampleSize; uint16_t sampleSize;
uint16_t frameSize; 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) virtual void read(std::istream& stream)