diff --git a/pvr.eon/addon.xml.in b/pvr.eon/addon.xml.in index 18118da..b22b61b 100644 --- a/pvr.eon/addon.xml.in +++ b/pvr.eon/addon.xml.in @@ -1,7 +1,7 @@ diff --git a/pvr.eon/changelog.txt b/pvr.eon/changelog.txt index 1a1b72e..5df959a 100644 --- a/pvr.eon/changelog.txt +++ b/pvr.eon/changelog.txt @@ -14,3 +14,5 @@ v20.7.1 - Adapt user agent header for platforms when streaming v20.7.2 - Fix EPG date +v20.7.3 + - Optionally use inputstream.ffmpegdirect diff --git a/pvr.eon/resources/language/resource.language.de_de/strings.po b/pvr.eon/resources/language/resource.language.de_de/strings.po index 4438190..cf27f2d 100644 --- a/pvr.eon/resources/language/resource.language.de_de/strings.po +++ b/pvr.eon/resources/language/resource.language.de_de/strings.po @@ -211,3 +211,23 @@ msgstr "" msgctxt "#30048" msgid "min Zeit." msgstr "" + +msgctxt "#30049" +msgid "Streaming" +msgstr "Streaming" + +msgctxt "#30050" +msgid "Inputstream" +msgstr "Inputstream" + +msgctxt "#30051" +msgid "Select Inputstream" +msgstr "Inputstream auswählen" + +msgctxt "#30052" +msgid "inputstream.adaptive" +msgstr "inputstream.adaptive" + +msgctxt "#30053" +msgid "inputstream.ffmpegdirect" +msgstr "inputstream.ffmpegdirect" diff --git a/pvr.eon/resources/language/resource.language.en_gb/strings.po b/pvr.eon/resources/language/resource.language.en_gb/strings.po index c6cf0f6..5373fb6 100644 --- a/pvr.eon/resources/language/resource.language.en_gb/strings.po +++ b/pvr.eon/resources/language/resource.language.en_gb/strings.po @@ -199,3 +199,23 @@ msgstr "" msgctxt "#30048" msgid "min left." msgstr "" + +msgctxt "#30049" +msgid "Streaming" +msgstr "" + +msgctxt "#30050" +msgid "Inputstream" +msgstr "" + +msgctxt "#30051" +msgid "Select Inputstream" +msgstr "" + +msgctxt "#30052" +msgid "inputstream.adaptive" +msgstr "" + +msgctxt "#30053" +msgid "inputstream.ffmpegdirect" +msgstr "" diff --git a/pvr.eon/resources/language/resource.language.en_us/strings.po b/pvr.eon/resources/language/resource.language.en_us/strings.po index cede618..d3f1f1e 100644 --- a/pvr.eon/resources/language/resource.language.en_us/strings.po +++ b/pvr.eon/resources/language/resource.language.en_us/strings.po @@ -203,3 +203,23 @@ msgstr "" msgctxt "#30048" msgid "min left." msgstr "" + +msgctxt "#30049" +msgid "Streaming" +msgstr "" + +msgctxt "#30050" +msgid "Inputstream" +msgstr "" + +msgctxt "#30051" +msgid "Select Inputstream" +msgstr "" + +msgctxt "#30052" +msgid "inputstream.adaptive" +msgstr "" + +msgctxt "#30053" +msgid "inputstream.ffmpegdirect" +msgstr "" diff --git a/pvr.eon/resources/settings.xml b/pvr.eon/resources/settings.xml index 3299a35..0c98281 100644 --- a/pvr.eon/resources/settings.xml +++ b/pvr.eon/resources/settings.xml @@ -186,5 +186,20 @@ + + + + 0 + 0 + + + + + + + + + + diff --git a/src/PVREon.cpp b/src/PVREon.cpp index 53e9b2c..93cbfcf 100644 --- a/src/PVREon.cpp +++ b/src/PVREon.cpp @@ -833,30 +833,41 @@ bool CPVREon::HandleSession(bool start, int cid, int epg_id) void CPVREon::SetStreamProperties(std::vector& properties, const std::string& url, - bool realtime, bool playTimeshiftBuffer, - const std::string& license) + const bool& realtime, const bool& playTimeshiftBuffer, const bool& isLive, + const int& starttime, const int& endtime) { kodi::Log(ADDON_LOG_DEBUG, "[PLAY STREAM] url: %s", url.c_str()); properties.emplace_back(PVR_STREAM_PROPERTY_STREAMURL, url); - properties.emplace_back(PVR_STREAM_PROPERTY_INPUTSTREAM, "inputstream.adaptive"); properties.emplace_back(PVR_STREAM_PROPERTY_ISREALTIMESTREAM, realtime ? "true" : "false"); - - kodi::Log(ADDON_LOG_DEBUG, "[PLAY STREAM] hls"); - properties.emplace_back("inputstream.adaptive.manifest_type", "hls"); properties.emplace_back(PVR_STREAM_PROPERTY_MIMETYPE, "application/x-mpegURL"); -// properties.emplace_back("inputstream.adaptive.original_audio_language", "bs"); -// properties.emplace_back("inputstream.adaptive.stream_selection_type", "adaptive"); - properties.emplace_back("inputstream.adaptive.stream_selection_type", "manual-osd"); - properties.emplace_back("inputstream.adaptive.manifest_headers", "User-Agent=" + m_parameters.user_agent); - -// properties.emplace_back("inputstream.adaptive.license_type", "com.widevine.alpha"); -// properties.emplace_back("inputstream.adaptive.license_key", -// "https://lic.drmtoday.com/license-proxy-widevine/cenc/" -// "|Content-Type=text%2Fxml&dt-custom-data=" + -// license + "|R{SSM}|JBlicense"); - - properties.emplace_back("inputstream.adaptive.manifest_update_parameter", "full"); + + int inputstream = m_settings->GetInputstream(); + + if (inputstream == INPUTSTREAM_ADAPTIVE) + { + properties.emplace_back(PVR_STREAM_PROPERTY_INPUTSTREAM, "inputstream.adaptive"); + properties.emplace_back("inputstream.adaptive.manifest_type", "hls"); + // properties.emplace_back("inputstream.adaptive.original_audio_language", "bs"); + // properties.emplace_back("inputstream.adaptive.stream_selection_type", "adaptive"); + properties.emplace_back("inputstream.adaptive.stream_selection_type", "manual-osd"); + properties.emplace_back("inputstream.adaptive.manifest_headers", "User-Agent=" + m_parameters.user_agent); + properties.emplace_back("inputstream.adaptive.manifest_update_parameter", "full"); + } else if (inputstream == INPUTSTREAM_FFMPEGDIRECT) + { + properties.emplace_back(PVR_STREAM_PROPERTY_INPUTSTREAM, "inputstream.ffmpegdirect"); + properties.emplace_back("inputstream.ffmpegdirect.manifest_type", "hls"); + properties.emplace_back("inputstream.ffmpegdirect.is_realtime_stream", "true"); + properties.emplace_back("inputstream.ffmpegdirect.stream_mode", isLive ? "timeshift" : "catchup"); + if (!isLive) { + properties.emplace_back("inputstream.ffmpegdirect.catchup_buffer_start_time", std::to_string(starttime)); + properties.emplace_back("inputstream.ffmpegdirect.catchup_buffer_end_time", std::to_string(endtime)); + properties.emplace_back("inputstream.ffmpegdirect.programme_start_time", std::to_string(starttime)); + properties.emplace_back("inputstream.ffmpegdirect.programme_end_time", std::to_string(endtime)); + } + } else { + kodi::Log(ADDON_LOG_DEBUG, "Unknown inputstream detected"); + } } @@ -1012,7 +1023,7 @@ PVR_ERROR CPVREon::GetEPGTagStreamProperties( { if (channel.iUniqueId == tag.GetUniqueChannelId()) { - return GetStreamProperties(channel, properties, tag.GetStartTime(), false); + return GetStreamProperties(channel, properties, tag.GetStartTime(), tag.GetEndTime(), false); } } return PVR_ERROR_NO_ERROR; @@ -1068,7 +1079,7 @@ PVR_ERROR CPVREon::GetChannels(bool bRadio, kodi::addon::PVRChannelsResultSet& r } PVR_ERROR CPVREon::GetStreamProperties( - const EonChannel& channel, std::vector& properties, int starttime, bool isLive) + const EonChannel& channel, std::vector& properties, const int& starttime, const int& endtime, const bool& isLive) { kodi::Log(ADDON_LOG_DEBUG, "function call: [%s]", __FUNCTION__); std::string streaming_profile = "hp7000"; @@ -1170,7 +1181,7 @@ PVR_ERROR CPVREon::GetStreamProperties( kodi::Log(ADDON_LOG_DEBUG, "Encrypted Stream URL -> %s", enc_url.c_str()); - SetStreamProperties(properties, enc_url, true, false, ""); + SetStreamProperties(properties, enc_url, true, false, isLive, starttime, endtime); return PVR_ERROR_NO_ERROR; } @@ -1182,7 +1193,7 @@ PVR_ERROR CPVREon::GetChannelStreamProperties( EonChannel addonChannel; if (GetChannel(channel, addonChannel)) { if (addonChannel.subscribed) { - return GetStreamProperties(addonChannel, properties, 0, true); + return GetStreamProperties(addonChannel, properties, 0, 0, true); } kodi::Log(ADDON_LOG_DEBUG, "Channel not subscribed"); return PVR_ERROR_SERVER_ERROR; diff --git a/src/PVREon.h b/src/PVREon.h index fde0452..b7ba59a 100644 --- a/src/PVREon.h +++ b/src/PVREon.h @@ -14,6 +14,9 @@ #include "http/HttpClient.h" #include "rapidjson/document.h" +static const int INPUTSTREAM_ADAPTIVE = 0; +static const int INPUTSTREAM_FFMPEGDIRECT = 1; + struct EonChannelCategory { int id; @@ -183,12 +186,12 @@ class ATTR_DLL_LOCAL CPVREon : public kodi::addon::CAddonBase, void SetStreamProperties(std::vector& properties, const std::string& url, - bool realtime, bool playTimeshiftBuffer, - const std::string& license); + const bool& realtime, const bool& playTimeshiftBuffer, const bool& isLive, + const int& starttime, const int& endtime); PVR_ERROR GetStreamProperties( const EonChannel& channel, - std::vector& properties, int starttime, bool isLive); + std::vector& properties, const int& starttime, const int& endtime, const bool& isLive); bool Parametrize(const int id); @@ -247,17 +250,4 @@ class ATTR_DLL_LOCAL CPVREon : public kodi::addon::CAddonBase, bool GetCategories(const bool isRadio); int GetDefaultNumber(const bool isRadio, int id); bool HandleSession(bool start, int cid, int epg_id); -/* - bool HrtiLogin(); - bool GetIpAddress(); - bool GrantAccess(); - bool RegisterDevice(); - bool LoadChannels(); - bool AuthorizeSession(std::string ref_id, std::string drm_id); - std::string GetLicense(std::string drm_id, std::string user_id); -*/ -// std::string ltrim(const std::string &s); -// std::string rtrim(const std::string &s); -// std::string trim(const std::string &s); -// std::string urlencode(const std::string &s); }; diff --git a/src/Settings.cpp b/src/Settings.cpp index 43e9251..d9480a9 100644 --- a/src/Settings.cpp +++ b/src/Settings.cpp @@ -164,6 +164,13 @@ bool CSettings::Load() return false; } + if (!kodi::addon::CheckSettingInt("inputstream", m_eonInputstream)) + { + /* If setting is unknown fallback to defaults */ + kodi::Log(ADDON_LOG_ERROR, "Couldn't get 'inputstream' setting"); + return false; + } + return true; } diff --git a/src/Settings.h b/src/Settings.h index ae49312..5e47a77 100644 --- a/src/Settings.h +++ b/src/Settings.h @@ -20,6 +20,7 @@ class ATTR_DLL_LOCAL CSettings const int& GetEonServiceProvider() const { return m_eonServiceProvider; } const int& GetPlatform() const { return m_eonPlatform; } + const int& GetInputstream() const { return m_eonInputstream; } const std::string& GetEonUsername() const { return m_eonUsername; } const std::string& GetEonPassword() const { return m_eonPassword; } const std::string& GetEonAccessToken() const { return m_eonAccessToken; } @@ -44,6 +45,7 @@ class ATTR_DLL_LOCAL CSettings private: int m_eonServiceProvider; int m_eonPlatform; + int m_eonInputstream; std::string m_eonUsername; std::string m_eonPassword; std::string m_eonAccessToken;