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.;
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);
}
}

View file

@ -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)
{

View file

@ -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<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::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();
msec age = std::chrono::duration_cast<msec>(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<msec>(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;
}

View file

@ -7,6 +7,7 @@
#include <condition_variable>
#include <vector>
#include <memory>
#include <chrono>
#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;
};

View file

@ -2,7 +2,11 @@
#define TIME_PROVIDER_H
#include <atomic>
#include <chrono>
#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<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:
TimeProvider();
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
#define PCM_CHUNK_H
#include <chrono>
#include "message.h"
#include "wireChunk.h"
#include "sampleFormat.h"
typedef std::chrono::time_point<std::chrono::high_resolution_clock, std::chrono::milliseconds> 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<T>(std::chrono::high_resolution_clock::now() - time_point);
}
*/
int seek(int frames);
double getDuration() const;
double getDurationUs() const;

View file

@ -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)