Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion media/client/ipc/source/MediaKeysIpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
Expand Down Expand Up @@ -334,7 +338,7 @@ bool MediaKeysIpc::containsKey(int32_t keySessionId, const std::vector<uint8_t>
}

MediaKeyErrorStatus MediaKeysIpc::createKeySession(KeySessionType sessionType, std::weak_ptr<IMediaKeysClient> client,
bool isLDL, int32_t &keySessionId)
bool isLDL, int32_t &keySessionId)
{
if (!reattachChannelIfRequired())
{
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 3 additions & 1 deletion media/public/include/MediaCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
};

/**
Expand Down Expand Up @@ -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_
8 changes: 7 additions & 1 deletion media/server/ipc/source/MediaKeysModuleService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -100,6 +104,7 @@ firebolt::rialto::InitDataType covertInitDataType(firebolt::rialto::GenerateRequ
return firebolt::rialto::InitDataType::UNKNOWN;
}
}

} // namespace

namespace firebolt::rialto::server::ipc
Expand Down Expand Up @@ -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<std::uint8_t>{request->init_data().begin(),
request->init_data().end()});


response->set_error_status(convertMediaKeyErrorStatus(status));
done->Run();
}
Expand Down
3 changes: 2 additions & 1 deletion media/server/main/source/ControlServerInternal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ ControlServerInternal::~ControlServerInternal()

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 = [&]()
{
if (!m_heartbeatHandler)
Expand All @@ -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);
}

void ControlServerInternal::setApplicationState(const ApplicationState &state)
Expand Down
2 changes: 2 additions & 0 deletions media/server/main/source/MediaKeysCapabilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
Expand Down
79 changes: 75 additions & 4 deletions media/server/main/source/MediaKeysServerInternal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,40 @@
*/

#include <stdexcept>
#include <chrono>
#include <thread>

#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)
Expand Down Expand Up @@ -51,6 +81,9 @@ std::shared_ptr<IMediaKeysFactory> IMediaKeysFactory::createFactory()

namespace firebolt::rialto::server
{
constexpr std::chrono::milliseconds kOutputRestrictedRetryInterval{100};
//constexpr std::chrono::seconds kOutputRestrictedRetryTimeout{6};

int32_t generateSessionId()
{
static int32_t keySessionId{0};
Expand Down Expand Up @@ -569,12 +602,48 @@ 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;
MediaKeyErrorStatus status{MediaKeyErrorStatus::FAIL};

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)
{
std::this_thread::sleep_for(kOutputRestrictedRetryInterval);
auto task = [&]() { status = decryptInternal(keySessionId, encrypted, caps); };
m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
RIALTO_SERVER_LOG_WARN("Decrypt returned OUTPUT_RESTRICTED, retrying once after delay");
}
return status;
}

Expand Down Expand Up @@ -604,12 +673,14 @@ bool MediaKeysServerInternal::isNetflixPlayreadyKeySystem() const
return m_kKeySystem.find("netflix") != std::string::npos;
}


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

MediaKeyErrorStatus MediaKeysServerInternal::getMetricSystemData(std::vector<uint8_t> &buffer)
Expand Down
4 changes: 4 additions & 0 deletions media/server/service/source/CdmService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,9 @@ 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;
}
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");
}

bool CdmService::isNetflixPlayreadyKeySystem(int32_t keySessionId)
Expand Down Expand Up @@ -581,11 +583,13 @@ void CdmService::decrementSessionIdUsageCounter(int32_t keySessionId)
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)
{
auto &mediaKeys = mediaKeyPair.second;
mediaKeys->ping(heartbeatProcedure->createHandler());
}
RIALTO_SERVER_LOG_ERROR("ping_cmd_service_is_exited");
}

MediaKeyErrorStatus CdmService::getMetricSystemData(int mediaKeysHandle, std::vector<uint8_t> &buffer)
Expand Down
2 changes: 2 additions & 0 deletions wrappers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ target_include_directories(

PRIVATE
include
../common/interface/
../logging/include/
${GStreamerApp_INCLUDE_DIRS}
$<TARGET_PROPERTY:RialtoPlayerPublic,INTERFACE_INCLUDE_DIRECTORIES>
${WRAPPER_INCLUDES}
Expand Down
2 changes: 2 additions & 0 deletions wrappers/include/OcdmSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand All @@ -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.
Expand Down
70 changes: 70 additions & 0 deletions wrappers/source/OcdmSession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include "opencdm/open_cdm_ext.h"
#include <dlfcn.h>
#include <mutex>
#include <vector>
#include "RialtoCommonLogging.h"

namespace
{
Expand Down Expand Up @@ -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)
Expand All @@ -119,8 +122,13 @@ 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(handle,"opencdm_gstreamer_session_decrypt_buffer_once");
if(m_ocdmGstSessionDecryptBufferOnce != NULL){
RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : m_ocdmGstSessionDecryptBufferOnce exists\n");
}
});
}

Expand Down Expand Up @@ -190,11 +198,73 @@ 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<uint8_t> keyId;
GstProtectionMeta *pm = reinterpret_cast<GstProtectionMeta *>(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<uint8_t>(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;
} else {
RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer() : returning error(Pre decrypt)\n");
}

}

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<uint8_t>(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;
} else {
RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer() : returning error(Post decrypt)\n");
}
}

return convertOpenCdmError(result);
}

// Fallback: adapter without _once handles retries internally.
OpenCDMError status = opencdm_gstreamer_session_decrypt_buffer(m_session, encrypted, caps);
return convertOpenCdmError(status);
}
Expand Down
Loading