[videodb] remove unused seasons table from episode_view
[xbmc.git] / xbmc / cores / VideoPlayer / DVDClock.cpp
blobd27c956ef30dd88a8d82e7ab3ae50caecfd71abe
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "DVDClock.h"
11 #include "VideoReferenceClock.h"
12 #include "cores/VideoPlayer/Interface/TimingConstants.h"
13 #include "utils/MathUtils.h"
14 #include "utils/TimeUtils.h"
15 #include "utils/log.h"
17 #include <inttypes.h>
18 #include <math.h>
19 #include <memory>
20 #include <mutex>
22 CDVDClock::CDVDClock()
24 std::unique_lock<CCriticalSection> lock(m_systemsection);
26 m_pauseClock = 0;
27 m_bReset = true;
28 m_paused = false;
29 m_speedAfterPause = DVD_PLAYSPEED_PAUSE;
30 m_iDisc = 0;
31 m_maxspeedadjust = 5.0;
32 m_systemAdjust = 0;
33 m_speedAdjust = 0;
34 m_startClock = 0;
35 m_vSyncAdjust = 0;
36 m_frameTime = DVD_TIME_BASE / 60.0;
38 m_videoRefClock = std::make_unique<CVideoReferenceClock>();
39 m_lastSystemTime = m_videoRefClock->GetTime();
40 m_systemOffset = m_videoRefClock->GetTime();
41 m_systemFrequency = CurrentHostFrequency();
42 m_systemUsed = m_systemFrequency;
45 CDVDClock::~CDVDClock() = default;
47 // Returns the current absolute clock in units of DVD_TIME_BASE (usually microseconds).
48 double CDVDClock::GetAbsoluteClock(bool interpolated /*= true*/)
50 std::unique_lock<CCriticalSection> lock(m_systemsection);
52 int64_t current;
53 current = m_videoRefClock->GetTime(interpolated);
55 return SystemToAbsolute(current);
58 double CDVDClock::GetClock(bool interpolated /*= true*/)
60 std::unique_lock<CCriticalSection> lock(m_critSection);
62 int64_t current = m_videoRefClock->GetTime(interpolated);
63 m_systemAdjust += m_speedAdjust * (current - m_lastSystemTime);
64 m_lastSystemTime = current;
66 return SystemToPlaying(current);
69 double CDVDClock::GetClock(double& absolute, bool interpolated /*= true*/)
71 int64_t current = m_videoRefClock->GetTime(interpolated);
73 std::unique_lock<CCriticalSection> lock(m_systemsection);
74 absolute = SystemToAbsolute(current);
76 m_systemAdjust += m_speedAdjust * (current - m_lastSystemTime);
77 m_lastSystemTime = current;
79 return SystemToPlaying(current);
82 void CDVDClock::SetVsyncAdjust(double adjustment)
84 std::unique_lock<CCriticalSection> lock(m_critSection);
85 m_vSyncAdjust = adjustment;
88 double CDVDClock::GetVsyncAdjust()
90 std::unique_lock<CCriticalSection> lock(m_critSection);
91 return m_vSyncAdjust;
94 void CDVDClock::Pause(bool pause)
96 std::unique_lock<CCriticalSection> lock(m_critSection);
98 if (pause && !m_paused)
100 if (!m_pauseClock)
101 m_speedAfterPause = m_systemFrequency * DVD_PLAYSPEED_NORMAL / m_systemUsed;
102 else
103 m_speedAfterPause = DVD_PLAYSPEED_PAUSE;
105 SetSpeed(DVD_PLAYSPEED_PAUSE);
106 m_paused = true;
108 else if (!pause && m_paused)
110 m_paused = false;
111 SetSpeed(m_speedAfterPause);
115 void CDVDClock::Advance(double time)
117 std::unique_lock<CCriticalSection> lock(m_critSection);
119 if (m_pauseClock)
121 m_pauseClock += time / DVD_TIME_BASE * m_systemFrequency;
125 void CDVDClock::SetSpeed(int iSpeed)
127 // this will sometimes be a little bit of due to rounding errors, ie clock might jump a bit when changing speed
128 std::unique_lock<CCriticalSection> lock(m_critSection);
130 if (m_paused)
132 m_speedAfterPause = iSpeed;
133 return;
136 if (iSpeed == DVD_PLAYSPEED_PAUSE)
138 if (!m_pauseClock)
139 m_pauseClock = m_videoRefClock->GetTime();
140 return;
143 int64_t current;
144 int64_t newfreq = m_systemFrequency * DVD_PLAYSPEED_NORMAL / iSpeed;
146 current = m_videoRefClock->GetTime();
147 if (m_pauseClock)
149 m_startClock += current - m_pauseClock;
150 m_pauseClock = 0;
153 m_startClock = current - (int64_t)((double)(current - m_startClock) * newfreq / m_systemUsed);
154 m_systemUsed = newfreq;
157 void CDVDClock::SetSpeedAdjust(double adjust)
159 CLog::Log(LOGDEBUG, "CDVDClock::SetSpeedAdjust - adjusted:{:f}", adjust);
161 std::unique_lock<CCriticalSection> lock(m_critSection);
162 m_speedAdjust = adjust;
165 double CDVDClock::GetSpeedAdjust()
167 std::unique_lock<CCriticalSection> lock(m_critSection);
168 return m_speedAdjust;
171 double CDVDClock::ErrorAdjust(double error, const char* log)
173 std::unique_lock<CCriticalSection> lock(m_critSection);
175 double clock, absolute, adjustment;
176 clock = GetClock(absolute);
178 // skip minor updates while speed adjust is active
179 // -> adjusting buffer levels
180 if (m_speedAdjust != 0 && error < DVD_MSEC_TO_TIME(100))
182 return 0;
185 adjustment = error;
187 if (m_vSyncAdjust != 0)
189 // Audio ahead is more noticeable then audio behind video.
190 // Correct if aufio is more than 20ms ahead or more then
191 // 27ms behind. In a worst case scenario we switch from
192 // 20ms ahead to 21ms behind (for fps of 23.976)
193 if (error > 0.02 * DVD_TIME_BASE)
194 adjustment = m_frameTime;
195 else if (error < -0.027 * DVD_TIME_BASE)
196 adjustment = -m_frameTime;
197 else
198 adjustment = 0;
201 if (adjustment == 0)
202 return 0;
204 Discontinuity(clock+adjustment, absolute);
206 CLog::Log(LOGDEBUG, "CDVDClock::ErrorAdjust - {} - error:{:f}, adjusted:{:f}", log, error,
207 adjustment);
208 return adjustment;
211 void CDVDClock::Discontinuity(double clock, double absolute)
213 std::unique_lock<CCriticalSection> lock(m_critSection);
214 m_startClock = AbsoluteToSystem(absolute);
215 if(m_pauseClock)
216 m_pauseClock = m_startClock;
217 m_iDisc = clock;
218 m_bReset = false;
219 m_systemAdjust = 0;
220 m_speedAdjust = 0;
223 void CDVDClock::SetMaxSpeedAdjust(double speed)
225 std::unique_lock<CCriticalSection> lock(m_speedsection);
227 m_maxspeedadjust = speed;
230 //returns the refreshrate if the videoreferenceclock is running, -1 otherwise
231 int CDVDClock::UpdateFramerate(double fps, double* interval /*= NULL*/)
233 //sent with fps of 0 means we are not playing video
234 if(fps == 0.0)
235 return -1;
237 m_frameTime = 1/fps * DVD_TIME_BASE;
239 //check if the videoreferenceclock is running, will return -1 if not
240 double rate = m_videoRefClock->GetRefreshRate(interval);
242 if (rate <= 0)
243 return -1;
245 std::unique_lock<CCriticalSection> lock(m_speedsection);
247 double weight = (rate * 2) / fps;
249 //set the speed of the videoreferenceclock based on fps, refreshrate and maximum speed adjust set by user
250 if (m_maxspeedadjust > 0.05)
252 if (weight / MathUtils::round_int(weight) < 1.0 + m_maxspeedadjust / 100.0 &&
253 weight / MathUtils::round_int(weight) > 1.0 - m_maxspeedadjust / 100.0)
254 weight = MathUtils::round_int(weight);
256 double speed = (rate * 2.0 ) / (fps * weight);
257 lock.unlock();
259 m_videoRefClock->SetSpeed(speed);
261 return rate;
264 bool CDVDClock::GetClockInfo(int& MissedVblanks, double& ClockSpeed, double& RefreshRate) const
266 return m_videoRefClock->GetClockInfo(MissedVblanks, ClockSpeed, RefreshRate);
269 double CDVDClock::SystemToAbsolute(int64_t system)
271 return DVD_TIME_BASE * (double)(system - m_systemOffset) / m_systemFrequency;
274 int64_t CDVDClock::AbsoluteToSystem(double absolute)
276 return (int64_t)(absolute / DVD_TIME_BASE * m_systemFrequency) + m_systemOffset;
279 double CDVDClock::SystemToPlaying(int64_t system)
281 int64_t current;
283 if (m_bReset)
285 m_startClock = system;
286 m_systemUsed = m_systemFrequency;
287 if(m_pauseClock)
288 m_pauseClock = m_startClock;
289 m_iDisc = 0;
290 m_systemAdjust = 0;
291 m_speedAdjust = 0;
292 m_vSyncAdjust = 0;
293 m_bReset = false;
296 if (m_pauseClock)
297 current = m_pauseClock;
298 else
299 current = system;
301 return DVD_TIME_BASE * (double)(current - m_startClock + m_systemAdjust) / m_systemUsed + m_iDisc;
304 double CDVDClock::GetClockSpeed()
306 std::unique_lock<CCriticalSection> lock(m_critSection);
308 double speed = (double)m_systemFrequency / m_systemUsed;
309 return m_videoRefClock->GetSpeed() * speed + m_speedAdjust;