From 0cc06143bdf5c4df9d72608298b8822e1133a5e2 Mon Sep 17 00:00:00 2001 From: Rainer Hochecker Date: Tue, 31 Jan 2017 19:27:37 +0100 Subject: VideoPlayer: VideoReferenceClock to the right place --- cmake/treedata/common/video.txt | 1 - xbmc/cores/VideoPlayer/CMakeLists.txt | 6 +- xbmc/cores/VideoPlayer/DVDClock.cpp | 2 +- xbmc/cores/VideoPlayer/VideoReferenceClock.cpp | 283 ++++++++++++++++++++ xbmc/cores/VideoPlayer/VideoReferenceClock.h | 65 +++++ xbmc/platform/darwin/ios/XBMCController.mm | 1 - xbmc/video/CMakeLists.txt | 2 - xbmc/video/VideoReferenceClock.cpp | 340 ------------------------- xbmc/video/VideoReferenceClock.h | 64 ----- xbmc/video/videosync/CMakeLists.txt | 50 ---- xbmc/video/videosync/VideoSync.h | 40 --- xbmc/video/videosync/VideoSyncAML.cpp | 110 -------- xbmc/video/videosync/VideoSyncAML.h | 41 --- xbmc/video/videosync/VideoSyncAndroid.cpp | 94 ------- xbmc/video/videosync/VideoSyncAndroid.h | 48 ---- xbmc/video/videosync/VideoSyncD3D.cpp | 158 ------------ xbmc/video/videosync/VideoSyncD3D.h | 50 ---- xbmc/video/videosync/VideoSyncDRM.cpp | 185 -------------- xbmc/video/videosync/VideoSyncDRM.h | 48 ---- xbmc/video/videosync/VideoSyncGLX.cpp | 292 --------------------- xbmc/video/videosync/VideoSyncGLX.h | 56 ---- xbmc/video/videosync/VideoSyncIMX.cpp | 84 ------ xbmc/video/videosync/VideoSyncIMX.h | 41 --- xbmc/video/videosync/VideoSyncIos.cpp | 112 -------- xbmc/video/videosync/VideoSyncIos.h | 52 ---- xbmc/video/videosync/VideoSyncOsx.cpp | 162 ------------ xbmc/video/videosync/VideoSyncOsx.h | 61 ----- xbmc/video/videosync/VideoSyncPi.cpp | 73 ------ xbmc/video/videosync/VideoSyncPi.h | 41 --- xbmc/windowing/CMakeLists.txt | 3 +- xbmc/windowing/VideoSync.h | 40 +++ xbmc/windowing/WinSystem.h | 5 + xbmc/windowing/X11/CMakeLists.txt | 4 + xbmc/windowing/X11/VideoSyncDRM.cpp | 185 ++++++++++++++ xbmc/windowing/X11/VideoSyncDRM.h | 45 ++++ xbmc/windowing/X11/VideoSyncGLX.cpp | 292 +++++++++++++++++++++ xbmc/windowing/X11/VideoSyncGLX.h | 56 ++++ xbmc/windowing/X11/WinSystemX11.cpp | 4 +- xbmc/windowing/X11/WinSystemX11GLContext.cpp | 19 +- xbmc/windowing/X11/WinSystemX11GLContext.h | 3 + xbmc/windowing/egl/VideoSyncAndroid.cpp | 94 +++++++ xbmc/windowing/egl/VideoSyncAndroid.h | 48 ++++ xbmc/windowing/egl/VideoSyncIMX.cpp | 84 ++++++ xbmc/windowing/egl/VideoSyncIMX.h | 41 +++ xbmc/windowing/egl/VideoSyncPi.cpp | 73 ++++++ xbmc/windowing/egl/VideoSyncPi.h | 41 +++ xbmc/windowing/osx/CMakeLists.txt | 12 +- xbmc/windowing/osx/VideoSyncIos.cpp | 112 ++++++++ xbmc/windowing/osx/VideoSyncIos.h | 52 ++++ xbmc/windowing/osx/VideoSyncOsx.cpp | 159 ++++++++++++ xbmc/windowing/osx/VideoSyncOsx.h | 59 +++++ xbmc/windowing/osx/WinSystemIOS.h | 2 + xbmc/windowing/osx/WinSystemIOS.mm | 13 +- xbmc/windowing/osx/WinSystemOSX.h | 3 + xbmc/windowing/osx/WinSystemOSX.mm | 9 +- xbmc/windowing/windows/VideoSyncD3D.cpp | 158 ++++++++++++ xbmc/windowing/windows/VideoSyncD3D.h | 50 ++++ 57 files changed, 2003 insertions(+), 2225 deletions(-) create mode 100644 xbmc/cores/VideoPlayer/VideoReferenceClock.cpp create mode 100644 xbmc/cores/VideoPlayer/VideoReferenceClock.h delete mode 100644 xbmc/video/VideoReferenceClock.cpp delete mode 100644 xbmc/video/VideoReferenceClock.h delete mode 100644 xbmc/video/videosync/CMakeLists.txt delete mode 100644 xbmc/video/videosync/VideoSync.h delete mode 100644 xbmc/video/videosync/VideoSyncAML.cpp delete mode 100644 xbmc/video/videosync/VideoSyncAML.h delete mode 100644 xbmc/video/videosync/VideoSyncAndroid.cpp delete mode 100644 xbmc/video/videosync/VideoSyncAndroid.h delete mode 100644 xbmc/video/videosync/VideoSyncD3D.cpp delete mode 100644 xbmc/video/videosync/VideoSyncD3D.h delete mode 100644 xbmc/video/videosync/VideoSyncDRM.cpp delete mode 100644 xbmc/video/videosync/VideoSyncDRM.h delete mode 100644 xbmc/video/videosync/VideoSyncGLX.cpp delete mode 100644 xbmc/video/videosync/VideoSyncGLX.h delete mode 100644 xbmc/video/videosync/VideoSyncIMX.cpp delete mode 100644 xbmc/video/videosync/VideoSyncIMX.h delete mode 100644 xbmc/video/videosync/VideoSyncIos.cpp delete mode 100644 xbmc/video/videosync/VideoSyncIos.h delete mode 100644 xbmc/video/videosync/VideoSyncOsx.cpp delete mode 100644 xbmc/video/videosync/VideoSyncOsx.h delete mode 100644 xbmc/video/videosync/VideoSyncPi.cpp delete mode 100644 xbmc/video/videosync/VideoSyncPi.h create mode 100644 xbmc/windowing/VideoSync.h create mode 100644 xbmc/windowing/X11/VideoSyncDRM.cpp create mode 100644 xbmc/windowing/X11/VideoSyncDRM.h create mode 100644 xbmc/windowing/X11/VideoSyncGLX.cpp create mode 100644 xbmc/windowing/X11/VideoSyncGLX.h create mode 100644 xbmc/windowing/egl/VideoSyncAndroid.cpp create mode 100644 xbmc/windowing/egl/VideoSyncAndroid.h create mode 100644 xbmc/windowing/egl/VideoSyncIMX.cpp create mode 100644 xbmc/windowing/egl/VideoSyncIMX.h create mode 100644 xbmc/windowing/egl/VideoSyncPi.cpp create mode 100644 xbmc/windowing/egl/VideoSyncPi.h create mode 100644 xbmc/windowing/osx/VideoSyncIos.cpp create mode 100644 xbmc/windowing/osx/VideoSyncIos.h create mode 100644 xbmc/windowing/osx/VideoSyncOsx.cpp create mode 100644 xbmc/windowing/osx/VideoSyncOsx.h create mode 100644 xbmc/windowing/windows/VideoSyncD3D.cpp create mode 100644 xbmc/windowing/windows/VideoSyncD3D.h diff --git a/cmake/treedata/common/video.txt b/cmake/treedata/common/video.txt index e7855a0809..acfb33bf57 100644 --- a/cmake/treedata/common/video.txt +++ b/cmake/treedata/common/video.txt @@ -1,5 +1,4 @@ xbmc/video video xbmc/video/dialogs video/dialogs xbmc/video/jobs video/jobs -xbmc/video/videosync video/sync xbmc/video/windows video/windows diff --git a/xbmc/cores/VideoPlayer/CMakeLists.txt b/xbmc/cores/VideoPlayer/CMakeLists.txt index 00d0232922..4ceff1b890 100644 --- a/xbmc/cores/VideoPlayer/CMakeLists.txt +++ b/xbmc/cores/VideoPlayer/CMakeLists.txt @@ -13,7 +13,8 @@ set(SOURCES DVDAudio.cpp VideoPlayerRadioRDS.cpp VideoPlayerSubtitle.cpp VideoPlayerTeletext.cpp - VideoPlayerVideo.cpp) + VideoPlayerVideo.cpp + VideoReferenceClock.cpp) set(HEADERS DVDAudio.h DVDClock.h @@ -32,6 +33,7 @@ set(HEADERS DVDAudio.h VideoPlayerRadioRDS.h VideoPlayerSubtitle.h VideoPlayerTeletext.h - VideoPlayerVideo.h) + VideoPlayerVideo.h + VideoReferenceClock.h) core_add_library(VideoPlayer) diff --git a/xbmc/cores/VideoPlayer/DVDClock.cpp b/xbmc/cores/VideoPlayer/DVDClock.cpp index f4ae45d816..4cf90d546e 100644 --- a/xbmc/cores/VideoPlayer/DVDClock.cpp +++ b/xbmc/cores/VideoPlayer/DVDClock.cpp @@ -19,7 +19,7 @@ */ #include "DVDClock.h" -#include "video/VideoReferenceClock.h" +#include "VideoReferenceClock.h" #include #include "utils/MathUtils.h" #include "threads/SingleLock.h" diff --git a/xbmc/cores/VideoPlayer/VideoReferenceClock.cpp b/xbmc/cores/VideoPlayer/VideoReferenceClock.cpp new file mode 100644 index 0000000000..0dd7ea9b87 --- /dev/null +++ b/xbmc/cores/VideoPlayer/VideoReferenceClock.cpp @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include "VideoReferenceClock.h" +#include "ServiceBroker.h" +#include "utils/MathUtils.h" +#include "utils/log.h" +#include "utils/TimeUtils.h" +#include "threads/SingleLock.h" +#include "guilib/GraphicContext.h" +#include "settings/Settings.h" +#include "windowing/VideoSync.h" +#include "windowing/WindowingFactory.h" + +CVideoReferenceClock::CVideoReferenceClock() : CThread("RefClock") +{ + m_SystemFrequency = CurrentHostFrequency(); + m_ClockSpeed = 1.0; + m_ClockOffset = 0; + m_TotalMissedVblanks = 0; + m_UseVblank = false; + + m_CurrTime = 0; + m_LastIntTime = 0; + m_CurrTimeFract = 0.0; + m_RefreshRate = 0.0; + m_MissedVblanks = 0; + m_VblankTime = 0; + + Start(); +} + +CVideoReferenceClock::~CVideoReferenceClock() +{ + StopThread(); +} + +void CVideoReferenceClock::Start() +{ + m_ClockOffset = CurrentHostCounter(); + if(CServiceBroker::GetSettings().GetBool(CSettings::SETTING_VIDEOPLAYER_USEDISPLAYASCLOCK) && !IsRunning()) + Create(); +} + +void CVideoReferenceClock::CBUpdateClock(int NrVBlanks, uint64_t time, void *clock) +{ + { + CVideoReferenceClock *refClock = static_cast(clock); + CSingleLock lock(refClock->m_CritSection); + refClock->m_VblankTime = time; + refClock->UpdateClock(NrVBlanks, true); + } +} + +void CVideoReferenceClock::Process() +{ + bool SetupSuccess = false; + int64_t Now; + + while(!m_bStop) + { + m_pVideoSync = g_Windowing.GetVideoSync(this); + + if (m_pVideoSync) + { + SetupSuccess = m_pVideoSync->Setup(CBUpdateClock); + UpdateRefreshrate(); + } + + CSingleLock SingleLock(m_CritSection); + Now = CurrentHostCounter(); + m_CurrTime = Now + m_ClockOffset; //add the clock offset from the previous time we stopped + m_LastIntTime = m_CurrTime; + m_CurrTimeFract = 0.0; + m_ClockSpeed = 1.0; + m_TotalMissedVblanks = 0; + m_MissedVblanks = 0; + + if (SetupSuccess) + { + m_UseVblank = true; //tell other threads we're using vblank as clock + m_VblankTime = Now; //initialize the timestamp of the last vblank + SingleLock.Leave(); + + //run the clock + m_pVideoSync->Run(m_bStop); + } + else + { + SingleLock.Leave(); + CLog::Log(LOGDEBUG, "CVideoReferenceClock: Setup failed, falling back to CurrentHostCounter()"); + } + + SingleLock.Enter(); + m_UseVblank = false; //we're back to using the systemclock + Now = CurrentHostCounter(); //set the clockoffset between the vblank clock and systemclock + m_ClockOffset = m_CurrTime - Now; + SingleLock.Leave(); + + //clean up the vblank clock + if (m_pVideoSync) + { + m_pVideoSync->Cleanup(); + m_pVideoSync.reset(); + } + + if (!SetupSuccess) + break; + } +} + +//this is called from the vblank run function and from CVideoReferenceClock::Wait in case of a late update +void CVideoReferenceClock::UpdateClock(int NrVBlanks, bool CheckMissed) +{ + if (CheckMissed) //set to true from the vblank run function, set to false from Wait and GetTime + { + if (NrVBlanks < m_MissedVblanks) //if this is true the vblank detection in the run function is wrong + CLog::Log(LOGDEBUG, "CVideoReferenceClock: detected %i vblanks, missed %i, refreshrate might have changed", + NrVBlanks, m_MissedVblanks); + + NrVBlanks -= m_MissedVblanks; //subtract the vblanks we missed + m_MissedVblanks = 0; + } + else + { + m_MissedVblanks += NrVBlanks; //tell the vblank clock how many vblanks it missed + m_TotalMissedVblanks += NrVBlanks; //for the codec information screen + m_VblankTime += m_SystemFrequency * static_cast(NrVBlanks) / MathUtils::round_int(m_RefreshRate); //set the vblank time forward + } + + if (NrVBlanks > 0) //update the clock with the adjusted frequency if we have any vblanks + { + double increment = UpdateInterval() * NrVBlanks; + double integer = floor(increment); + m_CurrTime += static_cast(integer + 0.5); //make sure it gets correctly converted to int + + //accumulate what we lost due to rounding in m_CurrTimeFract, then add the integer part of that to m_CurrTime + m_CurrTimeFract += increment - integer; + integer = floor(m_CurrTimeFract); + m_CurrTime += static_cast(integer + 0.5); + m_CurrTimeFract -= integer; + } +} + +double CVideoReferenceClock::UpdateInterval() const +{ + return m_ClockSpeed / m_RefreshRate * static_cast(m_SystemFrequency); +} + +//called from dvdclock to get the time +int64_t CVideoReferenceClock::GetTime(bool interpolated /* = true*/) +{ + CSingleLock SingleLock(m_CritSection); + + //when using vblank, get the time from that, otherwise use the systemclock + if (m_UseVblank) + { + int64_t NextVblank; + int64_t Now; + + Now = CurrentHostCounter(); //get current system time + NextVblank = TimeOfNextVblank(); //get time when the next vblank should happen + + while(Now >= NextVblank) //keep looping until the next vblank is in the future + { + UpdateClock(1, false); //update clock when next vblank should have happened already + NextVblank = TimeOfNextVblank(); //get time when the next vblank should happen + } + + if (interpolated) + { + //interpolate from the last time the clock was updated + double elapsed = static_cast(Now - m_VblankTime) * m_ClockSpeed; + //don't interpolate more than 2 vblank periods + elapsed = std::min(elapsed, UpdateInterval() * 2.0); + + //make sure the clock doesn't go backwards + int64_t intTime = m_CurrTime + static_cast(elapsed); + if (intTime > m_LastIntTime) + m_LastIntTime = intTime; + + return m_LastIntTime; + } + else + { + return m_CurrTime; + } + } + else + { + return CurrentHostCounter() + m_ClockOffset; + } +} + +void CVideoReferenceClock::SetSpeed(double Speed) +{ + CSingleLock SingleLock(m_CritSection); + //VideoPlayer can change the speed to fit the rereshrate + if (m_UseVblank) + { + if (Speed != m_ClockSpeed) + { + m_ClockSpeed = Speed; + CLog::Log(LOGDEBUG, "CVideoReferenceClock: Clock speed %f%%", m_ClockSpeed * 100.0); + } + } +} + +double CVideoReferenceClock::GetSpeed() +{ + CSingleLock SingleLock(m_CritSection); + + //VideoPlayer needs to know the speed for the resampler + if (m_UseVblank) + return m_ClockSpeed; + else + return 1.0; +} + +void CVideoReferenceClock::UpdateRefreshrate() +{ + CSingleLock SingleLock(m_CritSection); + m_RefreshRate = m_pVideoSync->GetFps(); + m_ClockSpeed = 1.0; + + CLog::Log(LOGDEBUG, "CVideoReferenceClock: Detected refreshrate: %.3f hertz", m_RefreshRate); +} + +//VideoPlayer needs to know the refreshrate for matching the fps of the video playing to it +double CVideoReferenceClock::GetRefreshRate(double* interval /*= NULL*/) +{ + CSingleLock SingleLock(m_CritSection); + + if (m_UseVblank) + { + if (interval) + *interval = m_ClockSpeed / m_RefreshRate; + + return m_RefreshRate; + } + else + return -1; +} + +#define MAXVBLANKDELAY 13LL +//guess when the next vblank should happen, +//based on the refreshrate and when the previous one happened +//increase that by 30% to allow for errors +int64_t CVideoReferenceClock::TimeOfNextVblank() const +{ + return m_VblankTime + (m_SystemFrequency / MathUtils::round_int(m_RefreshRate) * MAXVBLANKDELAY / 10LL); +} + +//for the codec information screen +bool CVideoReferenceClock::GetClockInfo(int& MissedVblanks, double& ClockSpeed, double& RefreshRate) const +{ + CSingleLock SingleLock(m_CritSection); + + if (m_UseVblank) + { + MissedVblanks = m_TotalMissedVblanks; + ClockSpeed = m_ClockSpeed; + RefreshRate = m_RefreshRate; + return true; + } + return false; +} diff --git a/xbmc/cores/VideoPlayer/VideoReferenceClock.h b/xbmc/cores/VideoPlayer/VideoReferenceClock.h new file mode 100644 index 0000000000..00f58bf7ec --- /dev/null +++ b/xbmc/cores/VideoPlayer/VideoReferenceClock.h @@ -0,0 +1,65 @@ +#pragma once +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include "threads/Thread.h" +#include "threads/CriticalSection.h" +#include + +class CVideoSync; + +class CVideoReferenceClock : public CThread +{ + public: + CVideoReferenceClock(); + virtual ~CVideoReferenceClock(); + + int64_t GetTime(bool interpolated = true); + void SetSpeed(double Speed); + double GetSpeed(); + double GetRefreshRate(double* interval = nullptr); + bool GetClockInfo(int& MissedVblanks, double& ClockSpeed, double& RefreshRate) const; + + private: + void Process() override; + void Start(); + void UpdateRefreshrate(); + void UpdateClock(int NrVBlanks, bool CheckMissed); + double UpdateInterval() const; + int64_t TimeOfNextVblank() const; + static void CBUpdateClock(int NrVBlanks, uint64_t time, void *clock); + + int64_t m_CurrTime; //the current time of the clock when using vblank as clock source + int64_t m_LastIntTime; //last interpolated clock value, to make sure the clock doesn't go backwards + double m_CurrTimeFract; //fractional part that is lost due to rounding when updating the clock + double m_ClockSpeed; //the frequency of the clock set by VideoPlayer + int64_t m_ClockOffset; //the difference between the vblank clock and systemclock, set when vblank clock is stopped + int64_t m_SystemFrequency; //frequency of the systemclock + + bool m_UseVblank; //set to true when vblank is used as clock source + double m_RefreshRate; //current refreshrate + int m_MissedVblanks; //number of clock updates missed by the vblank clock + int m_TotalMissedVblanks;//total number of clock updates missed, used by codec information screen + int64_t m_VblankTime; //last time the clock was updated when using vblank as clock + + CCriticalSection m_CritSection; + + std::unique_ptr m_pVideoSync; +}; diff --git a/xbmc/platform/darwin/ios/XBMCController.mm b/xbmc/platform/darwin/ios/XBMCController.mm index 380537e944..2d6b85fe56 100644 --- a/xbmc/platform/darwin/ios/XBMCController.mm +++ b/xbmc/platform/darwin/ios/XBMCController.mm @@ -37,7 +37,6 @@ #include "guilib/GUIControl.h" #include "input/Key.h" #include "windowing/WindowingFactory.h" -#include "video/VideoReferenceClock.h" #include "utils/log.h" #include "utils/TimeUtils.h" #include "Util.h" diff --git a/xbmc/video/CMakeLists.txt b/xbmc/video/CMakeLists.txt index 9842fce0aa..c3ee3d7554 100644 --- a/xbmc/video/CMakeLists.txt +++ b/xbmc/video/CMakeLists.txt @@ -9,7 +9,6 @@ set(SOURCES Bookmark.cpp VideoInfoScanner.cpp VideoInfoTag.cpp VideoLibraryQueue.cpp - VideoReferenceClock.cpp VideoThumbLoader.cpp ViewModeSettings.cpp) @@ -26,7 +25,6 @@ set(HEADERS Bookmark.h VideoInfoScanner.h VideoInfoTag.h VideoLibraryQueue.h - VideoReferenceClock.h VideoThumbLoader.h) core_add_library(video) diff --git a/xbmc/video/VideoReferenceClock.cpp b/xbmc/video/VideoReferenceClock.cpp deleted file mode 100644 index 2d85839d23..0000000000 --- a/xbmc/video/VideoReferenceClock.cpp +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright (C) 2005-2013 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ -#include "VideoReferenceClock.h" -#include "ServiceBroker.h" -#include "utils/MathUtils.h" -#include "utils/log.h" -#include "utils/TimeUtils.h" -#include "threads/SingleLock.h" -#include "guilib/GraphicContext.h" -#include "video/videosync/VideoSync.h" -#include "settings/Settings.h" - -#if defined(HAS_GLX) -#include "video/videosync/VideoSyncGLX.h" -#endif -#if defined(HAVE_X11) -#include "video/videosync/VideoSyncDRM.h" -#include "windowing/WindowingFactory.h" -#elif defined(TARGET_RASPBERRY_PI) -#include "video/videosync/VideoSyncPi.h" -#elif defined(HAS_IMXVPU) -#include "video/videosync/VideoSyncIMX.h" -#endif -#if defined(TARGET_WINDOWS) -#include "video/videosync/VideoSyncD3D.h" -#endif -#if defined(TARGET_DARWIN_OSX) -#include "video/videosync/VideoSyncOsx.h" -#endif -#if defined(TARGET_DARWIN_IOS) -#include "video/videosync/VideoSyncIos.h" -#endif -#if defined(TARGET_ANDROID) -#include "video/videosync/VideoSyncAndroid.h" -#endif -#if defined(HAS_LIBAMCODEC) -#include "video/videosync/VideoSyncAML.h" -#endif - -#ifdef TARGET_POSIX -#include "linux/XTimeUtils.h" -#endif - -CVideoReferenceClock::CVideoReferenceClock() : CThread("RefClock") -{ - m_SystemFrequency = CurrentHostFrequency(); - m_ClockSpeed = 1.0; - m_ClockOffset = 0; - m_TotalMissedVblanks = 0; - m_UseVblank = false; - - m_CurrTime = 0; - m_LastIntTime = 0; - m_CurrTimeFract = 0.0; - m_RefreshRate = 0.0; - m_MissedVblanks = 0; - m_VblankTime = 0; - - m_pVideoSync = nullptr; - - Start(); -} - -CVideoReferenceClock::~CVideoReferenceClock() -{ - StopThread(); -} - -void CVideoReferenceClock::Start() -{ - m_ClockOffset = CurrentHostCounter(); - if(CServiceBroker::GetSettings().GetBool(CSettings::SETTING_VIDEOPLAYER_USEDISPLAYASCLOCK) && !IsRunning()) - Create(); -} - -void CVideoReferenceClock::CBUpdateClock(int NrVBlanks, uint64_t time, CVideoReferenceClock *clock) -{ - { - CSingleLock lock(clock->m_CritSection); - clock->m_VblankTime = time; - clock->UpdateClock(NrVBlanks, true); - } -} - -void CVideoReferenceClock::Process() -{ - bool SetupSuccess = false; - int64_t Now; - - while(!m_bStop) - { - //set up the vblank clock -#if defined(HAVE_X11) - std::string gpuvendor = g_Windowing.GetRenderVendor(); - std::transform(gpuvendor.begin(), gpuvendor.end(), gpuvendor.begin(), ::tolower); - if ((gpuvendor.compare(0, 5, "intel") == 0 || - gpuvendor.compare(0, 5, "x.org") == 0)) // AMD - m_pVideoSync = new CVideoSyncDRM(this); -#if defined(HAS_GLX) - else - m_pVideoSync = new CVideoSyncGLX(this); -#endif -#elif defined(TARGET_WINDOWS) - m_pVideoSync = new CVideoSyncD3D(this); -#elif defined(TARGET_DARWIN_OSX) - m_pVideoSync = new CVideoSyncOsx(this); -#elif defined(TARGET_DARWIN_IOS) - m_pVideoSync = new CVideoSyncIos(this); -#elif defined(TARGET_RASPBERRY_PI) - m_pVideoSync = new CVideoSyncPi(this); -#elif defined(HAS_IMXVPU) - m_pVideoSync = new CVideoSyncIMX(this); -#elif defined(TARGET_ANDROID) - m_pVideoSync = new CVideoSyncAndroid(this); -#elif defined(HAS_LIBAMCODEC) - m_pVideoSync = new CVideoSyncAML(this); -#endif - - if (m_pVideoSync) - { - SetupSuccess = m_pVideoSync->Setup(CBUpdateClock); - UpdateRefreshrate(); - } - - CSingleLock SingleLock(m_CritSection); - Now = CurrentHostCounter(); - m_CurrTime = Now + m_ClockOffset; //add the clock offset from the previous time we stopped - m_LastIntTime = m_CurrTime; - m_CurrTimeFract = 0.0; - m_ClockSpeed = 1.0; - m_TotalMissedVblanks = 0; - m_MissedVblanks = 0; - - if (SetupSuccess) - { - m_UseVblank = true; //tell other threads we're using vblank as clock - m_VblankTime = Now; //initialize the timestamp of the last vblank - SingleLock.Leave(); - - //run the clock - m_pVideoSync->Run(m_bStop); - } - else - { - SingleLock.Leave(); - CLog::Log(LOGDEBUG, "CVideoReferenceClock: Setup failed, falling back to CurrentHostCounter()"); - } - - SingleLock.Enter(); - m_UseVblank = false; //we're back to using the systemclock - Now = CurrentHostCounter(); //set the clockoffset between the vblank clock and systemclock - m_ClockOffset = m_CurrTime - Now; - SingleLock.Leave(); - - //clean up the vblank clock - if (m_pVideoSync) - { - m_pVideoSync->Cleanup(); - delete m_pVideoSync; - m_pVideoSync = nullptr; - } - - if (!SetupSuccess) - break; - } -} - -//this is called from the vblank run function and from CVideoReferenceClock::Wait in case of a late update -void CVideoReferenceClock::UpdateClock(int NrVBlanks, bool CheckMissed) -{ - if (CheckMissed) //set to true from the vblank run function, set to false from Wait and GetTime - { - if (NrVBlanks < m_MissedVblanks) //if this is true the vblank detection in the run function is wrong - CLog::Log(LOGDEBUG, "CVideoReferenceClock: detected %i vblanks, missed %i, refreshrate might have changed", - NrVBlanks, m_MissedVblanks); - - NrVBlanks -= m_MissedVblanks; //subtract the vblanks we missed - m_MissedVblanks = 0; - } - else - { - m_MissedVblanks += NrVBlanks; //tell the vblank clock how many vblanks it missed - m_TotalMissedVblanks += NrVBlanks; //for the codec information screen - m_VblankTime += m_SystemFrequency * static_cast(NrVBlanks) / MathUtils::round_int(m_RefreshRate); //set the vblank time forward - } - - if (NrVBlanks > 0) //update the clock with the adjusted frequency if we have any vblanks - { - double increment = UpdateInterval() * NrVBlanks; - double integer = floor(increment); - m_CurrTime += static_cast(integer + 0.5); //make sure it gets correctly converted to int - - //accumulate what we lost due to rounding in m_CurrTimeFract, then add the integer part of that to m_CurrTime - m_CurrTimeFract += increment - integer; - integer = floor(m_CurrTimeFract); - m_CurrTime += static_cast(integer + 0.5); - m_CurrTimeFract -= integer; - } -} - -double CVideoReferenceClock::UpdateInterval() const -{ - return m_ClockSpeed / m_RefreshRate * static_cast(m_SystemFrequency); -} - -//called from dvdclock to get the time -int64_t CVideoReferenceClock::GetTime(bool interpolated /* = true*/) -{ - CSingleLock SingleLock(m_CritSection); - - //when using vblank, get the time from that, otherwise use the systemclock - if (m_UseVblank) - { - int64_t NextVblank; - int64_t Now; - - Now = CurrentHostCounter(); //get current system time - NextVblank = TimeOfNextVblank(); //get time when the next vblank should happen - - while(Now >= NextVblank) //keep looping until the next vblank is in the future - { - UpdateClock(1, false); //update clock when next vblank should have happened already - NextVblank = TimeOfNextVblank(); //get time when the next vblank should happen - } - - if (interpolated) - { - //interpolate from the last time the clock was updated - double elapsed = static_cast(Now - m_VblankTime) * m_ClockSpeed; - //don't interpolate more than 2 vblank periods - elapsed = std::min(elapsed, UpdateInterval() * 2.0); - - //make sure the clock doesn't go backwards - int64_t intTime = m_CurrTime + static_cast(elapsed); - if (intTime > m_LastIntTime) - m_LastIntTime = intTime; - - return m_LastIntTime; - } - else - { - return m_CurrTime; - } - } - else - { - return CurrentHostCounter() + m_ClockOffset; - } -} - -void CVideoReferenceClock::SetSpeed(double Speed) -{ - CSingleLock SingleLock(m_CritSection); - //VideoPlayer can change the speed to fit the rereshrate - if (m_UseVblank) - { - if (Speed != m_ClockSpeed) - { - m_ClockSpeed = Speed; - CLog::Log(LOGDEBUG, "CVideoReferenceClock: Clock speed %f%%", m_ClockSpeed * 100.0); - } - } -} - -double CVideoReferenceClock::GetSpeed() -{ - CSingleLock SingleLock(m_CritSection); - - //VideoPlayer needs to know the speed for the resampler - if (m_UseVblank) - return m_ClockSpeed; - else - return 1.0; -} - -void CVideoReferenceClock::UpdateRefreshrate() -{ - CSingleLock SingleLock(m_CritSection); - m_RefreshRate = m_pVideoSync->GetFps(); - m_ClockSpeed = 1.0; - - CLog::Log(LOGDEBUG, "CVideoReferenceClock: Detected refreshrate: %.3f hertz", m_RefreshRate); -} - -//VideoPlayer needs to know the refreshrate for matching the fps of the video playing to it -double CVideoReferenceClock::GetRefreshRate(double* interval /*= NULL*/) -{ - CSingleLock SingleLock(m_CritSection); - - if (m_UseVblank) - { - if (interval) - *interval = m_ClockSpeed / m_RefreshRate; - - return m_RefreshRate; - } - else - return -1; -} - -#define MAXVBLANKDELAY 13LL -//guess when the next vblank should happen, -//based on the refreshrate and when the previous one happened -//increase that by 30% to allow for errors -int64_t CVideoReferenceClock::TimeOfNextVblank() const -{ - return m_VblankTime + (m_SystemFrequency / MathUtils::round_int(m_RefreshRate) * MAXVBLANKDELAY / 10LL); -} - -//for the codec information screen -bool CVideoReferenceClock::GetClockInfo(int& MissedVblanks, double& ClockSpeed, double& RefreshRate) const -{ - CSingleLock SingleLock(m_CritSection); - - if (m_UseVblank) - { - MissedVblanks = m_TotalMissedVblanks; - ClockSpeed = m_ClockSpeed; - RefreshRate = m_RefreshRate; - return true; - } - return false; -} diff --git a/xbmc/video/VideoReferenceClock.h b/xbmc/video/VideoReferenceClock.h deleted file mode 100644 index 659e4269a2..0000000000 --- a/xbmc/video/VideoReferenceClock.h +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once -/* - * Copyright (C) 2005-2013 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#include "threads/Thread.h" -#include "threads/CriticalSection.h" - -class CVideoSync; - -class CVideoReferenceClock : public CThread -{ - public: - CVideoReferenceClock(); - virtual ~CVideoReferenceClock(); - - int64_t GetTime(bool interpolated = true); - void SetSpeed(double Speed); - double GetSpeed(); - double GetRefreshRate(double* interval = nullptr); - bool GetClockInfo(int& MissedVblanks, double& ClockSpeed, double& RefreshRate) const; - - private: - void Process() override; - void Start(); - void UpdateRefreshrate(); - void UpdateClock(int NrVBlanks, bool CheckMissed); - double UpdateInterval() const; - int64_t TimeOfNextVblank() const; - static void CBUpdateClock(int NrVBlanks, uint64_t time, CVideoReferenceClock *clock); - - int64_t m_CurrTime; //the current time of the clock when using vblank as clock source - int64_t m_LastIntTime; //last interpolated clock value, to make sure the clock doesn't go backwards - double m_CurrTimeFract; //fractional part that is lost due to rounding when updating the clock - double m_ClockSpeed; //the frequency of the clock set by VideoPlayer - int64_t m_ClockOffset; //the difference between the vblank clock and systemclock, set when vblank clock is stopped - int64_t m_SystemFrequency; //frequency of the systemclock - - bool m_UseVblank; //set to true when vblank is used as clock source - double m_RefreshRate; //current refreshrate - int m_MissedVblanks; //number of clock updates missed by the vblank clock - int m_TotalMissedVblanks;//total number of clock updates missed, used by codec information screen - int64_t m_VblankTime; //last time the clock was updated when using vblank as clock - - CCriticalSection m_CritSection; - - CVideoSync *m_pVideoSync; -}; diff --git a/xbmc/video/videosync/CMakeLists.txt b/xbmc/video/videosync/CMakeLists.txt deleted file mode 100644 index 177c656ea6..0000000000 --- a/xbmc/video/videosync/CMakeLists.txt +++ /dev/null @@ -1,50 +0,0 @@ -set(HEADERS VideoSync.h) - -if(OPENGL_FOUND) - list(APPEND SOURCES VideoSyncGLX.cpp) - list(APPEND HEADERS VideoSyncGLX.h) -endif() - -if(X_FOUND) - list(APPEND SOURCES VideoSyncDRM.cpp) - list(APPEND HEADERS VideoSyncDRM.h) -endif() - -if(CORE_SYSTEM_NAME STREQUAL windows) - list(APPEND SOURCES VideoSyncD3D.cpp) - list(APPEND HEADERS VideoSyncD3D.h) -endif() - -if(CORE_SYSTEM_NAME STREQUAL rbpi) - list(APPEND SOURCES VideoSyncPi.cpp) - list(APPEND HEADERS VideoSyncPi.h) -endif() - -if(CORE_SYSTEM_NAME STREQUAL osx) - list(APPEND SOURCES VideoSyncOsx.cpp) - list(APPEND HEADERS VideoSyncOsx.h) -endif() - -if(CORE_SYSTEM_NAME STREQUAL ios) - list(APPEND SOURCES VideoSyncIos.cpp) - list(APPEND HEADERS VideoSyncIos.h) -endif() - -if(CORE_SYSTEM_NAME STREQUAL android) - list(APPEND SOURCES VideoSyncAndroid.cpp) - list(APPEND HEADERS VideoSyncAndroid.h) -endif() - -if(IMX_FOUND) - list(APPEND SOURCES VideoSyncIMX.cpp) - list(APPEND HEADERS VideoSyncIMX.h) -endif() - -if(AML_FOUND) - list(APPEND SOURCES VideoSyncAML.cpp) - list(APPEND HEADERS VideoSyncAML.h) -endif() - -if(SOURCES AND HEADERS) - core_add_library(video_sync) -endif() diff --git a/xbmc/video/videosync/VideoSync.h b/xbmc/video/videosync/VideoSync.h deleted file mode 100644 index a430cb029f..0000000000 --- a/xbmc/video/videosync/VideoSync.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -/* - * Copyright (C) 2005-2014 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ -#include - -class CVideoReferenceClock; -typedef void (*PUPDATECLOCK)(int NrVBlanks, uint64_t time, CVideoReferenceClock *clock); - -class CVideoSync -{ -public: - CVideoSync(CVideoReferenceClock *clock) { m_refClock = clock; }; - virtual ~CVideoSync() {}; - virtual bool Setup(PUPDATECLOCK func) = 0; - virtual void Run(std::atomic& stop) = 0; - virtual void Cleanup() = 0; - virtual float GetFps() = 0; - virtual void RefreshChanged() {}; -protected: - PUPDATECLOCK UpdateClock; - float m_fps; - CVideoReferenceClock *m_refClock; -}; diff --git a/xbmc/video/videosync/VideoSyncAML.cpp b/xbmc/video/videosync/VideoSyncAML.cpp deleted file mode 100644 index cd8559e94d..0000000000 --- a/xbmc/video/videosync/VideoSyncAML.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2017 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#include "system.h" - -#if defined(HAS_LIBAMCODEC) - -#include "video/videosync/VideoSyncAML.h" -#include "guilib/GraphicContext.h" -#include "windowing/WindowingFactory.h" -#include "utils/TimeUtils.h" -#include "utils/log.h" -#include "threads/Thread.h" -#include - -#include -#include - -extern CEvent g_aml_sync_event; - -CVideoSyncAML::CVideoSyncAML(CVideoReferenceClock *clock) -: CVideoSync(clock) -, m_abort(false) -{ -} - -CVideoSyncAML::~CVideoSyncAML() -{ -} - -bool CVideoSyncAML::Setup(PUPDATECLOCK func) -{ - UpdateClock = func; - - m_abort = false; - - g_Windowing.Register(this); - CLog::Log(LOGDEBUG, "CVideoReferenceClock: setting up AML"); - - return true; -} - -void CVideoSyncAML::Run(std::atomic& stop) -{ - // We use the wall clock for timout handling (no AML h/w, startup) - std::chrono::time_point now(std::chrono::system_clock::now()); - unsigned int waittime (3000 / m_fps); - uint64_t numVBlanks (0); - - while (!stop && !m_abort) - { - int countVSyncs(1); - if( !g_aml_sync_event.WaitMSec(waittime)) - { - std::chrono::milliseconds elapsed(std::chrono::duration_cast(std::chrono::system_clock::now() - now).count()); - uint64_t curVBlanks = (m_fps * elapsed.count()) / 1000; - int64_t lastVBlankTime((curVBlanks * 1000) / m_fps); - if (elapsed.count() > lastVBlankTime) - { - lastVBlankTime = (++curVBlanks * 1000) / m_fps; - std::this_thread::sleep_for(std::chrono::milliseconds(lastVBlankTime - elapsed.count())); - } - countVSyncs = curVBlanks - numVBlanks; - numVBlanks = curVBlanks; - } - else - ++numVBlanks; - - uint64_t now = CurrentHostCounter(); - - UpdateClock(countVSyncs, now, m_refClock); - } -} - -void CVideoSyncAML::Cleanup() -{ - CLog::Log(LOGDEBUG, "CVideoReferenceClock: cleaning up AML"); - g_Windowing.Unregister(this); -} - -float CVideoSyncAML::GetFps() -{ - m_fps = g_graphicsContext.GetFPS(); - CLog::Log(LOGDEBUG, "CVideoReferenceClock: fps: %.3f", m_fps); - return m_fps; -} - -void CVideoSyncAML::OnResetDisplay() -{ - m_abort = true; -} - -#endif diff --git a/xbmc/video/videosync/VideoSyncAML.h b/xbmc/video/videosync/VideoSyncAML.h deleted file mode 100644 index f12230ea90..0000000000 --- a/xbmc/video/videosync/VideoSyncAML.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once -/* - * Copyright (C) 2017 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#if defined(HAS_LIBAMCODEC) - -#include "video/videosync/VideoSync.h" -#include "guilib/DispResource.h" - -class CVideoSyncAML : public CVideoSync, IDispResource -{ -public: - CVideoSyncAML(CVideoReferenceClock *clock); - virtual ~CVideoSyncAML(); - virtual bool Setup(PUPDATECLOCK func); - virtual void Run(std::atomic& stop); - virtual void Cleanup(); - virtual float GetFps(); - virtual void OnResetDisplay(); -private: - volatile bool m_abort; -}; - -#endif diff --git a/xbmc/video/videosync/VideoSyncAndroid.cpp b/xbmc/video/videosync/VideoSyncAndroid.cpp deleted file mode 100644 index 71d7906267..0000000000 --- a/xbmc/video/videosync/VideoSyncAndroid.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2015 Team Kodi - * http://kodi.tv - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#include "system.h" - -#if defined(TARGET_ANDROID) -#include "utils/log.h" -#include "VideoSyncAndroid.h" -#include "video/VideoReferenceClock.h" -#include "utils/TimeUtils.h" -#include "platform/android/activity/XBMCApp.h" -#include "windowing/WindowingFactory.h" -#include "guilib/GraphicContext.h" -#include "utils/MathUtils.h" -#include "linux/XTimeUtils.h" - - -bool CVideoSyncAndroid::Setup(PUPDATECLOCK func) -{ - CLog::Log(LOGDEBUG, "CVideoSyncAndroid::%s setting up", __FUNCTION__); - - //init the vblank timestamp - m_LastVBlankTime = CurrentHostCounter(); - UpdateClock = func; - m_abort = false; - - CXBMCApp::InitFrameCallback(this); - g_Windowing.Register(this); - - return true; -} - -void CVideoSyncAndroid::Run(std::atomic& stop) -{ - while(!stop && !m_abort) - { - Sleep(100); - } -} - -void CVideoSyncAndroid::Cleanup() -{ - CLog::Log(LOGDEBUG, "CVideoSyncAndroid::%s cleaning up", __FUNCTION__); - CXBMCApp::DeinitFrameCallback(); - g_Windowing.Unregister(this); -} - -float CVideoSyncAndroid::GetFps() -{ - m_fps = g_graphicsContext.GetFPS(); - CLog::Log(LOGDEBUG, "CVideoSyncAndroid::%s Detected refreshrate: %f hertz", __FUNCTION__, m_fps); - return m_fps; -} - -void CVideoSyncAndroid::OnResetDisplay() -{ - m_abort = true; -} - -void CVideoSyncAndroid::FrameCallback(int64_t frameTimeNanos) -{ - int NrVBlanks; - double VBlankTime; - int64_t nowtime = CurrentHostCounter(); - - //calculate how many vblanks happened - VBlankTime = (double)(nowtime - m_LastVBlankTime) / (double)CurrentHostFrequency(); - NrVBlanks = MathUtils::round_int(VBlankTime * m_fps); - - //save the timestamp of this vblank so we can calculate how many happened next time - m_LastVBlankTime = nowtime; - - //update the vblank timestamp, update the clock and send a signal that we got a vblank - UpdateClock(NrVBlanks, nowtime, m_refClock); -} - -#endif //TARGET_ANDROID diff --git a/xbmc/video/videosync/VideoSyncAndroid.h b/xbmc/video/videosync/VideoSyncAndroid.h deleted file mode 100644 index 803df561b2..0000000000 --- a/xbmc/video/videosync/VideoSyncAndroid.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once -/* - * Copyright (C) 2015 Team Kodi - * http://kodi.tv - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#if defined(TARGET_ANDROID) -#include "VideoSync.h" -#include "guilib/DispResource.h" - -class CVideoSyncAndroid : public CVideoSync, IDispResource -{ -public: - CVideoSyncAndroid(CVideoReferenceClock *clock) : CVideoSync(clock), m_LastVBlankTime(0), m_abort(false){} - - // CVideoSync interface - virtual bool Setup(PUPDATECLOCK func); - virtual void Run(std::atomic& stop); - virtual void Cleanup(); - virtual float GetFps(); - - // IDispResource interface - virtual void OnResetDisplay(); - - // Choreographer callback - void FrameCallback(int64_t frameTimeNanos); - -private: - int64_t m_LastVBlankTime; //timestamp of the last vblank, used for calculating how many vblanks happened - volatile bool m_abort; -}; - -#endif// TARGET_ANDROID diff --git a/xbmc/video/videosync/VideoSyncD3D.cpp b/xbmc/video/videosync/VideoSyncD3D.cpp deleted file mode 100644 index e48b91e121..0000000000 --- a/xbmc/video/videosync/VideoSyncD3D.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2005-2014 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#include "system.h" - -#if defined(TARGET_WINDOWS) - -#include "utils/log.h" -#include "Utils/TimeUtils.h" -#include "Utils/MathUtils.h" -#include "windowing\WindowingFactory.h" -#include "video/videosync/VideoSyncD3D.h" -#include "guilib/GraphicContext.h" -#include "platform/win32/dxerr.h" -#include "utils/StringUtils.h" - -void CVideoSyncD3D::OnLostDisplay() -{ - if (!m_displayLost) - { - m_displayLost = true; - m_lostEvent.Wait(); - } -} - -void CVideoSyncD3D::OnResetDisplay() -{ - m_displayReset = true; -} - -void CVideoSyncD3D::RefreshChanged() -{ - m_displayReset = true; -} - -bool CVideoSyncD3D::Setup(PUPDATECLOCK func) -{ - CLog::Log(LOGDEBUG, "CVideoSyncD3D: Setting up Direct3d"); - CSingleLock lock(g_graphicsContext); - g_Windowing.Register(this); - m_displayLost = false; - m_displayReset = false; - m_lostEvent.Reset(); - UpdateClock = func; - - // we need a high priority thread to get accurate timing - if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL)) - CLog::Log(LOGDEBUG, "CVideoSyncD3D: SetThreadPriority failed"); - - return true; -} - -void CVideoSyncD3D::Run(std::atomic& stop) -{ - int64_t Now; - int64_t LastVBlankTime; - int NrVBlanks; - double VBlankTime; - int64_t systemFrequency = CurrentHostFrequency(); - - // init the vblanktime - Now = CurrentHostCounter(); - LastVBlankTime = Now; - m_lastUpdateTime = Now - systemFrequency; - while (!stop && !m_displayLost && !m_displayReset) - { - // sleep until vblank - HRESULT hr = g_Windowing.GetCurrentOutput()->WaitForVBlank(); - - // calculate how many vblanks happened - Now = CurrentHostCounter(); - VBlankTime = (double)(Now - LastVBlankTime) / (double)systemFrequency; - NrVBlanks = MathUtils::round_int(VBlankTime * m_fps); - - // update the vblank timestamp, update the clock and send a signal that we got a vblank - UpdateClock(NrVBlanks, Now, m_refClock); - - // save the timestamp of this vblank so we can calculate how many vblanks happened next time - LastVBlankTime = Now; - - if ((Now - m_lastUpdateTime) >= systemFrequency) - { - float fps = m_fps; - if (fps != GetFps()) - break; - } - - // because we had a vblank, sleep until half the refreshrate period because i think WaitForVBlank block any rendering stuf - // without sleeping we have freeze rendering - int SleepTime = (int)((LastVBlankTime + (systemFrequency / MathUtils::round_int(m_fps) / 2) - Now) * 1000 / systemFrequency); - if (SleepTime > 50) - SleepTime = 50; //failsafe - if (SleepTime > 0) - ::Sleep(SleepTime); - } - - m_lostEvent.Set(); - while (!stop && m_displayLost && !m_displayReset) - { - Sleep(10); - } -} - -void CVideoSyncD3D::Cleanup() -{ - CLog::Log(LOGDEBUG, "CVideoSyncD3D: Cleaning up Direct3d"); - - m_lostEvent.Set(); - g_Windowing.Unregister(this); -} - -float CVideoSyncD3D::GetFps() -{ - DXGI_MODE_DESC DisplayMode; - g_Windowing.GetDisplayMode(&DisplayMode, true); - - m_fps = (DisplayMode.RefreshRate.Denominator != 0) ? (float)DisplayMode.RefreshRate.Numerator / (float)DisplayMode.RefreshRate.Denominator : 0.0f; - - if (m_fps == 0.0) - m_fps = 60.0f; - - if (m_fps == 23 || m_fps == 29 || m_fps == 59) - m_fps++; - - if (g_Windowing.Interlaced()) - { - m_fps *= 2; - } - return m_fps; -} - -std::string CVideoSyncD3D::GetErrorDescription(HRESULT hr) -{ - WCHAR buff[1024]; - DXGetErrorDescription(hr, buff, 1024); - std::wstring error(DXGetErrorString(hr)); - std::wstring descr(buff); - return StringUtils::Format("%ls: %ls", error.c_str(), descr.c_str()); -} - -#endif diff --git a/xbmc/video/videosync/VideoSyncD3D.h b/xbmc/video/videosync/VideoSyncD3D.h deleted file mode 100644 index 486b6206f6..0000000000 --- a/xbmc/video/videosync/VideoSyncD3D.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once -/* - * Copyright (C) 2005-2014 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#if defined(TARGET_WINDOWS) - -#include "video/videosync/VideoSync.h" -#include "guilib/DispResource.h" -#include "threads/Event.h" - -class CVideoSyncD3D : public CVideoSync, IDispResource -{ -public: - CVideoSyncD3D(CVideoReferenceClock *clock) : CVideoSync(clock) {}; - bool Setup(PUPDATECLOCK func) override; - void Run(std::atomic& stop) override; - void Cleanup() override; - float GetFps() override; - void RefreshChanged() override; - // IDispResource overrides - void OnLostDisplay() override; - void OnResetDisplay() override; - -private: - static std::string GetErrorDescription(HRESULT hr); - - volatile bool m_displayLost; - volatile bool m_displayReset; - CEvent m_lostEvent; - int64_t m_lastUpdateTime; -}; - -#endif diff --git a/xbmc/video/videosync/VideoSyncDRM.cpp b/xbmc/video/videosync/VideoSyncDRM.cpp deleted file mode 100644 index c86a7b771d..0000000000 --- a/xbmc/video/videosync/VideoSyncDRM.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2005-2014 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#include "system.h" - -#if defined(HAVE_X11) - -#include "video/videosync/VideoSyncDRM.h" -#include "xf86drm.h" -#include -#include -#include "utils/TimeUtils.h" -#include "utils/MathUtils.h" -#include "windowing/WindowingFactory.h" -#include "guilib/GraphicContext.h" -#include "utils/log.h" - -static drmVBlankSeqType CrtcSel(void) -{ - int crtc = g_Windowing.GetCrtc(); - int ret = 0; - - if (crtc == 1) - { - ret = DRM_VBLANK_SECONDARY; - } - else if (crtc > 1) - { - ret = (crtc << DRM_VBLANK_HIGH_CRTC_SHIFT) & DRM_VBLANK_HIGH_CRTC_MASK; - } - return (drmVBlankSeqType)ret; -} - -bool CVideoSyncDRM::Setup(PUPDATECLOCK func) -{ - CLog::Log(LOGDEBUG, "CVideoSyncDRM::%s - setting up DRM", __FUNCTION__); - - UpdateClock = func; - - m_fd = open("/dev/dri/card0", O_RDWR, 0); - if (m_fd < 0) - { - CLog::Log(LOGERROR, "CVideoSyncDRM::%s - can't open /dev/dri/card0", __FUNCTION__); - return false; - } - - drmVBlank vbl; - int ret; - vbl.request.type = (drmVBlankSeqType)(DRM_VBLANK_RELATIVE | CrtcSel()); - vbl.request.sequence = 0; - ret = drmWaitVBlank(m_fd, &vbl); - if (ret != 0) - { - CLog::Log(LOGERROR, "CVideoSyncDRM::%s - drmWaitVBlank returned error", __FUNCTION__); - return false; - } - - m_abort = false; - g_Windowing.Register(this); - - return true; -} - -void CVideoSyncDRM::Run(std::atomic& stop) -{ - drmVBlank vbl; - VblInfo info; - int ret; - drmVBlankSeqType crtcSel = CrtcSel(); - - vbl.request.type = (drmVBlankSeqType)(DRM_VBLANK_RELATIVE | crtcSel); - vbl.request.sequence = 0; - ret = drmWaitVBlank(m_fd, &vbl); - if (ret != 0) - { - CLog::Log(LOGERROR, "CVideoSyncDRM::%s - drmWaitVBlank returned error", __FUNCTION__); - return; - } - - info.start = CurrentHostCounter(); - info.videoSync = this; - - vbl.request.type = (drmVBlankSeqType)(DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT | crtcSel); - vbl.request.sequence = 1; - vbl.request.signal = (unsigned long)&info; - ret = drmWaitVBlank(m_fd, &vbl); - if (ret != 0) - { - CLog::Log(LOGERROR, "CVideoSyncDRM::%s - drmWaitVBlank returned error", __FUNCTION__); - return; - } - - drmEventContext evctx; - memset(&evctx, 0, sizeof evctx); - evctx.version = DRM_EVENT_CONTEXT_VERSION; - evctx.vblank_handler = EventHandler; - evctx.page_flip_handler = NULL; - - timeval timeout; - fd_set fds; - FD_ZERO(&fds); - FD_SET(m_fd, &fds); - - while (!stop && !m_abort) - { - timeout.tv_sec = 1; - timeout.tv_usec = 0; - ret = select(m_fd + 1, &fds, NULL, NULL, &timeout); - - if (ret <= 0) - { - continue; - } - - ret = drmHandleEvent(m_fd, &evctx); - if (ret != 0) - { - CLog::Log(LOGERROR, "CVideoSyncDRM::%s - drmHandleEvent returned error", __FUNCTION__); - break; - } - } -} - -void CVideoSyncDRM::Cleanup() -{ - close(m_fd); - g_Windowing.Unregister(this); -} - -void CVideoSyncDRM::EventHandler(int fd, unsigned int frame, unsigned int sec, - unsigned int usec, void *data) -{ - drmVBlank vbl; - VblInfo *info = (VblInfo*)data; - drmVBlankSeqType crtcSel = CrtcSel(); - - vbl.request.type = (drmVBlankSeqType)(DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT | crtcSel); - vbl.request.sequence = 1; - vbl.request.signal = (unsigned long)data; - - drmWaitVBlank(info->videoSync->m_fd, &vbl); - - uint64_t now = CurrentHostCounter(); - float diff = (float)(now - info->start)/CurrentHostFrequency(); - int vblanks = MathUtils::round_int(diff * info->videoSync->m_fps); - info->start = now; - - info->videoSync->UpdateClock(vblanks, now, info->videoSync->m_refClock); -} - -void CVideoSyncDRM::OnResetDisplay() -{ - m_abort = true; -} - -float CVideoSyncDRM::GetFps() -{ - m_fps = g_graphicsContext.GetFPS(); - return m_fps; -} - -void CVideoSyncDRM::RefreshChanged() -{ - if (m_fps != g_graphicsContext.GetFPS()) - m_abort = true; -} - -#endif diff --git a/xbmc/video/videosync/VideoSyncDRM.h b/xbmc/video/videosync/VideoSyncDRM.h deleted file mode 100644 index b6807171f3..0000000000 --- a/xbmc/video/videosync/VideoSyncDRM.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once -/* - * Copyright (C) 2005-2014 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#if defined(HAVE_X11) - -#include "video/videosync/VideoSync.h" -#include "guilib/DispResource.h" - -class CVideoSyncDRM : public CVideoSync, IDispResource -{ -public: - CVideoSyncDRM(CVideoReferenceClock *clock) : CVideoSync(clock) {}; - virtual bool Setup(PUPDATECLOCK func); - virtual void Run(std::atomic& stop); - virtual void Cleanup(); - virtual float GetFps(); - virtual void OnResetDisplay(); - virtual void RefreshChanged(); -private: - static void EventHandler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data); - int m_fd; - volatile bool m_abort; - struct VblInfo - { - uint64_t start; - CVideoSyncDRM *videoSync; - }; -}; - -#endif diff --git a/xbmc/video/videosync/VideoSyncGLX.cpp b/xbmc/video/videosync/VideoSyncGLX.cpp deleted file mode 100644 index fd28e007e3..0000000000 --- a/xbmc/video/videosync/VideoSyncGLX.cpp +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright (C) 2005-2014 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#include "system.h" - -#if defined(HAS_GLX) - -#include "video/videosync/VideoSyncGLX.h" -#include -#include -#include "windowing/WindowingFactory.h" -#include "guilib/GraphicContext.h" -#include "threads/SingleLock.h" -#include "utils/log.h" -#include "utils/TimeUtils.h" -#include - -#ifdef TARGET_POSIX -#include "linux/XTimeUtils.h" -#endif - -Display* CVideoSyncGLX::m_Dpy = NULL; - -void CVideoSyncGLX::OnLostDisplay() -{ - if (!m_displayLost) - { - m_displayLost = true; - m_lostEvent.Wait(); - } -} - -void CVideoSyncGLX::OnResetDisplay() -{ - m_displayReset = true; -} - -bool CVideoSyncGLX::Setup(PUPDATECLOCK func) -{ - CSingleLock lock(g_graphicsContext); - - m_glXWaitVideoSyncSGI = NULL; - m_glXGetVideoSyncSGI = NULL; - m_vInfo = NULL; - m_Window = 0; - m_Context = NULL; - UpdateClock = func; - - int singleBufferAttributes[] = { - GLX_RGBA, - GLX_RED_SIZE, 0, - GLX_GREEN_SIZE, 0, - GLX_BLUE_SIZE, 0, - None - }; - - int ReturnV, SwaMask; - unsigned int GlxTest; - XSetWindowAttributes Swa; - - m_vInfo = NULL; - m_Context = NULL; - m_Window = 0; - - CLog::Log(LOGDEBUG, "CVideoReferenceClock: Setting up GLX"); - - g_Windowing.Register(this); - - m_displayLost = false; - m_displayReset = false; - m_lostEvent.Reset(); - - if (!m_Dpy) - { - m_Dpy = XOpenDisplay(NULL); - if (!m_Dpy) - { - CLog::Log(LOGDEBUG, "CVideoReferenceClock: Unable to open display"); - return false; - } - } - - if (!glXQueryExtension(m_Dpy, NULL, NULL)) - { - CLog::Log(LOGDEBUG, "CVideoReferenceClock: X server does not support GLX"); - return false; - } - - bool ExtensionFound = false; - std::istringstream Extensions(glXQueryExtensionsString(m_Dpy, g_Windowing.GetCurrentScreen())); - std::string ExtensionStr; - - while (!ExtensionFound) - { - Extensions >> ExtensionStr; - if (Extensions.fail()) - break; - - if (ExtensionStr == "GLX_SGI_video_sync") - ExtensionFound = true; - } - - if (!ExtensionFound) - { - CLog::Log(LOGDEBUG, "CVideoReferenceClock: X server does not support GLX_SGI_video_sync"); - return false; - } - - m_vInfo = glXChooseVisual(m_Dpy, g_Windowing.GetCurrentScreen(), singleBufferAttributes); - if (!m_vInfo) - { - CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXChooseVisual returned NULL"); - return false; - } - - Swa.border_pixel = 0; - Swa.event_mask = StructureNotifyMask; - Swa.colormap = XCreateColormap(m_Dpy, g_Windowing.GetWindow(), m_vInfo->visual, AllocNone ); - SwaMask = CWBorderPixel | CWColormap | CWEventMask; - - m_Window = XCreateWindow(m_Dpy, g_Windowing.GetWindow(), 0, 0, 256, 256, 0, - m_vInfo->depth, InputOutput, m_vInfo->visual, SwaMask, &Swa); - - m_Context = glXCreateContext(m_Dpy, m_vInfo, NULL, True); - if (!m_Context) - { - CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXCreateContext returned NULL"); - return false; - } - - ReturnV = glXMakeCurrent(m_Dpy, m_Window, m_Context); - if (ReturnV != True) - { - CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXMakeCurrent returned %i", ReturnV); - return false; - } - - m_glXWaitVideoSyncSGI = (int (*)(int, int, unsigned int*))glXGetProcAddress((const GLubyte*)"glXWaitVideoSyncSGI"); - if (!m_glXWaitVideoSyncSGI) - { - CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXWaitVideoSyncSGI not found"); - return false; - } - - ReturnV = m_glXWaitVideoSyncSGI(2, 0, &GlxTest); - if (ReturnV) - { - CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXWaitVideoSyncSGI returned %i", ReturnV); - return false; - } - - m_glXGetVideoSyncSGI = (int (*)(unsigned int*))glXGetProcAddress((const GLubyte*)"glXGetVideoSyncSGI"); - if (!m_glXGetVideoSyncSGI) - { - CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXGetVideoSyncSGI not found"); - return false; - } - - ReturnV = m_glXGetVideoSyncSGI(&GlxTest); - if (ReturnV) - { - CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXGetVideoSyncSGI returned %i", ReturnV); - return false; - } - - return true; -} - -void CVideoSyncGLX::Run(std::atomic& stop) -{ - unsigned int PrevVblankCount; - unsigned int VblankCount; - int ReturnV; - bool IsReset = false; - int64_t Now; - - //get the current vblank counter - m_glXGetVideoSyncSGI(&VblankCount); - PrevVblankCount = VblankCount; - - while(!stop && !m_displayLost && !m_displayReset) - { - //wait for the next vblank - ReturnV = m_glXWaitVideoSyncSGI(2, (VblankCount + 1) % 2, &VblankCount); - m_glXGetVideoSyncSGI(&VblankCount); //the vblank count returned by glXWaitVideoSyncSGI is not always correct - Now = CurrentHostCounter(); //get the timestamp of this vblank - - if(ReturnV) - { - CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXWaitVideoSyncSGI returned %i", ReturnV); - return; - } - - if (VblankCount > PrevVblankCount) - { - UpdateClock((int)(VblankCount - PrevVblankCount), Now, m_refClock); - IsReset = false; - } - else - { - CLog::Log(LOGDEBUG, "CVideoReferenceClock: Vblank counter has reset"); - - //only try reattaching once - if (IsReset) - return; - - //because of a bug in the nvidia driver, glXWaitVideoSyncSGI breaks when the vblank counter resets - CLog::Log(LOGDEBUG, "CVideoReferenceClock: Detaching glX context"); - ReturnV = glXMakeCurrent(m_Dpy, None, NULL); - if (ReturnV != True) - { - CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXMakeCurrent returned %i", ReturnV); - return; - } - - //sleep here so we don't busy spin when this constantly happens, for example when the display went to sleep - Sleep(1000); - - CLog::Log(LOGDEBUG, "CVideoReferenceClock: Attaching glX context"); - ReturnV = glXMakeCurrent(m_Dpy, m_Window, m_Context); - if (ReturnV != True) - { - CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXMakeCurrent returned %i", ReturnV); - return; - } - - m_glXGetVideoSyncSGI(&VblankCount); - - IsReset = true; - } - PrevVblankCount = VblankCount; - } - m_lostEvent.Set(); - while(!stop && m_displayLost && !m_displayReset) - { - Sleep(10); - } -} - -void CVideoSyncGLX::Cleanup() -{ - CLog::Log(LOGDEBUG, "CVideoReferenceClock: Cleaning up GLX"); - - { - CSingleLock lock(g_graphicsContext); - - if (m_vInfo) - { - XFree(m_vInfo); - m_vInfo = NULL; - } - if (m_Context) - { - glXMakeCurrent(m_Dpy, None, NULL); - glXDestroyContext(m_Dpy, m_Context); - m_Context = NULL; - } - if (m_Window) - { - XDestroyWindow(m_Dpy, m_Window); - m_Window = 0; - } - } - - m_lostEvent.Set(); - g_Windowing.Unregister(this); -} - -float CVideoSyncGLX::GetFps() -{ - m_fps = g_graphicsContext.GetFPS(); - return m_fps; -} - -#endif diff --git a/xbmc/video/videosync/VideoSyncGLX.h b/xbmc/video/videosync/VideoSyncGLX.h deleted file mode 100644 index 7d23c47f03..0000000000 --- a/xbmc/video/videosync/VideoSyncGLX.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once -/* - * Copyright (C) 2005-2014 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#if defined(HAS_GLX) - -#include "video/videosync/VideoSync.h" -#include "system_gl.h" -#include -#include -#include -#include "guilib/DispResource.h" -#include "threads/Event.h" - -class CVideoSyncGLX : public CVideoSync, IDispResource -{ -public: - CVideoSyncGLX(CVideoReferenceClock *clock) : CVideoSync(clock) {}; - virtual bool Setup(PUPDATECLOCK func); - virtual void Run(std::atomic& stop); - virtual void Cleanup(); - virtual float GetFps(); - virtual void OnLostDisplay(); - virtual void OnResetDisplay(); - -private: - int (*m_glXWaitVideoSyncSGI) (int, int, unsigned int*); - int (*m_glXGetVideoSyncSGI) (unsigned int*); - - static Display* m_Dpy; - XVisualInfo *m_vInfo; - Window m_Window; - GLXContext m_Context; - volatile bool m_displayLost; - volatile bool m_displayReset; - CEvent m_lostEvent; -}; - -#endif diff --git a/xbmc/video/videosync/VideoSyncIMX.cpp b/xbmc/video/videosync/VideoSyncIMX.cpp deleted file mode 100644 index fa7c27c4e5..0000000000 --- a/xbmc/video/videosync/VideoSyncIMX.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2005-2014 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#include "system.h" - -#if defined(HAS_IMXVPU) - -#include "video/videosync/VideoSyncIMX.h" -#include "guilib/GraphicContext.h" -#include "windowing/WindowingFactory.h" -#include "utils/TimeUtils.h" -#include "utils/log.h" -#include "linux/imx/IMX.h" - -CVideoSyncIMX::CVideoSyncIMX(CVideoReferenceClock *clock) : CVideoSync(clock) -{ - g_IMX.Initialize(); -} - -CVideoSyncIMX::~CVideoSyncIMX() -{ - g_IMX.Deinitialize(); -} - -bool CVideoSyncIMX::Setup(PUPDATECLOCK func) -{ - UpdateClock = func; - - m_abort = false; - - g_Windowing.Register(this); - CLog::Log(LOGDEBUG, "CVideoReferenceClock: setting up IMX"); - return true; -} - -void CVideoSyncIMX::Run(std::atomic& stop) -{ - int counter; - - while (!stop && !m_abort) - { - counter = g_IMX.WaitVsync(); - uint64_t now = CurrentHostCounter(); - - UpdateClock(counter, now, m_refClock); - } -} - -void CVideoSyncIMX::Cleanup() -{ - CLog::Log(LOGDEBUG, "CVideoReferenceClock: cleaning up IMX"); - g_Windowing.Unregister(this); -} - -float CVideoSyncIMX::GetFps() -{ - m_fps = g_graphicsContext.GetFPS(); - CLog::Log(LOGDEBUG, "CVideoReferenceClock: fps: %.3f", m_fps); - return m_fps; -} - -void CVideoSyncIMX::OnResetDisplay() -{ - m_abort = true; -} - -#endif diff --git a/xbmc/video/videosync/VideoSyncIMX.h b/xbmc/video/videosync/VideoSyncIMX.h deleted file mode 100644 index 7220ac60ba..0000000000 --- a/xbmc/video/videosync/VideoSyncIMX.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once -/* - * Copyright (C) 2005-2014 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#if defined(HAS_IMXVPU) - -#include "video/videosync/VideoSync.h" -#include "guilib/DispResource.h" - -class CVideoSyncIMX : public CVideoSync, IDispResource -{ -public: - CVideoSyncIMX(CVideoReferenceClock *clock); - virtual ~CVideoSyncIMX(); - virtual bool Setup(PUPDATECLOCK func); - virtual void Run(std::atomic& stop); - virtual void Cleanup(); - virtual float GetFps(); - virtual void OnResetDisplay(); -private: - volatile bool m_abort; -}; - -#endif diff --git a/xbmc/video/videosync/VideoSyncIos.cpp b/xbmc/video/videosync/VideoSyncIos.cpp deleted file mode 100644 index 026dd7ed91..0000000000 --- a/xbmc/video/videosync/VideoSyncIos.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2015 Team Kodi - * http://kodi.tv - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#include "system.h" - -#if defined(TARGET_DARWIN_IOS) -#include "utils/log.h" -#include "VideoSyncIos.h" -#include "utils/MathUtils.h" -#include "video/VideoReferenceClock.h" -#include "guilib/GraphicContext.h" -#include "windowing/WindowingFactory.h" -#include "utils/TimeUtils.h" - -bool CVideoSyncIos::Setup(PUPDATECLOCK func) -{ - CLog::Log(LOGDEBUG, "CVideoSyncIos::%s setting up OSX", __FUNCTION__); - - //init the vblank timestamp - m_LastVBlankTime = CurrentHostCounter(); - UpdateClock = func; - m_abort = false; - - bool setupOk = InitDisplayLink(); - if (setupOk) - { - g_Windowing.Register(this); - } - - return setupOk; -} - -void CVideoSyncIos::Run(std::atomic& stop) -{ - //because cocoa has a vblank callback, we just keep sleeping until we're asked to stop the thread - while(!stop && !m_abort) - { - usleep(100000); - } -} - -void CVideoSyncIos::Cleanup() -{ - CLog::Log(LOGDEBUG, "CVideoSyncIos::%s cleaning up OSX", __FUNCTION__); - DeinitDisplayLink(); - g_Windowing.Unregister(this); -} - -float CVideoSyncIos::GetFps() -{ - m_fps = g_graphicsContext.GetFPS(); - CLog::Log(LOGDEBUG, "CVideoSyncIos::%s Detected refreshrate: %f hertz", __FUNCTION__, m_fps); - return m_fps; -} - -void CVideoSyncIos::OnResetDisplay() -{ - m_abort = true; -} - -void CVideoSyncIos::IosVblankHandler() -{ - int NrVBlanks; - double VBlankTime; - int64_t nowtime = CurrentHostCounter(); - - //calculate how many vblanks happened - VBlankTime = (double)(nowtime - m_LastVBlankTime) / (double)CurrentHostFrequency(); - NrVBlanks = MathUtils::round_int(VBlankTime * m_fps); - - //save the timestamp of this vblank so we can calculate how many happened next time - m_LastVBlankTime = nowtime; - - //update the vblank timestamp, update the clock and send a signal that we got a vblank - UpdateClock(NrVBlanks, nowtime, m_refClock); -} - -bool CVideoSyncIos::InitDisplayLink() -{ - bool ret = true; - CLog::Log(LOGDEBUG, "CVideoSyncIos: setting up displaylink"); - if (!g_Windowing.InitDisplayLink(this)) - { - CLog::Log(LOGDEBUG, "CVideoSyncIos: InitDisplayLink failed"); - ret = false; - } - return ret; -} - -void CVideoSyncIos::DeinitDisplayLink() -{ - g_Windowing.DeinitDisplayLink(); -} - -#endif//TARGET_DARWIN_IOS diff --git a/xbmc/video/videosync/VideoSyncIos.h b/xbmc/video/videosync/VideoSyncIos.h deleted file mode 100644 index bf336b80dd..0000000000 --- a/xbmc/video/videosync/VideoSyncIos.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once -/* - * Copyright (C) 2015 Team Kodi - * http://kodi.tv - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#if defined(TARGET_DARWIN_IOS) -#include "VideoSync.h" -#include "guilib/DispResource.h" - -class CVideoSyncIos : public CVideoSync, IDispResource -{ -public: - CVideoSyncIos(CVideoReferenceClock *clock) : CVideoSync(clock), m_LastVBlankTime(0), m_abort(false){} - - // CVideoSync interface - virtual bool Setup(PUPDATECLOCK func) override; - virtual void Run(std::atomic& stop) override; - virtual void Cleanup() override; - virtual float GetFps() override; - - // IDispResource interface - virtual void OnResetDisplay() override; - - // used in the displaylink callback - void IosVblankHandler(); - -private: - // CVideoSyncDarwin interface - virtual bool InitDisplayLink(); - virtual void DeinitDisplayLink(); - - int64_t m_LastVBlankTime; //timestamp of the last vblank, used for calculating how many vblanks happened - volatile bool m_abort; -}; - -#endif// TARGET_DARWIN_IOS diff --git a/xbmc/video/videosync/VideoSyncOsx.cpp b/xbmc/video/videosync/VideoSyncOsx.cpp deleted file mode 100644 index f6320c49b3..0000000000 --- a/xbmc/video/videosync/VideoSyncOsx.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2005-2014 Team Kodi - * http://kodi.tv - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#include "system.h" - -#if defined(TARGET_DARWIN_OSX) -#include "utils/log.h" -#include "VideoSyncOsx.h" -#include "utils/MathUtils.h" -#include "video/VideoReferenceClock.h" -#include "guilib/GraphicContext.h" -#include "utils/TimeUtils.h" -#include "windowing/WindowingFactory.h" -#include -#include -#include "platform/darwin/osx/CocoaInterface.h" -#include - -bool CVideoSyncOsx::Setup(PUPDATECLOCK func) -{ - CLog::Log(LOGDEBUG, "CVideoSyncOsx::%s setting up OSX", __FUNCTION__); - - //init the vblank timestamp - m_LastVBlankTime = 0; - UpdateClock = func; - m_displayLost = false; - m_displayReset = false; - m_lostEvent.Reset(); - - g_Windowing.Register(this); - - return true; -} - -void CVideoSyncOsx::Run(std::atomic& stop) -{ - InitDisplayLink(); - - //because cocoa has a vblank callback, we just keep sleeping until we're asked to stop the thread - while(!stop && !m_displayLost && !m_displayReset) - { - usleep(100000); - } - - m_lostEvent.Set(); - - while(!stop && m_displayLost && !m_displayReset) - { - usleep(10000); - } - - DeinitDisplayLink(); -} - -void CVideoSyncOsx::Cleanup() -{ - CLog::Log(LOGDEBUG, "CVideoSyncOsx::%s cleaning up OSX", __FUNCTION__); - m_lostEvent.Set(); - m_LastVBlankTime = 0; - g_Windowing.Unregister(this); -} - -float CVideoSyncOsx::GetFps() -{ - m_fps = g_graphicsContext.GetFPS(); - CLog::Log(LOGDEBUG, "CVideoSyncOsx::%s Detected refreshrate: %f hertz", __FUNCTION__, m_fps); - return m_fps; -} - -void CVideoSyncOsx::RefreshChanged() -{ - m_displayReset = true; -} - -void CVideoSyncOsx::OnLostDisplay() -{ - if (!m_displayLost) - { - m_displayLost = true; - m_lostEvent.WaitMSec(1000); - } -} - -void CVideoSyncOsx::OnResetDisplay() -{ - m_displayReset = true; -} - -void CVideoSyncOsx::VblankHandler(int64_t nowtime, uint32_t timebase) -{ - int NrVBlanks; - double VBlankTime; - int64_t Now = CurrentHostCounter(); - - if (m_LastVBlankTime != 0) - { - VBlankTime = (double)(nowtime - m_LastVBlankTime) / (double)timebase; - NrVBlanks = MathUtils::round_int(VBlankTime * m_fps); - - //update the vblank timestamp, update the clock and send a signal that we got a vblank - UpdateClock(NrVBlanks, Now, m_refClock); - } - - //save the timestamp of this vblank so we can calculate how many happened next time - m_LastVBlankTime = nowtime; -} - -// Called by the Core Video Display Link whenever it's appropriate to render a frame. -static CVReturn DisplayLinkCallBack(CVDisplayLinkRef displayLink, const CVTimeStamp* inNow, const CVTimeStamp* inOutputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext) -{ - // Create an autorelease pool (necessary to call into non-Obj-C code from Obj-C code) - void* pool = Cocoa_Create_AutoReleasePool(); - - CVideoSyncOsx *VideoSyncOsx = reinterpret_cast(displayLinkContext); - - if (inOutputTime->flags & kCVTimeStampHostTimeValid) - VideoSyncOsx->VblankHandler(inOutputTime->hostTime, CVGetHostClockFrequency()); - else - VideoSyncOsx->VblankHandler(CVGetCurrentHostTime(), CVGetHostClockFrequency()); - - // Destroy the autorelease pool - Cocoa_Destroy_AutoReleasePool(pool); - - return kCVReturnSuccess; -} - -bool CVideoSyncOsx::InitDisplayLink() -{ - bool ret = true; - CLog::Log(LOGDEBUG, "CVideoSyncOsx::%s setting up displaylink", __FUNCTION__); - - if (!Cocoa_CVDisplayLinkCreate((void*)DisplayLinkCallBack, reinterpret_cast(this))) - { - CLog::Log(LOGDEBUG, "CVideoSyncOsx::%s Cocoa_CVDisplayLinkCreate failed", __FUNCTION__); - ret = false; - } - return ret; -} - -void CVideoSyncOsx::DeinitDisplayLink() -{ - Cocoa_CVDisplayLinkRelease(); -} - -#endif//TARGET_DARWIN_OSX diff --git a/xbmc/video/videosync/VideoSyncOsx.h b/xbmc/video/videosync/VideoSyncOsx.h deleted file mode 100644 index 1a2eedcd7e..0000000000 --- a/xbmc/video/videosync/VideoSyncOsx.h +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once -/* - * Copyright (C) 2005-2014 Team Kodi - * http://kodi.tv - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#if defined(TARGET_DARWIN_OSX) -#include "VideoSync.h" -#include "guilib/DispResource.h" -#include "threads/Event.h" - -class CVideoSyncOsx : public CVideoSync, IDispResource -{ -public: - - CVideoSyncOsx(CVideoReferenceClock *clock) : - CVideoSync(clock), - m_LastVBlankTime(0), - m_displayLost(false), - m_displayReset(false){}; - - // CVideoSync interface - virtual bool Setup(PUPDATECLOCK func) override; - virtual void Run(std::atomic& stop) override; - virtual void Cleanup() override; - virtual float GetFps() override; - virtual void RefreshChanged() override; - - // IDispResource interface - virtual void OnLostDisplay() override; - virtual void OnResetDisplay() override; - - // used in the displaylink callback - void VblankHandler(int64_t nowtime, uint32_t timebase); - -private: - virtual bool InitDisplayLink(); - virtual void DeinitDisplayLink(); - - int64_t m_LastVBlankTime; //timestamp of the last vblank, used for calculating how many vblanks happened - volatile bool m_displayLost; - volatile bool m_displayReset; - CEvent m_lostEvent; -}; - -#endif// TARGET_DARWIN_OSX diff --git a/xbmc/video/videosync/VideoSyncPi.cpp b/xbmc/video/videosync/VideoSyncPi.cpp deleted file mode 100644 index 0b512d3b0b..0000000000 --- a/xbmc/video/videosync/VideoSyncPi.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2005-2014 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#include "system.h" - -#if defined(TARGET_RASPBERRY_PI) - -#include "video/videosync/VideoSyncPi.h" -#include "guilib/GraphicContext.h" -#include "windowing/WindowingFactory.h" -#include "utils/TimeUtils.h" -#include "utils/log.h" -#include "linux/RBP.h" -#include "threads/Thread.h" - -bool CVideoSyncPi::Setup(PUPDATECLOCK func) -{ - UpdateClock = func; - m_abort = false; - g_Windowing.Register(this); - CLog::Log(LOGDEBUG, "CVideoReferenceClock: setting up RPi"); - return true; -} - -void CVideoSyncPi::Run(std::atomic& stop) -{ - /* This shouldn't be very busy and timing is important so increase priority */ - CThread::GetCurrentThread()->SetPriority(CThread::GetCurrentThread()->GetPriority()+1); - - while (!stop && !m_abort) - { - g_RBP.WaitVsync(); - uint64_t now = CurrentHostCounter(); - UpdateClock(1, now, m_refClock); - } -} - -void CVideoSyncPi::Cleanup() -{ - CLog::Log(LOGDEBUG, "CVideoReferenceClock: cleaning up RPi"); - g_Windowing.Unregister(this); -} - -float CVideoSyncPi::GetFps() -{ - m_fps = g_graphicsContext.GetFPS(); - CLog::Log(LOGDEBUG, "CVideoReferenceClock: fps: %.2f", m_fps); - return m_fps; -} - -void CVideoSyncPi::OnResetDisplay() -{ - m_abort = true; -} - -#endif diff --git a/xbmc/video/videosync/VideoSyncPi.h b/xbmc/video/videosync/VideoSyncPi.h deleted file mode 100644 index c7c3d12c71..0000000000 --- a/xbmc/video/videosync/VideoSyncPi.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once -/* - * Copyright (C) 2005-2014 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#if defined(TARGET_RASPBERRY_PI) - -#include "video/videosync/VideoSync.h" -#include "guilib/DispResource.h" - -class CVideoSyncPi : public CVideoSync, IDispResource -{ -public: - CVideoSyncPi(CVideoReferenceClock *clock) : CVideoSync(clock) {}; - virtual bool Setup(PUPDATECLOCK func); - virtual void Run(std::atomic& stop); - virtual void Cleanup(); - virtual float GetFps(); - virtual void OnResetDisplay(); - -private: - volatile bool m_abort; -}; - -#endif diff --git a/xbmc/windowing/CMakeLists.txt b/xbmc/windowing/CMakeLists.txt index 0e0cf87a1e..b8924a3104 100644 --- a/xbmc/windowing/CMakeLists.txt +++ b/xbmc/windowing/CMakeLists.txt @@ -4,7 +4,8 @@ set(SOURCES WinEvents.cpp set(HEADERS WindowingFactory.h WinEvents.h WinSystem.h - XBMC_events.h) + XBMC_events.h + VideoSync.h) if (NOT MIR_FOUND) if(SDL_FOUND AND NOT X_FOUND) diff --git a/xbmc/windowing/VideoSync.h b/xbmc/windowing/VideoSync.h new file mode 100644 index 0000000000..8db21957ca --- /dev/null +++ b/xbmc/windowing/VideoSync.h @@ -0,0 +1,40 @@ +#pragma once +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +class CVideoReferenceClock; +typedef void (*PUPDATECLOCK)(int NrVBlanks, uint64_t time, void *clock); + +class CVideoSync +{ +public: + CVideoSync(void *clock) { m_refClock = clock; }; + virtual ~CVideoSync() {}; + virtual bool Setup(PUPDATECLOCK func) = 0; + virtual void Run(std::atomic& stop) = 0; + virtual void Cleanup() = 0; + virtual float GetFps() = 0; + virtual void RefreshChanged() {}; +protected: + PUPDATECLOCK UpdateClock; + float m_fps; + void *m_refClock; +}; diff --git a/xbmc/windowing/WinSystem.h b/xbmc/windowing/WinSystem.h index d67a2a9298..95676b4358 100644 --- a/xbmc/windowing/WinSystem.h +++ b/xbmc/windowing/WinSystem.h @@ -21,8 +21,10 @@ #ifndef WINDOW_SYSTEM_BASE_H #define WINDOW_SYSTEM_BASE_H +#include "VideoSync.h" #include "WinEvents.h" #include "guilib/Resolution.h" +#include #include typedef enum _WindowSystemType @@ -84,6 +86,9 @@ public: virtual bool Hide() { return false; } virtual bool Show(bool raise = true) { return false; } + // videosync + virtual std::unique_ptr GetVideoSync(void *clock) { return nullptr; } + // notifications virtual void OnMove(int x, int y) {} diff --git a/xbmc/windowing/X11/CMakeLists.txt b/xbmc/windowing/X11/CMakeLists.txt index 6d2527d563..902dea50a4 100644 --- a/xbmc/windowing/X11/CMakeLists.txt +++ b/xbmc/windowing/X11/CMakeLists.txt @@ -6,6 +6,8 @@ if (X_FOUND) WinSystemX11GLContext.cpp WinSystemX11GLESContext.cpp XRandR.cpp + VideoSyncGLX.cpp + VideoSyncDRM.cpp WinSystemX11.cpp) set(HEADERS GLContext.h @@ -14,6 +16,8 @@ if (X_FOUND) WinSystemX11GLContext.h WinSystemX11GLESContext.h XRandR.h + VideoSyncGLX.h + VideoSyncDRM.h WinSystemX11.h) core_add_library(windowing_X11) diff --git a/xbmc/windowing/X11/VideoSyncDRM.cpp b/xbmc/windowing/X11/VideoSyncDRM.cpp new file mode 100644 index 0000000000..f31b349124 --- /dev/null +++ b/xbmc/windowing/X11/VideoSyncDRM.cpp @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include "system.h" + +#if defined(HAVE_X11) + +#include "VideoSyncDRM.h" +#include "xf86drm.h" +#include +#include +#include "utils/TimeUtils.h" +#include "utils/MathUtils.h" +#include "windowing/WindowingFactory.h" +#include "guilib/GraphicContext.h" +#include "utils/log.h" + +static drmVBlankSeqType CrtcSel(void) +{ + int crtc = g_Windowing.GetCrtc(); + int ret = 0; + + if (crtc == 1) + { + ret = DRM_VBLANK_SECONDARY; + } + else if (crtc > 1) + { + ret = (crtc << DRM_VBLANK_HIGH_CRTC_SHIFT) & DRM_VBLANK_HIGH_CRTC_MASK; + } + return (drmVBlankSeqType)ret; +} + +bool CVideoSyncDRM::Setup(PUPDATECLOCK func) +{ + CLog::Log(LOGDEBUG, "CVideoSyncDRM::%s - setting up DRM", __FUNCTION__); + + UpdateClock = func; + + m_fd = open("/dev/dri/card0", O_RDWR, 0); + if (m_fd < 0) + { + CLog::Log(LOGERROR, "CVideoSyncDRM::%s - can't open /dev/dri/card0", __FUNCTION__); + return false; + } + + drmVBlank vbl; + int ret; + vbl.request.type = (drmVBlankSeqType)(DRM_VBLANK_RELATIVE | CrtcSel()); + vbl.request.sequence = 0; + ret = drmWaitVBlank(m_fd, &vbl); + if (ret != 0) + { + CLog::Log(LOGERROR, "CVideoSyncDRM::%s - drmWaitVBlank returned error", __FUNCTION__); + return false; + } + + m_abort = false; + g_Windowing.Register(this); + + return true; +} + +void CVideoSyncDRM::Run(std::atomic& stop) +{ + drmVBlank vbl; + VblInfo info; + int ret; + drmVBlankSeqType crtcSel = CrtcSel(); + + vbl.request.type = (drmVBlankSeqType)(DRM_VBLANK_RELATIVE | crtcSel); + vbl.request.sequence = 0; + ret = drmWaitVBlank(m_fd, &vbl); + if (ret != 0) + { + CLog::Log(LOGERROR, "CVideoSyncDRM::%s - drmWaitVBlank returned error", __FUNCTION__); + return; + } + + info.start = CurrentHostCounter(); + info.videoSync = this; + + vbl.request.type = (drmVBlankSeqType)(DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT | crtcSel); + vbl.request.sequence = 1; + vbl.request.signal = (unsigned long)&info; + ret = drmWaitVBlank(m_fd, &vbl); + if (ret != 0) + { + CLog::Log(LOGERROR, "CVideoSyncDRM::%s - drmWaitVBlank returned error", __FUNCTION__); + return; + } + + drmEventContext evctx; + memset(&evctx, 0, sizeof evctx); + evctx.version = DRM_EVENT_CONTEXT_VERSION; + evctx.vblank_handler = EventHandler; + evctx.page_flip_handler = NULL; + + timeval timeout; + fd_set fds; + FD_ZERO(&fds); + FD_SET(m_fd, &fds); + + while (!stop && !m_abort) + { + timeout.tv_sec = 1; + timeout.tv_usec = 0; + ret = select(m_fd + 1, &fds, NULL, NULL, &timeout); + + if (ret <= 0) + { + continue; + } + + ret = drmHandleEvent(m_fd, &evctx); + if (ret != 0) + { + CLog::Log(LOGERROR, "CVideoSyncDRM::%s - drmHandleEvent returned error", __FUNCTION__); + break; + } + } +} + +void CVideoSyncDRM::Cleanup() +{ + close(m_fd); + g_Windowing.Unregister(this); +} + +void CVideoSyncDRM::EventHandler(int fd, unsigned int frame, unsigned int sec, + unsigned int usec, void *data) +{ + drmVBlank vbl; + VblInfo *info = (VblInfo*)data; + drmVBlankSeqType crtcSel = CrtcSel(); + + vbl.request.type = (drmVBlankSeqType)(DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT | crtcSel); + vbl.request.sequence = 1; + vbl.request.signal = (unsigned long)data; + + drmWaitVBlank(info->videoSync->m_fd, &vbl); + + uint64_t now = CurrentHostCounter(); + float diff = (float)(now - info->start)/CurrentHostFrequency(); + int vblanks = MathUtils::round_int(diff * info->videoSync->m_fps); + info->start = now; + + info->videoSync->UpdateClock(vblanks, now, info->videoSync->m_refClock); +} + +void CVideoSyncDRM::OnResetDisplay() +{ + m_abort = true; +} + +float CVideoSyncDRM::GetFps() +{ + m_fps = g_graphicsContext.GetFPS(); + return m_fps; +} + +void CVideoSyncDRM::RefreshChanged() +{ + if (m_fps != g_graphicsContext.GetFPS()) + m_abort = true; +} + +#endif diff --git a/xbmc/windowing/X11/VideoSyncDRM.h b/xbmc/windowing/X11/VideoSyncDRM.h new file mode 100644 index 0000000000..3f41cc25ee --- /dev/null +++ b/xbmc/windowing/X11/VideoSyncDRM.h @@ -0,0 +1,45 @@ +#pragma once +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include "windowing/VideoSync.h" +#include "guilib/DispResource.h" + +class CVideoSyncDRM : public CVideoSync, IDispResource +{ +public: + CVideoSyncDRM(void *clock) : CVideoSync(clock) {}; + virtual bool Setup(PUPDATECLOCK func); + virtual void Run(std::atomic& stop); + virtual void Cleanup(); + virtual float GetFps(); + virtual void OnResetDisplay(); + virtual void RefreshChanged(); +private: + static void EventHandler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data); + int m_fd; + volatile bool m_abort; + struct VblInfo + { + uint64_t start; + CVideoSyncDRM *videoSync; + }; +}; + diff --git a/xbmc/windowing/X11/VideoSyncGLX.cpp b/xbmc/windowing/X11/VideoSyncGLX.cpp new file mode 100644 index 0000000000..a0da423254 --- /dev/null +++ b/xbmc/windowing/X11/VideoSyncGLX.cpp @@ -0,0 +1,292 @@ +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include "system.h" + +#if defined(HAS_GLX) + +#include "VideoSyncGLX.h" +#include +#include +#include "windowing/WindowingFactory.h" +#include "guilib/GraphicContext.h" +#include "threads/SingleLock.h" +#include "utils/log.h" +#include "utils/TimeUtils.h" +#include + +#ifdef TARGET_POSIX +#include "linux/XTimeUtils.h" +#endif + +Display* CVideoSyncGLX::m_Dpy = NULL; + +void CVideoSyncGLX::OnLostDisplay() +{ + if (!m_displayLost) + { + m_displayLost = true; + m_lostEvent.Wait(); + } +} + +void CVideoSyncGLX::OnResetDisplay() +{ + m_displayReset = true; +} + +bool CVideoSyncGLX::Setup(PUPDATECLOCK func) +{ + CSingleLock lock(g_graphicsContext); + + m_glXWaitVideoSyncSGI = NULL; + m_glXGetVideoSyncSGI = NULL; + m_vInfo = NULL; + m_Window = 0; + m_Context = NULL; + UpdateClock = func; + + int singleBufferAttributes[] = { + GLX_RGBA, + GLX_RED_SIZE, 0, + GLX_GREEN_SIZE, 0, + GLX_BLUE_SIZE, 0, + None + }; + + int ReturnV, SwaMask; + unsigned int GlxTest; + XSetWindowAttributes Swa; + + m_vInfo = NULL; + m_Context = NULL; + m_Window = 0; + + CLog::Log(LOGDEBUG, "CVideoReferenceClock: Setting up GLX"); + + g_Windowing.Register(this); + + m_displayLost = false; + m_displayReset = false; + m_lostEvent.Reset(); + + if (!m_Dpy) + { + m_Dpy = XOpenDisplay(NULL); + if (!m_Dpy) + { + CLog::Log(LOGDEBUG, "CVideoReferenceClock: Unable to open display"); + return false; + } + } + + if (!glXQueryExtension(m_Dpy, NULL, NULL)) + { + CLog::Log(LOGDEBUG, "CVideoReferenceClock: X server does not support GLX"); + return false; + } + + bool ExtensionFound = false; + std::istringstream Extensions(glXQueryExtensionsString(m_Dpy, g_Windowing.GetCurrentScreen())); + std::string ExtensionStr; + + while (!ExtensionFound) + { + Extensions >> ExtensionStr; + if (Extensions.fail()) + break; + + if (ExtensionStr == "GLX_SGI_video_sync") + ExtensionFound = true; + } + + if (!ExtensionFound) + { + CLog::Log(LOGDEBUG, "CVideoReferenceClock: X server does not support GLX_SGI_video_sync"); + return false; + } + + m_vInfo = glXChooseVisual(m_Dpy, g_Windowing.GetCurrentScreen(), singleBufferAttributes); + if (!m_vInfo) + { + CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXChooseVisual returned NULL"); + return false; + } + + Swa.border_pixel = 0; + Swa.event_mask = StructureNotifyMask; + Swa.colormap = XCreateColormap(m_Dpy, g_Windowing.GetWindow(), m_vInfo->visual, AllocNone ); + SwaMask = CWBorderPixel | CWColormap | CWEventMask; + + m_Window = XCreateWindow(m_Dpy, g_Windowing.GetWindow(), 0, 0, 256, 256, 0, + m_vInfo->depth, InputOutput, m_vInfo->visual, SwaMask, &Swa); + + m_Context = glXCreateContext(m_Dpy, m_vInfo, NULL, True); + if (!m_Context) + { + CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXCreateContext returned NULL"); + return false; + } + + ReturnV = glXMakeCurrent(m_Dpy, m_Window, m_Context); + if (ReturnV != True) + { + CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXMakeCurrent returned %i", ReturnV); + return false; + } + + m_glXWaitVideoSyncSGI = (int (*)(int, int, unsigned int*))glXGetProcAddress((const GLubyte*)"glXWaitVideoSyncSGI"); + if (!m_glXWaitVideoSyncSGI) + { + CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXWaitVideoSyncSGI not found"); + return false; + } + + ReturnV = m_glXWaitVideoSyncSGI(2, 0, &GlxTest); + if (ReturnV) + { + CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXWaitVideoSyncSGI returned %i", ReturnV); + return false; + } + + m_glXGetVideoSyncSGI = (int (*)(unsigned int*))glXGetProcAddress((const GLubyte*)"glXGetVideoSyncSGI"); + if (!m_glXGetVideoSyncSGI) + { + CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXGetVideoSyncSGI not found"); + return false; + } + + ReturnV = m_glXGetVideoSyncSGI(&GlxTest); + if (ReturnV) + { + CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXGetVideoSyncSGI returned %i", ReturnV); + return false; + } + + return true; +} + +void CVideoSyncGLX::Run(std::atomic& stop) +{ + unsigned int PrevVblankCount; + unsigned int VblankCount; + int ReturnV; + bool IsReset = false; + int64_t Now; + + //get the current vblank counter + m_glXGetVideoSyncSGI(&VblankCount); + PrevVblankCount = VblankCount; + + while(!stop && !m_displayLost && !m_displayReset) + { + //wait for the next vblank + ReturnV = m_glXWaitVideoSyncSGI(2, (VblankCount + 1) % 2, &VblankCount); + m_glXGetVideoSyncSGI(&VblankCount); //the vblank count returned by glXWaitVideoSyncSGI is not always correct + Now = CurrentHostCounter(); //get the timestamp of this vblank + + if(ReturnV) + { + CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXWaitVideoSyncSGI returned %i", ReturnV); + return; + } + + if (VblankCount > PrevVblankCount) + { + UpdateClock((int)(VblankCount - PrevVblankCount), Now, m_refClock); + IsReset = false; + } + else + { + CLog::Log(LOGDEBUG, "CVideoReferenceClock: Vblank counter has reset"); + + //only try reattaching once + if (IsReset) + return; + + //because of a bug in the nvidia driver, glXWaitVideoSyncSGI breaks when the vblank counter resets + CLog::Log(LOGDEBUG, "CVideoReferenceClock: Detaching glX context"); + ReturnV = glXMakeCurrent(m_Dpy, None, NULL); + if (ReturnV != True) + { + CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXMakeCurrent returned %i", ReturnV); + return; + } + + //sleep here so we don't busy spin when this constantly happens, for example when the display went to sleep + Sleep(1000); + + CLog::Log(LOGDEBUG, "CVideoReferenceClock: Attaching glX context"); + ReturnV = glXMakeCurrent(m_Dpy, m_Window, m_Context); + if (ReturnV != True) + { + CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXMakeCurrent returned %i", ReturnV); + return; + } + + m_glXGetVideoSyncSGI(&VblankCount); + + IsReset = true; + } + PrevVblankCount = VblankCount; + } + m_lostEvent.Set(); + while(!stop && m_displayLost && !m_displayReset) + { + Sleep(10); + } +} + +void CVideoSyncGLX::Cleanup() +{ + CLog::Log(LOGDEBUG, "CVideoReferenceClock: Cleaning up GLX"); + + { + CSingleLock lock(g_graphicsContext); + + if (m_vInfo) + { + XFree(m_vInfo); + m_vInfo = NULL; + } + if (m_Context) + { + glXMakeCurrent(m_Dpy, None, NULL); + glXDestroyContext(m_Dpy, m_Context); + m_Context = NULL; + } + if (m_Window) + { + XDestroyWindow(m_Dpy, m_Window); + m_Window = 0; + } + } + + m_lostEvent.Set(); + g_Windowing.Unregister(this); +} + +float CVideoSyncGLX::GetFps() +{ + m_fps = g_graphicsContext.GetFPS(); + return m_fps; +} + +#endif diff --git a/xbmc/windowing/X11/VideoSyncGLX.h b/xbmc/windowing/X11/VideoSyncGLX.h new file mode 100644 index 0000000000..eb390d6a84 --- /dev/null +++ b/xbmc/windowing/X11/VideoSyncGLX.h @@ -0,0 +1,56 @@ +#pragma once +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#if defined(HAS_GLX) + +#include "windowing/VideoSync.h" +#include "system_gl.h" +#include +#include +#include +#include "guilib/DispResource.h" +#include "threads/Event.h" + +class CVideoSyncGLX : public CVideoSync, IDispResource +{ +public: + CVideoSyncGLX(void *clock) : CVideoSync(clock) {}; + virtual bool Setup(PUPDATECLOCK func); + virtual void Run(std::atomic& stop); + virtual void Cleanup(); + virtual float GetFps(); + virtual void OnLostDisplay(); + virtual void OnResetDisplay(); + +private: + int (*m_glXWaitVideoSyncSGI) (int, int, unsigned int*); + int (*m_glXGetVideoSyncSGI) (unsigned int*); + + static Display* m_Dpy; + XVisualInfo *m_vInfo; + Window m_Window; + GLXContext m_Context; + volatile bool m_displayLost; + volatile bool m_displayReset; + CEvent m_lostEvent; +}; + +#endif diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp index 291bbf6420..ff7abe675d 100644 --- a/xbmc/windowing/X11/WinSystemX11.cpp +++ b/xbmc/windowing/X11/WinSystemX11.cpp @@ -20,8 +20,6 @@ #include "system.h" -#if defined(HAVE_X11) - #include "WinSystemX11.h" #include "ServiceBroker.h" #include "settings/DisplaySettings.h" @@ -1071,4 +1069,4 @@ void CWinSystemX11::UpdateCrtc() g_graphicsContext.SetFPS(fps); } -#endif + diff --git a/xbmc/windowing/X11/WinSystemX11GLContext.cpp b/xbmc/windowing/X11/WinSystemX11GLContext.cpp index 33c5858b8b..c776dbdf96 100644 --- a/xbmc/windowing/X11/WinSystemX11GLContext.cpp +++ b/xbmc/windowing/X11/WinSystemX11GLContext.cpp @@ -19,7 +19,7 @@ */ #include "system.h" -#if defined(HAVE_X11) && defined(HAS_GL) +#if defined(HAS_GL) #include #include @@ -34,6 +34,8 @@ #include "threads/SingleLock.h" #include #include "Application.h" +#include "VideoSyncDRM.h" +#include "VideoSyncGLX.h" CWinSystemX11GLContext::CWinSystemX11GLContext() { @@ -219,4 +221,19 @@ bool CWinSystemX11GLContext::RefreshGLContext(bool force) return ret; } +std::unique_ptr CWinSystemX11GLContext::GetVideoSync(void *clock) +{ + std::unique_ptr pVSync; + + if (dynamic_cast(m_pGLContext)) + { + pVSync.reset(new CVideoSyncDRM(clock)); + } + else if (dynamic_cast(m_pGLContext)) + { + pVSync.reset(new CVideoSyncGLX(clock)); + } + return pVSync; +} + #endif diff --git a/xbmc/windowing/X11/WinSystemX11GLContext.h b/xbmc/windowing/X11/WinSystemX11GLContext.h index 4e0ca8c62e..b4e7f390d9 100644 --- a/xbmc/windowing/X11/WinSystemX11GLContext.h +++ b/xbmc/windowing/X11/WinSystemX11GLContext.h @@ -43,6 +43,9 @@ public: bool IsExtSupported(const char* extension) override; + // videosync + virtual std::unique_ptr GetVideoSync(void *clock) override; + GLXWindow GetWindow() const; GLXContext GetGlxContext() const; EGLDisplay GetEGLDisplay() const; diff --git a/xbmc/windowing/egl/VideoSyncAndroid.cpp b/xbmc/windowing/egl/VideoSyncAndroid.cpp new file mode 100644 index 0000000000..71d7906267 --- /dev/null +++ b/xbmc/windowing/egl/VideoSyncAndroid.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2015 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include "system.h" + +#if defined(TARGET_ANDROID) +#include "utils/log.h" +#include "VideoSyncAndroid.h" +#include "video/VideoReferenceClock.h" +#include "utils/TimeUtils.h" +#include "platform/android/activity/XBMCApp.h" +#include "windowing/WindowingFactory.h" +#include "guilib/GraphicContext.h" +#include "utils/MathUtils.h" +#include "linux/XTimeUtils.h" + + +bool CVideoSyncAndroid::Setup(PUPDATECLOCK func) +{ + CLog::Log(LOGDEBUG, "CVideoSyncAndroid::%s setting up", __FUNCTION__); + + //init the vblank timestamp + m_LastVBlankTime = CurrentHostCounter(); + UpdateClock = func; + m_abort = false; + + CXBMCApp::InitFrameCallback(this); + g_Windowing.Register(this); + + return true; +} + +void CVideoSyncAndroid::Run(std::atomic& stop) +{ + while(!stop && !m_abort) + { + Sleep(100); + } +} + +void CVideoSyncAndroid::Cleanup() +{ + CLog::Log(LOGDEBUG, "CVideoSyncAndroid::%s cleaning up", __FUNCTION__); + CXBMCApp::DeinitFrameCallback(); + g_Windowing.Unregister(this); +} + +float CVideoSyncAndroid::GetFps() +{ + m_fps = g_graphicsContext.GetFPS(); + CLog::Log(LOGDEBUG, "CVideoSyncAndroid::%s Detected refreshrate: %f hertz", __FUNCTION__, m_fps); + return m_fps; +} + +void CVideoSyncAndroid::OnResetDisplay() +{ + m_abort = true; +} + +void CVideoSyncAndroid::FrameCallback(int64_t frameTimeNanos) +{ + int NrVBlanks; + double VBlankTime; + int64_t nowtime = CurrentHostCounter(); + + //calculate how many vblanks happened + VBlankTime = (double)(nowtime - m_LastVBlankTime) / (double)CurrentHostFrequency(); + NrVBlanks = MathUtils::round_int(VBlankTime * m_fps); + + //save the timestamp of this vblank so we can calculate how many happened next time + m_LastVBlankTime = nowtime; + + //update the vblank timestamp, update the clock and send a signal that we got a vblank + UpdateClock(NrVBlanks, nowtime, m_refClock); +} + +#endif //TARGET_ANDROID diff --git a/xbmc/windowing/egl/VideoSyncAndroid.h b/xbmc/windowing/egl/VideoSyncAndroid.h new file mode 100644 index 0000000000..803df561b2 --- /dev/null +++ b/xbmc/windowing/egl/VideoSyncAndroid.h @@ -0,0 +1,48 @@ +#pragma once +/* + * Copyright (C) 2015 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#if defined(TARGET_ANDROID) +#include "VideoSync.h" +#include "guilib/DispResource.h" + +class CVideoSyncAndroid : public CVideoSync, IDispResource +{ +public: + CVideoSyncAndroid(CVideoReferenceClock *clock) : CVideoSync(clock), m_LastVBlankTime(0), m_abort(false){} + + // CVideoSync interface + virtual bool Setup(PUPDATECLOCK func); + virtual void Run(std::atomic& stop); + virtual void Cleanup(); + virtual float GetFps(); + + // IDispResource interface + virtual void OnResetDisplay(); + + // Choreographer callback + void FrameCallback(int64_t frameTimeNanos); + +private: + int64_t m_LastVBlankTime; //timestamp of the last vblank, used for calculating how many vblanks happened + volatile bool m_abort; +}; + +#endif// TARGET_ANDROID diff --git a/xbmc/windowing/egl/VideoSyncIMX.cpp b/xbmc/windowing/egl/VideoSyncIMX.cpp new file mode 100644 index 0000000000..fa7c27c4e5 --- /dev/null +++ b/xbmc/windowing/egl/VideoSyncIMX.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include "system.h" + +#if defined(HAS_IMXVPU) + +#include "video/videosync/VideoSyncIMX.h" +#include "guilib/GraphicContext.h" +#include "windowing/WindowingFactory.h" +#include "utils/TimeUtils.h" +#include "utils/log.h" +#include "linux/imx/IMX.h" + +CVideoSyncIMX::CVideoSyncIMX(CVideoReferenceClock *clock) : CVideoSync(clock) +{ + g_IMX.Initialize(); +} + +CVideoSyncIMX::~CVideoSyncIMX() +{ + g_IMX.Deinitialize(); +} + +bool CVideoSyncIMX::Setup(PUPDATECLOCK func) +{ + UpdateClock = func; + + m_abort = false; + + g_Windowing.Register(this); + CLog::Log(LOGDEBUG, "CVideoReferenceClock: setting up IMX"); + return true; +} + +void CVideoSyncIMX::Run(std::atomic& stop) +{ + int counter; + + while (!stop && !m_abort) + { + counter = g_IMX.WaitVsync(); + uint64_t now = CurrentHostCounter(); + + UpdateClock(counter, now, m_refClock); + } +} + +void CVideoSyncIMX::Cleanup() +{ + CLog::Log(LOGDEBUG, "CVideoReferenceClock: cleaning up IMX"); + g_Windowing.Unregister(this); +} + +float CVideoSyncIMX::GetFps() +{ + m_fps = g_graphicsContext.GetFPS(); + CLog::Log(LOGDEBUG, "CVideoReferenceClock: fps: %.3f", m_fps); + return m_fps; +} + +void CVideoSyncIMX::OnResetDisplay() +{ + m_abort = true; +} + +#endif diff --git a/xbmc/windowing/egl/VideoSyncIMX.h b/xbmc/windowing/egl/VideoSyncIMX.h new file mode 100644 index 0000000000..7220ac60ba --- /dev/null +++ b/xbmc/windowing/egl/VideoSyncIMX.h @@ -0,0 +1,41 @@ +#pragma once +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#if defined(HAS_IMXVPU) + +#include "video/videosync/VideoSync.h" +#include "guilib/DispResource.h" + +class CVideoSyncIMX : public CVideoSync, IDispResource +{ +public: + CVideoSyncIMX(CVideoReferenceClock *clock); + virtual ~CVideoSyncIMX(); + virtual bool Setup(PUPDATECLOCK func); + virtual void Run(std::atomic& stop); + virtual void Cleanup(); + virtual float GetFps(); + virtual void OnResetDisplay(); +private: + volatile bool m_abort; +}; + +#endif diff --git a/xbmc/windowing/egl/VideoSyncPi.cpp b/xbmc/windowing/egl/VideoSyncPi.cpp new file mode 100644 index 0000000000..0b512d3b0b --- /dev/null +++ b/xbmc/windowing/egl/VideoSyncPi.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include "system.h" + +#if defined(TARGET_RASPBERRY_PI) + +#include "video/videosync/VideoSyncPi.h" +#include "guilib/GraphicContext.h" +#include "windowing/WindowingFactory.h" +#include "utils/TimeUtils.h" +#include "utils/log.h" +#include "linux/RBP.h" +#include "threads/Thread.h" + +bool CVideoSyncPi::Setup(PUPDATECLOCK func) +{ + UpdateClock = func; + m_abort = false; + g_Windowing.Register(this); + CLog::Log(LOGDEBUG, "CVideoReferenceClock: setting up RPi"); + return true; +} + +void CVideoSyncPi::Run(std::atomic& stop) +{ + /* This shouldn't be very busy and timing is important so increase priority */ + CThread::GetCurrentThread()->SetPriority(CThread::GetCurrentThread()->GetPriority()+1); + + while (!stop && !m_abort) + { + g_RBP.WaitVsync(); + uint64_t now = CurrentHostCounter(); + UpdateClock(1, now, m_refClock); + } +} + +void CVideoSyncPi::Cleanup() +{ + CLog::Log(LOGDEBUG, "CVideoReferenceClock: cleaning up RPi"); + g_Windowing.Unregister(this); +} + +float CVideoSyncPi::GetFps() +{ + m_fps = g_graphicsContext.GetFPS(); + CLog::Log(LOGDEBUG, "CVideoReferenceClock: fps: %.2f", m_fps); + return m_fps; +} + +void CVideoSyncPi::OnResetDisplay() +{ + m_abort = true; +} + +#endif diff --git a/xbmc/windowing/egl/VideoSyncPi.h b/xbmc/windowing/egl/VideoSyncPi.h new file mode 100644 index 0000000000..c7c3d12c71 --- /dev/null +++ b/xbmc/windowing/egl/VideoSyncPi.h @@ -0,0 +1,41 @@ +#pragma once +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#if defined(TARGET_RASPBERRY_PI) + +#include "video/videosync/VideoSync.h" +#include "guilib/DispResource.h" + +class CVideoSyncPi : public CVideoSync, IDispResource +{ +public: + CVideoSyncPi(CVideoReferenceClock *clock) : CVideoSync(clock) {}; + virtual bool Setup(PUPDATECLOCK func); + virtual void Run(std::atomic& stop); + virtual void Cleanup(); + virtual float GetFps(); + virtual void OnResetDisplay(); + +private: + volatile bool m_abort; +}; + +#endif diff --git a/xbmc/windowing/osx/CMakeLists.txt b/xbmc/windowing/osx/CMakeLists.txt index a007c38df2..0191ddefb5 100644 --- a/xbmc/windowing/osx/CMakeLists.txt +++ b/xbmc/windowing/osx/CMakeLists.txt @@ -1,17 +1,21 @@ if(CORE_SYSTEM_NAME STREQUAL osx) set(SOURCES WinEventsOSX.mm WinSystemOSX.mm - WinSystemOSXGL.mm) + WinSystemOSXGL.mm + VideoSyncOsx.cpp) set(HEADERS WinEventsOSX.h WinSystemOSX.h - WinSystemOSXGL.h) + WinSystemOSXGL.h + VideoSyncOsx.h) endif() if(CORE_SYSTEM_NAME STREQUAL ios) set(SOURCES WinEventsIOS.mm - WinSystemIOS.mm) + WinSystemIOS.mm + VideoSyncIos.cpp) set(HEADERS WinEventsIOS.h - WinSystemIOS.h) + WinSystemIOS.h + VideoSyncIos.h) endif() core_add_library(windowing_osx) diff --git a/xbmc/windowing/osx/VideoSyncIos.cpp b/xbmc/windowing/osx/VideoSyncIos.cpp new file mode 100644 index 0000000000..ac23993dd8 --- /dev/null +++ b/xbmc/windowing/osx/VideoSyncIos.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2015 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include "system.h" + +#if defined(TARGET_DARWIN_IOS) +#include "utils/log.h" +#include "VideoSyncIos.h" +#include "utils/MathUtils.h" +#include "cores/VideoPlayer/VideoReferenceClock.h" +#include "guilib/GraphicContext.h" +#include "windowing/WindowingFactory.h" +#include "utils/TimeUtils.h" + +bool CVideoSyncIos::Setup(PUPDATECLOCK func) +{ + CLog::Log(LOGDEBUG, "CVideoSyncIos::%s setting up OSX", __FUNCTION__); + + //init the vblank timestamp + m_LastVBlankTime = CurrentHostCounter(); + UpdateClock = func; + m_abort = false; + + bool setupOk = InitDisplayLink(); + if (setupOk) + { + g_Windowing.Register(this); + } + + return setupOk; +} + +void CVideoSyncIos::Run(std::atomic& stop) +{ + //because cocoa has a vblank callback, we just keep sleeping until we're asked to stop the thread + while(!stop && !m_abort) + { + usleep(100000); + } +} + +void CVideoSyncIos::Cleanup() +{ + CLog::Log(LOGDEBUG, "CVideoSyncIos::%s cleaning up OSX", __FUNCTION__); + DeinitDisplayLink(); + g_Windowing.Unregister(this); +} + +float CVideoSyncIos::GetFps() +{ + m_fps = g_graphicsContext.GetFPS(); + CLog::Log(LOGDEBUG, "CVideoSyncIos::%s Detected refreshrate: %f hertz", __FUNCTION__, m_fps); + return m_fps; +} + +void CVideoSyncIos::OnResetDisplay() +{ + m_abort = true; +} + +void CVideoSyncIos::IosVblankHandler() +{ + int NrVBlanks; + double VBlankTime; + int64_t nowtime = CurrentHostCounter(); + + //calculate how many vblanks happened + VBlankTime = (double)(nowtime - m_LastVBlankTime) / (double)CurrentHostFrequency(); + NrVBlanks = MathUtils::round_int(VBlankTime * m_fps); + + //save the timestamp of this vblank so we can calculate how many happened next time + m_LastVBlankTime = nowtime; + + //update the vblank timestamp, update the clock and send a signal that we got a vblank + UpdateClock(NrVBlanks, nowtime, m_refClock); +} + +bool CVideoSyncIos::InitDisplayLink() +{ + bool ret = true; + CLog::Log(LOGDEBUG, "CVideoSyncIos: setting up displaylink"); + if (!g_Windowing.InitDisplayLink(this)) + { + CLog::Log(LOGDEBUG, "CVideoSyncIos: InitDisplayLink failed"); + ret = false; + } + return ret; +} + +void CVideoSyncIos::DeinitDisplayLink() +{ + g_Windowing.DeinitDisplayLink(); +} + +#endif//TARGET_DARWIN_IOS diff --git a/xbmc/windowing/osx/VideoSyncIos.h b/xbmc/windowing/osx/VideoSyncIos.h new file mode 100644 index 0000000000..6d129eb63d --- /dev/null +++ b/xbmc/windowing/osx/VideoSyncIos.h @@ -0,0 +1,52 @@ +#pragma once +/* + * Copyright (C) 2015 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#if defined(TARGET_DARWIN_IOS) +#include "windowing/VideoSync.h" +#include "guilib/DispResource.h" + +class CVideoSyncIos : public CVideoSync, IDispResource +{ +public: + CVideoSyncIos(void *clock) : CVideoSync(clock), m_LastVBlankTime(0), m_abort(false){} + + // CVideoSync interface + virtual bool Setup(PUPDATECLOCK func) override; + virtual void Run(std::atomic& stop) override; + virtual void Cleanup() override; + virtual float GetFps() override; + + // IDispResource interface + virtual void OnResetDisplay() override; + + // used in the displaylink callback + void IosVblankHandler(); + +private: + // CVideoSyncDarwin interface + virtual bool InitDisplayLink(); + virtual void DeinitDisplayLink(); + + int64_t m_LastVBlankTime; //timestamp of the last vblank, used for calculating how many vblanks happened + volatile bool m_abort; +}; + +#endif// TARGET_DARWIN_IOS diff --git a/xbmc/windowing/osx/VideoSyncOsx.cpp b/xbmc/windowing/osx/VideoSyncOsx.cpp new file mode 100644 index 0000000000..9ea7145b33 --- /dev/null +++ b/xbmc/windowing/osx/VideoSyncOsx.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2005-2014 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include "system.h" + +#include "utils/log.h" +#include "VideoSyncOsx.h" +#include "utils/MathUtils.h" +#include "guilib/GraphicContext.h" +#include "utils/TimeUtils.h" +#include "windowing/WindowingFactory.h" +#include +#include +#include "platform/darwin/osx/CocoaInterface.h" +#include + +bool CVideoSyncOsx::Setup(PUPDATECLOCK func) +{ + CLog::Log(LOGDEBUG, "CVideoSyncOsx::%s setting up OSX", __FUNCTION__); + + //init the vblank timestamp + m_LastVBlankTime = 0; + UpdateClock = func; + m_displayLost = false; + m_displayReset = false; + m_lostEvent.Reset(); + + g_Windowing.Register(this); + + return true; +} + +void CVideoSyncOsx::Run(std::atomic& stop) +{ + InitDisplayLink(); + + //because cocoa has a vblank callback, we just keep sleeping until we're asked to stop the thread + while(!stop && !m_displayLost && !m_displayReset) + { + usleep(100000); + } + + m_lostEvent.Set(); + + while(!stop && m_displayLost && !m_displayReset) + { + usleep(10000); + } + + DeinitDisplayLink(); +} + +void CVideoSyncOsx::Cleanup() +{ + CLog::Log(LOGDEBUG, "CVideoSyncOsx::%s cleaning up OSX", __FUNCTION__); + m_lostEvent.Set(); + m_LastVBlankTime = 0; + g_Windowing.Unregister(this); +} + +float CVideoSyncOsx::GetFps() +{ + m_fps = g_graphicsContext.GetFPS(); + CLog::Log(LOGDEBUG, "CVideoSyncOsx::%s Detected refreshrate: %f hertz", __FUNCTION__, m_fps); + return m_fps; +} + +void CVideoSyncOsx::RefreshChanged() +{ + m_displayReset = true; +} + +void CVideoSyncOsx::OnLostDisplay() +{ + if (!m_displayLost) + { + m_displayLost = true; + m_lostEvent.WaitMSec(1000); + } +} + +void CVideoSyncOsx::OnResetDisplay() +{ + m_displayReset = true; +} + +void CVideoSyncOsx::VblankHandler(int64_t nowtime, uint32_t timebase) +{ + int NrVBlanks; + double VBlankTime; + int64_t Now = CurrentHostCounter(); + + if (m_LastVBlankTime != 0) + { + VBlankTime = (double)(nowtime - m_LastVBlankTime) / (double)timebase; + NrVBlanks = MathUtils::round_int(VBlankTime * m_fps); + + //update the vblank timestamp, update the clock and send a signal that we got a vblank + UpdateClock(NrVBlanks, Now, m_refClock); + } + + //save the timestamp of this vblank so we can calculate how many happened next time + m_LastVBlankTime = nowtime; +} + +// Called by the Core Video Display Link whenever it's appropriate to render a frame. +static CVReturn DisplayLinkCallBack(CVDisplayLinkRef displayLink, const CVTimeStamp* inNow, const CVTimeStamp* inOutputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext) +{ + // Create an autorelease pool (necessary to call into non-Obj-C code from Obj-C code) + void* pool = Cocoa_Create_AutoReleasePool(); + + CVideoSyncOsx *VideoSyncOsx = reinterpret_cast(displayLinkContext); + + if (inOutputTime->flags & kCVTimeStampHostTimeValid) + VideoSyncOsx->VblankHandler(inOutputTime->hostTime, CVGetHostClockFrequency()); + else + VideoSyncOsx->VblankHandler(CVGetCurrentHostTime(), CVGetHostClockFrequency()); + + // Destroy the autorelease pool + Cocoa_Destroy_AutoReleasePool(pool); + + return kCVReturnSuccess; +} + +bool CVideoSyncOsx::InitDisplayLink() +{ + bool ret = true; + CLog::Log(LOGDEBUG, "CVideoSyncOsx::%s setting up displaylink", __FUNCTION__); + + if (!Cocoa_CVDisplayLinkCreate((void*)DisplayLinkCallBack, reinterpret_cast(this))) + { + CLog::Log(LOGDEBUG, "CVideoSyncOsx::%s Cocoa_CVDisplayLinkCreate failed", __FUNCTION__); + ret = false; + } + return ret; +} + +void CVideoSyncOsx::DeinitDisplayLink() +{ + Cocoa_CVDisplayLinkRelease(); +} + diff --git a/xbmc/windowing/osx/VideoSyncOsx.h b/xbmc/windowing/osx/VideoSyncOsx.h new file mode 100644 index 0000000000..276c9085a5 --- /dev/null +++ b/xbmc/windowing/osx/VideoSyncOsx.h @@ -0,0 +1,59 @@ +#pragma once +/* + * Copyright (C) 2005-2014 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include "windowing/VideoSync.h" +#include "guilib/DispResource.h" +#include "threads/Event.h" + +class CVideoSyncOsx : public CVideoSync, IDispResource +{ +public: + + CVideoSyncOsx(void *clock) : + CVideoSync(clock), + m_LastVBlankTime(0), + m_displayLost(false), + m_displayReset(false){}; + + // CVideoSync interface + virtual bool Setup(PUPDATECLOCK func) override; + virtual void Run(std::atomic& stop) override; + virtual void Cleanup() override; + virtual float GetFps() override; + virtual void RefreshChanged() override; + + // IDispResource interface + virtual void OnLostDisplay() override; + virtual void OnResetDisplay() override; + + // used in the displaylink callback + void VblankHandler(int64_t nowtime, uint32_t timebase); + +private: + virtual bool InitDisplayLink(); + virtual void DeinitDisplayLink(); + + int64_t m_LastVBlankTime; //timestamp of the last vblank, used for calculating how many vblanks happened + volatile bool m_displayLost; + volatile bool m_displayReset; + CEvent m_lostEvent; +}; + diff --git a/xbmc/windowing/osx/WinSystemIOS.h b/xbmc/windowing/osx/WinSystemIOS.h index 7ecdf672a7..2ee5645b22 100644 --- a/xbmc/windowing/osx/WinSystemIOS.h +++ b/xbmc/windowing/osx/WinSystemIOS.h @@ -72,6 +72,8 @@ public: virtual int GetNumScreens(); virtual int GetCurrentScreen(); + virtual std::unique_ptr GetVideoSync(void *clock) override; + bool InitDisplayLink(CVideoSyncIos *syncImpl); void DeinitDisplayLink(void); void OnAppFocusChange(bool focus); diff --git a/xbmc/windowing/osx/WinSystemIOS.mm b/xbmc/windowing/osx/WinSystemIOS.mm index a2e74332a4..84f1770185 100644 --- a/xbmc/windowing/osx/WinSystemIOS.mm +++ b/xbmc/windowing/osx/WinSystemIOS.mm @@ -18,7 +18,6 @@ * */ -#if defined(TARGET_DARWIN_IOS) //hack around problem with xbmc's typedef int BOOL // and obj-c's typedef unsigned char BOOL #define BOOL XBMC_BOOL @@ -26,7 +25,8 @@ #undef BOOL #ifdef HAS_EGL -#define BOOL XBMC_BOOL +#define BOOL XBMC_BOOL +#include "VideoSyncIos.h" #include "WinSystemIOS.h" #include "utils/log.h" #include "filesystem/SpecialProtocol.h" @@ -37,7 +37,7 @@ #include "utils/StringUtils.h" #include "guilib/DispResource.h" #include "threads/SingleLock.h" -#include "video/videosync/VideoSyncIos.h" +#include "VideoSyncIos.h" #include #undef BOOL @@ -485,6 +485,11 @@ void* CWinSystemIOS::GetEAGLContextObj() return [g_xbmcController getEAGLContextObj]; } -#endif +std::unique_ptr CWinSystemIOS::GetVideoSync(void *clock) +{ + std::unique_ptr pVSync(new CVideoSyncIos(clock)); + return pVSync; +} #endif + diff --git a/xbmc/windowing/osx/WinSystemOSX.h b/xbmc/windowing/osx/WinSystemOSX.h index c46e27b41e..fe37b26b68 100644 --- a/xbmc/windowing/osx/WinSystemOSX.h +++ b/xbmc/windowing/osx/WinSystemOSX.h @@ -74,6 +74,8 @@ public: virtual int GetNumScreens(); virtual int GetCurrentScreen(); virtual double GetCurrentRefreshrate() { return m_refreshRate; } + + virtual std::unique_ptr GetVideoSync(void *clock) override; void WindowChangedScreen(); @@ -88,6 +90,7 @@ public: std::string GetClipboardText(void); + protected: void HandlePossibleRefreshrateChange(); void* CreateWindowedContext(void* shareCtx); diff --git a/xbmc/windowing/osx/WinSystemOSX.mm b/xbmc/windowing/osx/WinSystemOSX.mm index 752e8655a8..365bb0badb 100644 --- a/xbmc/windowing/osx/WinSystemOSX.mm +++ b/xbmc/windowing/osx/WinSystemOSX.mm @@ -18,13 +18,12 @@ * */ -#if defined(TARGET_DARWIN_OSX) - //hack around problem with xbmc's typedef int BOOL // and obj-c's typedef unsigned char BOOL #define BOOL XBMC_BOOL #include "WinSystemOSX.h" #include "WinEventsOSX.h" +#include "VideoSyncOsx.h" #include "Application.h" #include "ServiceBroker.h" #include "messaging/ApplicationMessenger.h" @@ -1798,4 +1797,8 @@ std::string CWinSystemOSX::GetClipboardText(void) return utf8_text; } -#endif +std::unique_ptr CWinSystemOSX::GetVideoSync(void *clock) +{ + std::unique_ptr pVSync(new CVideoSyncOsx(clock)); + return pVSync; +} diff --git a/xbmc/windowing/windows/VideoSyncD3D.cpp b/xbmc/windowing/windows/VideoSyncD3D.cpp new file mode 100644 index 0000000000..e48b91e121 --- /dev/null +++ b/xbmc/windowing/windows/VideoSyncD3D.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include "system.h" + +#if defined(TARGET_WINDOWS) + +#include "utils/log.h" +#include "Utils/TimeUtils.h" +#include "Utils/MathUtils.h" +#include "windowing\WindowingFactory.h" +#include "video/videosync/VideoSyncD3D.h" +#include "guilib/GraphicContext.h" +#include "platform/win32/dxerr.h" +#include "utils/StringUtils.h" + +void CVideoSyncD3D::OnLostDisplay() +{ + if (!m_displayLost) + { + m_displayLost = true; + m_lostEvent.Wait(); + } +} + +void CVideoSyncD3D::OnResetDisplay() +{ + m_displayReset = true; +} + +void CVideoSyncD3D::RefreshChanged() +{ + m_displayReset = true; +} + +bool CVideoSyncD3D::Setup(PUPDATECLOCK func) +{ + CLog::Log(LOGDEBUG, "CVideoSyncD3D: Setting up Direct3d"); + CSingleLock lock(g_graphicsContext); + g_Windowing.Register(this); + m_displayLost = false; + m_displayReset = false; + m_lostEvent.Reset(); + UpdateClock = func; + + // we need a high priority thread to get accurate timing + if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL)) + CLog::Log(LOGDEBUG, "CVideoSyncD3D: SetThreadPriority failed"); + + return true; +} + +void CVideoSyncD3D::Run(std::atomic& stop) +{ + int64_t Now; + int64_t LastVBlankTime; + int NrVBlanks; + double VBlankTime; + int64_t systemFrequency = CurrentHostFrequency(); + + // init the vblanktime + Now = CurrentHostCounter(); + LastVBlankTime = Now; + m_lastUpdateTime = Now - systemFrequency; + while (!stop && !m_displayLost && !m_displayReset) + { + // sleep until vblank + HRESULT hr = g_Windowing.GetCurrentOutput()->WaitForVBlank(); + + // calculate how many vblanks happened + Now = CurrentHostCounter(); + VBlankTime = (double)(Now - LastVBlankTime) / (double)systemFrequency; + NrVBlanks = MathUtils::round_int(VBlankTime * m_fps); + + // update the vblank timestamp, update the clock and send a signal that we got a vblank + UpdateClock(NrVBlanks, Now, m_refClock); + + // save the timestamp of this vblank so we can calculate how many vblanks happened next time + LastVBlankTime = Now; + + if ((Now - m_lastUpdateTime) >= systemFrequency) + { + float fps = m_fps; + if (fps != GetFps()) + break; + } + + // because we had a vblank, sleep until half the refreshrate period because i think WaitForVBlank block any rendering stuf + // without sleeping we have freeze rendering + int SleepTime = (int)((LastVBlankTime + (systemFrequency / MathUtils::round_int(m_fps) / 2) - Now) * 1000 / systemFrequency); + if (SleepTime > 50) + SleepTime = 50; //failsafe + if (SleepTime > 0) + ::Sleep(SleepTime); + } + + m_lostEvent.Set(); + while (!stop && m_displayLost && !m_displayReset) + { + Sleep(10); + } +} + +void CVideoSyncD3D::Cleanup() +{ + CLog::Log(LOGDEBUG, "CVideoSyncD3D: Cleaning up Direct3d"); + + m_lostEvent.Set(); + g_Windowing.Unregister(this); +} + +float CVideoSyncD3D::GetFps() +{ + DXGI_MODE_DESC DisplayMode; + g_Windowing.GetDisplayMode(&DisplayMode, true); + + m_fps = (DisplayMode.RefreshRate.Denominator != 0) ? (float)DisplayMode.RefreshRate.Numerator / (float)DisplayMode.RefreshRate.Denominator : 0.0f; + + if (m_fps == 0.0) + m_fps = 60.0f; + + if (m_fps == 23 || m_fps == 29 || m_fps == 59) + m_fps++; + + if (g_Windowing.Interlaced()) + { + m_fps *= 2; + } + return m_fps; +} + +std::string CVideoSyncD3D::GetErrorDescription(HRESULT hr) +{ + WCHAR buff[1024]; + DXGetErrorDescription(hr, buff, 1024); + std::wstring error(DXGetErrorString(hr)); + std::wstring descr(buff); + return StringUtils::Format("%ls: %ls", error.c_str(), descr.c_str()); +} + +#endif diff --git a/xbmc/windowing/windows/VideoSyncD3D.h b/xbmc/windowing/windows/VideoSyncD3D.h new file mode 100644 index 0000000000..486b6206f6 --- /dev/null +++ b/xbmc/windowing/windows/VideoSyncD3D.h @@ -0,0 +1,50 @@ +#pragma once +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#if defined(TARGET_WINDOWS) + +#include "video/videosync/VideoSync.h" +#include "guilib/DispResource.h" +#include "threads/Event.h" + +class CVideoSyncD3D : public CVideoSync, IDispResource +{ +public: + CVideoSyncD3D(CVideoReferenceClock *clock) : CVideoSync(clock) {}; + bool Setup(PUPDATECLOCK func) override; + void Run(std::atomic& stop) override; + void Cleanup() override; + float GetFps() override; + void RefreshChanged() override; + // IDispResource overrides + void OnLostDisplay() override; + void OnResetDisplay() override; + +private: + static std::string GetErrorDescription(HRESULT hr); + + volatile bool m_displayLost; + volatile bool m_displayReset; + CEvent m_lostEvent; + int64_t m_lastUpdateTime; +}; + +#endif -- cgit v1.2.3