Merge pull request #26362 from ksooo/estuary-rework-pvr-info-dialog
[xbmc.git] / xbmc / windowing / osx / VideoSyncOsx.mm
blobc45d0e6e46b96ebbbb7b0351ae629c3307d3bc20
1 /*
2  *  Copyright (C) 2005-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
9 #include "VideoSyncOsx.h"
11 #include "ServiceBroker.h"
12 #include "cores/VideoPlayer/VideoReferenceClock.h"
13 #include "utils/MathUtils.h"
14 #include "utils/TimeUtils.h"
15 #include "utils/log.h"
16 #include "windowing/GraphicContext.h"
17 #include "windowing/WinSystem.h"
19 #include "platform/darwin/osx/CocoaInterface.h"
21 #include <CoreVideo/CVHostTime.h>
22 #include <QuartzCore/CVDisplayLink.h>
23 #include <unistd.h>
25 using namespace std::chrono_literals;
27 bool CVideoSyncOsx::Setup()
29   CLog::Log(LOGDEBUG, "CVideoSyncOsx::{} setting up OSX", __FUNCTION__);
31   //init the vblank timestamp
32   m_LastVBlankTime = 0;
33   m_displayLost = false;
34   m_displayReset = false;
35   m_lostEvent.Reset();
37   CServiceBroker::GetWinSystem()->Register(this);
39   return true;
42 void CVideoSyncOsx::Run(CEvent& stopEvent)
44   InitDisplayLink();
46   //because cocoa has a vblank callback, we just keep sleeping until we're asked to stop the thread
47   while(!stopEvent.Signaled() && !m_displayLost && !m_displayReset)
48   {
49     usleep(100000);
50   }
52   m_lostEvent.Set();
54   while(!stopEvent.Signaled() && m_displayLost && !m_displayReset)
55   {
56     usleep(10000);
57   }
59   DeinitDisplayLink();
62 void CVideoSyncOsx::Cleanup()
64   CLog::Log(LOGDEBUG, "CVideoSyncOsx::{} cleaning up OSX", __FUNCTION__);
65   m_lostEvent.Set();
66   m_LastVBlankTime = 0;
67   CServiceBroker::GetWinSystem()->Unregister(this);
70 float CVideoSyncOsx::GetFps()
72   m_fps = CServiceBroker::GetWinSystem()->GetGfxContext().GetFPS();
73   CLog::Log(LOGDEBUG, "CVideoSyncOsx::{} Detected refreshrate: {:f} hertz", __FUNCTION__, m_fps);
74   return m_fps;
77 void CVideoSyncOsx::RefreshChanged()
79   m_displayReset = true;
82 void CVideoSyncOsx::OnLostDisplay()
84   if (!m_displayLost)
85   {
86     m_displayLost = true;
87     m_lostEvent.Wait(1000ms);
88   }
91 void CVideoSyncOsx::OnResetDisplay()
93   m_displayReset = true;
96 void CVideoSyncOsx::VblankHandler(int64_t nowtime, uint32_t timebase)
98   int           NrVBlanks;
99   double        VBlankTime;
100   int64_t       Now = CurrentHostCounter();
102   if (m_LastVBlankTime != 0)
103   {
104     VBlankTime = (double)(nowtime - m_LastVBlankTime) / (double)timebase;
105     NrVBlanks = MathUtils::round_int(VBlankTime * static_cast<double>(m_fps));
107     //update the vblank timestamp, update the clock and send a signal that we got a vblank
108     m_refClock->UpdateClock(NrVBlanks, Now);
109   }
111   //save the timestamp of this vblank so we can calculate how many happened next time
112   m_LastVBlankTime = nowtime;
115 // Called by the Core Video Display Link whenever it's appropriate to render a frame.
116 static CVReturn DisplayLinkCallBack(CVDisplayLinkRef displayLink, const CVTimeStamp* inNow, const CVTimeStamp* inOutputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)
118   @autoreleasepool
119   {
120     CVideoSyncOsx* VideoSyncOsx = reinterpret_cast<CVideoSyncOsx*>(displayLinkContext);
122     if (inOutputTime->flags & kCVTimeStampHostTimeValid)
123       VideoSyncOsx->VblankHandler(inOutputTime->hostTime, CVGetHostClockFrequency());
124     else
125       VideoSyncOsx->VblankHandler(CVGetCurrentHostTime(), CVGetHostClockFrequency());
126   }
128   return kCVReturnSuccess;
131 bool CVideoSyncOsx::InitDisplayLink()
133   bool ret = true;
134   CLog::Log(LOGDEBUG, "CVideoSyncOsx::{} setting up displaylink", __FUNCTION__);
136   if (!Cocoa_CVDisplayLinkCreate((void*)DisplayLinkCallBack, reinterpret_cast<void*>(this)))
137   {
138     CLog::Log(LOGDEBUG, "CVideoSyncOsx::{} Cocoa_CVDisplayLinkCreate failed", __FUNCTION__);
139     ret = false;
140   }
141   return ret;
144 void CVideoSyncOsx::DeinitDisplayLink()
146   Cocoa_CVDisplayLinkRelease();