diff options
-rw-r--r-- | cmake/scripts/windows/ArchSetup.cmake | 2 | ||||
-rw-r--r-- | cmake/scripts/windowsstore/ArchSetup.cmake | 2 | ||||
-rw-r--r-- | docs/README.Windows.md | 3 | ||||
-rw-r--r-- | xbmc/HDRStatus.h | 1 | ||||
-rw-r--r-- | xbmc/SeekHandler.cpp | 4 | ||||
-rw-r--r-- | xbmc/application/ApplicationPlayer.cpp | 4 | ||||
-rw-r--r-- | xbmc/application/ApplicationPlayer.h | 2 | ||||
-rw-r--r-- | xbmc/cores/Direction.h | 18 | ||||
-rw-r--r-- | xbmc/cores/IPlayer.h | 3 | ||||
-rw-r--r-- | xbmc/cores/VideoPlayer/Edl.cpp | 105 | ||||
-rw-r--r-- | xbmc/cores/VideoPlayer/Edl.h | 48 | ||||
-rw-r--r-- | xbmc/cores/VideoPlayer/VideoPlayer.cpp | 17 | ||||
-rw-r--r-- | xbmc/cores/VideoPlayer/VideoPlayer.h | 2 | ||||
-rw-r--r-- | xbmc/cores/VideoPlayer/test/edl/TestEdl.cpp | 21 | ||||
-rw-r--r-- | xbmc/platform/win10/CMakeLists.txt | 4 | ||||
-rw-r--r-- | xbmc/platform/win32/CMakeLists.txt | 4 | ||||
-rw-r--r-- | xbmc/platform/win32/WIN32Util.cpp | 75 | ||||
-rw-r--r-- | xbmc/platform/win32/WIN32Util.h | 3 | ||||
-rw-r--r-- | xbmc/platform/win32/WinRtUtil.cpp | 202 | ||||
-rw-r--r-- | xbmc/platform/win32/WinRtUtil.h | 22 | ||||
-rw-r--r-- | xbmc/rendering/dx/DeviceResources.h | 1 | ||||
-rw-r--r-- | xbmc/rendering/dx/DirectXHelper.h | 16 |
22 files changed, 386 insertions, 173 deletions
diff --git a/cmake/scripts/windows/ArchSetup.cmake b/cmake/scripts/windows/ArchSetup.cmake index b19789d5bb..7116196207 100644 --- a/cmake/scripts/windows/ArchSetup.cmake +++ b/cmake/scripts/windows/ArchSetup.cmake @@ -1,5 +1,5 @@ # Minimum SDK version we support -set(VS_MINIMUM_SDK_VERSION 10.0.18362.0) +set(VS_MINIMUM_SDK_VERSION 10.0.22621.0) if(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION VERSION_LESS VS_MINIMUM_SDK_VERSION) message(FATAL_ERROR "Detected Windows SDK version is ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}.\n" diff --git a/cmake/scripts/windowsstore/ArchSetup.cmake b/cmake/scripts/windowsstore/ArchSetup.cmake index c3e580aa69..a39914cca0 100644 --- a/cmake/scripts/windowsstore/ArchSetup.cmake +++ b/cmake/scripts/windowsstore/ArchSetup.cmake @@ -1,5 +1,5 @@ # Minimum SDK version we support -set(VS_MINIMUM_SDK_VERSION 10.0.18362.0) +set(VS_MINIMUM_SDK_VERSION 10.0.22621.0) if(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION VERSION_LESS VS_MINIMUM_SDK_VERSION) message(FATAL_ERROR "Detected Windows SDK version is ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}.\n" diff --git a/docs/README.Windows.md b/docs/README.Windows.md index 44ab5ee352..60ece12300 100644 --- a/docs/README.Windows.md +++ b/docs/README.Windows.md @@ -1,7 +1,7 @@ ![Kodi Logo](resources/banner_slim.png) # Windows build guide -This guide has been tested with Windows 10 Pro x64, version 21H2, build 19044.1415. Please read it in full before you proceed to familiarize yourself with the build procedure. +This guide has been tested with Windows 10 Pro x64, version 22H2, build 19045.4529. Please read it in full before you proceed to familiarize yourself with the build procedure. ## Table of Contents 1. **[Document conventions](#1-document-conventions)** @@ -83,6 +83,7 @@ Default options are fine. Start the Visual Studio installer and click **Workloads** select * Under **Desktop & Mobile** section select * `Desktop development with C++` + * Select the optional element Windows 11 SDK (10.0.22621.0) * `Universal Windows Platform development` (if compiling for UWP or UWP-ARM) Click in **Individual components** select diff --git a/xbmc/HDRStatus.h b/xbmc/HDRStatus.h index 8fe5aaec53..72613e12cd 100644 --- a/xbmc/HDRStatus.h +++ b/xbmc/HDRStatus.h @@ -10,6 +10,7 @@ enum class HDR_STATUS { + HDR_UNKNOWN = -2, HDR_TOGGLE_FAILED = -1, HDR_UNSUPPORTED = 0, HDR_OFF = 1, diff --git a/xbmc/SeekHandler.cpp b/xbmc/SeekHandler.cpp index 3e93694b16..7d84926348 100644 --- a/xbmc/SeekHandler.cpp +++ b/xbmc/SeekHandler.cpp @@ -311,12 +311,12 @@ bool CSeekHandler::OnAction(const CAction &action) } case ACTION_NEXT_SCENE: { - appPlayer->SeekScene(true); + appPlayer->SeekScene(Direction::FORWARD); return true; } case ACTION_PREV_SCENE: { - appPlayer->SeekScene(false); + appPlayer->SeekScene(Direction::BACKWARD); return true; } case ACTION_ANALOG_SEEK_FORWARD: diff --git a/xbmc/application/ApplicationPlayer.cpp b/xbmc/application/ApplicationPlayer.cpp index 18e78d3c0c..9a59242a85 100644 --- a/xbmc/application/ApplicationPlayer.cpp +++ b/xbmc/application/ApplicationPlayer.cpp @@ -327,10 +327,10 @@ bool CApplicationPlayer::CanSeek() const return (player && player->CanSeek()); } -bool CApplicationPlayer::SeekScene(bool bPlus) +bool CApplicationPlayer::SeekScene(Direction seekDirection) { std::shared_ptr<IPlayer> player = GetInternal(); - return (player && player->SeekScene(bPlus)); + return (player && player->SeekScene(seekDirection)); } void CApplicationPlayer::SeekTime(int64_t iTime) diff --git a/xbmc/application/ApplicationPlayer.h b/xbmc/application/ApplicationPlayer.h index d695f66aef..ccee506bd6 100644 --- a/xbmc/application/ApplicationPlayer.h +++ b/xbmc/application/ApplicationPlayer.h @@ -144,7 +144,7 @@ public: void Seek(bool bPlus = true, bool bLargeStep = false, bool bChapterOverride = false); int SeekChapter(int iChapter); void SeekPercentage(float fPercent = 0); - bool SeekScene(bool bPlus = true); + bool SeekScene(Direction seekDirection); void SeekTime(int64_t iTime = 0); void SeekTimeRelative(int64_t iTime = 0); void SetAudioStream(int iStream); diff --git a/xbmc/cores/Direction.h b/xbmc/cores/Direction.h new file mode 100644 index 0000000000..ffcfe73683 --- /dev/null +++ b/xbmc/cores/Direction.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2024 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +/*! + * @brief Specifies/Abstracts a direction +*/ +enum class Direction : bool +{ + FORWARD, /*!< Forward */ + BACKWARD /*!< Backward */ +}; diff --git a/xbmc/cores/IPlayer.h b/xbmc/cores/IPlayer.h index a782dd72ac..d988d77527 100644 --- a/xbmc/cores/IPlayer.h +++ b/xbmc/cores/IPlayer.h @@ -8,6 +8,7 @@ #pragma once +#include "Direction.h" #include "IPlayerCallback.h" #include "Interface/StreamInfo.h" #include "MenuType.h" @@ -105,7 +106,7 @@ public: virtual bool IsPassthrough() const { return false;} virtual bool CanSeek() const { return true; } virtual void Seek(bool bPlus = true, bool bLargeStep = false, bool bChapterOverride = false) = 0; - virtual bool SeekScene(bool bPlus = true) {return false;} + virtual bool SeekScene(Direction seekDirection) { return false; } virtual void SeekPercentage(float fPercent = 0){} virtual float GetCachePercentage() const { return 0; } virtual void SetMute(bool bOnOff){} diff --git a/xbmc/cores/VideoPlayer/Edl.cpp b/xbmc/cores/VideoPlayer/Edl.cpp index 01c7ed09b1..664358a4f5 100644 --- a/xbmc/cores/VideoPlayer/Edl.cpp +++ b/xbmc/cores/VideoPlayer/Edl.cpp @@ -43,56 +43,57 @@ void CEdl::Clear() m_lastEditTime = -1; } -bool CEdl::ReadEditDecisionLists(const CFileItem& fileItem, const float fFramesPerSecond) +bool CEdl::ReadEditDecisionLists(const CFileItem& fileItem, float fps) { - bool bFound = false; + bool found = false; /* * Only check for edit decision lists if the movie is on the local hard drive, or accessed over a * network share (even if from a different private network). */ - const std::string& strMovie = fileItem.GetDynPath(); - if ((URIUtils::IsHD(strMovie) || URIUtils::IsOnLAN(strMovie, LanCheckMode::ANY_PRIVATE_SUBNET)) && - !URIUtils::IsInternetStream(strMovie)) + const std::string& mediaFilePath = fileItem.GetDynPath(); + if ((URIUtils::IsHD(mediaFilePath) || + URIUtils::IsOnLAN(mediaFilePath, LanCheckMode::ANY_PRIVATE_SUBNET)) && + !URIUtils::IsInternetStream(mediaFilePath)) { CLog::Log(LOGDEBUG, "{} - Checking for edit decision lists (EDL) on local drive or remote share for: {}", - __FUNCTION__, CURL::GetRedacted(strMovie)); + __FUNCTION__, CURL::GetRedacted(mediaFilePath)); /* * Read any available file format until a valid EDL related file is found. */ - if (!bFound) - bFound = ReadVideoReDo(strMovie); + if (!found) + found = ReadVideoReDo(mediaFilePath); - if (!bFound) - bFound = ReadEdl(strMovie, fFramesPerSecond); + if (!found) + found = ReadEdl(mediaFilePath, fps); - if (!bFound) - bFound = ReadComskip(strMovie, fFramesPerSecond); + if (!found) + found = ReadComskip(mediaFilePath, fps); - if (!bFound) - bFound = ReadBeyondTV(strMovie); + if (!found) + found = ReadBeyondTV(mediaFilePath); } else { - bFound = ReadPvr(fileItem); + found = ReadPvr(fileItem); } - if (bFound) + if (found) { MergeShortCommBreaks(); AddSceneMarkersAtStartAndEndOfEdits(); } - return bFound; + return found; } -bool CEdl::ReadEdl(const std::string& strMovie, const float fFramesPerSecond) +bool CEdl::ReadEdl(const std::string& mediaFilePath, float fps) { Clear(); - std::string edlFilename(URIUtils::ReplaceExtension(strMovie, ".edl")); + const std::string edlFilename(URIUtils::ReplaceExtension(mediaFilePath, ".edl")); if (!CFile::Exists(edlFilename)) return false; @@ -190,10 +191,10 @@ bool CEdl::ReadEdl(const std::string& strMovie, const float fFramesPerSecond) } else if (strFields[i][0] == '#') // #12345 format for frame number { - if (fFramesPerSecond > 0.0f) + if (fps > 0.0f) { - editStartEnd[i] = static_cast<int64_t>(std::atol(strFields[i].substr(1).c_str()) / - fFramesPerSecond * 1000); // frame number to ms + editStartEnd[i] = static_cast<int64_t>(std::atol(strFields[i].substr(1).c_str()) / fps * + 1000); // frame number to ms } else { @@ -281,11 +282,11 @@ bool CEdl::ReadEdl(const std::string& strMovie, const float fFramesPerSecond) } } -bool CEdl::ReadComskip(const std::string& strMovie, const float fFramesPerSecond) +bool CEdl::ReadComskip(const std::string& mediaFilePath, float fps) { Clear(); - std::string comskipFilename(URIUtils::ReplaceExtension(strMovie, ".txt")); + const std::string comskipFilename(URIUtils::ReplaceExtension(mediaFilePath, ".txt")); if (!CFile::Exists(comskipFilename)) return false; @@ -315,9 +316,9 @@ bool CEdl::ReadComskip(const std::string& strMovie, const float fFramesPerSecond /* * Not all generated Comskip files have the frame rate information. */ - if (fFramesPerSecond > 0.0f) + if (fps > 0.0f) { - fFrameRate = fFramesPerSecond; + fFrameRate = fps; CLog::Log(LOGWARNING, "Edl::ReadComskip - Frame rate not in Comskip file. Using detected frames per " "second: {:.3f}", @@ -376,7 +377,7 @@ bool CEdl::ReadComskip(const std::string& strMovie, const float fFramesPerSecond } } -bool CEdl::ReadVideoReDo(const std::string& strMovie) +bool CEdl::ReadVideoReDo(const std::string& mediaFilePath) { /* * VideoReDo file is strange. Tags are XML like, but it isn't an XML file. @@ -385,7 +386,7 @@ bool CEdl::ReadVideoReDo(const std::string& strMovie) */ Clear(); - std::string videoReDoFilename(URIUtils::ReplaceExtension(strMovie, ".Vprj")); + const std::string videoReDoFilename(URIUtils::ReplaceExtension(mediaFilePath, ".Vprj")); if (!CFile::Exists(videoReDoFilename)) return false; @@ -474,11 +475,12 @@ bool CEdl::ReadVideoReDo(const std::string& strMovie) } } -bool CEdl::ReadBeyondTV(const std::string& strMovie) +bool CEdl::ReadBeyondTV(const std::string& mediaFilePath) { Clear(); - std::string beyondTVFilename(URIUtils::ReplaceExtension(strMovie, URIUtils::GetExtension(strMovie) + ".chapters.xml")); + const std::string beyondTVFilename(URIUtils::ReplaceExtension( + mediaFilePath, URIUtils::GetExtension(mediaFilePath) + ".chapters.xml")); if (!CFile::Exists(beyondTVFilename)) return false; @@ -707,7 +709,7 @@ bool CEdl::AddEdit(const Edit& newEdit) return true; } -bool CEdl::AddSceneMarker(const int iSceneMarker) +bool CEdl::AddSceneMarker(int iSceneMarker) { Edit edit; @@ -882,37 +884,35 @@ EDL::Action CEdl::GetLastEditActionType() const return m_lastEditActionType; } -bool CEdl::GetNextSceneMarker(bool bPlus, const int iClock, int *iSceneMarker) +std::optional<int> CEdl::GetNextSceneMarker(Direction direction, int clock) { if (!HasSceneMarker()) - return false; + return std::nullopt; - int iSeek = GetTimeAfterRestoringCuts(iClock); + std::optional<int> sceneMarker; + const int seekTime = GetTimeAfterRestoringCuts(clock); - int iDiff = 10 * 60 * 60 * 1000; // 10 hours to ms. - bool bFound = false; + int diff = 10 * 60 * 60 * 1000; // 10 hours to ms. - if (bPlus) // Find closest scene forwards + if (direction == Direction::FORWARD) // Find closest scene forwards { for (int i = 0; i < (int)m_vecSceneMarkers.size(); i++) { - if ((m_vecSceneMarkers[i] > iSeek) && ((m_vecSceneMarkers[i] - iSeek) < iDiff)) + if ((m_vecSceneMarkers[i] > seekTime) && ((m_vecSceneMarkers[i] - seekTime) < diff)) { - iDiff = m_vecSceneMarkers[i] - iSeek; - *iSceneMarker = m_vecSceneMarkers[i]; - bFound = true; + diff = m_vecSceneMarkers[i] - seekTime; + sceneMarker = m_vecSceneMarkers[i]; } } } - else // Find closest scene backwards + else if (direction == Direction::BACKWARD) // Find closest scene backwards { for (int i = 0; i < (int)m_vecSceneMarkers.size(); i++) { - if ((m_vecSceneMarkers[i] < iSeek) && ((iSeek - m_vecSceneMarkers[i]) < iDiff)) + if ((m_vecSceneMarkers[i] < seekTime) && ((seekTime - m_vecSceneMarkers[i]) < diff)) { - iDiff = iSeek - m_vecSceneMarkers[i]; - *iSceneMarker = m_vecSceneMarkers[i]; - bFound = true; + diff = seekTime - m_vecSceneMarkers[i]; + sceneMarker = m_vecSceneMarkers[i]; } } } @@ -922,16 +922,17 @@ bool CEdl::GetNextSceneMarker(bool bPlus, const int iClock, int *iSceneMarker) * picked up when scene markers are added. */ Edit edit; - if (bFound && InEdit(*iSceneMarker, &edit) && edit.action == Action::CUT) - *iSceneMarker = edit.end; + if (sceneMarker && InEdit(sceneMarker.value(), &edit) && edit.action == Action::CUT) + sceneMarker = edit.end; - return bFound; + return sceneMarker; } -std::string CEdl::MillisecondsToTimeString(const int iMilliseconds) +std::string CEdl::MillisecondsToTimeString(int milliSeconds) { - std::string strTimeString = StringUtils::SecondsToTimeString((long)(iMilliseconds / 1000), TIME_FORMAT_HH_MM_SS); // milliseconds to seconds - strTimeString += StringUtils::Format(".{:03}", iMilliseconds % 1000); + std::string strTimeString = StringUtils::SecondsToTimeString( + static_cast<long>(milliSeconds / 1000), TIME_FORMAT_HH_MM_SS); // milliseconds to seconds + strTimeString += StringUtils::Format(".{:03}", milliSeconds % 1000); return strTimeString; } diff --git a/xbmc/cores/VideoPlayer/Edl.h b/xbmc/cores/VideoPlayer/Edl.h index faf3e732f1..3b0279c34d 100644 --- a/xbmc/cores/VideoPlayer/Edl.h +++ b/xbmc/cores/VideoPlayer/Edl.h @@ -8,8 +8,10 @@ #pragma once +#include "cores/Direction.h" #include "cores/EdlEdit.h" +#include <optional> #include <string> #include <vector> @@ -20,10 +22,7 @@ class CEdl public: CEdl(); - // FIXME: remove const modifier for fFramesPerSecond as it makes no sense as it means nothing - // for the reader of the interface, but limits the implementation - // to not modify the parameter on stack - bool ReadEditDecisionLists(const CFileItem& fileItem, const float fFramesPerSecond); + bool ReadEditDecisionLists(const CFileItem& fileItem, float fps); void Clear(); /*! @@ -144,15 +143,15 @@ public: */ EDL::Action GetLastEditActionType() const; - // FIXME: remove const modifier for iClock as it makes no sense as it means nothing - // for the reader of the interface, but limits the implementation - // to not modify the parameter on stack - bool GetNextSceneMarker(bool bPlus, const int iClock, int *iSceneMarker); + /*! + * @brief Get the next scene marker with respect to the provided clock time + * @param direction (the direction of the search - backward or forward) + * @param clock the current position of the clock + * @return the position of the scenemarker (nullopt if none) + */ + std::optional<int> GetNextSceneMarker(Direction direction, int clock); - // FIXME: remove const modifier as it makes no sense as it means nothing - // for the reader of the interface, but limits the implementation - // to not modify the parameter on stack - static std::string MillisecondsToTimeString(const int iMilliseconds); + static std::string MillisecondsToTimeString(int milliSeconds); private: // total cut time (edl cuts) in ms @@ -170,22 +169,10 @@ private: */ EDL::Action m_lastEditActionType{EDL::EDL_ACTION_NONE}; - // FIXME: remove const modifier for fFramesPerSecond as it makes no sense as it means nothing - // for the reader of the interface, but limits the implementation - // to not modify the parameter on stack - bool ReadEdl(const std::string& strMovie, const float fFramesPerSecond); - // FIXME: remove const modifier for fFramesPerSecond as it makes no sense as it means nothing - // for the reader of the interface, but limits the implementation - // to not modify the parameter on stack - bool ReadComskip(const std::string& strMovie, const float fFramesPerSecond); - // FIXME: remove const modifier for strMovie as it makes no sense as it means nothing - // for the reader of the interface, but limits the implementation - // to not modify the parameter on stack - bool ReadVideoReDo(const std::string& strMovie); - // FIXME: remove const modifier for strMovie as it makes no sense as it means nothing - // for the reader of the interface, but limits the implementation - // to not modify the parameter on stack - bool ReadBeyondTV(const std::string& strMovie); + bool ReadEdl(const std::string& mediaFilePath, float fps); + bool ReadComskip(const std::string& mediaFilePath, float fps); + bool ReadVideoReDo(const std::string& mediaFilePath); + bool ReadBeyondTV(const std::string& mediaFilePath); bool ReadPvr(const CFileItem& fileItem); /*! @@ -195,10 +182,7 @@ private: */ bool AddEdit(const EDL::Edit& newEdit); - // FIXME: remove const modifier for strMovie as it makes no sense as it means nothing - // for the reader of the interface, but limits the implementation - // to not modify the parameter on stack - bool AddSceneMarker(const int sceneMarker); + bool AddSceneMarker(int sceneMarker); void MergeShortCommBreaks(); diff --git a/xbmc/cores/VideoPlayer/VideoPlayer.cpp b/xbmc/cores/VideoPlayer/VideoPlayer.cpp index d2568bd710..be3d3a030b 100644 --- a/xbmc/cores/VideoPlayer/VideoPlayer.cpp +++ b/xbmc/cores/VideoPlayer/VideoPlayer.cpp @@ -3254,7 +3254,7 @@ void CVideoPlayer::Seek(bool bPlus, bool bLargeStep, bool bChapterOverride) m_callback.OnPlayBackSeek(seekTarget, seekTarget - time); } -bool CVideoPlayer::SeekScene(bool bPlus) +bool CVideoPlayer::SeekScene(Direction seekDirection) { if (!m_Edl.HasSceneMarker()) return false; @@ -3264,18 +3264,19 @@ bool CVideoPlayer::SeekScene(bool bPlus) * grace period applied it is impossible to go backwards past a scene marker. */ int64_t clock = GetTime(); - if (!bPlus && clock > 5 * 1000) // 5 seconds + if (seekDirection == Direction::BACKWARD && clock > 5 * 1000) // 5 seconds clock -= 5 * 1000; - int iScenemarker; - if (m_Edl.GetNextSceneMarker(bPlus, clock, &iScenemarker)) + const std::optional<int> sceneMarker = + m_Edl.GetNextSceneMarker(seekDirection, static_cast<int>(clock)); + if (sceneMarker) { /* * Seeking is flushed and inaccurate, just like Seek() */ CDVDMsgPlayerSeek::CMode mode; - mode.time = iScenemarker; - mode.backward = !bPlus; + mode.time = sceneMarker.value(); + mode.backward = seekDirection == Direction::BACKWARD; mode.accurate = false; mode.restore = false; mode.trickplay = false; @@ -4527,7 +4528,7 @@ bool CVideoPlayer::OnAction(const CAction &action) m_processInfo->SeekFinished(0); return true; } - else if (SeekScene(true)) + else if (SeekScene(Direction::FORWARD)) return true; else break; @@ -4538,7 +4539,7 @@ bool CVideoPlayer::OnAction(const CAction &action) m_processInfo->SeekFinished(0); return true; } - else if (SeekScene(false)) + else if (SeekScene(Direction::BACKWARD)) return true; else break; diff --git a/xbmc/cores/VideoPlayer/VideoPlayer.h b/xbmc/cores/VideoPlayer/VideoPlayer.h index 1300b0fd4e..f340b85e83 100644 --- a/xbmc/cores/VideoPlayer/VideoPlayer.h +++ b/xbmc/cores/VideoPlayer/VideoPlayer.h @@ -264,7 +264,7 @@ public: bool IsPassthrough() const override; bool CanSeek() const override; void Seek(bool bPlus, bool bLargeStep, bool bChapterOverride) override; - bool SeekScene(bool bPlus = true) override; + bool SeekScene(Direction seekDirection) override; void SeekPercentage(float iPercent) override; float GetCachePercentage() const override; diff --git a/xbmc/cores/VideoPlayer/test/edl/TestEdl.cpp b/xbmc/cores/VideoPlayer/test/edl/TestEdl.cpp index 7098b9144e..4516d9666c 100644 --- a/xbmc/cores/VideoPlayer/test/edl/TestEdl.cpp +++ b/xbmc/cores/VideoPlayer/test/edl/TestEdl.cpp @@ -84,17 +84,20 @@ TEST_F(TestEdl, TestParsingMplayerTimeBasedEDL) const auto commbreak = edl.GetEditList().at(1); EXPECT_EQ(commbreak.action, Action::COMM_BREAK); // We should have a scenemarker at the commbreak start and another on commbreak end - int time; + std::optional<int> time = edl.GetNextSceneMarker(Direction::FORWARD, commbreak.start - 1); // lets cycle to the next scenemarker if starting from 1 msec before the start (or end) of the commbreak - EXPECT_EQ(edl.GetNextSceneMarker(true, commbreak.start - 1, &time), true); - EXPECT_EQ(edl.GetTimeWithoutCuts(time), commbreak.start); - EXPECT_EQ(edl.GetNextSceneMarker(true, commbreak.end - 1, &time), true); - EXPECT_EQ(edl.GetTimeWithoutCuts(time), commbreak.end); + EXPECT_NE(time, std::nullopt); + EXPECT_EQ(edl.GetTimeWithoutCuts(time.value()), commbreak.start); + time = edl.GetNextSceneMarker(Direction::FORWARD, commbreak.end - 1); + EXPECT_NE(time, std::nullopt); + EXPECT_EQ(edl.GetTimeWithoutCuts(time.value()), commbreak.end); // same if we cycle backwards - EXPECT_EQ(edl.GetNextSceneMarker(false, commbreak.start + 1, &time), true); - EXPECT_EQ(edl.GetTimeWithoutCuts(time), commbreak.start); - EXPECT_EQ(edl.GetNextSceneMarker(false, commbreak.end + 1, &time), true); - EXPECT_EQ(edl.GetTimeWithoutCuts(time), commbreak.end); + time = edl.GetNextSceneMarker(Direction::BACKWARD, commbreak.start + 1); + EXPECT_NE(time, std::nullopt); + EXPECT_EQ(edl.GetTimeWithoutCuts(time.value()), commbreak.start); + time = edl.GetNextSceneMarker(Direction::BACKWARD, commbreak.end + 1); + EXPECT_NE(time, std::nullopt); + EXPECT_EQ(edl.GetTimeWithoutCuts(time.value()), commbreak.end); // We should be in an edit if we are in the middle of a commbreak... // lets check and confirm the edits match (after restoring cuts) Edit thisEdit; diff --git a/xbmc/platform/win10/CMakeLists.txt b/xbmc/platform/win10/CMakeLists.txt index 19bc19f0e5..ff6260e36a 100644 --- a/xbmc/platform/win10/CMakeLists.txt +++ b/xbmc/platform/win10/CMakeLists.txt @@ -11,6 +11,7 @@ set(SOURCES CPUInfoWin10.cpp ../win32/MemUtils.cpp ../win32/pch.cpp ../win32/WIN32Util.cpp + ../win32/WinRtUtil.cpp ../win32/XTimeUtils.cpp) set(HEADERS AsyncHelpers.h @@ -29,6 +30,7 @@ set(HEADERS AsyncHelpers.h ../win32/PlatformDefs.h ../win32/resource.h ../win32/unistd.h - ../win32/WIN32Util.h) + ../win32/WIN32Util.h + ../win32/WinRtUtil.h) core_add_library(platform_win10) diff --git a/xbmc/platform/win32/CMakeLists.txt b/xbmc/platform/win32/CMakeLists.txt index 28faedb9c0..ab54d6c8b2 100644 --- a/xbmc/platform/win32/CMakeLists.txt +++ b/xbmc/platform/win32/CMakeLists.txt @@ -10,6 +10,7 @@ set(SOURCES CharsetConverter.cpp PlatformWin32.cpp WIN32Util.cpp WindowHelper.cpp + WinRtUtil.cpp XTimeUtils.cpp) set(HEADERS CharsetConverter.h @@ -27,6 +28,7 @@ set(HEADERS CharsetConverter.h resource.h unistd.h WIN32Util.h - WindowHelper.h) + WindowHelper.h + WinRtUtil.h) core_add_library(platform_win32) diff --git a/xbmc/platform/win32/WIN32Util.cpp b/xbmc/platform/win32/WIN32Util.cpp index 29658a42a9..46726af482 100644 --- a/xbmc/platform/win32/WIN32Util.cpp +++ b/xbmc/platform/win32/WIN32Util.cpp @@ -11,6 +11,7 @@ #include "CompileInfo.h" #include "ServiceBroker.h" #include "Util.h" +#include "WinRtUtil.h" #include "WindowHelper.h" #include "guilib/LocalizeStrings.h" #include "my_ntddscsi.h" @@ -1347,53 +1348,13 @@ HDR_STATUS CWIN32Util::ToggleWindowsHDR(DXGI_MODE_DESC& modeDesc) return status; } -HDR_STATUS CWIN32Util::GetWindowsHDRStatus() +HDR_STATUS CWIN32Util::GetWindowsHDRStatusWin32() { + HDR_STATUS status = HDR_STATUS::HDR_UNKNOWN; + +#ifdef TARGET_WINDOWS_DESKTOP bool advancedColorSupported = false; bool advancedColorEnabled = false; - HDR_STATUS status = HDR_STATUS::HDR_UNSUPPORTED; - -#ifdef TARGET_WINDOWS_STORE - auto displayInformation = DisplayInformation::GetForCurrentView(); - - if (displayInformation) - { - auto advancedColorInfo = displayInformation.GetAdvancedColorInfo(); - - if (advancedColorInfo) - { - if (advancedColorInfo.CurrentAdvancedColorKind() == AdvancedColorKind::HighDynamicRange) - { - advancedColorSupported = true; - advancedColorEnabled = true; - } - } - } - // Try to find out if the display supports HDR even if Windows HDR switch is OFF - if (!advancedColorEnabled) - { - auto displayManager = DisplayManager::Create(DisplayManagerOptions::None); - - if (displayManager) - { - auto targets = displayManager.GetCurrentTargets(); - - for (const auto& target : targets) - { - if (target.IsConnected()) - { - auto displayMonitor = target.TryGetMonitor(); - if (displayMonitor.MaxLuminanceInNits() >= 400.0f) - { - advancedColorSupported = true; - break; - } - } - } - displayManager.Close(); - } - } -#else uint32_t pathCount = 0; uint32_t modeCount = 0; @@ -1451,7 +1412,6 @@ HDR_STATUS CWIN32Util::GetWindowsHDRStatus() } } } -#endif if (!advancedColorSupported) { @@ -1466,10 +1426,35 @@ HDR_STATUS CWIN32Util::GetWindowsHDRStatus() CLog::LogF(LOGDEBUG, "Display is HDR capable and current HDR status is {}", advancedColorEnabled ? "ON" : "OFF"); } +#endif // TARGET_WINDOWS_DESKTOP return status; } +HDR_STATUS CWIN32Util::GetWindowsHDRStatus() +{ + HDR_STATUS status = HDR_STATUS::HDR_UNKNOWN; + +#ifdef TARGET_WINDOWS_STORE + if (CSysInfo::GetWindowsDeviceFamily() == CSysInfo::Xbox && + HDR_STATUS::HDR_UNKNOWN != (status = CWinRtUtil::GetWindowsHDRStatus())) + return status; + + // Not Xbox or detection failure: fallback to traditional UWP method + status = CWinRtUtil::GetWindowsHDRStatusUWP(); + return status == HDR_STATUS::HDR_UNKNOWN ? HDR_STATUS::HDR_UNSUPPORTED : status; +#else + // WinRT detection available for Win 11 22621 and above. + if (CSysInfo::IsWindowsVersionAtLeast(CSysInfo::WindowsVersionWin11_22H2) && + HDR_STATUS::HDR_UNKNOWN != (status = CWinRtUtil::GetWindowsHDRStatus())) + return status; + + // Not Win11 or detection failure: fallback to traditional Win32 method + status = GetWindowsHDRStatusWin32(); + return status == HDR_STATUS::HDR_UNKNOWN ? HDR_STATUS::HDR_UNSUPPORTED : status; +#endif +} + /*! * \brief Retrieve from the system the max luminance of SDR content in HDR. * diff --git a/xbmc/platform/win32/WIN32Util.h b/xbmc/platform/win32/WIN32Util.h index 054ca262bd..33033fb431 100644 --- a/xbmc/platform/win32/WIN32Util.h +++ b/xbmc/platform/win32/WIN32Util.h @@ -105,4 +105,7 @@ public: * Undefined results when the strings are not formatted properly. */ static bool IsDriverVersionAtLeast(const std::string& version1, const std::string& version2); + +private: + static HDR_STATUS GetWindowsHDRStatusWin32(); }; diff --git a/xbmc/platform/win32/WinRtUtil.cpp b/xbmc/platform/win32/WinRtUtil.cpp new file mode 100644 index 0000000000..ce239a722e --- /dev/null +++ b/xbmc/platform/win32/WinRtUtil.cpp @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2024 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "WinRtUtil.h" + +#include "rendering/dx/DirectXHelper.h" +#include "utils/SystemInfo.h" +#include "utils/log.h" + +#ifdef TARGET_WINDOWS_DESKTOP +#include <Windows.Graphics.Display.Interop.h> + +#else +#include <winrt/Windows.Devices.Display.Core.h> + +using namespace winrt::Windows::Devices::Display::Core; +#endif + +#include <winrt/Windows.Graphics.Display.h> + +using namespace winrt::Windows::Graphics::Display; + +#ifdef TARGET_WINDOWS_DESKTOP +extern HWND g_hWnd; +#endif + +static constexpr std::string_view AdvancedColorKindToString(AdvancedColorKind kind) +{ + switch (kind) + { + case AdvancedColorKind::StandardDynamicRange: + return "SDR"; + case AdvancedColorKind::WideColorGamut: + return "WCG"; + case AdvancedColorKind::HighDynamicRange: + return "HDR"; + default: + return "unknown"; + } +} + +static void LogAdvancedColorInfo(AdvancedColorInfo colorInfo) +{ + std::string availableKinds; + static constexpr std::array<AdvancedColorKind, 3> kinds{AdvancedColorKind::StandardDynamicRange, + AdvancedColorKind::WideColorGamut, + AdvancedColorKind::HighDynamicRange}; + + for (const AdvancedColorKind& kind : kinds) + { + if (colorInfo.IsAdvancedColorKindAvailable(kind)) + availableKinds.append(AdvancedColorKindToString(kind)).append(" "); + } + + CLog::LogF(LOGDEBUG, "Current advanced color kind: {}, supported kinds: {}", + AdvancedColorKindToString(colorInfo.CurrentAdvancedColorKind()), availableKinds); +} + +HDR_STATUS CWinRtUtil::GetWindowsHDRStatus() +{ + DisplayInformation displayInformation{nullptr}; + +#ifdef TARGET_WINDOWS_STORE + displayInformation = DisplayInformation::GetForCurrentView(); + + if (!displayInformation) + { + CLog::LogF(LOGERROR, "unable to retrieve DisplayInformation."); + return HDR_STATUS::HDR_UNKNOWN; + } +#else + auto factory{ + winrt::try_get_activation_factory<DisplayInformation, IDisplayInformationStaticsInterop>()}; + + if (!factory) + { + CLog::LogF(LOGERROR, + "unable to activate IDisplayInformationStaticsInterop. Windows version too low?"); + return HDR_STATUS::HDR_UNKNOWN; + } + + HMONITOR hm{}; + if (g_hWnd) + { + RECT rect{}; + + if (FALSE == GetWindowRect(g_hWnd, &rect)) + { + CLog::LogF(LOGERROR, "unable to retrieve window rect, error {}", + DX::GetErrorDescription(GetLastError())); + return HDR_STATUS::HDR_UNKNOWN; + } + + hm = MonitorFromRect(&rect, MONITOR_DEFAULTTONULL); + + if (hm == NULL) + { + CLog::LogF(LOGERROR, "unable to retrieve monitor intersecting with application window"); + return HDR_STATUS::HDR_UNKNOWN; + } + } + else + { + POINT point{}; + + hm = MonitorFromPoint(point, MONITOR_DEFAULTTONULL); + + if (hm == NULL) + { + CLog::LogF(LOGERROR, "unable to retrieve primary monitor"); + return HDR_STATUS::HDR_UNKNOWN; + } + } + + HRESULT hr = factory->GetForMonitor(hm, winrt::guid_of<DisplayInformation>(), + winrt::put_abi(displayInformation)); + if (FAILED(hr)) + { + CLog::LogF(LOGERROR, "unable to retrieve DisplayInformation for window, error {}", + DX::GetErrorDescription(hr)); + return HDR_STATUS::HDR_UNKNOWN; + } +#endif + + AdvancedColorInfo colorInfo{displayInformation.GetAdvancedColorInfo()}; + + if (!colorInfo) + { + CLog::LogF(LOGERROR, "unable to retrieve advanced color info"); + return HDR_STATUS::HDR_UNKNOWN; + } + + LogAdvancedColorInfo(colorInfo); + + if (colorInfo.CurrentAdvancedColorKind() == AdvancedColorKind::HighDynamicRange) + return HDR_STATUS::HDR_ON; + + // IsAdvancedColorKindAvailable works for desktop Windows 11 22H2+ and Xbox + if (colorInfo.IsAdvancedColorKindAvailable(AdvancedColorKind::HighDynamicRange)) + return HDR_STATUS::HDR_OFF; + else + return HDR_STATUS::HDR_UNSUPPORTED; +} + +HDR_STATUS CWinRtUtil::GetWindowsHDRStatusUWP() +{ +#ifdef TARGET_WINDOWS_STORE + // Legacy detection, useful for UWP desktop at this point + DisplayInformation displayInformation = DisplayInformation::GetForCurrentView(); + + if (!displayInformation) + { + CLog::LogF(LOGERROR, "unable to retrieve DisplayInformation."); + return HDR_STATUS::HDR_UNKNOWN; + } + + AdvancedColorInfo colorInfo{displayInformation.GetAdvancedColorInfo()}; + + if (!colorInfo) + { + CLog::LogF(LOGERROR, "unable to retrieve advanced color info"); + return HDR_STATUS::HDR_UNKNOWN; + } + + if (colorInfo.CurrentAdvancedColorKind() == AdvancedColorKind::HighDynamicRange) + return HDR_STATUS::HDR_ON; + + // Detects any hdr-capable screen connected to the system, not necessarily the one that contains + // the Kodi window + bool hdrSupported{false}; + auto displayManager = DisplayManager::Create(DisplayManagerOptions::None); + + if (displayManager) + { + auto targets = displayManager.GetCurrentTargets(); + + for (const auto& target : targets) + { + if (target.IsConnected()) + { + auto displayMonitor = target.TryGetMonitor(); + if (displayMonitor.MaxLuminanceInNits() >= 400.0f) + { + hdrSupported = true; + break; + } + } + } + displayManager.Close(); + } + + if (hdrSupported) + return HDR_STATUS::HDR_OFF; +#endif // TARGET_WINDOWS_STORE + + return HDR_STATUS::HDR_UNSUPPORTED; +} diff --git a/xbmc/platform/win32/WinRtUtil.h b/xbmc/platform/win32/WinRtUtil.h new file mode 100644 index 0000000000..7d58fe7dc1 --- /dev/null +++ b/xbmc/platform/win32/WinRtUtil.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2024 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "HDRStatus.h" + +class CWinRtUtil +{ +private: + CWinRtUtil() = default; + ~CWinRtUtil() = default; + +public: + static HDR_STATUS GetWindowsHDRStatus(); + static HDR_STATUS GetWindowsHDRStatusUWP(); +}; diff --git a/xbmc/rendering/dx/DeviceResources.h b/xbmc/rendering/dx/DeviceResources.h index b0ed0f4882..a512e5a0bb 100644 --- a/xbmc/rendering/dx/DeviceResources.h +++ b/xbmc/rendering/dx/DeviceResources.h @@ -17,6 +17,7 @@ #include <concrt.h> #include <dxgi1_5.h> +#include <winrt/windows.foundation.h> #include <wrl.h> #include <wrl/client.h> diff --git a/xbmc/rendering/dx/DirectXHelper.h b/xbmc/rendering/dx/DirectXHelper.h index 779b8751d5..368bfcbad9 100644 --- a/xbmc/rendering/dx/DirectXHelper.h +++ b/xbmc/rendering/dx/DirectXHelper.h @@ -202,18 +202,4 @@ namespace DX const std::string DXGIColorSpaceTypeToString(DXGI_COLOR_SPACE_TYPE type); const std::string D3D11VideoProcessorFormatSupportToString( D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT value); -} - -#ifdef TARGET_WINDOWS_DESKTOP -namespace winrt -{ - namespace Windows - { - namespace Foundation - { - typedef DX::SizeGen<float> Size; - typedef DX::SizeGen<int> SizeInt; - } - } -} -#endif + } // namespace DX |