Skip to content

Commit

Permalink
Merge branch 'master' of github.com:MythTV/mythtv
Browse files Browse the repository at this point in the history
  • Loading branch information
Beirdo committed Jun 3, 2011
2 parents 50f9145 + 031b9a4 commit e28dc10
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 5 deletions.
135 changes: 130 additions & 5 deletions mythtv/libs/libmythtv/ringbuffer.cpp
Expand Up @@ -185,7 +185,8 @@ RingBuffer::RingBuffer(void) :
readblocksize(CHUNK), wanttoread(0),
numfailures(0), commserror(false),
oldfile(false), livetvchain(NULL),
ignoreliveeof(false), readAdjust(0)
ignoreliveeof(false), readAdjust(0),
bitrateMonitorEnabled(false)
{
{
QMutexLocker locker(&subExtLock);
Expand Down Expand Up @@ -752,14 +753,14 @@ void RingBuffer::run(void)
read_return = safe_read(readAheadBuffer + rbwpos, totfree);

int sr_elapsed = sr_timer.elapsed();
uint64_t bps = !sr_elapsed ? 1000000001 :
(uint64_t)(((double)read_return * 8000.0) / (double)sr_elapsed);
VERBOSE(VB_FILE, LOC +
QString("safe_read(...@%1, %2) -> %3, took %4 ms %5")
.arg(rbwpos).arg(totfree).arg(read_return)
.arg(sr_elapsed)
.arg(!sr_elapsed ? "" :
QString("(%1Mbps)").arg(((float)read_return *
(8000.0 / (float)sr_elapsed)) / 1048576)));

.arg(QString("(%1Mbps)").arg((double)bps / 1000000.0)));
UpdateStorageRate(bps);
rbwlock.unlock();
}

Expand Down Expand Up @@ -977,7 +978,13 @@ int RingBuffer::ReadDirect(void *buf, int count, bool peek)
poslock.unlock();
}

MythTimer timer;
timer.start();
int ret = safe_read(buf, count);
int elapsed = timer.elapsed();
uint64_t bps = !elapsed ? 1000000001 :
(uint64_t)(((float)ret * 8000.0) / (float)elapsed);
UpdateStorageRate(bps);

poslock.lockForWrite();
if (ignorereadpos >= 0 && ret > 0)
Expand Down Expand Up @@ -1168,9 +1175,127 @@ int RingBuffer::Read(void *buf, int count)
readpos += ret;
poslock.unlock();
}

UpdateDecoderRate(ret);
return ret;
}

QString RingBuffer::BitrateToString(uint64_t rate)
{
QString msg;
float bitrate;
int range = 0;
if (rate < 1)
{
return "-";
}
else if (rate > 1000000000)
{
return QObject::tr(">1Gbps");
}
else if (rate >= 1000000)
{
msg = QObject::tr("%1Mbps");
bitrate = (float)rate / (1000000.0);
range = 1;
}
else if (rate >= 1000)
{
msg = QObject::tr("%1Kbps");
bitrate = (float)rate / 1000.0;
}
else
{
msg = QObject::tr("%1bps");
bitrate = (float)rate;
}
return msg.arg(bitrate, 0, 'f', range);
}

QString RingBuffer::GetDecoderRate(void)
{
return BitrateToString(UpdateDecoderRate());
}

QString RingBuffer::GetStorageRate(void)
{
return BitrateToString(UpdateStorageRate());
}

QString RingBuffer::GetAvailableBuffer(void)
{
int avail = (rbwpos >= rbrpos) ? rbwpos - rbrpos : kBufferSize - rbrpos + rbwpos;
return QString("%1%").arg((int)(((float)avail / (float)kBufferSize) * 100.0));
}

uint64_t RingBuffer::UpdateDecoderRate(uint64_t latest)
{
if (!bitrateMonitorEnabled)
return 0;

static QDateTime epoch = QDateTime(QDate(1971, 1, 1));
QDateTime now = QDateTime::currentDateTime();
qint64 age = epoch.msecsTo(now);
qint64 oldest = age - 1000;

decoderReadLock.lock();
uint64_t total = 0;
QMutableMapIterator<qint64,uint64_t> it(decoderReads);
while (it.hasNext())
{
it.next();
if (it.key() < oldest)
it.remove();
else
total += it.value();
}

if (latest)
decoderReads.insert(age, latest);

uint64_t average = (uint64_t)((double)total * 8.0);
decoderReadLock.unlock();

VERBOSE(VB_FILE, LOC + QString("Decoder read speed: %1 %2")
.arg(average).arg(decoderReads.size()));
return average;
}

uint64_t RingBuffer::UpdateStorageRate(uint64_t latest)
{
if (!bitrateMonitorEnabled)
return 0;

static QDateTime epoch = QDateTime(QDate(1971, 1, 1));
QDateTime now = QDateTime::currentDateTime();
qint64 age = epoch.msecsTo(now);
qint64 oldest = age - 1000;

storageReadLock.lock();
uint64_t total = 0;
QMutableMapIterator<qint64,uint64_t> it(storageReads);
while (it.hasNext())
{
it.next();
if (it.key() < oldest)
it.remove();
else
total += it.value();
}

if (latest)
storageReads.insert(age, latest);

int size = storageReads.size();
storageReadLock.unlock();

uint64_t average = size ? (uint64_t)(((double)total) / (double)size) : 0;

VERBOSE(VB_FILE, LOC + QString("Average storage read speed: %1 %2")
.arg(average).arg(storageReads.size()));
return average;
}

/** \fn RingBuffer::Write(const void*, uint)
* \brief Writes buffer to ThreadedFileWriter::Write(const void*,uint)
* \return Bytes written, or -1 on error.
Expand Down
16 changes: 16 additions & 0 deletions mythtv/libs/libmythtv/ringbuffer.h
Expand Up @@ -8,6 +8,7 @@
#include <QString>
#include <QThread>
#include <QMutex>
#include <QMap>

#include "mythconfig.h"

Expand Down Expand Up @@ -45,6 +46,7 @@ class MTV_PUBLIC RingBuffer : protected QThread
void SetOldFile(bool is_old);
void UpdateRawBitrate(uint rawbitrate);
void UpdatePlaySpeed(float playspeed);
void EnableBitrateMonitor(bool enable) { bitrateMonitorEnabled = enable; }

// Gets
QString GetFilename(void) const;
Expand All @@ -55,6 +57,9 @@ class MTV_PUBLIC RingBuffer : protected QThread
bool isPaused(void) const;
/// \brief Returns how far into the file we have read.
virtual long long GetReadPosition(void) const = 0;
QString GetDecoderRate(void);
QString GetStorageRate(void);
QString GetAvailableBuffer(void);
long long GetWritePosition(void) const;
/// \brief Returns the size of the file we are reading/writing,
/// or -1 if the query fails.
Expand Down Expand Up @@ -149,6 +154,10 @@ class MTV_PUBLIC RingBuffer : protected QThread
void ResetReadAhead(long long newinternal);
void KillReadAheadThread(void);

static QString BitrateToString(uint64_t rate);
uint64_t UpdateDecoderRate(uint64_t latest = 0);
uint64_t UpdateStorageRate(uint64_t latest = 0);

protected:
mutable QReadWriteLock poslock;
long long readpos; // protected by poslock
Expand Down Expand Up @@ -202,6 +211,13 @@ class MTV_PUBLIC RingBuffer : protected QThread

long long readAdjust; // protected by rwlock

// bitrate monitors
bool bitrateMonitorEnabled;
QMutex decoderReadLock;
QMap<qint64, uint64_t> decoderReads;
QMutex storageReadLock;
QMap<qint64, uint64_t> storageReads;

// note 1: numfailures is modified with only a read lock in the
// read ahead thread, but this is safe since all other places
// that use it are protected by a write lock. But this is a
Expand Down

0 comments on commit e28dc10

Please sign in to comment.