From 84496a2499ad757774d9308714dbf8dc2abfc966 Mon Sep 17 00:00:00 2001 From: LekshmiMR Date: Wed, 20 May 2026 18:31:00 +0000 Subject: [PATCH 01/19] HDCP retry to rialto --- media/client/ipc/source/MediaKeysIpc.cpp | 7 +- media/public/include/MediaCommon.h | 4 +- .../ipc/source/MediaKeysModuleService.cpp | 8 +- .../main/source/MediaKeysCapabilities.cpp | 2 + .../main/source/MediaKeysServerInternal.cpp | 86 ++++++++++++++++--- wrappers/CMakeLists.txt | 2 + wrappers/include/OcdmSession.h | 2 + wrappers/source/OcdmSession.cpp | 65 ++++++++++++++ 8 files changed, 163 insertions(+), 13 deletions(-) diff --git a/media/client/ipc/source/MediaKeysIpc.cpp b/media/client/ipc/source/MediaKeysIpc.cpp index 24909664e..aa664fc55 100644 --- a/media/client/ipc/source/MediaKeysIpc.cpp +++ b/media/client/ipc/source/MediaKeysIpc.cpp @@ -123,6 +123,10 @@ const char *toString(const firebolt::rialto::MediaKeyErrorStatus &errorStatus) { return "FAIL"; } + case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED: + { + return "OUTPUT_RESTRICTED"; + } } return "UNKNOWN"; } @@ -334,7 +338,7 @@ bool MediaKeysIpc::containsKey(int32_t keySessionId, const std::vector } MediaKeyErrorStatus MediaKeysIpc::createKeySession(KeySessionType sessionType, std::weak_ptr client, - bool isLDL, int32_t &keySessionId) + bool isLDL, int32_t &keySessionId) { if (!reattachChannelIfRequired()) { @@ -415,6 +419,7 @@ MediaKeyErrorStatus MediaKeysIpc::generateRequest(int32_t keySessionId, InitData break; } + firebolt::rialto::GenerateRequestRequest request; request.set_media_keys_handle(m_mediaKeysHandle); request.set_key_session_id(keySessionId); diff --git a/media/public/include/MediaCommon.h b/media/public/include/MediaCommon.h index 92b544b8c..50252b01b 100644 --- a/media/public/include/MediaCommon.h +++ b/media/public/include/MediaCommon.h @@ -292,7 +292,8 @@ enum class MediaKeyErrorStatus NOT_SUPPORTED, /**< The request parameters are not supported. */ INVALID_STATE, /**< The object is in an invalid state for the operation. */ INTERFACE_NOT_IMPLEMENTED, /**< The interface is not implemented. */ - BUFFER_TOO_SMALL /**< The size of the buffer is too small. */ + BUFFER_TOO_SMALL, /**< The size of the buffer is too small. */ + OUTPUT_RESTRICTED }; /** @@ -473,6 +474,7 @@ struct PlaybackInfo int64_t currentPosition{-1}; /**< The current playback position */ double volume{1.0}; /**< The current volume */ }; + } // namespace firebolt::rialto #endif // FIREBOLT_RIALTO_MEDIA_COMMON_H_ diff --git a/media/server/ipc/source/MediaKeysModuleService.cpp b/media/server/ipc/source/MediaKeysModuleService.cpp index 4cb5f6293..68cc5772e 100644 --- a/media/server/ipc/source/MediaKeysModuleService.cpp +++ b/media/server/ipc/source/MediaKeysModuleService.cpp @@ -66,6 +66,10 @@ convertMediaKeyErrorStatus(const firebolt::rialto::MediaKeyErrorStatus &errorSta { return firebolt::rialto::ProtoMediaKeyErrorStatus::FAIL; } + case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED: + { + // TODO + } } return firebolt::rialto::ProtoMediaKeyErrorStatus::FAIL; } @@ -100,6 +104,7 @@ firebolt::rialto::InitDataType covertInitDataType(firebolt::rialto::GenerateRequ return firebolt::rialto::InitDataType::UNKNOWN; } } + } // namespace namespace firebolt::rialto::server::ipc @@ -277,11 +282,12 @@ void MediaKeysModuleService::generateRequest(::google::protobuf::RpcController * ::google::protobuf::Closure *done) { RIALTO_SERVER_LOG_DEBUG("entry:"); - MediaKeyErrorStatus status = m_cdmService.generateRequest(request->media_keys_handle(), request->key_session_id(), covertInitDataType(request->init_data_type()), std::vector{request->init_data().begin(), request->init_data().end()}); + + response->set_error_status(convertMediaKeyErrorStatus(status)); done->Run(); } diff --git a/media/server/main/source/MediaKeysCapabilities.cpp b/media/server/main/source/MediaKeysCapabilities.cpp index f0ad87a81..9988d61eb 100644 --- a/media/server/main/source/MediaKeysCapabilities.cpp +++ b/media/server/main/source/MediaKeysCapabilities.cpp @@ -47,6 +47,8 @@ const char *toString(const firebolt::rialto::MediaKeyErrorStatus &status) return "NOT_SUPPORTED"; case firebolt::rialto::MediaKeyErrorStatus::INVALID_STATE: return "INVALID_STATE"; + case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED: + return "OUTPUT_RESTRICTED"; } return "Unknown"; } diff --git a/media/server/main/source/MediaKeysServerInternal.cpp b/media/server/main/source/MediaKeysServerInternal.cpp index 7fd1b58bf..3f5d69b28 100644 --- a/media/server/main/source/MediaKeysServerInternal.cpp +++ b/media/server/main/source/MediaKeysServerInternal.cpp @@ -18,10 +18,40 @@ */ #include +#include +#include #include "MediaKeysServerInternal.h" #include "RialtoServerLogging.h" +/*namespace +{ +const char *toString(const firebolt::rialto::MediaKeyErrorStatus &status) +{ + switch (status) + { + case firebolt::rialto::MediaKeyErrorStatus::OK: + return "OK"; + case firebolt::rialto::MediaKeyErrorStatus::FAIL: + return "FAIL"; + case firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID: + return "BAD_SESSION_ID"; + case firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED: + return "INTERFACE_NOT_IMPLEMENTED"; + case firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL: + return "BUFFER_TOO_SMALL"; + case firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED: + return "NOT_SUPPORTED"; + case firebolt::rialto::MediaKeyErrorStatus::INVALID_STATE: + return "INVALID_STATE"; + case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED: + return "OUTPUT_RESTRICTED"; + } + return "Unknown"; +} +} */// namespace + + namespace firebolt::rialto { const char *mediaKeyErrorStatusToString(const MediaKeyErrorStatus &status) @@ -51,6 +81,9 @@ std::shared_ptr IMediaKeysFactory::createFactory() namespace firebolt::rialto::server { +constexpr std::chrono::milliseconds kOutputRestrictedRetryInterval{250}; +constexpr std::chrono::seconds kOutputRestrictedRetryTimeout{6}; + int32_t generateSessionId() { static int32_t keySessionId{0}; @@ -569,12 +602,51 @@ MediaKeyErrorStatus MediaKeysServerInternal::getCdmKeySessionIdInternal(int32_t MediaKeyErrorStatus MediaKeysServerInternal::decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) { - RIALTO_SERVER_LOG_DEBUG("entry:"); + RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: entry:decrypt"); - MediaKeyErrorStatus status; - auto task = [&]() { status = decryptInternal(keySessionId, encrypted, caps); }; + MediaKeyErrorStatus status{MediaKeyErrorStatus::FAIL}; + const auto deadline = std::chrono::steady_clock::now() + kOutputRestrictedRetryTimeout; + do + { + auto task = [&]() { status = decryptInternal(keySessionId, encrypted, caps); }; + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session id :%d", keySessionId); + switch (status) + { + case firebolt::rialto::MediaKeyErrorStatus::OK: + RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : OK"); + break; + case firebolt::rialto::MediaKeyErrorStatus::FAIL: + RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : FAIL"); + break; + case firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID: + RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : BAD_SESSION_ID"); + break; + case firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED: + RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : INTERFACE_NOT_IMPLEMENTED"); + break; + case firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL: + RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : BUFFER_TOO_SMALL"); + break; + case firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED: + RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : NOT_SUPPORTED"); + break; + case firebolt::rialto::MediaKeyErrorStatus::INVALID_STATE: + RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : INVALID_STATE"); + break; + case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED: + RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : OUTPUT_RESTRICTED"); + break; + } + + if (status != MediaKeyErrorStatus::OUTPUT_RESTRICTED) + { + break; + } + RIALTO_SERVER_LOG_WARN("Decrypt returned OUTPUT_RESTRICTED, retrying after delay"); + std::this_thread::sleep_for(kOutputRestrictedRetryInterval); + } while (std::chrono::steady_clock::now() < deadline); - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); return status; } @@ -598,12 +670,6 @@ MediaKeyErrorStatus MediaKeysServerInternal::decryptInternal(int32_t keySessionI return status; } -bool MediaKeysServerInternal::isNetflixPlayreadyKeySystem() const -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - return m_kKeySystem.find("netflix") != std::string::npos; -} - void MediaKeysServerInternal::ping(std::unique_ptr &&heartbeatHandler) { RIALTO_SERVER_LOG_DEBUG("entry:"); diff --git a/wrappers/CMakeLists.txt b/wrappers/CMakeLists.txt index 3be841fd1..d70a28037 100644 --- a/wrappers/CMakeLists.txt +++ b/wrappers/CMakeLists.txt @@ -110,6 +110,8 @@ target_include_directories( PRIVATE include + ../common/interface/ + ../logging/include/ ${GStreamerApp_INCLUDE_DIRS} $ ${WRAPPER_INCLUDES} diff --git a/wrappers/include/OcdmSession.h b/wrappers/include/OcdmSession.h index 51841f701..c76716106 100644 --- a/wrappers/include/OcdmSession.h +++ b/wrappers/include/OcdmSession.h @@ -94,6 +94,7 @@ class OcdmSession : public IOcdmSession private: using OcdmGstSessionDecryptExFn = OpenCDMError (*)(struct OpenCDMSession *, GstBuffer *, GstBuffer *, const uint32_t, GstBuffer *, GstBuffer *, uint32_t, GstCaps *); + using OcdmGstSessionDecryptBufferOnceFn = OpenCDMError (*)(struct OpenCDMSession *, GstBuffer *, GstCaps *); /** * @brief The System handle. */ @@ -115,6 +116,7 @@ class OcdmSession : public IOcdmSession struct OpenCDMSession *m_session; static OcdmGstSessionDecryptExFn m_ocdmGstSessionDecryptEx; + static OcdmGstSessionDecryptBufferOnceFn m_ocdmGstSessionDecryptBufferOnce; /** * @brief Requests the processing of the challenge data. diff --git a/wrappers/source/OcdmSession.cpp b/wrappers/source/OcdmSession.cpp index a236826a9..821cd3043 100644 --- a/wrappers/source/OcdmSession.cpp +++ b/wrappers/source/OcdmSession.cpp @@ -23,6 +23,8 @@ #include "opencdm/open_cdm_ext.h" #include #include +#include +#include "RialtoCommonLogging.h" namespace { @@ -109,6 +111,7 @@ const firebolt::rialto::KeyStatus convertKeyStatus(const KeyStatus &ocdmKeyStatu namespace firebolt::rialto::wrappers { OcdmSession::OcdmGstSessionDecryptExFn OcdmSession::m_ocdmGstSessionDecryptEx{nullptr}; +OcdmSession::OcdmGstSessionDecryptBufferOnceFn OcdmSession::m_ocdmGstSessionDecryptBufferOnce{nullptr}; OcdmSession::OcdmSession(struct OpenCDMSystem *systemHandle, IOcdmSessionClient *client) : m_systemHandle(systemHandle), m_ocdmSessionClient(client), m_session(nullptr) @@ -121,6 +124,11 @@ OcdmSession::OcdmSession(struct OpenCDMSystem *systemHandle, IOcdmSessionClient { m_ocdmGstSessionDecryptEx = (OcdmGstSessionDecryptExFn)dlsym(RTLD_DEFAULT, "opencdm_gstreamer_session_decrypt_ex"); + m_ocdmGstSessionDecryptBufferOnce = + (OcdmGstSessionDecryptBufferOnceFn)dlsym(RTLD_DEFAULT, "opencdm_gstreamer_session_decrypt_buffer_once"); + if(m_ocdmGstSessionDecryptBufferOnce != NULL){ + RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : m_ocdmGstSessionDecryptBufferOnce exists\n"); + } }); } @@ -190,11 +198,68 @@ MediaKeyErrorStatus OcdmSession::update(const uint8_t response[], uint32_t respo MediaKeyErrorStatus OcdmSession::decryptBuffer(GstBuffer *encrypted, GstCaps *caps) { + RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer()\n"); if (!m_session) { return MediaKeyErrorStatus::FAIL; } + if (m_ocdmGstSessionDecryptBufferOnce) + { + // Extract key ID from the buffer's protection metadata + std::vector keyId; + GstProtectionMeta *pm = reinterpret_cast(gst_buffer_get_protection_meta(encrypted)); + if (pm) + { + const GValue *kidValue = gst_structure_get_value(pm->info, "kid"); + if (kidValue) + { + GstBuffer *kidBuf = gst_value_get_buffer(kidValue); + if (kidBuf) + { + GstMapInfo kidMap; + if (gst_buffer_map(kidBuf, &kidMap, GST_MAP_READ)) + { + keyId.assign(kidMap.data, kidMap.data + kidMap.size); + gst_buffer_unmap(kidBuf, &kidMap); + } + } + } + } + + // Pre-decrypt key status check: return OUTPUT_RESTRICTED immediately (no sleep) so + // the caller (MediaKeysServerInternal::decrypt) can retry from the GStreamer thread. + if (!keyId.empty()) + { + const ::KeyStatus preStatus = + opencdm_session_status(m_session, keyId.data(), static_cast(keyId.size())); + if (preStatus == OutputRestricted || preStatus == OutputRestrictedHDCP22) + { + + RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer() : returning MediaKeyErrorStatus::OUTPUT_RESTRICTED(Pre decrypt)\n"); + return MediaKeyErrorStatus::OUTPUT_RESTRICTED; + } + } + + OpenCDMError result = m_ocdmGstSessionDecryptBufferOnce(m_session, encrypted, caps); + + // Post-decrypt status check: a failed decrypt during HDCP reauth may not carry a + // specific error code, so confirm via key status before signalling the caller to retry. + if (result != ERROR_NONE && !keyId.empty()) + { + const ::KeyStatus postStatus = + opencdm_session_status(m_session, keyId.data(), static_cast(keyId.size())); + if (postStatus == OutputRestricted || postStatus == OutputRestrictedHDCP22) + { + RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer() : returning MediaKeyErrorStatus::OUTPUT_RESTRICTED(Post decrypt)\n"); + return MediaKeyErrorStatus::OUTPUT_RESTRICTED; + } + } + + return convertOpenCdmError(result); + } + + // Fallback: adapter without _once handles retries internally. OpenCDMError status = opencdm_gstreamer_session_decrypt_buffer(m_session, encrypted, caps); return convertOpenCdmError(status); } From 31c94c5083175cd22c15ab7ab270d6067960dc2b Mon Sep 17 00:00:00 2001 From: LekshmiMR Date: Wed, 20 May 2026 22:20:21 +0000 Subject: [PATCH 02/19] Adding dlopen() --- media/server/main/source/MediaKeysServerInternal.cpp | 7 +++++++ wrappers/source/OcdmSession.cpp | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/media/server/main/source/MediaKeysServerInternal.cpp b/media/server/main/source/MediaKeysServerInternal.cpp index 3f5d69b28..a6ccf09ee 100644 --- a/media/server/main/source/MediaKeysServerInternal.cpp +++ b/media/server/main/source/MediaKeysServerInternal.cpp @@ -670,6 +670,13 @@ MediaKeyErrorStatus MediaKeysServerInternal::decryptInternal(int32_t keySessionI return status; } +bool MediaKeysServerInternal::isNetflixPlayreadyKeySystem() const +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + return m_kKeySystem.find("netflix") != std::string::npos; +} + + void MediaKeysServerInternal::ping(std::unique_ptr &&heartbeatHandler) { RIALTO_SERVER_LOG_DEBUG("entry:"); diff --git a/wrappers/source/OcdmSession.cpp b/wrappers/source/OcdmSession.cpp index 821cd3043..80e8a1954 100644 --- a/wrappers/source/OcdmSession.cpp +++ b/wrappers/source/OcdmSession.cpp @@ -122,10 +122,10 @@ OcdmSession::OcdmSession(struct OpenCDMSystem *systemHandle, IOcdmSessionClient std::call_once(flag, []() { + void* handle = dlopen("libocdm.so", RTLD_LAZY); m_ocdmGstSessionDecryptEx = (OcdmGstSessionDecryptExFn)dlsym(RTLD_DEFAULT, "opencdm_gstreamer_session_decrypt_ex"); - m_ocdmGstSessionDecryptBufferOnce = - (OcdmGstSessionDecryptBufferOnceFn)dlsym(RTLD_DEFAULT, "opencdm_gstreamer_session_decrypt_buffer_once"); + m_ocdmGstSessionDecryptBufferOnce = (OcdmGstSessionDecryptBufferOnceFn)dlsym(handle,"opencdm_gstreamer_session_decrypt_buffer_once"); if(m_ocdmGstSessionDecryptBufferOnce != NULL){ RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : m_ocdmGstSessionDecryptBufferOnce exists\n"); } From 1467ce83682addc9aa51c41c0ace55dda0c09a12 Mon Sep 17 00:00:00 2001 From: LekshmiMR Date: Wed, 20 May 2026 22:36:36 +0000 Subject: [PATCH 03/19] More logging for keyStatus --- wrappers/source/OcdmSession.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/wrappers/source/OcdmSession.cpp b/wrappers/source/OcdmSession.cpp index 80e8a1954..1c1b33638 100644 --- a/wrappers/source/OcdmSession.cpp +++ b/wrappers/source/OcdmSession.cpp @@ -238,7 +238,10 @@ MediaKeyErrorStatus OcdmSession::decryptBuffer(GstBuffer *encrypted, GstCaps *ca RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer() : returning MediaKeyErrorStatus::OUTPUT_RESTRICTED(Pre decrypt)\n"); return MediaKeyErrorStatus::OUTPUT_RESTRICTED; + } else { + RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer() : returning error(Pre decrypt)\n"); } + } OpenCDMError result = m_ocdmGstSessionDecryptBufferOnce(m_session, encrypted, caps); @@ -253,7 +256,9 @@ MediaKeyErrorStatus OcdmSession::decryptBuffer(GstBuffer *encrypted, GstCaps *ca { RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer() : returning MediaKeyErrorStatus::OUTPUT_RESTRICTED(Post decrypt)\n"); return MediaKeyErrorStatus::OUTPUT_RESTRICTED; - } + } else { + RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer() : returning error(Post decrypt)\n"); + } } return convertOpenCdmError(result); From ffee15ba1c458545bdf05bc469486da8a894b6bc Mon Sep 17 00:00:00 2001 From: balasaraswathy-n Date: Thu, 21 May 2026 15:38:41 +0530 Subject: [PATCH 04/19] Update MediaKeysServerInternal.cpp --- media/server/main/source/MediaKeysServerInternal.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/media/server/main/source/MediaKeysServerInternal.cpp b/media/server/main/source/MediaKeysServerInternal.cpp index a6ccf09ee..fa66f7b9a 100644 --- a/media/server/main/source/MediaKeysServerInternal.cpp +++ b/media/server/main/source/MediaKeysServerInternal.cpp @@ -81,8 +81,8 @@ std::shared_ptr IMediaKeysFactory::createFactory() namespace firebolt::rialto::server { -constexpr std::chrono::milliseconds kOutputRestrictedRetryInterval{250}; -constexpr std::chrono::seconds kOutputRestrictedRetryTimeout{6}; +constexpr std::chrono::seconds kOutputRestrictedRetryInterval{1}; +constexpr std::chrono::seconds kOutputRestrictedRetryTimeout{4}; int32_t generateSessionId() { From 881e8434cc3052a105264a554cbfe7fed43fad63 Mon Sep 17 00:00:00 2001 From: LekshmiMR Date: Thu, 21 May 2026 14:53:16 +0000 Subject: [PATCH 05/19] Revert interval time changes --- media/server/main/source/MediaKeysServerInternal.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/media/server/main/source/MediaKeysServerInternal.cpp b/media/server/main/source/MediaKeysServerInternal.cpp index fa66f7b9a..a309332fa 100644 --- a/media/server/main/source/MediaKeysServerInternal.cpp +++ b/media/server/main/source/MediaKeysServerInternal.cpp @@ -81,8 +81,8 @@ std::shared_ptr IMediaKeysFactory::createFactory() namespace firebolt::rialto::server { -constexpr std::chrono::seconds kOutputRestrictedRetryInterval{1}; -constexpr std::chrono::seconds kOutputRestrictedRetryTimeout{4}; +constexpr std::chrono::seconds kOutputRestrictedRetryInterval{250}; +constexpr std::chrono::seconds kOutputRestrictedRetryTimeout{6}; int32_t generateSessionId() { From f9fd54af80e336b8f60df141233056b63b009484 Mon Sep 17 00:00:00 2001 From: LekshmiMR Date: Thu, 21 May 2026 17:45:18 +0000 Subject: [PATCH 06/19] Reverting the interval change --- media/server/main/source/MediaKeysServerInternal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media/server/main/source/MediaKeysServerInternal.cpp b/media/server/main/source/MediaKeysServerInternal.cpp index a309332fa..a6ccf09ee 100644 --- a/media/server/main/source/MediaKeysServerInternal.cpp +++ b/media/server/main/source/MediaKeysServerInternal.cpp @@ -81,7 +81,7 @@ std::shared_ptr IMediaKeysFactory::createFactory() namespace firebolt::rialto::server { -constexpr std::chrono::seconds kOutputRestrictedRetryInterval{250}; +constexpr std::chrono::milliseconds kOutputRestrictedRetryInterval{250}; constexpr std::chrono::seconds kOutputRestrictedRetryTimeout{6}; int32_t generateSessionId() From c60ab3c193c4d16696f8e4707d208cddf5254b69 Mon Sep 17 00:00:00 2001 From: LekshmiMR Date: Fri, 22 May 2026 00:27:30 +0000 Subject: [PATCH 07/19] Increase the priority of ping routine --- media/server/main/source/MediaKeysServerInternal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media/server/main/source/MediaKeysServerInternal.cpp b/media/server/main/source/MediaKeysServerInternal.cpp index a6ccf09ee..72c920055 100644 --- a/media/server/main/source/MediaKeysServerInternal.cpp +++ b/media/server/main/source/MediaKeysServerInternal.cpp @@ -682,7 +682,7 @@ void MediaKeysServerInternal::ping(std::unique_ptr &&heartbea RIALTO_SERVER_LOG_DEBUG("entry:"); auto task = [&]() { heartbeatHandler.reset(); }; - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + m_mainThread->enqueuePriorityTaskAndWait(m_mainThreadClientId, task); } MediaKeyErrorStatus MediaKeysServerInternal::getMetricSystemData(std::vector &buffer) From 004ba6d2539f1670c07c741a67e88f000a3c0040 Mon Sep 17 00:00:00 2001 From: varatharajan568 <130632918+varatharajan568@users.noreply.github.com> Date: Fri, 22 May 2026 07:41:49 +0530 Subject: [PATCH 08/19] Update MediaKeysServerInternal.cpp --- media/server/main/source/MediaKeysServerInternal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media/server/main/source/MediaKeysServerInternal.cpp b/media/server/main/source/MediaKeysServerInternal.cpp index 72c920055..82283d982 100644 --- a/media/server/main/source/MediaKeysServerInternal.cpp +++ b/media/server/main/source/MediaKeysServerInternal.cpp @@ -679,7 +679,7 @@ bool MediaKeysServerInternal::isNetflixPlayreadyKeySystem() const void MediaKeysServerInternal::ping(std::unique_ptr &&heartbeatHandler) { - RIALTO_SERVER_LOG_DEBUG("entry:"); + RIALTO_SERVER_LOG_ERROR("entry:"); auto task = [&]() { heartbeatHandler.reset(); }; m_mainThread->enqueuePriorityTaskAndWait(m_mainThreadClientId, task); From 06af3626f83375fec26e691ae039c7e7d97c65c9 Mon Sep 17 00:00:00 2001 From: varatharajan568 <130632918+varatharajan568@users.noreply.github.com> Date: Fri, 22 May 2026 07:43:16 +0530 Subject: [PATCH 09/19] Update MediaKeysServerInternal.cpp --- media/server/main/source/MediaKeysServerInternal.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/media/server/main/source/MediaKeysServerInternal.cpp b/media/server/main/source/MediaKeysServerInternal.cpp index 82283d982..2f1cb7ee7 100644 --- a/media/server/main/source/MediaKeysServerInternal.cpp +++ b/media/server/main/source/MediaKeysServerInternal.cpp @@ -683,6 +683,7 @@ void MediaKeysServerInternal::ping(std::unique_ptr &&heartbea auto task = [&]() { heartbeatHandler.reset(); }; m_mainThread->enqueuePriorityTaskAndWait(m_mainThreadClientId, task); + RIALTO_SERVER_LOG_ERROR("exit:"); } MediaKeyErrorStatus MediaKeysServerInternal::getMetricSystemData(std::vector &buffer) From d8312264749aff8b7ce5d2963d2e02dfc6aa70d8 Mon Sep 17 00:00:00 2001 From: LekshmiMR Date: Fri, 22 May 2026 19:22:36 +0000 Subject: [PATCH 10/19] Comment the mutex for ping --- media/server/service/source/CdmService.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/media/server/service/source/CdmService.cpp b/media/server/service/source/CdmService.cpp index 8ea716f61..f79db0cf1 100644 --- a/media/server/service/source/CdmService.cpp +++ b/media/server/service/source/CdmService.cpp @@ -494,6 +494,7 @@ MediaKeyErrorStatus CdmService::decrypt(int32_t keySessionId, GstBuffer *encrypt { RIALTO_SERVER_LOG_DEBUG("CdmService requested to decrypt, key session id: %d", keySessionId); + RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : CdmService : decrypt entry"); std::lock_guard lock{m_mediaKeysMutex}; auto mediaKeysHandleIter{m_sessionInfo.find(keySessionId)}; if (mediaKeysHandleIter == m_sessionInfo.end()) @@ -580,12 +581,14 @@ void CdmService::decrementSessionIdUsageCounter(int32_t keySessionId) void CdmService::ping(const std::shared_ptr &heartbeatProcedure) { - std::lock_guard lock{m_mediaKeysMutex}; +// std::lock_guard lock{m_mediaKeysMutex}; + RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: ping entry") for (const auto &mediaKeyPair : m_mediaKeys) { auto &mediaKeys = mediaKeyPair.second; mediaKeys->ping(heartbeatProcedure->createHandler()); } + RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: ping exit") } MediaKeyErrorStatus CdmService::getMetricSystemData(int mediaKeysHandle, std::vector &buffer) From 7f1c8efc590869732e2c2ab33d37c2773d9237ea Mon Sep 17 00:00:00 2001 From: LekshmiMR Date: Fri, 22 May 2026 19:32:11 +0000 Subject: [PATCH 11/19] Uncommenting the mutex with ping --- media/server/service/source/CdmService.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media/server/service/source/CdmService.cpp b/media/server/service/source/CdmService.cpp index f79db0cf1..6892daeb3 100644 --- a/media/server/service/source/CdmService.cpp +++ b/media/server/service/source/CdmService.cpp @@ -581,7 +581,7 @@ void CdmService::decrementSessionIdUsageCounter(int32_t keySessionId) void CdmService::ping(const std::shared_ptr &heartbeatProcedure) { -// std::lock_guard lock{m_mediaKeysMutex}; + std::lock_guard lock{m_mediaKeysMutex}; RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: ping entry") for (const auto &mediaKeyPair : m_mediaKeys) { From 88573bae94fba1126896f6f8a56b9e00923c9f1f Mon Sep 17 00:00:00 2001 From: LekshmiMR Date: Fri, 22 May 2026 19:47:43 +0000 Subject: [PATCH 12/19] Commenting the mutex with ping --- media/server/service/source/CdmService.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/media/server/service/source/CdmService.cpp b/media/server/service/source/CdmService.cpp index 6892daeb3..71e467252 100644 --- a/media/server/service/source/CdmService.cpp +++ b/media/server/service/source/CdmService.cpp @@ -581,14 +581,14 @@ void CdmService::decrementSessionIdUsageCounter(int32_t keySessionId) void CdmService::ping(const std::shared_ptr &heartbeatProcedure) { - std::lock_guard lock{m_mediaKeysMutex}; - RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: ping entry") +// std::lock_guard lock{m_mediaKeysMutex}; + RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: ping entry"); for (const auto &mediaKeyPair : m_mediaKeys) { auto &mediaKeys = mediaKeyPair.second; mediaKeys->ping(heartbeatProcedure->createHandler()); } - RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: ping exit") + RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: ping exit"); } MediaKeyErrorStatus CdmService::getMetricSystemData(int mediaKeysHandle, std::vector &buffer) From e0a350d6d0ecd90382870ab67b6e25bd21bc06fe Mon Sep 17 00:00:00 2001 From: LekshmiMR Date: Fri, 22 May 2026 19:57:27 +0000 Subject: [PATCH 13/19] Handling ping and decrypt with rialto --- media/server/service/source/CdmService.cpp | 41 +++++++++++++++++++--- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/media/server/service/source/CdmService.cpp b/media/server/service/source/CdmService.cpp index 71e467252..e16dc58c9 100644 --- a/media/server/service/source/CdmService.cpp +++ b/media/server/service/source/CdmService.cpp @@ -492,7 +492,26 @@ bool CdmService::isServerCertificateSupported(const std::string &keySystem) MediaKeyErrorStatus CdmService::decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) { - RIALTO_SERVER_LOG_DEBUG("CdmService requested to decrypt, key session id: %d", keySessionId); + + RIALTO_SERVER_LOG_ERROR("CdmService requested to decrypt, key session id: %d", keySessionId); + + // Acquire mutex ONLY to resolve the pointer — then release immediately + IMediaKeysServerInternal *mediaKeys{nullptr}; + { + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysHandleIter{m_sessionInfo.find(keySessionId)}; + if (mediaKeysHandleIter == m_sessionInfo.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle for mksId: %d does not exist", keySessionId); + return MediaKeyErrorStatus::FAIL; + } + mediaKeys = m_mediaKeys[mediaKeysHandleIter->second.mediaKeysHandle].get(); + } + // Mutex released — ping() can now proceed freely + + return mediaKeys->decrypt(keySessionId, encrypted, caps); + +/* RIALTO_SERVER_LOG_DEBUG("CdmService requested to decrypt, key session id: %d", keySessionId); RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : CdmService : decrypt entry"); std::lock_guard lock{m_mediaKeysMutex}; @@ -502,7 +521,7 @@ MediaKeyErrorStatus CdmService::decrypt(int32_t keySessionId, GstBuffer *encrypt RIALTO_SERVER_LOG_ERROR("Media keys handle for mksId: %d does not exists", keySessionId); return MediaKeyErrorStatus::FAIL; } - return m_mediaKeys[mediaKeysHandleIter->second.mediaKeysHandle]->decrypt(keySessionId, encrypted, caps); + return m_mediaKeys[mediaKeysHandleIter->second.mediaKeysHandle]->decrypt(keySessionId, encrypted, caps);*/ } bool CdmService::isNetflixPlayreadyKeySystem(int32_t keySessionId) @@ -581,14 +600,28 @@ void CdmService::decrementSessionIdUsageCounter(int32_t keySessionId) void CdmService::ping(const std::shared_ptr &heartbeatProcedure) { -// std::lock_guard lock{m_mediaKeysMutex}; + + std::unique_lock lock{m_mediaKeysMutex, std::try_to_lock}; + if (!lock.owns_lock()) + { + // Server is alive but busy in decrypt retry — acknowledge ping + RIALTO_SERVER_LOG_WARN("CdmService::ping - mutex busy (decrypt in progress), skipping CDM ping"); + return; // HeartbeatProcedure destructor sends success ack + } + for (const auto &mediaKeyPair : m_mediaKeys) + { + auto &mediaKeys = mediaKeyPair.second; + mediaKeys->ping(heartbeatProcedure->createHandler()); + } + + /*std::lock_guard lock{m_mediaKeysMutex}; RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: ping entry"); for (const auto &mediaKeyPair : m_mediaKeys) { auto &mediaKeys = mediaKeyPair.second; mediaKeys->ping(heartbeatProcedure->createHandler()); } - RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: ping exit"); + RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: ping exit");*/ } MediaKeyErrorStatus CdmService::getMetricSystemData(int mediaKeysHandle, std::vector &buffer) From acce42dff1effc1491fec29babc0d55900858733 Mon Sep 17 00:00:00 2001 From: LekshmiMR Date: Fri, 22 May 2026 21:02:48 +0000 Subject: [PATCH 14/19] Handling corner cases especially crash --- .../main/include/MediaKeysServerInternal.h | 6 +++++ .../main/source/MediaKeysServerInternal.cpp | 9 +++++++- media/server/service/source/CdmService.cpp | 23 ++++++++----------- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/media/server/main/include/MediaKeysServerInternal.h b/media/server/main/include/MediaKeysServerInternal.h index 6e934e004..f0c8c5527 100644 --- a/media/server/main/include/MediaKeysServerInternal.h +++ b/media/server/main/include/MediaKeysServerInternal.h @@ -28,6 +28,9 @@ #include #include #include +#include +#include +#include namespace firebolt::rialto::server { @@ -149,6 +152,9 @@ class MediaKeysServerInternal : public IMediaKeysServerInternal */ uint32_t m_mainThreadClientId; + + std::atomic_bool m_isShuttingDown{false}; + /** * @brief Creates a session internally, only to be called on the main thread. * diff --git a/media/server/main/source/MediaKeysServerInternal.cpp b/media/server/main/source/MediaKeysServerInternal.cpp index 2f1cb7ee7..0ee356f28 100644 --- a/media/server/main/source/MediaKeysServerInternal.cpp +++ b/media/server/main/source/MediaKeysServerInternal.cpp @@ -178,7 +178,7 @@ MediaKeysServerInternal::MediaKeysServerInternal( MediaKeysServerInternal::~MediaKeysServerInternal() { RIALTO_SERVER_LOG_DEBUG("entry:"); - + m_isShuttingDown = true; auto task = [&]() { m_ocdmSystem.reset(); @@ -643,8 +643,15 @@ MediaKeyErrorStatus MediaKeysServerInternal::decrypt(int32_t keySessionId, GstBu { break; } + if (m_isShuttingDown.load()) + { + RIALTO_SERVER_LOG_ERROR("Decrypt retry aborted — shutdown in progress"); + break; + } RIALTO_SERVER_LOG_WARN("Decrypt returned OUTPUT_RESTRICTED, retrying after delay"); + std::this_thread::sleep_for(kOutputRestrictedRetryInterval); + } while (std::chrono::steady_clock::now() < deadline); return status; diff --git a/media/server/service/source/CdmService.cpp b/media/server/service/source/CdmService.cpp index e16dc58c9..3f5fcb881 100644 --- a/media/server/service/source/CdmService.cpp +++ b/media/server/service/source/CdmService.cpp @@ -493,23 +493,18 @@ bool CdmService::isServerCertificateSupported(const std::string &keySystem) MediaKeyErrorStatus CdmService::decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) { - RIALTO_SERVER_LOG_ERROR("CdmService requested to decrypt, key session id: %d", keySessionId); - - // Acquire mutex ONLY to resolve the pointer — then release immediately IMediaKeysServerInternal *mediaKeys{nullptr}; { std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysHandleIter{m_sessionInfo.find(keySessionId)}; - if (mediaKeysHandleIter == m_sessionInfo.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle for mksId: %d does not exist", keySessionId); - return MediaKeyErrorStatus::FAIL; - } - mediaKeys = m_mediaKeys[mediaKeysHandleIter->second.mediaKeysHandle].get(); - } - // Mutex released — ping() can now proceed freely - - return mediaKeys->decrypt(keySessionId, encrypted, caps); + auto iter = m_sessionInfo.find(keySessionId); + if (iter == m_sessionInfo.end()) return MediaKeyErrorStatus::FAIL; + mediaKeys = m_mediaKeys[iter->second.mediaKeysHandle].get(); + // Increment ref counter to prevent destruction while in use + ++iter->second.refCounter; + } + auto status = mediaKeys->decrypt(keySessionId, encrypted, caps); + decrementSessionIdUsageCounter(keySessionId); // May trigger deferred release + return status; /* RIALTO_SERVER_LOG_DEBUG("CdmService requested to decrypt, key session id: %d", keySessionId); From bca5ce10a7002ef06ec63ef941b550df32384bab Mon Sep 17 00:00:00 2001 From: balasaraswathy-n Date: Mon, 25 May 2026 16:24:46 +0530 Subject: [PATCH 15/19] Update OcdmSession.cpp --- wrappers/source/OcdmSession.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wrappers/source/OcdmSession.cpp b/wrappers/source/OcdmSession.cpp index 1c1b33638..a6c9eea6a 100644 --- a/wrappers/source/OcdmSession.cpp +++ b/wrappers/source/OcdmSession.cpp @@ -198,7 +198,7 @@ MediaKeyErrorStatus OcdmSession::update(const uint8_t response[], uint32_t respo MediaKeyErrorStatus OcdmSession::decryptBuffer(GstBuffer *encrypted, GstCaps *caps) { - RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer()\n"); + // RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer()\n"); if (!m_session) { return MediaKeyErrorStatus::FAIL; @@ -239,7 +239,7 @@ MediaKeyErrorStatus OcdmSession::decryptBuffer(GstBuffer *encrypted, GstCaps *ca RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer() : returning MediaKeyErrorStatus::OUTPUT_RESTRICTED(Pre decrypt)\n"); return MediaKeyErrorStatus::OUTPUT_RESTRICTED; } else { - RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer() : returning error(Pre decrypt)\n"); + // RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer() : returning no error(Pre decrypt)\n"); } } @@ -257,7 +257,7 @@ MediaKeyErrorStatus OcdmSession::decryptBuffer(GstBuffer *encrypted, GstCaps *ca RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer() : returning MediaKeyErrorStatus::OUTPUT_RESTRICTED(Post decrypt)\n"); return MediaKeyErrorStatus::OUTPUT_RESTRICTED; } else { - RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer() : returning error(Post decrypt)\n"); + //RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer() : returning no error(Post decrypt)\n"); } } From 9574d44f498f51c4dc510295afef85e5528782bf Mon Sep 17 00:00:00 2001 From: balasaraswathy-n Date: Mon, 25 May 2026 16:27:03 +0530 Subject: [PATCH 16/19] Update MediaKeysServerInternal.cpp --- media/server/main/source/MediaKeysServerInternal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media/server/main/source/MediaKeysServerInternal.cpp b/media/server/main/source/MediaKeysServerInternal.cpp index 0ee356f28..38db56f66 100644 --- a/media/server/main/source/MediaKeysServerInternal.cpp +++ b/media/server/main/source/MediaKeysServerInternal.cpp @@ -602,7 +602,7 @@ MediaKeyErrorStatus MediaKeysServerInternal::getCdmKeySessionIdInternal(int32_t MediaKeyErrorStatus MediaKeysServerInternal::decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) { - RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: entry:decrypt"); + //RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: entry:decrypt"); MediaKeyErrorStatus status{MediaKeyErrorStatus::FAIL}; const auto deadline = std::chrono::steady_clock::now() + kOutputRestrictedRetryTimeout; From a483e98fb4b73829d88304f86bd84d4121b888e7 Mon Sep 17 00:00:00 2001 From: balasaraswathy-n Date: Mon, 25 May 2026 16:31:44 +0530 Subject: [PATCH 17/19] Update MediaKeysServerInternal.cpp --- media/server/main/source/MediaKeysServerInternal.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/media/server/main/source/MediaKeysServerInternal.cpp b/media/server/main/source/MediaKeysServerInternal.cpp index 38db56f66..a23491ac4 100644 --- a/media/server/main/source/MediaKeysServerInternal.cpp +++ b/media/server/main/source/MediaKeysServerInternal.cpp @@ -602,7 +602,7 @@ MediaKeyErrorStatus MediaKeysServerInternal::getCdmKeySessionIdInternal(int32_t MediaKeyErrorStatus MediaKeysServerInternal::decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) { - //RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: entry:decrypt"); + // RIALTO_SERVER_LOG_DEBUG("DEBUG PURPOSE: entry:decrypt"); MediaKeyErrorStatus status{MediaKeyErrorStatus::FAIL}; const auto deadline = std::chrono::steady_clock::now() + kOutputRestrictedRetryTimeout; @@ -610,8 +610,8 @@ MediaKeyErrorStatus MediaKeysServerInternal::decrypt(int32_t keySessionId, GstBu { auto task = [&]() { status = decryptInternal(keySessionId, encrypted, caps); }; m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session id :%d", keySessionId); - switch (status) + RIALTO_SERVER_LOG_DEBUG("DEBUG PURPOSE : Key session id :%d", keySessionId); + /* switch (status) { case firebolt::rialto::MediaKeyErrorStatus::OK: RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : OK"); @@ -637,7 +637,7 @@ MediaKeyErrorStatus MediaKeysServerInternal::decrypt(int32_t keySessionId, GstBu case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED: RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : OUTPUT_RESTRICTED"); break; - } + }*/ if (status != MediaKeyErrorStatus::OUTPUT_RESTRICTED) { From 0d20baec75fbf52b90d1d111f1d0cee65bf6288e Mon Sep 17 00:00:00 2001 From: N Date: Tue, 26 May 2026 10:42:39 +0530 Subject: [PATCH 18/19] Stale segment flush --- .../main/include/MediaKeysServerInternal.h | 2 ++ .../main/source/MediaKeysServerInternal.cpp | 22 +++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/media/server/main/include/MediaKeysServerInternal.h b/media/server/main/include/MediaKeysServerInternal.h index f0c8c5527..693ed20b5 100644 --- a/media/server/main/include/MediaKeysServerInternal.h +++ b/media/server/main/include/MediaKeysServerInternal.h @@ -155,6 +155,8 @@ class MediaKeysServerInternal : public IMediaKeysServerInternal std::atomic_bool m_isShuttingDown{false}; + std::atomic_bool m_outputWasRestricted{false}; + /** * @brief Creates a session internally, only to be called on the main thread. * diff --git a/media/server/main/source/MediaKeysServerInternal.cpp b/media/server/main/source/MediaKeysServerInternal.cpp index a23491ac4..c11c96e00 100644 --- a/media/server/main/source/MediaKeysServerInternal.cpp +++ b/media/server/main/source/MediaKeysServerInternal.cpp @@ -83,6 +83,7 @@ namespace firebolt::rialto::server { constexpr std::chrono::milliseconds kOutputRestrictedRetryInterval{250}; constexpr std::chrono::seconds kOutputRestrictedRetryTimeout{6}; +constexpr std::chrono::seconds kStaleThreshold{4}; int32_t generateSessionId() { @@ -173,6 +174,8 @@ MediaKeysServerInternal::MediaKeysServerInternal( { throw std::runtime_error("MediaKeys construction failed"); } + + m_outputWasRestricted = false; } MediaKeysServerInternal::~MediaKeysServerInternal() @@ -602,9 +605,21 @@ MediaKeyErrorStatus MediaKeysServerInternal::getCdmKeySessionIdInternal(int32_t MediaKeyErrorStatus MediaKeysServerInternal::decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) { - // RIALTO_SERVER_LOG_DEBUG("DEBUG PURPOSE: entry:decrypt"); + RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: entry:decrypt"); MediaKeyErrorStatus status{MediaKeyErrorStatus::FAIL}; + // Check if this buffer is stale (timestamp too far behind current position) + if (m_outputWasRestricted && GST_BUFFER_PTS_IS_VALID(encrypted)) + { + GstClockTime bufferPts = GST_BUFFER_PTS(encrypted); + GstClockTime currentPos = getCurrentPlaybackPosition(); + if (currentPos > bufferPts && (currentPos - bufferPts) > kStaleThreshold) // e.g., 4 seconds + { + RIALTO_SERVER_LOG_WARN("Dropping stale segment (%.3fs behind) after HDCP recovery", + (currentPos - bufferPts) / 1e9); + return MediaKeyErrorStatus::OK; // Drop silently, pretend decrypt succeeded + } + } const auto deadline = std::chrono::steady_clock::now() + kOutputRestrictedRetryTimeout; do { @@ -641,13 +656,16 @@ MediaKeyErrorStatus MediaKeysServerInternal::decrypt(int32_t keySessionId, GstBu if (status != MediaKeyErrorStatus::OUTPUT_RESTRICTED) { + m_outputWasRestricted = false; break; } - if (m_isShuttingDown.load()) + m_outputWasRestricted = true; + if (m_isShuttingDown.load()) { RIALTO_SERVER_LOG_ERROR("Decrypt retry aborted — shutdown in progress"); break; } + RIALTO_SERVER_LOG_WARN("Decrypt returned OUTPUT_RESTRICTED, retrying after delay"); std::this_thread::sleep_for(kOutputRestrictedRetryInterval); From cc4c8f5c95e647e71de0a88e08f656c8e2d50df1 Mon Sep 17 00:00:00 2001 From: Varatharajan_Narayanan Date: Tue, 26 May 2026 07:32:46 +0000 Subject: [PATCH 19/19] Resolved the compilation error faced due to getCurrentPlaybackPosition Signed-off-by: Varatharajan_Narayanan --- .../main/include/MediaKeysServerInternal.h | 4 ++++ .../main/source/MediaKeysServerInternal.cpp | 24 +++++++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/media/server/main/include/MediaKeysServerInternal.h b/media/server/main/include/MediaKeysServerInternal.h index 693ed20b5..4694f3e4a 100644 --- a/media/server/main/include/MediaKeysServerInternal.h +++ b/media/server/main/include/MediaKeysServerInternal.h @@ -157,6 +157,10 @@ class MediaKeysServerInternal : public IMediaKeysServerInternal std::atomic_bool m_outputWasRestricted{false}; + std::atomic m_currentPositionPts{0}; + + std::atomic_bool m_hasCurrentPositionPts{false}; + /** * @brief Creates a session internally, only to be called on the main thread. * diff --git a/media/server/main/source/MediaKeysServerInternal.cpp b/media/server/main/source/MediaKeysServerInternal.cpp index c11c96e00..ea32f4a64 100644 --- a/media/server/main/source/MediaKeysServerInternal.cpp +++ b/media/server/main/source/MediaKeysServerInternal.cpp @@ -83,7 +83,7 @@ namespace firebolt::rialto::server { constexpr std::chrono::milliseconds kOutputRestrictedRetryInterval{250}; constexpr std::chrono::seconds kOutputRestrictedRetryTimeout{6}; -constexpr std::chrono::seconds kStaleThreshold{4}; +constexpr GstClockTime kStaleThreshold{4 * GST_SECOND}; int32_t generateSessionId() { @@ -608,18 +608,28 @@ MediaKeyErrorStatus MediaKeysServerInternal::decrypt(int32_t keySessionId, GstBu RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: entry:decrypt"); MediaKeyErrorStatus status{MediaKeyErrorStatus::FAIL}; - // Check if this buffer is stale (timestamp too far behind current position) - if (m_outputWasRestricted && GST_BUFFER_PTS_IS_VALID(encrypted)) + + if (GST_BUFFER_PTS_IS_VALID(encrypted)) { GstClockTime bufferPts = GST_BUFFER_PTS(encrypted); - GstClockTime currentPos = getCurrentPlaybackPosition(); - if (currentPos > bufferPts && (currentPos - bufferPts) > kStaleThreshold) // e.g., 4 seconds + + if (!m_hasCurrentPositionPts.load() || bufferPts > m_currentPositionPts.load()) + { + m_currentPositionPts = bufferPts; + m_hasCurrentPositionPts = true; + } + + // After OUTPUT_RESTRICTED recovery, drop buffered segments that are behind live playback. + const GstClockTime currentPos = m_currentPositionPts.load(); + if (m_outputWasRestricted.load() && m_hasCurrentPositionPts.load() && currentPos > bufferPts && + (currentPos - bufferPts) > kStaleThreshold) { - RIALTO_SERVER_LOG_WARN("Dropping stale segment (%.3fs behind) after HDCP recovery", - (currentPos - bufferPts) / 1e9); + const double lagSeconds = static_cast(currentPos - bufferPts) / GST_SECOND; + RIALTO_SERVER_LOG_WARN("Dropping stale segment (%.3fs behind) after HDCP recovery", lagSeconds); return MediaKeyErrorStatus::OK; // Drop silently, pretend decrypt succeeded } } + const auto deadline = std::chrono::steady_clock::now() + kOutputRestrictedRetryTimeout; do {