bool CDVDClock::Update(double clock, double absolute, double limit, const char* log) { CExclusiveLock lock(m_critSection); double was_absolute = SystemToAbsolute(m_startClock); double was_clock = m_iDisc + absolute - was_absolute; lock.Leave(); double error = std::abs(clock - was_clock); // skip minor updates while speed adjust is active // -> adjusting buffer levels if (m_speedAdjust != 0 && error < DVD_MSEC_TO_TIME(100)) { return false; } else if (error > limit) { Discontinuity(clock, absolute); CLog::Log(LOGDEBUG, "CDVDClock::Discontinuity - %s - was:%f, should be:%f, error:%f" , log , was_clock , clock , clock - was_clock); return true; } else return false; }
double CDVDClock::ErrorAdjust(double error, const char* log) { CSingleLock lock(m_critSection); double clock, absolute, adjustment; clock = GetClock(absolute); // skip minor updates while speed adjust is active // -> adjusting buffer levels if (m_speedAdjust != 0 && error < DVD_MSEC_TO_TIME(100)) { return 0; } adjustment = error; if (m_vSyncAdjust != 0) { if (error > 0.5 * m_frameTime) adjustment = m_frameTime; else if (error < -0.5 * m_frameTime) adjustment = -m_frameTime; else adjustment = 0; } if (adjustment == 0) return 0; Discontinuity(clock+adjustment, absolute); CLog::Log(LOGDEBUG, "CDVDClock::ErrorAdjust - %s - error:%f, adjusted:%f", log, error, adjustment); return adjustment; }
static int Flush(codecidct* p) { Discontinuity(p); p->FrameEnd = 0; p->Dropping = 0; BufferClear(&p->Buffer); if (p->Flush) p->Flush(p); return ERR_NONE; }
bool CDVDClock::Update(double clock, double absolute, double limit, const char* log) { CExclusiveLock lock(m_critSection); double was_absolute = SystemToAbsolute(m_startClock); double was_clock = m_iDisc + absolute - was_absolute; lock.Leave(); if(std::abs(clock - was_clock) > limit) { Discontinuity(clock, absolute); CLog::Log(LOGDEBUG, "CDVDClock::Discontinuity - %s - was:%f, should be:%f, error:%f" , log , was_clock , clock , clock - was_clock); return true; } else return false; }
double CDVDClock::ErrorAdjust(double error, const char* log) { CSingleLock lock(m_critSection); double clock, absolute, adjustment; clock = GetClock(absolute); // skip minor updates while speed adjust is active // -> adjusting buffer levels if (m_speedAdjust != 0 && error < DVD_MSEC_TO_TIME(100)) { return 0; } adjustment = error; if (m_vSyncAdjust != 0) { // Audio ahead is more noticeable then audio behind video. // Correct if aufio is more than 20ms ahead or more then // 27ms behind. In a worst case scenario we switch from // 20ms ahead to 21ms behind (for fps of 23.976) if (error > 0.02 * DVD_TIME_BASE) adjustment = m_frameTime; else if (error < -0.027 * DVD_TIME_BASE) adjustment = -m_frameTime; else adjustment = 0; } if (adjustment == 0) return 0; Discontinuity(clock+adjustment, absolute); CLog::Log(LOGDEBUG, "CDVDClock::ErrorAdjust - %s - error:%f, adjusted:%f", log, error, adjustment); return adjustment; }
static int Process(codecidct* p, const packet* Packet, const flowstate* State) { int Result; idct* IDCT = p->IDCT.Ptr; if (p->IDCT.Count<=0 && p->IDCT.Width>0 && p->IDCT.Height>0) return ERR_INVALID_DATA; p->State.CurrTime = State->CurrTime; if (State->DropLevel > 1) Discontinuity(p); if (p->Show>=0) // pending frame? { Result = IDCT->Send(IDCT,p->RefTime,&p->State); if (Result == ERR_BUFFER_FULL) return Result; p->Show = -1; } if (!Packet) // end of file or dropped return IDCT->Null(IDCT,State,0); if ((p->In.Format.Video.Pixel.Flags & PF_FRAGMENTED) && p->FindNext) { bool_t Processed = 0; if (p->RefTime >= 0) p->RefTime += p->FrameTime; for (;;) { if (!p->FindNext(p)) { if (Processed) { Result = ERR_NEED_MORE_DATA; break; } p->FrameEnd -= p->Buffer.ReadPos; BufferPack(&p->Buffer,0); BufferWrite(&p->Buffer,Packet->Data[0],Packet->Length,32768); Processed = 1; if (Packet->RefTime >= 0) { p->RefTime = Packet->RefTime; // if (p->IDCT.Count >= 3 && p->FrameTime>0 && p->RefTime >= p->FrameTime) // p->RefTime -= p->FrameTime; } } else { p->State.DropLevel = p->RefTime >= 0 && State->CurrTime >= 0 && p->RefTime < (State->CurrTime - p->DropTolerance); if (State->DropLevel > 1) { p->IDCT.Ptr->Null(p->IDCT.Ptr,NULL,0); Result = ERR_NONE; } else Result = p->Frame(p,p->Buffer.Data+p->Buffer.ReadPos,p->FrameEnd-p->Buffer.ReadPos); p->Buffer.ReadPos = p->FrameEnd; if (Result==ERR_NONE && p->Show>=0) { if (!Processed) Result = ERR_BUFFER_FULL; // resend packet next time break; } } } } else { if (State->DropLevel > 1) { p->IDCT.Ptr->Null(p->IDCT.Ptr,NULL,0); Result = ERR_NONE; } else { p->State.DropLevel = State->DropLevel; p->RefTime = Packet->RefTime; // if (p->IDCT.Count >= 3 && p->FrameTime>0 && p->RefTime >= p->FrameTime) // p->RefTime -= p->FrameTime; Result = p->Frame(p,Packet->Data[0],Packet->Length); } } if (p->Show>=0 && IDCT->Send(IDCT,p->RefTime,&p->State) != ERR_BUFFER_FULL) p->Show = -1; return Result; }