Skip to content

ADDED THE RETRY MECHANISM IN RIALTO#509

Open
varatharajan568 wants to merge 14 commits into
release/v0.15.2from
feature/RDKEMW-18675_1
Open

ADDED THE RETRY MECHANISM IN RIALTO#509
varatharajan568 wants to merge 14 commits into
release/v0.15.2from
feature/RDKEMW-18675_1

Conversation

@varatharajan568
Copy link
Copy Markdown

ADDED THE RETRY MECHANISM IN RIALTO

Copilot AI review requested due to automatic review settings May 22, 2026 02:25
@github-actions
Copy link
Copy Markdown

Pull request must be merged with a description containing the required fields,

Summary:
Type: Feature/Fix/Cleanup
Test Plan:
Jira:

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.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_RESTRICTED and propagated it to some status-to-string helpers.
  • Added optional use of opencdm_gstreamer_session_decrypt_buffer_once and key-status checks in OcdmSession::decryptBuffer.
  • Implemented retry logic in MediaKeysServerInternal::decrypt when OUTPUT_RESTRICTED is 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 else branch 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 else logs "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.

Comment on lines +125 to +131
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");
}
Comment on lines 199 to 205
MediaKeyErrorStatus OcdmSession::decryptBuffer(GstBuffer *encrypted, GstCaps *caps)
{
RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer()\n");
if (!m_session)
{
return MediaKeyErrorStatus::FAIL;
}
Comment thread wrappers/CMakeLists.txt
Comment on lines 105 to 115
target_include_directories(
RialtoWrappers

PUBLIC
interface

PRIVATE
include
../common/interface/
../logging/include/
${GStreamerApp_INCLUDE_DIRS}
Comment on lines +27 to +54
/*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


Comment on lines +608 to 649
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);

Comment on lines +607 to +648
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);
Comment on lines 680 to +686
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
Comment on lines +295 to +296
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)
Copilot AI review requested due to automatic review settings May 22, 2026 09:31
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 introduced MediaKeyErrorStatus::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";
    }

Comment on lines +125 to +131
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");
}
Comment on lines +241 to +242
} else {
RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer() : returning error(Pre decrypt)\n");
Comment on lines +27 to +54
/*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


Comment on lines +605 to +640
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;
}
Comment on lines +642 to +648
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);
Comment on lines +613 to +648
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);
Comment on lines +682 to +686
RIALTO_SERVER_LOG_ERROR("entry:");
auto task = [&]() { heartbeatHandler.reset(); };

m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
RIALTO_SERVER_LOG_ERROR("exit:");
Comment on lines 99 to 118
@@ -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
Comment on lines +295 to +296
BUFFER_TOO_SMALL, /**< The size of the buffer is too small. */
OUTPUT_RESTRICTED
Copilot AI review requested due to automatic review settings May 22, 2026 13:22
@github-actions
Copy link
Copy Markdown

media/server/service/source/CdmService.cpp:506:5: style: Statements following 'return' will never be executed. [unreachableCode]
RIALTO_SERVER_LOG_ERROR("ping_cmd_service_is_exit");
^
nofile:0:0: information: Active checkers: 161/592 (use --checkers-report= to see details) [checkersReport]

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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::ping iterates m_mediaKeys without holding m_mediaKeysMutex (the lock is commented out). Other methods consistently take this lock before accessing m_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 for m_mediaKeys during 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::decrypt is not covered by existing unit tests (there are tests for OK/INVALID_STATE/BAD_SESSION_ID). Please add a test that verifies decrypt retries when decryptInternal returns OUTPUT_RESTRICTED and stops retrying once it returns OK (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

  • mediaKeyErrorStatusToString does not have explicit cases for FAIL, INVALID_STATE, or the newly added OUTPUT_RESTRICTED and 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::decrypt adds 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::ping was 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)
Comment on lines +125 to +129
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");
Comment on lines +239 to +243
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");
}
Comment on lines 99 to 102
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 = [&]()
Comment on lines +295 to +296
BUFFER_TOO_SMALL, /**< The size of the buffer is too small. */
OUTPUT_RESTRICTED
}
case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED:
{
// TODO
Comment on lines +504 to +506
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");
Comment on lines +27 to +54
/*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


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants