@@ -77,6 +77,24 @@ std::shared_ptr<DRM::IDecrypter> CreateDRM(std::string_view keySystem)
7777 return drm;
7878}
7979
80+ /* !
81+ * \brief Get a DRMInfo by Key System
82+ * \param drmInfos The manifest DRM info
83+ * \param keySystem The Key System to search
84+ * \return The DRMInfo if found, otherwise nullptr
85+ */
86+ DRM::DRMInfo* GetDRMInfoByKS (std::vector<DRM::DRMInfo>& drmInfos, std::string_view keySystem)
87+ {
88+ // If no key system is provided its assumend CENC content compatible with any DRM
89+ auto itDrmInfo = std::find_if (drmInfos.begin (), drmInfos.end (), [&](const DRMInfo& info)
90+ { return info.keySystem == keySystem || info.keySystem .empty (); });
91+
92+ if (itDrmInfo != drmInfos.end ())
93+ return &(*itDrmInfo);
94+
95+ return nullptr ;
96+ }
97+
8098} // unnamed namespace
8199
82100void DRM::CDRMEngine::Initialize ()
@@ -205,6 +223,21 @@ bool DRM::CDRMEngine::InitializeSession(std::vector<DRM::DRMInfo> drmInfos,
205223
206224 ConfigureClearKey (drmInfos);
207225
226+ auto & kodiProps = CSrvBroker::GetKodiProps ();
227+
228+ // This is a kind of hack,
229+ // some services use manifests (usually SmoothStreaming) with PlayReady DRM only,
230+ // but they have also a Widevine license server that allow to play same stream with Widevine,
231+ // this will allow to force change the manifest DRMInfo KeySytem to Widevine and replace the init data
232+ bool isPRtoWVKeySystem{false };
233+ if (HasKeySystemSupport (KS_WIDEVINE) && drmInfos.size () == 1 &&
234+ drmInfos[0 ].keySystem == KS_PLAYREADY && kodiProps.GetDrmConfigs ().size () == 1 &&
235+ kodiProps.HasDrmConfig (KS_WIDEVINE))
236+ {
237+ drmInfos[0 ].keySystem = KS_WIDEVINE;
238+ isPRtoWVKeySystem = true ;
239+ }
240+
208241 if (!SelectDRM (drmInfos))
209242 {
210243 LOG::LogF (LOGERROR, " The stream is encrypted with a DRM not supported by this system" );
@@ -213,34 +246,35 @@ bool DRM::CDRMEngine::InitializeSession(std::vector<DRM::DRMInfo> drmInfos,
213246 }
214247
215248 // Find a compatible DRM info
216- auto itDrmInfo = std::find_if (drmInfos.begin (), drmInfos.end (), [&](const DRMInfo& info) {
217- return info.keySystem == m_keySystem;});
249+ auto pDrmInfo = GetDRMInfoByKS (drmInfos, m_keySystem);
218250
219- if (itDrmInfo == drmInfos. end ()) // Should not happens
251+ if (!pDrmInfo)
220252 {
221253 LOG::LogF (LOGERROR, " The Key System \" %s\" does not match any DRMInfo" , m_keySystem.c_str ());
222254 m_status = EngineStatus::DRM_NOT_SUPPORTED;
223255 return false ;
224256 }
225257
226- DRM::DRMInfo& drmInfo = *itDrmInfo ;
227- const auto drmPropCfg = CSrvBroker::GetKodiProps () .GetDrmConfig (drmInfo. keySystem );
258+ DRM::DRMInfo& drmInfo = *pDrmInfo ;
259+ const auto drmPropCfg = kodiProps .GetDrmConfig (m_keySystem );
228260
229261 // Set custom init data PSSH provided from property,
230262 // can allow to initialize a DRM that could be also not specified
231263 // as supported in the manifest (e.g. missing DASH ContentProtection tags)
232- if (!drmPropCfg.initData .empty ())
264+ if (!drmPropCfg.initData .empty () || isPRtoWVKeySystem )
233265 {
234266 drmInfo.initData .clear ();
235- LOG::Log (LOGDEBUG, " Custom init PSSH provided by the \" license \" property " );
267+
236268 std::vector<uint8_t > customInitData = BASE64::Decode (drmPropCfg.initData );
237269
238270 if (DRM::IsValidPsshHeader (customInitData))
239271 {
272+ LOG::Log (LOGDEBUG, " Use custom init PSSH provided by the \" license\" property" );
240273 drmInfo.initData = customInitData;
241274 }
242275 else if (m_keySystem == DRM::KS_WIDEVINE) // Try to create a PSSH box, KID should be provided by manifest
243276 {
277+ LOG::Log (LOGDEBUG, " Make a Widevine init PSSH to replace PlayReady init data" );
244278 drmInfo.initData =
245279 DRM::PSSH::MakeWidevine ({DRM::ConvertKidStrToBytes (drmInfo.defaultKid )}, customInitData);
246280 }
@@ -513,14 +547,10 @@ bool DRM::CDRMEngine::SelectDRM(std::vector<DRM::DRMInfo>& drmInfos)
513547 // the lower index have the higher priority
514548 for (const std::string& ks : m_supportedKs)
515549 {
516- auto itDrmInfo = std::find_if (drmInfos.begin (), drmInfos.end (), [&](const DRMInfo& info)
517- { return info.keySystem == ks || info.keySystem .empty (); });
550+ const DRM::DRMInfo* drmInfo = GetDRMInfoByKS (drmInfos, ks);
518551
519- if (itDrmInfo != drmInfos. end () )
552+ if (drmInfo )
520553 {
521- if (itDrmInfo->keySystem .empty ())
522- itDrmInfo->keySystem = ks;
523-
524554 m_keySystem = ks;
525555 break ;
526556 }
@@ -637,6 +667,11 @@ void DRM::CDRMEngine::DeleteSessionsByType(const DRMMediaType mediaType)
637667 m_sessions.end ());
638668}
639669
670+ bool DRM::CDRMEngine::HasKeySystemSupport (std::string_view keySystem) const
671+ {
672+ return std::find (m_supportedKs.cbegin (), m_supportedKs.cend (), keySystem) != m_supportedKs.cend ();
673+ }
674+
640675void DRM::CDRMEngine::Dispose ()
641676{
642677 LOG::Log (LOGDEBUG, " Dispose DRM Engine" );
0 commit comments