⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 timer.h

📁 linux下实现视频播放的播放器
💻 H
字号:
/* *  Copyright (C) 2005-2007  gulikoza * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* $Id$ */#ifndef TIMER_H#define TIMER_H#include <math.h>#define MODULE "Timer"#define NO_WAIT 0xffffffffclass HPTimer {    private:	MUTEX * tm_mutex;	SDL_semaphore * sem;	SDL_TimerID timer;	// Current time in ms	double time;	double advance;	double lastupdate, tick;	// When to exit	unsigned int waittime;	const int DELAY;	// Difference between current time and pts	int ticksdiff;	void WaitMS(unsigned int ms) {	    if(ms) {		MUTEX_LOCK(tm_mutex);		waittime = (unsigned int)lrint(time) + ms;		MUTEX_UNLOCK(tm_mutex);		// Wait for semaphore#ifdef SEM_SILENT		SDL_SemWait(sem);#else                while(SDL_SemWaitTimeout(sem, 1000) == SDL_MUTEX_TIMEDOUT) {                    ERROR_MSG("Semaphore timeout expired, line: %d, thread: %u", __LINE__, SDL_ThreadID());		}#endif		DEBUG_MSG("Sleep complete");	    }	}    public:	// File playback has to provide own clock	bool unlocked;	HPTimer(int d):time(0.0),advance(0.0),lastupdate(0.0),tick(0.0),ticksdiff(0),unlocked(false),DELAY(d) {	    tm_mutex = MUTEX_CREATE();	    if(tm_mutex == NULL)		throw "Timer: Failed to create mutex";	    sem = SDL_CreateSemaphore(0);	    if(sem == NULL) {		MUTEX_DESTROY(tm_mutex);		throw "Timer: Failed to create semaphore";	    }	    // Add 1 ms timer	    timer = SDL_AddTimer(1, Callback, (void*)this);	    waittime = SDL_GetTicks();	    if(SDL_SemWaitTimeout(sem, 500) == SDL_MUTEX_TIMEDOUT)		throw "Timer: Failed to create timer!";	    ERROR_MSG("Created timer with delay %d in thread %u", DELAY, SDL_ThreadID());	}	static Uint32 Callback(Uint32 interval, void *param) {	    HPTimer *tm = (HPTimer*)param;	    MUTEX_LOCK(tm->tm_mutex);	    if(tm->tick > 0.0) {		tm->time += tm->advance;		if(lrint(tm->time) > tm->waittime) {		    tm->waittime = NO_WAIT;		    SDL_SemPost(tm->sem);		}		DEBUG_MSG("Time set to %.2f, PTS: %d", tm->time, (unsigned int)tm->time+tm->ticksdiff);		MUTEX_UNLOCK(tm->tm_mutex);		return interval;	    }	    tm->time += 1.0;	    // Calibrate starting interval	    if(tm->time > 25.0) {		tm->tick = (double)(SDL_GetTicks()-tm->waittime)/tm->time;		tm->advance = tm->time = tm->tick;		tm->waittime = NO_WAIT;		SDL_SemPost(tm->sem);		LOG_MSG("Timer calibrated, tick set to %.2f", tm->tick);	    }	    MUTEX_UNLOCK(tm->tm_mutex);	    return interval;	}	unsigned int GetPTS(void) {	    MUTEX_LOCK(tm_mutex);	    unsigned int ret = (unsigned int)lrint(time+ticksdiff);	    MUTEX_UNLOCK(tm_mutex);	    return ret;	}	void SetPTS(unsigned int pts) {	    MUTEX_LOCK(tm_mutex);	    double curPTS = time+ticksdiff;	    LOG_MSG("Cur PTS: %.2f, has to be %.2f", curPTS, (double)pts-DELAY);	    if(lastupdate == 0.0f) {		curPTS = pts-DELAY;		ticksdiff = pts-(int)lrint(time)-DELAY;		LOG_MSG("PTS set to %.2f (%d)", curPTS, (pts-(time+ticksdiff)));	    } else if(unlocked) {		// Do some rate limiting		if(pts-(DELAY<<1) > (unsigned int)lrint(curPTS)) {		    MUTEX_UNLOCK(tm_mutex);		    int delay = (pts-DELAY-(unsigned int)lrint(curPTS));		    if(delay > 1000)			delay = 1000;		    SDL_Delay(delay);		    MUTEX_LOCK(tm_mutex);		}	    } else if(fabs(lastupdate-curPTS) > 4) { // Allow at least 5 ms between updates		double realPTS = (double)pts-DELAY;		LOG_MSG("%.2f PTS difference, last update @%.2f", realPTS-curPTS, lastupdate);		realPTS = tick + (realPTS-curPTS)/((curPTS-lastupdate)*10);		// Do not allow more than 20% differnce)		if(fabs(realPTS-tick) < 0.20) {		    advance = realPTS;		    LOG_MSG("Advance set to %lf", advance);		} else {		    LOG_MSG("Weird PTS sample, ignored");		}	    }	    lastupdate = curPTS;	    MUTEX_UNLOCK(tm_mutex);	}	bool SleepPTS(unsigned int pts) {	    MUTEX_LOCK(tm_mutex);	    unsigned int curPTS = (unsigned int)lrint(time+ticksdiff);	    MUTEX_UNLOCK(tm_mutex);	    if(curPTS > pts) {		// Only 10ms late, don't sleep just return		if(curPTS-pts < 10)		    return false;		// Sorry, too late		LOG_MSG("%d ms late (%d > %d)", curPTS-pts, curPTS, pts);		return true;	    }	    // If sleep lasts more than a sec, it's probably an error	    if((pts - curPTS) > 5000) {		LOG_MSG("Sleep to long (%u ms), current time: %u", pts-curPTS, curPTS);		return true;	    }	    WaitMS(pts - curPTS);	    return false;	}	void Reset(void) {	    MUTEX_LOCK(tm_mutex);	    time = 0.0;	    waittime = 0;	    advance = tick;	    ticksdiff = 0;	    lastupdate = 0.0;	    MUTEX_UNLOCK(tm_mutex);	}	~HPTimer() {	    SDL_RemoveTimer(timer);	    SDL_Delay(10);	    MUTEX_LOCK(tm_mutex);	    SDL_SemPost(sem);	    SDL_DestroySemaphore(sem);	    MUTEX_UNLOCK(tm_mutex);	    MUTEX_DESTROY(tm_mutex);	    ERROR_MSG("Destroyed timer in thread %u", SDL_ThreadID());	}};// Make timer globalextern HPTimer * timer;#undef MODULE#endif // TIMER_H

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -