ADDED THE RETRY MECHANISM IN RIALTO#509
Conversation
|
Pull request must be merged with a description containing the required fields, Summary: If there is no jira releated to this change, please put 'Jira: NO-JIRA'. Description can be changed by editing the top comment on your pull request and making a new commit. |
There was a problem hiding this comment.
Pull request overview
This PR introduces an OUTPUT_RESTRICTED decrypt outcome and attempts to add a retry mechanism when output restrictions (e.g., HDCP re-auth) prevent decryption, including support for a new OCdm adapter entry point (opencdm_gstreamer_session_decrypt_buffer_once).
Changes:
- Added
MediaKeyErrorStatus::OUTPUT_RESTRICTEDand propagated it to some status-to-string helpers. - Added optional use of
opencdm_gstreamer_session_decrypt_buffer_onceand key-status checks inOcdmSession::decryptBuffer. - Implemented retry logic in
MediaKeysServerInternal::decryptwhenOUTPUT_RESTRICTEDis returned.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| wrappers/source/OcdmSession.cpp | Loads optional OCdm decrypt symbol and adds pre/post decrypt key-status checks returning OUTPUT_RESTRICTED. |
| wrappers/include/OcdmSession.h | Declares function pointer type/static for the new decrypt entry point. |
| wrappers/CMakeLists.txt | Adds include paths to access common/logging headers used by new logging calls. |
| media/server/main/source/MediaKeysServerInternal.cpp | Adds retry loop for decrypt and modifies ping behavior/logging. |
| media/server/main/source/MediaKeysCapabilities.cpp | Adds OUTPUT_RESTRICTED to MediaKeyErrorStatus string conversion. |
| media/server/ipc/source/MediaKeysModuleService.cpp | Starts adding server-side IPC mapping for OUTPUT_RESTRICTED (currently incomplete). |
| media/public/include/MediaCommon.h | Adds OUTPUT_RESTRICTED to the public MediaKeyErrorStatus enum. |
| media/client/ipc/source/MediaKeysIpc.cpp | Adds OUTPUT_RESTRICTED to client-side status string conversion; minor formatting change. |
Comments suppressed due to low confidence (3)
wrappers/source/OcdmSession.cpp:244
- The
elsebranch logs "returning error" even though the code does not return an error there (it continues to decrypt). This is misleading and will generate erroneous ERROR logs whenever the key status is not output-restricted. Either remove these logs, or change them to an accurate message at a non-error level.
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");
}
wrappers/source/OcdmSession.cpp:261
- Same issue post-decrypt: this
elselogs "returning error(Post decrypt)" but the function does not return an error at that point. This produces misleading ERROR logs and should be removed or corrected (and likely downgraded from ERROR).
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");
}
media/server/main/source/MediaKeysServerInternal.cpp:640
- This adds a large amount of "DEBUG PURPOSE" logging at ERROR level (including a full switch over statuses) on the hot decrypt path. This will spam error logs during normal operation and impacts performance. Please remove it or replace it with a single DEBUG/TRACE log using an existing status-to-string helper.
RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: entry:decrypt");
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;
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| void* handle = dlopen("libocdm.so", RTLD_LAZY); | ||
| m_ocdmGstSessionDecryptEx = | ||
| (OcdmGstSessionDecryptExFn)dlsym(RTLD_DEFAULT, "opencdm_gstreamer_session_decrypt_ex"); | ||
| 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"); | ||
| } |
| MediaKeyErrorStatus OcdmSession::decryptBuffer(GstBuffer *encrypted, GstCaps *caps) | ||
| { | ||
| RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer()\n"); | ||
| if (!m_session) | ||
| { | ||
| return MediaKeyErrorStatus::FAIL; | ||
| } |
| target_include_directories( | ||
| RialtoWrappers | ||
|
|
||
| PUBLIC | ||
| interface | ||
|
|
||
| PRIVATE | ||
| include | ||
| ../common/interface/ | ||
| ../logging/include/ | ||
| ${GStreamerApp_INCLUDE_DIRS} |
| /*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 | ||
|
|
||
|
|
| 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); | ||
|
|
| 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); |
| void MediaKeysServerInternal::ping(std::unique_ptr<IHeartbeatHandler> &&heartbeatHandler) | ||
| { | ||
| RIALTO_SERVER_LOG_DEBUG("entry:"); | ||
| RIALTO_SERVER_LOG_ERROR("entry:"); | ||
| auto task = [&]() { heartbeatHandler.reset(); }; | ||
|
|
||
| m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); | ||
| RIALTO_SERVER_LOG_ERROR("exit:"); |
| } | ||
| case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED: | ||
| { | ||
| // TODO |
| BUFFER_TOO_SMALL, /**< The size of the buffer is too small. */ | ||
| OUTPUT_RESTRICTED |
|
|
||
| MediaKeyErrorStatus MediaKeysIpc::createKeySession(KeySessionType sessionType, std::weak_ptr<IMediaKeysClient> client, | ||
| bool isLDL, int32_t &keySessionId) | ||
| bool isLDL, int32_t &keySessionId) |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 10 comments.
Comments suppressed due to low confidence (2)
wrappers/source/OcdmSession.cpp:205
- Please remove or downgrade these "DEBUG PURPOSE" logs (currently using ERROR severity and embedding newlines). This path is on the decryption hot path and will spam error logs during normal operation; use the existing logging conventions (e.g., DEBUG/TRACE without trailing \n) if logging is still needed.
MediaKeyErrorStatus OcdmSession::decryptBuffer(GstBuffer *encrypted, GstCaps *caps)
{
RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer()\n");
if (!m_session)
{
return MediaKeyErrorStatus::FAIL;
}
media/server/main/source/MediaKeysServerInternal.cpp:73
firebolt::rialto::mediaKeyErrorStatusToString()does not handle the newly introducedMediaKeyErrorStatus::OUTPUT_RESTRICTED(it will currently hit the default and return "FAIL"). Please add an explicit case for OUTPUT_RESTRICTED so logs/diagnostics report the correct status.
const char *mediaKeyErrorStatusToString(const MediaKeyErrorStatus &status)
{
switch (status)
{
case firebolt::rialto::MediaKeyErrorStatus::OK:
return "OK";
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";
default:
return "FAIL";
}
| void* handle = dlopen("libocdm.so", RTLD_LAZY); | ||
| m_ocdmGstSessionDecryptEx = | ||
| (OcdmGstSessionDecryptExFn)dlsym(RTLD_DEFAULT, "opencdm_gstreamer_session_decrypt_ex"); | ||
| 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"); | ||
| } |
| } else { | ||
| RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer() : returning error(Pre decrypt)\n"); |
| /*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 | ||
|
|
||
|
|
| 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); |
| 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); |
| RIALTO_SERVER_LOG_ERROR("entry:"); | ||
| auto task = [&]() { heartbeatHandler.reset(); }; | ||
|
|
||
| m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); | ||
| RIALTO_SERVER_LOG_ERROR("exit:"); |
| @@ -114,6 +114,7 @@ void ControlServerInternal::ack(int32_t ackId) | |||
| m_heartbeatHandler.reset(); | |||
| }; | |||
| m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); | |||
| RIALTO_SERVER_LOG_ERROR("Control with id: %d received ack for ping: %d task exit", m_controlId, ackId); | |||
| } | |||
| } | ||
| case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED: | ||
| { | ||
| // TODO |
| BUFFER_TOO_SMALL, /**< The size of the buffer is too small. */ | ||
| OUTPUT_RESTRICTED |
|
media/server/service/source/CdmService.cpp:506:5: style: Statements following 'return' will never be executed. [unreachableCode] |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 9 comments.
Comments suppressed due to low confidence (7)
media/server/service/source/CdmService.cpp:507
- The "ping_cmd_service_is_exit" log is unreachable because it appears after a
return. Please remove it, or log before returning if this is needed for tracing.
RIALTO_SERVER_LOG_ERROR("ping_cmd_service_is_entry");
return m_mediaKeys[mediaKeysHandleIter->second.mediaKeysHandle]->decrypt(keySessionId, encrypted, caps);
RIALTO_SERVER_LOG_ERROR("ping_cmd_service_is_exit");
}
media/server/service/source/CdmService.cpp:587
CdmService::pingiteratesm_mediaKeyswithout holdingm_mediaKeysMutex(the lock is commented out). Other methods consistently take this lock before accessingm_mediaKeys/m_sessionInfo, so this introduces a data race/use-after-free risk if media keys are created/destroyed concurrently. Please restore the lock or otherwise guarantee thread-safety form_mediaKeysduring ping.
void CdmService::ping(const std::shared_ptr<IHeartbeatProcedure> &heartbeatProcedure)
{
// std::lock_guard<std::mutex> lock{m_mediaKeysMutex};
RIALTO_SERVER_LOG_ERROR("ping_cmd_service_is_entry");
for (const auto &mediaKeyPair : m_mediaKeys)
media/server/main/source/MediaKeysServerInternal.cpp:648
- The retry loop sleeps the calling thread (
std::this_thread::sleep_for). Since decrypt is typically called from a streaming/GStreamer thread, this can stall playback and tie up threads under HDCP re-auth. Consider making the retry asynchronous (schedule a delayed retry on the main thread) or otherwise ensure this blocking behavior is acceptable.
RIALTO_SERVER_LOG_WARN("Decrypt returned OUTPUT_RESTRICTED, retrying after delay");
std::this_thread::sleep_for(kOutputRestrictedRetryInterval);
} while (std::chrono::steady_clock::now() < deadline);
media/server/main/source/MediaKeysServerInternal.cpp:607
- The new OUTPUT_RESTRICTED retry behavior in
MediaKeysServerInternal::decryptis not covered by existing unit tests (there are tests for OK/INVALID_STATE/BAD_SESSION_ID). Please add a test that verifies decrypt retries whendecryptInternalreturnsOUTPUT_RESTRICTEDand stops retrying once it returnsOK(and/or times out).
MediaKeyErrorStatus MediaKeysServerInternal::decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps)
{
RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: entry:decrypt");
MediaKeyErrorStatus status{MediaKeyErrorStatus::FAIL};
media/server/main/source/MediaKeysServerInternal.cpp:61
mediaKeyErrorStatusToStringdoes not have explicit cases forFAIL,INVALID_STATE, or the newly addedOUTPUT_RESTRICTEDand will stringify them as "FAIL" via the default case. Please add the missing cases (or reuse a single shared mapping) so logs are accurate.
const char *mediaKeyErrorStatusToString(const MediaKeyErrorStatus &status)
{
switch (status)
{
case firebolt::rialto::MediaKeyErrorStatus::OK:
media/server/main/source/MediaKeysServerInternal.cpp:609
MediaKeysServerInternal::decryptadds very verbose "DEBUG PURPOSE" logging at ERROR level. This will spam error logs on normal code paths; please switch these to DEBUG/TRACE and consider using a helper (e.g.,mediaKeyErrorStatusToString) rather than duplicating large status logging logic.
RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: entry:decrypt");
MediaKeyErrorStatus status{MediaKeyErrorStatus::FAIL};
const auto deadline = std::chrono::steady_clock::now() + kOutputRestrictedRetryTimeout;
do
media/server/main/source/MediaKeysServerInternal.cpp:684
MediaKeysServerInternal::pingwas changed to log at ERROR level on entry for a normal control path. Please revert to DEBUG (or remove) to avoid inflating error logs.
void MediaKeysServerInternal::ping(std::unique_ptr<IHeartbeatHandler> &&heartbeatHandler)
{
RIALTO_SERVER_LOG_ERROR("entry:");
auto task = [&]() { heartbeatHandler.reset(); };
|
|
||
| MediaKeyErrorStatus MediaKeysIpc::createKeySession(KeySessionType sessionType, std::weak_ptr<IMediaKeysClient> client, | ||
| bool isLDL, int32_t &keySessionId) | ||
| bool isLDL, int32_t &keySessionId) |
| void* handle = dlopen("libocdm.so", RTLD_LAZY); | ||
| m_ocdmGstSessionDecryptEx = | ||
| (OcdmGstSessionDecryptExFn)dlsym(RTLD_DEFAULT, "opencdm_gstreamer_session_decrypt_ex"); | ||
| m_ocdmGstSessionDecryptBufferOnce = (OcdmGstSessionDecryptBufferOnceFn)dlsym(handle,"opencdm_gstreamer_session_decrypt_buffer_once"); | ||
| if(m_ocdmGstSessionDecryptBufferOnce != NULL){ |
|
|
||
| MediaKeyErrorStatus OcdmSession::decryptBuffer(GstBuffer *encrypted, GstCaps *caps) | ||
| { | ||
| RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer()\n"); |
| 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"); | ||
| } |
| void ControlServerInternal::ack(int32_t ackId) | ||
| { | ||
| RIALTO_SERVER_LOG_DEBUG("Control with id: %d received ack for ping: %d", m_controlId, ackId); | ||
| RIALTO_SERVER_LOG_ERROR("Control with id: %d received ack for ping: %d", m_controlId, ackId); | ||
| auto task = [&]() |
| BUFFER_TOO_SMALL, /**< The size of the buffer is too small. */ | ||
| OUTPUT_RESTRICTED |
| } | ||
| case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED: | ||
| { | ||
| // TODO |
| RIALTO_SERVER_LOG_ERROR("ping_cmd_service_is_entry"); | ||
| return m_mediaKeys[mediaKeysHandleIter->second.mediaKeysHandle]->decrypt(keySessionId, encrypted, caps); | ||
| RIALTO_SERVER_LOG_ERROR("ping_cmd_service_is_exit"); |
| /*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 | ||
|
|
||
|
|
ADDED THE RETRY MECHANISM IN RIALTO