diff --git a/src/CompKodiProps.cpp b/src/CompKodiProps.cpp index cdf11f9c7..28d9a8b47 100644 --- a/src/CompKodiProps.cpp +++ b/src/CompKodiProps.cpp @@ -90,7 +90,7 @@ void LogDrmJsonDictKeys(std::string_view keyName, } } // unnamed namespace -ADP::KODI_PROPS::CCompKodiProps::CCompKodiProps(const std::map& props) +void ADP::KODI_PROPS::CCompKodiProps::Init(const std::map& props) { std::string licenseUrl; diff --git a/src/CompKodiProps.h b/src/CompKodiProps.h index 0aa43cf08..60a4e425f 100644 --- a/src/CompKodiProps.h +++ b/src/CompKodiProps.h @@ -117,9 +117,11 @@ struct DrmCfg class ATTR_DLL_LOCAL CCompKodiProps { public: - CCompKodiProps(const std::map& props); + CCompKodiProps() = default; ~CCompKodiProps() = default; + void Init(const std::map& props); + // \brief HTTP parameters used to download manifest updates std::string GetManifestUpdParams() const { return m_manifestUpdParams; } // \brief HTTP parameters used to download manifests diff --git a/src/CompResources.h b/src/CompResources.h index 48b78db40..a60a53bf0 100644 --- a/src/CompResources.h +++ b/src/CompResources.h @@ -16,6 +16,7 @@ #include #endif +#include #include #include #include @@ -30,6 +31,22 @@ namespace ADP { namespace RESOURCES { +struct ScreenInfo +{ + ScreenInfo() = default; + ScreenInfo(int widthPx, int heightPx, int maxWidthPx, int maxHeightPx) + { + width = widthPx; + height = heightPx; + maxWidth = maxWidthPx; + maxHeight = maxHeightPx; + } + int width{0}; + int height{0}; + int maxWidth{0}; + int maxHeight{0}; +}; + class ATTR_DLL_LOCAL CCompResources { public: @@ -38,6 +55,18 @@ class ATTR_DLL_LOCAL CCompResources void InitStage2(adaptive::AdaptiveTree* tree) { m_tree = tree; } + /*! + * \brief Get the current screen info. + * \return The screen info. + */ + ScreenInfo GetScreenInfo() const { return m_screenInfo.load(); } + + /*! + * \brief Set the screen info. + * \param screenInfo The scren info + */ + void SetScreenInfo(const ScreenInfo& screenInfo) { m_screenInfo = screenInfo; } + /*! * \brief Cookies that can be shared along with HTTP requests. * Some video services require you to accept cookies and send cookies along with requests. @@ -58,6 +87,7 @@ class ATTR_DLL_LOCAL CCompResources const adaptive::AdaptiveTree& GetTree() const { return *m_tree; } private: + std::atomic m_screenInfo; std::unordered_set m_cookies; std::mutex m_cookiesMutex; adaptive::AdaptiveTree* m_tree{nullptr}; diff --git a/src/Session.cpp b/src/Session.cpp index a15c8aa6e..09660ebf4 100644 --- a/src/Session.cpp +++ b/src/Session.cpp @@ -34,27 +34,6 @@ using namespace PLAYLIST; using namespace SESSION; using namespace UTILS; -CSession::CSession(const std::string& manifestUrl) : m_manifestUrl(manifestUrl) -{ - m_reprChooser = CHOOSER::CreateRepresentationChooser(); - - switch (kodi::addon::GetSettingInt("MEDIATYPE")) - { - case 1: - m_mediaTypeMask = static_cast(1U) << static_cast(StreamType::AUDIO); - break; - case 2: - m_mediaTypeMask = static_cast(1U) << static_cast(StreamType::VIDEO); - break; - case 3: - m_mediaTypeMask = (static_cast(1U) << static_cast(StreamType::VIDEO)) | - (static_cast(1U) << static_cast(StreamType::SUBTITLE)); - break; - default: - m_mediaTypeMask = static_cast(~0); - } -} - CSession::~CSession() { LOG::Log(LOGDEBUG, "CSession::~CSession()"); @@ -124,8 +103,26 @@ void CSession::DisposeDecrypter() | initialize +---------------------------------------------------------------------*/ -bool CSession::Initialize() +bool CSession::Initialize(std::string manifestUrl) { + m_reprChooser = CHOOSER::CreateRepresentationChooser(); + + switch (CSrvBroker::GetSettings().GetMediaType()) + { + case 1: + m_mediaTypeMask = static_cast(1U) << static_cast(StreamType::AUDIO); + break; + case 2: + m_mediaTypeMask = static_cast(1U) << static_cast(StreamType::VIDEO); + break; + case 3: + m_mediaTypeMask = (static_cast(1U) << static_cast(StreamType::VIDEO)) | + (static_cast(1U) << static_cast(StreamType::SUBTITLE)); + break; + default: + m_mediaTypeMask = static_cast(~0); + } + auto& kodiProps = CSrvBroker::GetKodiProps(); // Get URN's wich are supported by this addon @@ -160,7 +157,6 @@ bool CSession::Initialize() } } - std::string manifestUrl = m_manifestUrl; URL::RemovePipePart(manifestUrl); // No pipe char uses, must be used Kodi properties only URL::AppendParameters(manifestUrl, kodiProps.GetManifestParams()); @@ -1017,9 +1013,9 @@ void CSession::StartReader( m_changed = true; } -void CSession::SetVideoResolution(int width, int height, int maxWidth, int maxHeight) +void CSession::OnScreenResChange() { - m_reprChooser->SetScreenResolution(width, height, maxWidth, maxHeight); + m_reprChooser->OnUpdateScreenRes(); }; bool CSession::GetNextSample(ISampleReader*& sampleReader) diff --git a/src/Session.h b/src/Session.h index cc93dcb1c..ebf435404 100644 --- a/src/Session.h +++ b/src/Session.h @@ -13,9 +13,6 @@ #include "common/AdaptiveTree.h" #include "decrypters/IDecrypter.h" -#include -#include - #if defined(ANDROID) #include #endif @@ -29,15 +26,16 @@ namespace SESSION class ATTR_DLL_LOCAL CSession : public adaptive::AdaptiveStreamObserver { public: - CSession(const std::string& manifestUrl); + CSession() = default; virtual ~CSession(); void DeleteStreams(); /*! \brief Initialize the session + * \param manifestUrl The manifest URL * \return True if has success, false otherwise */ - bool Initialize(); + bool Initialize(std::string manifestUrl); /* * \brief Check HDCP parameters to remove unplayable representations @@ -206,11 +204,10 @@ class ATTR_DLL_LOCAL CSession : public adaptive::AdaptiveStreamObserver return ret; }; - /*! \brief To inform of Kodi's current screen resolution - * \param width The width in pixels - * \param height The height in pixels + /*! + * \brief Callback for screen resolution change. */ - void SetVideoResolution(int width, int height, int maxWidth, int maxHeight); + void OnScreenResChange(); /*! \brief Seek streams and readers to a specified time * \param seekTime The seek time in seconds @@ -342,8 +339,6 @@ class ATTR_DLL_LOCAL CSession : public adaptive::AdaptiveStreamObserver const std::vector& keySystems); private: - std::string m_manifestUrl; - std::unique_ptr m_dllHelper; std::shared_ptr m_decrypter; struct CCdmSession @@ -355,7 +350,7 @@ class ATTR_DLL_LOCAL CSession : public adaptive::AdaptiveStreamObserver std::vector m_cdmSessions; adaptive::AdaptiveTree* m_adaptiveTree{nullptr}; - CHOOSER::IRepresentationChooser* m_reprChooser; + CHOOSER::IRepresentationChooser* m_reprChooser{nullptr}; std::vector> m_streams; CStream* m_timingStream{nullptr}; diff --git a/src/SrvBroker.cpp b/src/SrvBroker.cpp index b2e467c8e..9b0bfb93c 100644 --- a/src/SrvBroker.cpp +++ b/src/SrvBroker.cpp @@ -14,14 +14,17 @@ using namespace ADP; -CSrvBroker::CSrvBroker() = default; +CSrvBroker::CSrvBroker() +{ + m_compKodiProps = std::make_unique(); + m_compResources = std::make_unique(); + m_compSettings = std::make_unique(); +}; CSrvBroker::~CSrvBroker() = default; void CSrvBroker::Init(const std::map& kodiProps) { - m_compKodiProps = std::make_unique(kodiProps); - m_compResources = std::make_unique(); - m_compSettings = std::make_unique(); + m_compKodiProps->Init(kodiProps); } void CSrvBroker::InitStage2(adaptive::AdaptiveTree* tree) diff --git a/src/common/Chooser.cpp b/src/common/Chooser.cpp index 127770d4f..5edfd8578 100644 --- a/src/common/Chooser.cpp +++ b/src/common/Chooser.cpp @@ -8,6 +8,7 @@ #include "Chooser.h" +#include "CompResources.h" #include "ChooserAskQuality.h" #include "ChooserDefault.h" #include "ChooserFixedRes.h" @@ -70,6 +71,7 @@ IRepresentationChooser* CHOOSER::CreateRepresentationChooser() if (!reprChooser) reprChooser = new CRepresentationChooserDefault(); + reprChooser->OnUpdateScreenRes(); reprChooser->Initialize(props); return reprChooser; @@ -84,14 +86,13 @@ CHOOSER::IRepresentationChooser::IRepresentationChooser() m_isAdjustRefreshRate = true; } -void CHOOSER::IRepresentationChooser::SetScreenResolution(const int width, - const int height, - const int maxWidth, - const int maxHeight) +void CHOOSER::IRepresentationChooser::OnUpdateScreenRes() { + const auto sInfo = CSrvBroker::GetResources().GetScreenInfo(); + LOG::Log(LOGINFO, "[Repr. chooser] Resolution set: %dx%d, max allowed: %dx%d, Adjust refresh rate: %i", - width, height, maxWidth, maxHeight, m_isAdjustRefreshRate); + sInfo.width, sInfo.height, sInfo.maxWidth, sInfo.maxHeight, m_isAdjustRefreshRate); // Use case: User chooses to upscale Kodi GUI from TV instead of Kodi engine. // In this case "Adjust refresh rate" setting can be enabled and then @@ -100,16 +101,16 @@ void CHOOSER::IRepresentationChooser::SetScreenResolution(const int width, // For example we can have the GUI at 1080p and when playback starts can be // auto-switched to 4k, but to allow Kodi do this we have to provide the // stream resolution that match the max allowed screen resolution. - if (m_isAdjustRefreshRate && width < maxWidth && height < maxHeight) + if (m_isAdjustRefreshRate && sInfo.width < sInfo.maxWidth && sInfo.height < sInfo.maxHeight) { - m_screenCurrentWidth = maxWidth; - m_screenCurrentHeight = maxHeight; + m_screenCurrentWidth = sInfo.maxWidth; + m_screenCurrentHeight = sInfo.maxHeight; m_isForceStartsMaxRes = true; } else { - m_screenCurrentWidth = width; - m_screenCurrentHeight = height; + m_screenCurrentWidth = sInfo.width; + m_screenCurrentHeight = sInfo.height; } } diff --git a/src/common/Chooser.h b/src/common/Chooser.h index 57c91d73d..b3126dacc 100644 --- a/src/common/Chooser.h +++ b/src/common/Chooser.h @@ -60,17 +60,9 @@ class ATTR_DLL_LOCAL IRepresentationChooser virtual void PostInit() {} /*! - * \brief Set the current screen resolution. - * To be called every time the screen resolution change. - * \param width Width resolution - * \param height Height resolution - * \param maxWidth Max width resolution - * \param maxHeight Max height resolution + * \brief Callback to update screen resolution. */ - void SetScreenResolution(const int width, - const int height, - const int maxWidth, - const int maxHeight); + void OnUpdateScreenRes(); /*! * \brief Set the current download speed. diff --git a/src/main.cpp b/src/main.cpp index 207a62fe9..a6ec67eea 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,6 +8,7 @@ #include "main.h" +#include "CompResources.h" #include "CompKodiProps.h" #include "SrvBroker.h" #include "Stream.h" @@ -37,15 +38,11 @@ bool CInputStreamAdaptive::Open(const kodi::addon::InputstreamProperty& props) { LOG::Log(LOGDEBUG, "Open()"); - std::string url = props.GetURL(); - CSrvBroker::GetInstance()->Init(props.GetProperties()); - m_session = std::make_shared(url); - m_session->SetVideoResolution(m_currentVideoWidth, m_currentVideoHeight, m_currentVideoMaxWidth, - m_currentVideoMaxHeight); + m_session = std::make_shared(); - if (!m_session->Initialize()) + if (!m_session->Initialize(props.GetURL())) { m_session = nullptr; return false; @@ -467,21 +464,19 @@ bool CInputStreamAdaptive::DemuxSeekTime(double time, bool backwards, double& st return true; } -// Kodi callback, called just before CInputStreamAdaptive::Open method, -// and every time the resolution change while in playback (e.g. window resize) void CInputStreamAdaptive::SetVideoResolution(unsigned int width, unsigned int height, unsigned int maxWidth, unsigned int maxHeight) { - m_currentVideoWidth = static_cast(width); - m_currentVideoHeight = static_cast(height); - m_currentVideoMaxWidth = static_cast(maxWidth); - m_currentVideoMaxHeight = static_cast(maxHeight); + CSrvBroker::GetResources().SetScreenInfo({static_cast(width), static_cast(height), + static_cast(maxWidth), + static_cast(maxHeight)}); - // This can be called just after CInputStreamAdaptive::Open callback + // SetVideoResolution method is initially called before CInputStreamAdaptive::Open so there is no session yet + // After that, other callbacks may be made during playback (e.g. for window resize) if (m_session) - m_session->SetVideoResolution(width, height, maxWidth, maxHeight); + m_session->OnScreenResChange(); } bool CInputStreamAdaptive::PosTime(int ms) diff --git a/src/main.h b/src/main.h index aa2fce9aa..a6dbb8ed6 100644 --- a/src/main.h +++ b/src/main.h @@ -56,11 +56,7 @@ class ATTR_DLL_LOCAL CInputStreamAdaptive : public kodi::addon::CInstanceInputSt std::shared_ptr GetSession() { return m_session; }; private: - std::shared_ptr m_session{nullptr}; - int m_currentVideoWidth{0}; - int m_currentVideoHeight{0}; - int m_currentVideoMaxWidth{0}; - int m_currentVideoMaxHeight{0}; + std::shared_ptr m_session; std::map m_IncludedStreams; int m_failedSeekTime = ~0; std::string m_chapterName; diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 2ed234956..9c163249e 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -53,7 +53,11 @@ add_executable(${BINARY} ../utils/XMLUtils.cpp ) -target_link_libraries(${BINARY} PRIVATE ${BENTO4_LIBRARIES} ${PUGIXML_LIBRARIES} ${GTEST_LIBRARIES} Threads::Threads ${CMAKE_DL_LIBS}) +if(LINUX) + SET(ADD_LINK_LIBS "atomic") +endif() + +target_link_libraries(${BINARY} PRIVATE ${BENTO4_LIBRARIES} ${PUGIXML_LIBRARIES} ${GTEST_LIBRARIES} Threads::Threads ${CMAKE_DL_LIBS} ${ADD_LINK_LIBS}) set(TEST_DATA_DIR "${CMAKE_SOURCE_DIR}/src/test/manifests") add_test(NAME manifest_tests COMMAND ${BINARY} "${TEST_DATA_DIR}")