diff options
Diffstat (limited to 'mpeglib/lib/util/syncClockMPEG.cpp')
-rw-r--r-- | mpeglib/lib/util/syncClockMPEG.cpp | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/mpeglib/lib/util/syncClockMPEG.cpp b/mpeglib/lib/util/syncClockMPEG.cpp new file mode 100644 index 00000000..53ae7e2d --- /dev/null +++ b/mpeglib/lib/util/syncClockMPEG.cpp @@ -0,0 +1,221 @@ +/* + synchronisation of audio/video (PTS) against system clock stamps (SCR) + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#include "syncClockMPEG.h" + + +#include <iostream> + +using namespace std; + + +SyncClockMPEG::SyncClockMPEG() { + syncMode=__SYNC_NONE; + abs_thread_mutex_init(&scrMut); + abs_thread_mutex_init(&changeMut); + lastSCR=0.0; + lastPTS=0.0; + jitter=0.0; + oldjitter=0.0; + + TimeWrapper::gettimeofday(&lastPTS_time); + + +} + + +SyncClockMPEG::~SyncClockMPEG() { + abs_thread_mutex_destroy(&changeMut); + abs_thread_mutex_destroy(&scrMut); +} + + + +int SyncClockMPEG::getSyncMode() { + return syncMode; +} + + +void SyncClockMPEG::setSyncMode(int syncMode) { + this->syncMode=syncMode; +} + + + +int SyncClockMPEG::syncAudio(double pts,double scr) { + switch(syncMode) { + case __SYNC_AUDIO: + markLastPTSTime(scr,pts); + break; + default: + cout << "syncMode not implemented:"<<syncMode<<endl; + } + return true; +} + + +int SyncClockMPEG::syncVideo(double pts,double scr, + TimeStamp* earlyTime, + TimeStamp* waitTime) { + int back; + switch(syncMode) { + case __SYNC_AUDIO: + back=gowait(scr,pts,earlyTime,waitTime); + return back; + break; + case __SYNC_NONE: + return true; + default: + cout << "syncMode not implemented"<<endl; + } + return true; +} + + +void SyncClockMPEG::lockSyncClock() { + abs_thread_mutex_lock(&changeMut); + abs_thread_mutex_lock(&scrMut); + abs_thread_mutex_unlock(&changeMut); + +} + + +void SyncClockMPEG::unlockSyncClock() { + abs_thread_mutex_unlock(&scrMut); +} + + +double SyncClockMPEG::getPTSTime(double* window) { + lockSyncClock(); + double currentPTS; + timeval_t current_time; + timeval_t passed_time; + TimeWrapper::gettimeofday(¤t_time); + + a_Minus_b_Is_C(¤t_time,&lastPTS_time,&passed_time); + currentPTS=lastPTS+timeval2Double(&passed_time); + *window=jitter+oldjitter; + + + unlockSyncClock(); + return currentPTS; +} + + +void SyncClockMPEG::markLastPTSTime(double ,double pts) { + double tmp; + double expect_time=getPTSTime(&tmp); + + lockSyncClock(); + oldjitter=jitter; + jitter=expect_time-pts; + + TimeWrapper::gettimeofday(&lastPTS_time); + lastPTS=pts; + + + unlockSyncClock(); + /* + cout << "(audio) pts stream:"<<pts + << " expect:"<<expect_time<<" jitter:"<<jitter<<endl; + */ + +} + + +int SyncClockMPEG::a_Minus_b_Is_C(timeval_t* a,timeval_t* b,timeval_t* c){ + c->tv_usec=a->tv_usec; + c->tv_sec=a->tv_sec; + + c->tv_usec-=b->tv_usec; + c->tv_sec-=b->tv_sec; + + if (c->tv_usec <= 0) { + c->tv_usec=c->tv_usec+1000000; + c->tv_sec--; + } + if (c->tv_usec >= 1000000) { + c->tv_usec=c->tv_usec-1000000; + c->tv_sec++; + } + return true; +} + + +double SyncClockMPEG::timeval2Double(timeval_t* a) { + return (double)a->tv_sec+(double)(a->tv_usec)/1000000.0; +} + + +void SyncClockMPEG::double2Timeval(double a,timeval_t* dest) { + dest->tv_sec=(int)a; + dest->tv_usec=(int)(1000000.0*(double)(a-(double)dest->tv_sec)); +} + + +int SyncClockMPEG::gowait(double ,double pts, + TimeStamp* earlyTime,TimeStamp* ) { + double window; + double currentPTS=getPTSTime(&window); + double diff_time; + + // in window we have the jitter + // diff_time is positive when we are in the future + diff_time=pts-(currentPTS+window); + + + + // tolerate one frame (for 25 frames/s) in the future + // but wait a bit + if (diff_time > 0.0) { + diff_time=diff_time/4.0; + + double2Timeval(diff_time,earlyTime->getTime()); + if (diff_time > 1) { + // cannot be, we assume stange clock error + earlyTime->set(1,0); + } + + return true; + } + + earlyTime->set(0,0); + // one frame late, display it, without waiting + // and hope we catch up + if (diff_time > -0.04) { + return true; + } + /* + cout << "(video) pts stream:"<<pts + << " pts expect:"<<currentPTS + << " window:"<<window<<endl; + */ + return false; +} + + +void SyncClockMPEG::printTime(timeval_t* a,char* text) { + cout << text + << "time(sec):"<<a->tv_sec + << "time(usec)"<<a->tv_usec<<endl; +} + +void SyncClockMPEG::print(char* text) { + cout << text + << " lastPTS:"<<lastPTS + << " lastSCR:"<<lastSCR + << " jitter:"<<jitter; + printTime(&lastPTS_time,(char*)"lastPTS_time"); + printTime(&lastSCR_time,(char*)"lastSCR_time"); +} |