#include #include #include #include #include #include #include "avtimer.h" #include "log.h" //************************************************************// //**************** define the avtimer context ****************// //************************************************************// typedef struct AvTimerContext { AvTimer sAvTimer; //* the avtimer interface. int nSpeed; //* counting at this speed. int64_t nStartTime; //* start counting from this time. int eStatus; //* status of this timer. struct timeval startOsTime; //* the system's time when this timer starts. struct timeval lastOsTime; //* the system's time at last operation. pthread_mutex_t mutex; //* mutex to lock the timer. int64_t nStartPts; //* pts of the first frame int64_t nStartSystemTime; //* render systemtime of the first frame }AvTimerContext; static int64_t __systemTime() { struct timespec t; t.tv_sec = t.tv_nsec = 0; clock_gettime(CLOCK_MONOTONIC, &t); return t.tv_sec*1000000000LL + t.tv_nsec; } //************************************************************// //****************** declare static methods ******************// //************************************************************// static int AvTimerSetSpeed(AvTimer* t, int nSpeed); static int AvTimerGetSpeed(AvTimer* t); static int AvTimerSetTime(AvTimer* t, int64_t nTime); static int64_t AvTimerGetTime(AvTimer* t); static int64_t AvTimerPtsToSystemTime(AvTimer* t, int64_t pts); static int AvTimerStart(AvTimer* t); static void AvTimerStop(AvTimer* t); static int AvTimerGetStatus(AvTimer* t); //************************************************************// //********************** implementation **********************// //************************************************************// AvTimer* AvTimerCreate(void) { AvTimerContext* pAvTimerCtx; AvTimer* pAvTimer; pAvTimerCtx = (AvTimerContext*) malloc(sizeof(AvTimerContext)); if(pAvTimerCtx == NULL) { loge("malloc memory fail."); return NULL; } memset(pAvTimerCtx, 0, sizeof(AvTimerContext)); pAvTimer = (AvTimer*)pAvTimerCtx; pAvTimer->SetSpeed = AvTimerSetSpeed; pAvTimer->GetSpeed = AvTimerGetSpeed; pAvTimer->SetTime = AvTimerSetTime; pAvTimer->GetTime = AvTimerGetTime; pAvTimer->PtsToSystemTime = AvTimerPtsToSystemTime; pAvTimer->Start = AvTimerStart; pAvTimer->Stop = AvTimerStop; pAvTimer->GetStatus = AvTimerGetStatus; pAvTimerCtx->nSpeed = 1000; pAvTimerCtx->nStartTime = 0; pAvTimerCtx->eStatus = TIMER_STATUS_STOP; pthread_mutex_init(&pAvTimerCtx->mutex, NULL); return pAvTimer; } void AvTimerDestroy(AvTimer* t) { AvTimerContext* pAvTimerCtx; pAvTimerCtx = (AvTimerContext*)t; pthread_mutex_destroy(&pAvTimerCtx->mutex); free(pAvTimerCtx); } static int AvTimerStart(AvTimer* t) { AvTimerContext* pAvTimerCtx; pAvTimerCtx = (AvTimerContext*)t; pthread_mutex_lock(&pAvTimerCtx->mutex); pAvTimerCtx->eStatus = TIMER_STATUS_START; //* record the system's time when timer starts. gettimeofday(&pAvTimerCtx->startOsTime, NULL); pAvTimerCtx->lastOsTime.tv_sec = pAvTimerCtx->startOsTime.tv_sec; pAvTimerCtx->lastOsTime.tv_usec = pAvTimerCtx->startOsTime.tv_usec; pthread_mutex_unlock(&pAvTimerCtx->mutex); return 0; } static void AvTimerStop(AvTimer* t) { AvTimerContext* pAvTimerCtx; int64_t nPassedTime; pAvTimerCtx = (AvTimerContext*)t; pthread_mutex_lock(&pAvTimerCtx->mutex); //* record the system's time when timer stops. gettimeofday(&pAvTimerCtx->lastOsTime, NULL); //* change the start counting point. nPassedTime = (int64_t)(pAvTimerCtx->lastOsTime.tv_sec - pAvTimerCtx->startOsTime.tv_sec) * 1000000; nPassedTime += (pAvTimerCtx->lastOsTime.tv_usec - pAvTimerCtx->startOsTime.tv_usec); pAvTimerCtx->nStartTime += pAvTimerCtx->nSpeed * nPassedTime / 1000; pAvTimerCtx->startOsTime.tv_sec = pAvTimerCtx->lastOsTime.tv_sec; pAvTimerCtx->startOsTime.tv_usec = pAvTimerCtx->lastOsTime.tv_usec; pAvTimerCtx->eStatus = TIMER_STATUS_STOP; pthread_mutex_unlock(&pAvTimerCtx->mutex); return; } static int AvTimerSetSpeed(AvTimer* t, int nSpeed) { AvTimerContext* pAvTimerCtx; int64_t nPassedTime; pAvTimerCtx = (AvTimerContext*)t; pthread_mutex_lock(&pAvTimerCtx->mutex); //* record the system's time. gettimeofday(&pAvTimerCtx->lastOsTime, NULL); //* change the start counting point. nPassedTime = (int64_t)(pAvTimerCtx->lastOsTime.tv_sec - pAvTimerCtx->startOsTime.tv_sec) * 1000000; nPassedTime += (pAvTimerCtx->lastOsTime.tv_usec - pAvTimerCtx->startOsTime.tv_usec); pAvTimerCtx->nStartTime += pAvTimerCtx->nSpeed * nPassedTime / 1000; pAvTimerCtx->startOsTime.tv_sec = pAvTimerCtx->lastOsTime.tv_sec; pAvTimerCtx->startOsTime.tv_usec = pAvTimerCtx->lastOsTime.tv_usec; //* change the counting speed. pAvTimerCtx->nSpeed = nSpeed; pthread_mutex_unlock(&pAvTimerCtx->mutex); return 0; } static int AvTimerGetSpeed(AvTimer* t) { AvTimerContext* pAvTimerCtx; pAvTimerCtx = (AvTimerContext*)t; return pAvTimerCtx->nSpeed; } static int AvTimerGetStatus(AvTimer* t) { AvTimerContext* pAvTimerCtx; pAvTimerCtx = (AvTimerContext*)t; return pAvTimerCtx->eStatus; } static int64_t AvTimerGetTime(AvTimer* t) { AvTimerContext* pAvTimerCtx; int64_t nPassedTime; int64_t c; pAvTimerCtx = (AvTimerContext*)t; pthread_mutex_lock(&pAvTimerCtx->mutex); if(pAvTimerCtx->eStatus == TIMER_STATUS_START) { //* record the system's time. gettimeofday(&pAvTimerCtx->lastOsTime, NULL); //* change the start counting point. nPassedTime = (int64_t)(pAvTimerCtx->lastOsTime.tv_sec - pAvTimerCtx->startOsTime.tv_sec) * 1000000; nPassedTime += (pAvTimerCtx->lastOsTime.tv_usec - pAvTimerCtx->startOsTime.tv_usec); nPassedTime = pAvTimerCtx->nStartTime + (pAvTimerCtx->nSpeed * nPassedTime / 1000); } else //* in stop status. { //* return the last record time. nPassedTime = pAvTimerCtx->nStartTime; } pthread_mutex_unlock(&pAvTimerCtx->mutex); return nPassedTime; } static int64_t AvTimerPtsToSystemTime(AvTimer* t, int64_t pts) { AvTimerContext* pAvTimerCtx; int64_t nPtsAbs; pAvTimerCtx = (AvTimerContext*)t; pthread_mutex_lock(&pAvTimerCtx->mutex); if(pAvTimerCtx->eStatus == TIMER_STATUS_START) { //* record the system's time. nPtsAbs = pAvTimerCtx->nStartSystemTime + (pts - pAvTimerCtx->nStartPts) * 1000LL; } else //* in stop status. { //* return the last record time. nPtsAbs = pAvTimerCtx->nStartSystemTime; } pthread_mutex_unlock(&pAvTimerCtx->mutex); return nPtsAbs; } static int AvTimerSetTime(AvTimer* t, int64_t nTime) { AvTimerContext* pAvTimerCtx; int64_t c; pAvTimerCtx = (AvTimerContext*)t; pthread_mutex_lock(&pAvTimerCtx->mutex); gettimeofday(&pAvTimerCtx->startOsTime, NULL); pAvTimerCtx->lastOsTime.tv_sec = pAvTimerCtx->startOsTime.tv_sec; pAvTimerCtx->lastOsTime.tv_usec = pAvTimerCtx->startOsTime.tv_usec; pAvTimerCtx->nStartTime = nTime; pAvTimerCtx->nStartPts = nTime; pAvTimerCtx->nStartSystemTime = __systemTime() + 30000000LL; pthread_mutex_unlock(&pAvTimerCtx->mutex); return 0; }