Merge pull request #26273 from 78andyp/blurayfixes2
[xbmc.git] / xbmc / windowing / gbm / VideoSyncGbm.cpp
blob238eb472373a8a6fcd7e088b925260d6c0b0c6ec
1 /*
2 * Copyright (C) 2005-2021 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 "VideoSyncGbm.h"
11 #include "ServiceBroker.h"
12 #include "cores/VideoPlayer/VideoReferenceClock.h"
13 #include "threads/Thread.h"
14 #include "utils/TimeUtils.h"
15 #include "utils/log.h"
16 #include "windowing/GraphicContext.h"
17 #include "windowing/WinSystem.h"
18 #include "windowing/gbm/WinSystemGbm.h"
19 #include "xf86drm.h"
20 #include "xf86drmMode.h"
22 #include <assert.h>
23 #include <stdint.h>
24 #include <stdlib.h>
26 #include <unistd.h>
28 CVideoSyncGbm::CVideoSyncGbm(CVideoReferenceClock* clock)
29 : CVideoSync(clock), m_winSystem(CServiceBroker::GetWinSystem())
31 if (!m_winSystem)
32 throw std::runtime_error("window system not available");
35 bool CVideoSyncGbm::Setup()
37 m_abort = false;
38 m_winSystem->Register(this);
39 CLog::Log(LOGDEBUG, "CVideoSyncGbm::{} setting up", __FUNCTION__);
41 auto winSystemGbm = dynamic_cast<KODI::WINDOWING::GBM::CWinSystemGbm*>(m_winSystem);
42 if (!winSystemGbm)
44 CLog::Log(LOGWARNING, "CVideoSyncGbm::{}: failed to get winSystem", __FUNCTION__);
45 return false;
48 auto drm = winSystemGbm->GetDrm();
49 if (!drm)
51 CLog::Log(LOGWARNING, "CVideoSyncGbm::{}: failed to get drm", __FUNCTION__);
52 return false;
55 auto crtc = drm->GetCrtc();
56 if (!crtc)
58 CLog::Log(LOGWARNING, "CVideoSyncGbm::{}: failed to get crtc", __FUNCTION__);
59 return false;
62 uint64_t ns = 0;
63 m_crtcId = crtc->GetCrtcId();
64 m_fd = drm->GetFileDescriptor();
65 int s = drmCrtcGetSequence(m_fd, m_crtcId, &m_sequence, &ns);
66 m_offset = CurrentHostCounter() - ns;
67 if (s != 0)
69 CLog::Log(LOGWARNING, "CVideoSyncGbm::{}: drmCrtcGetSequence failed ({})", __FUNCTION__, s);
70 return false;
73 CLog::Log(LOGINFO, "CVideoSyncGbm::{}: opened (fd:{} crtc:{} seq:{} ns:{}:{})", __FUNCTION__,
74 m_fd, m_crtcId, m_sequence, ns, m_offset + ns);
75 return true;
78 void CVideoSyncGbm::Run(CEvent& stopEvent)
80 /* This shouldn't be very busy and timing is important so increase priority */
81 CThread::GetCurrentThread()->SetPriority(ThreadPriority::ABOVE_NORMAL);
83 if (m_fd < 0)
85 CLog::Log(LOGWARNING, "CVideoSyncGbm::{}: failed to open device ({})", __FUNCTION__, m_fd);
86 return;
88 CLog::Log(LOGDEBUG, "CVideoSyncGbm::{}: started {}", __FUNCTION__, m_fd);
90 while (!stopEvent.Signaled() && !m_abort)
92 uint64_t sequence = 0, ns = 0;
93 usleep(1000);
94 int s = drmCrtcGetSequence(m_fd, m_crtcId, &sequence, &ns);
95 if (s != 0)
97 CLog::Log(LOGWARNING, "CVideoSyncGbm::{}: drmCrtcGetSequence failed ({})", __FUNCTION__, s);
98 break;
101 if (sequence == m_sequence)
102 continue;
104 m_refClock->UpdateClock(sequence - m_sequence, m_offset + ns);
105 m_sequence = sequence;
109 void CVideoSyncGbm::Cleanup()
111 CLog::Log(LOGDEBUG, "CVideoSyncGbm::{}: cleaning up", __FUNCTION__);
112 m_winSystem->Unregister(this);
115 float CVideoSyncGbm::GetFps()
117 m_fps = m_winSystem->GetGfxContext().GetFPS();
118 CLog::Log(LOGDEBUG, "CVideoSyncGbm::{}: fps:{}", __FUNCTION__, m_fps);
119 return m_fps;
122 void CVideoSyncGbm::OnResetDisplay()
124 m_abort = true;
127 void CVideoSyncGbm::RefreshChanged()
129 if (m_fps != m_winSystem->GetGfxContext().GetFPS())
130 m_abort = true;