- enforce locking before getting.

- explicitly keep track of last now time to determine max delta.
- refactoring.


git-svn-id: https://gambatte.svn.sourceforge.net/svnroot/gambatte@306 9dfb2916-2d38-0410-aef4-c5fe6c9ffc24
This commit is contained in:
sinamas 2011-11-13 22:30:35 +00:00
parent 9118428047
commit ae91cda89f
5 changed files with 53 additions and 37 deletions

View File

@ -24,10 +24,8 @@
#include <QtGlobal> // for Q_WS_WIN define
MainWindow::FrameBuffer::Locked::Locked(FrameBuffer fb) : mw(0), pb() {
if (fb.mw->tryLockFrameBuf()) {
if (fb.mw->tryLockFrameBuf(pb))
mw = fb.mw;
pb = fb.mw->frameBuf();
}
}
MainWindow::FrameBuffer::Locked::~Locked() {

View File

@ -19,6 +19,7 @@
#include "mediawidget.h"
#include <QEvent>
#include <QKeyEvent>
#include <QMutexLocker>
#include <QCoreApplication>
#include <QtGlobal> // for Q_WS_WIN define
#include "adaptivesleep.h"
@ -130,11 +131,17 @@ public:
bool cancelBlit();
void paused();
void audioEngineFailure();
bool tryLockVideoBuffer() { return mw.vbmut.tryLock(); }
void unlockVideoBuffer() { mw.vbmut.unlock(); }
const PixelBuffer& videoBuffer() {
return mw.blitterContainer->blitter()->inBuffer();
bool tryLockVideoBuffer(PixelBuffer &pb) {
if (mw.vbmut.tryLock()) {
pb = mw.blitterContainer->blitter()->inBuffer();
return true;
}
return false;
}
void unlockVideoBuffer() { mw.vbmut.unlock(); }
void consumeBlitRequest();
};
@ -364,13 +371,13 @@ void MediaWidget::setBlitter(BlitterWidget *const blitter) {
void MediaWidget::setVideo(const unsigned w, const unsigned h, BlitterWidget *const blitter) {
if (QSize(w, h) != blitterContainer->sourceSize() || blitter != blitterContainer->blitter()) {
vbmut.lock();
setBlitter(blitter);
{
const QMutexLocker vblock(&vbmut);
setBlitter(blitter);
if (running)
blitterContainer->blitter()->setVideoFormat(w, h);
vbmut.unlock();
if (running)
blitterContainer->blitter()->setVideoFormat(w, h);
}
blitterContainer->setSourceSize(QSize(w, h));
}

View File

@ -120,9 +120,16 @@ public:
void keyPressEvent(QKeyEvent*);
void keyReleaseEvent(QKeyEvent*);
bool tryLockFrameBuf() { return vbmut.tryLock(); }
bool tryLockFrameBuf(PixelBuffer &pb) {
if (vbmut.tryLock()) {
pb = running ? blitterContainer->blitter()->inBuffer() : PixelBuffer();
return true;
}
return false;
}
void unlockFrameBuf() { vbmut.unlock(); }
const PixelBuffer frameBuf() const { return running ? blitterContainer->blitter()->inBuffer() : PixelBuffer(); }
const QSize& videoSize() const { return blitterContainer->sourceSize(); }

View File

@ -311,11 +311,9 @@ long MediaWorker::sourceUpdate() {
Callback *cb;
PixelBuffer pb;
public:
VidBuf(Callback *cb) : cb(cb), pb(cb->videoBuffer()) {
if (!cb->tryLockVideoBuffer()) {
pb.data = 0;
explicit VidBuf(Callback *cb) : cb(cb), pb() {
if (!cb->tryLockVideoBuffer(pb))
this->cb = 0;
}
}
~VidBuf() { if (cb) cb->unlockVideoBuffer(); }
@ -335,23 +333,29 @@ void MediaWorker::adjustResamplerRate(const long outRate) {
sndOutBuffer.reset(sz);
}
static usec_t frameWait(const usec_t base, const usec_t syncft, const usec_t usecsFromUnderrun, SyncVar &waitingForSync) {
const usec_t now = getusecs();
namespace {
struct NowDelta { usec_t now, inc;
NowDelta(usec_t now, usec_t inc) : now(now), inc(inc) {} };
}
if (base + syncft - now < syncft * 2) {
if (base + syncft - now >= usecsFromUnderrun - (usecsFromUnderrun >> 2))
return base;
static const NowDelta frameWait(const NowDelta basetime,
const usec_t syncft, const usec_t usecsFromUnderrun, SyncVar &waitingForSync) {
const usec_t now = getusecs();
const usec_t target = basetime.now + basetime.inc + syncft;
if (target - now < basetime.inc + syncft) {
if (target - now >= usecsFromUnderrun - (usecsFromUnderrun >> 2))
return basetime;
SyncVar::Locked wfs(waitingForSync);
/*while*/if (!wfs.get() && /*wfs.wait(now, base + syncft - now)*/ wfs.wait((base + syncft - now) / 1000)) {
;
}
return base + syncft;
if (!wfs.get())
wfs.wait((target - now) / 1000);
return NowDelta(now, target - now);
}
return now;
return NowDelta(now, 0);
}
static void blitWait(MediaWorker::Callback *const cb, SyncVar &waitingForSync) {
@ -410,7 +414,7 @@ void MediaWorker::run() {
SkipSched skipSched;
bool audioBufLow = false;
usec_t base = 0;
NowDelta basetime(0, 0);
for (;;) {
pauseVar.waitWhilePaused(callback.get(), *ao_);
@ -428,7 +432,7 @@ void MediaWorker::run() {
const bool blit = blitSamples >= 0 && !skipSched.skipNext(audioBufLow);
if (blit)
callback->blit(base, syncft);
callback->blit(basetime.now, basetime.inc + syncft);
const long outsamples = sampleBuffer.read(
blit ? blitSamples : sampleBuffer.samplesBuffered(),
@ -446,7 +450,8 @@ void MediaWorker::run() {
audioBufLow = audioBufIsLow(bstate, outsamples);
if (blit) {
base = frameWait(base, syncft, usecsFromUnderrun(bstate, outsamples, ao_->estimatedRate()), waitingForSync_);
basetime = frameWait(basetime, syncft, usecsFromUnderrun(
bstate, outsamples, ao_->estimatedRate()), waitingForSync_);
blitWait(callback.get(), waitingForSync_);
}
}

View File

@ -40,9 +40,8 @@ public:
virtual bool cancelBlit() = 0;
// virtual void sync() = 0;
virtual void audioEngineFailure() = 0;
virtual bool tryLockVideoBuffer() = 0;
virtual bool tryLockVideoBuffer(PixelBuffer &pb) = 0;
virtual void unlockVideoBuffer() = 0;
virtual const PixelBuffer& videoBuffer() = 0;
virtual ~Callback() {}
};