Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanups to session / service broker / chooser interface #1680

Merged
merged 3 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/CompKodiProps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ void LogDrmJsonDictKeys(std::string_view keyName,
}
} // unnamed namespace

ADP::KODI_PROPS::CCompKodiProps::CCompKodiProps(const std::map<std::string, std::string>& props)
void ADP::KODI_PROPS::CCompKodiProps::Init(const std::map<std::string, std::string>& props)
{
std::string licenseUrl;

Expand Down
4 changes: 3 additions & 1 deletion src/CompKodiProps.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,11 @@ struct DrmCfg
class ATTR_DLL_LOCAL CCompKodiProps
{
public:
CCompKodiProps(const std::map<std::string, std::string>& props);
CCompKodiProps() = default;
~CCompKodiProps() = default;

void Init(const std::map<std::string, std::string>& props);

// \brief HTTP parameters used to download manifest updates
std::string GetManifestUpdParams() const { return m_manifestUpdParams; }
// \brief HTTP parameters used to download manifests
Expand Down
30 changes: 30 additions & 0 deletions src/CompResources.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <kodi/AddonBase.h>
#endif

#include <atomic>
#include <mutex>
#include <string>
#include <unordered_set>
Expand All @@ -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:
Expand All @@ -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.
Expand All @@ -58,6 +87,7 @@ class ATTR_DLL_LOCAL CCompResources
const adaptive::AdaptiveTree& GetTree() const { return *m_tree; }

private:
std::atomic<ScreenInfo> m_screenInfo;
std::unordered_set<UTILS::CURL::Cookie> m_cookies;
std::mutex m_cookiesMutex;
adaptive::AdaptiveTree* m_tree{nullptr};
Expand Down
46 changes: 21 additions & 25 deletions src/Session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<uint8_t>(1U) << static_cast<int>(StreamType::AUDIO);
break;
case 2:
m_mediaTypeMask = static_cast<uint8_t>(1U) << static_cast<int>(StreamType::VIDEO);
break;
case 3:
m_mediaTypeMask = (static_cast<uint8_t>(1U) << static_cast<int>(StreamType::VIDEO)) |
(static_cast<uint8_t>(1U) << static_cast<int>(StreamType::SUBTITLE));
break;
default:
m_mediaTypeMask = static_cast<uint8_t>(~0);
}
}

CSession::~CSession()
{
LOG::Log(LOGDEBUG, "CSession::~CSession()");
Expand Down Expand Up @@ -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<uint8_t>(1U) << static_cast<int>(StreamType::AUDIO);
break;
case 2:
m_mediaTypeMask = static_cast<uint8_t>(1U) << static_cast<int>(StreamType::VIDEO);
break;
case 3:
m_mediaTypeMask = (static_cast<uint8_t>(1U) << static_cast<int>(StreamType::VIDEO)) |
(static_cast<uint8_t>(1U) << static_cast<int>(StreamType::SUBTITLE));
break;
default:
m_mediaTypeMask = static_cast<uint8_t>(~0);
}

auto& kodiProps = CSrvBroker::GetKodiProps();

// Get URN's wich are supported by this addon
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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)
Expand Down
19 changes: 7 additions & 12 deletions src/Session.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@
#include "common/AdaptiveTree.h"
#include "decrypters/IDecrypter.h"

#include <bento4/Ap4.h>
#include <kodi/tools/DllHelper.h>

#if defined(ANDROID)
#include <kodi/platform/android/System.h>
#endif
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -342,8 +339,6 @@ class ATTR_DLL_LOCAL CSession : public adaptive::AdaptiveStreamObserver
const std::vector<std::string_view>& keySystems);

private:
std::string m_manifestUrl;
std::unique_ptr<kodi::tools::CDllHelper> m_dllHelper;
std::shared_ptr<DRM::IDecrypter> m_decrypter;

struct CCdmSession
Expand All @@ -355,7 +350,7 @@ class ATTR_DLL_LOCAL CSession : public adaptive::AdaptiveStreamObserver
std::vector<CCdmSession> m_cdmSessions;

adaptive::AdaptiveTree* m_adaptiveTree{nullptr};
CHOOSER::IRepresentationChooser* m_reprChooser;
CHOOSER::IRepresentationChooser* m_reprChooser{nullptr};

std::vector<std::unique_ptr<CStream>> m_streams;
CStream* m_timingStream{nullptr};
Expand Down
11 changes: 7 additions & 4 deletions src/SrvBroker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,17 @@

using namespace ADP;

CSrvBroker::CSrvBroker() = default;
CSrvBroker::CSrvBroker()
{
m_compKodiProps = std::make_unique<KODI_PROPS::CCompKodiProps>();
m_compResources = std::make_unique<RESOURCES::CCompResources>();
m_compSettings = std::make_unique<SETTINGS::CCompSettings>();
};
CSrvBroker::~CSrvBroker() = default;

void CSrvBroker::Init(const std::map<std::string, std::string>& kodiProps)
{
m_compKodiProps = std::make_unique<KODI_PROPS::CCompKodiProps>(kodiProps);
m_compResources = std::make_unique<RESOURCES::CCompResources>();
m_compSettings = std::make_unique<SETTINGS::CCompSettings>();
m_compKodiProps->Init(kodiProps);
}

void CSrvBroker::InitStage2(adaptive::AdaptiveTree* tree)
Expand Down
21 changes: 11 additions & 10 deletions src/common/Chooser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "Chooser.h"

#include "CompResources.h"
#include "ChooserAskQuality.h"
#include "ChooserDefault.h"
#include "ChooserFixedRes.h"
Expand Down Expand Up @@ -70,6 +71,7 @@ IRepresentationChooser* CHOOSER::CreateRepresentationChooser()
if (!reprChooser)
reprChooser = new CRepresentationChooserDefault();

reprChooser->OnUpdateScreenRes();
reprChooser->Initialize(props);

return reprChooser;
Expand All @@ -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
Expand All @@ -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;
}
}

Expand Down
12 changes: 2 additions & 10 deletions src/common/Chooser.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
23 changes: 9 additions & 14 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "main.h"

#include "CompResources.h"
#include "CompKodiProps.h"
#include "SrvBroker.h"
#include "Stream.h"
Expand Down Expand Up @@ -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<CSession>(url);
m_session->SetVideoResolution(m_currentVideoWidth, m_currentVideoHeight, m_currentVideoMaxWidth,
m_currentVideoMaxHeight);
m_session = std::make_shared<CSession>();

if (!m_session->Initialize())
if (!m_session->Initialize(props.GetURL()))
{
m_session = nullptr;
return false;
Expand Down Expand Up @@ -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<int>(width);
m_currentVideoHeight = static_cast<int>(height);
m_currentVideoMaxWidth = static_cast<int>(maxWidth);
m_currentVideoMaxHeight = static_cast<int>(maxHeight);
CSrvBroker::GetResources().SetScreenInfo({static_cast<int>(width), static_cast<int>(height),
static_cast<int>(maxWidth),
static_cast<int>(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)
Expand Down
6 changes: 1 addition & 5 deletions src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,7 @@ class ATTR_DLL_LOCAL CInputStreamAdaptive : public kodi::addon::CInstanceInputSt
std::shared_ptr<SESSION::CSession> GetSession() { return m_session; };

private:
std::shared_ptr<SESSION::CSession> m_session{nullptr};
int m_currentVideoWidth{0};
int m_currentVideoHeight{0};
int m_currentVideoMaxWidth{0};
int m_currentVideoMaxHeight{0};
std::shared_ptr<SESSION::CSession> m_session;
std::map<INPUTSTREAM_TYPE, unsigned int> m_IncludedStreams;
int m_failedSeekTime = ~0;
std::string m_chapterName;
Expand Down
6 changes: 5 additions & 1 deletion src/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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}")