Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
67d4001
RDKEMW-26815: Add virtual destructor to DeviceInterfaceBase
muthumanik Oct 13, 2026
9701547
RDKEMW-26816: Check gst_element_link() return values and fail bin ass…
muthumanik Oct 13, 2026
c45c699
RDKEMW-26817: Replace raw printf() with MW_LOG/GST logging in product…
muthumanik Oct 13, 2026
e06957f
RDKEMW-26818: Remove blocking sleep(5) from OCDM decrypt recovery path
muthumanik Oct 13, 2026
6dc56a6
RDKEMW-26819: RAII ownership for raw-owned buffers (std::string/uniqu…
muthumanik Oct 13, 2026
94cfa62
RDKEMW-26821: Null-check DeviceInterfaceBase consumers and container-…
muthumanik Oct 13, 2026
d61ce9c
RDKEMW-26814: HDCP event coalescing + video-rect parse cache
muthumanik Oct 13, 2026
3d962d3
L1 test patches
KevinReji28 Oct 14, 2026
c396678
Revert "L1 test patches"
KevinReji28 Oct 15, 2026
2c360b5
Add L1 test coverage
Oct 15, 2026
53875e6
Revert "Add L1 test coverage"
Oct 15, 2026
d4dd5c0
Add L1 test coverage
Oct 15, 2026
f371c44
Revert "Add L1 test coverage"
Oct 15, 2026
ae2b856
Add L1 test coverage
KevinReji28 Oct 15, 2026
4ccbc90
Merge pull request #300 from rdkcentral/feature/l1-test
KevinReji28 Oct 15, 2026
9b7d4fe
L1 test patch update
Oct 15, 2026
fbf2e86
L1 test patch update2
KevinReji28 Oct 15, 2026
5597e71
RDKEMW:26814 :Code Improvements in Player Interface Library
KevinReji28 Oct 19, 2026
f372f6b
RDKEMW:26814 :Code Improvements in Player Interface Library
KevinReji28 Oct 19, 2026
65c0b86
Change string parameters to const references in ThunderAccessPlayer
KevinReji28 Oct 23, 2026
689dd62
Rename g_free mock method to mock_g_free
KevinReji28 Oct 23, 2026
e1acdbc
Rename g_free to mock_g_free in FakeGLib
KevinReji28 Oct 23, 2026
664405b
Fix GLib g_free macro conflict in fake mock layer
KevinReji28 Oct 23, 2026
071cca0
Merge branch 'develop' into feature/RDKEMW-26814-phase1
KevinReji28 Nov 3, 2026
91892a7
Change expected rc value in Acquire test case
KevinReji28 Nov 3, 2026
a601ea7
Update expected return code in Acquire test
KevinReji28 Nov 3, 2026
935e1b9
Update expected result for Acquire function test
KevinReji28 Nov 3, 2026
48202be
Merge branch 'develop' into feature/RDKEMW-26814-phase1
KevinReji28 Nov 4, 2026
fa5aac5
RDKEMW-26814:Code improvements in Player interface Library
KevinReji28 Nov 4, 2026
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
2 changes: 2 additions & 0 deletions InterfacePlayerPriv.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ struct GstPlayerPriv
bool usingRialtoSink; /**< true if rialto sink is used for video and audio sinks */
bool usingClosedCaptionsControl; /**< true if subtitle sink being used for CC control */
char videoRectangle[VIDEO_COORDINATES_SIZE];
int videoRectangleWidth; /**< Cached width parsed from videoRectangle; 0 when unset/invalid */
int videoRectangleHeight; /**< Cached height parsed from videoRectangle; 0 when unset/invalid */
bool pauseOnStartPlayback; /**< true if should start playback paused */
std::atomic<bool> eosSignalled; /**< Indicates if EOS has signaled */
gboolean buffering_enabled; /**< enable buffering based on multiqueue */
Expand Down
50 changes: 20 additions & 30 deletions InterfacePlayerRDK.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ static void TransformToEncryptedCaps(GstCaps *caps, const char *drmSystem)
/*InterfacePlayerRDK constructor*/
InterfacePlayerRDK::InterfacePlayerRDK(bool isRialto) :
mProtectionLock(), mPauseInjector(false), mSourceSetupMutex(), stopCallback(NULL), tearDownCb(NULL), notifyFirstFrameCallback(NULL),
mSourceSetupCV(), mScheduler(), callbackMap(), setupStreamCallbackMap(), mDrmSystem(NULL), mEncrypt(NULL), mDRMSessionManager(NULL),
mSourceSetupCV(), mScheduler(), callbackMap(), setupStreamCallbackMap(), mDrmSystem(), mEncrypt(NULL), mDRMSessionManager(NULL),
trickTeardown(false), mFirstFrameRequired(false), mResumeInjector(false), PipelineSetToReady(false), mSchedulerStarted(false)
{
interfacePlayerPriv = new InterfacePlayerPriv(isRialto);
Expand Down Expand Up @@ -231,10 +231,6 @@ trickTeardown(false), mFirstFrameRequired(false), mResumeInjector(false), Pipeli
InterfacePlayerRDK::~InterfacePlayerRDK()
{
DestroyPipeline();
if (mDrmSystem)
{
delete[] mDrmSystem;
}
/* safe delete configuration parameter */
MW_SAFE_DELETE(m_gstConfigParam);
mScheduler.StopScheduler();
Expand Down Expand Up @@ -294,6 +290,8 @@ aSyncControl(), syncControl(), callbackControl(), seekPosition(0)
* using the westerossink connected using westeros compositor.
*/
strcpy(videoRectangle, "");
videoRectangleWidth = 0;
videoRectangleHeight = 0;
for (int i = 0; i < GST_TRACK_COUNT; i++)
{
protectionEvent[i] = NULL;
Expand Down Expand Up @@ -1072,19 +1070,7 @@ void InterfacePlayerRDK::SetPreferredDRM(const char *drmID)
{
if (drmID != NULL)
{
if (mDrmSystem != NULL)
{
delete[] mDrmSystem;
}
mDrmSystem = new char[strlen(drmID) + 1];
if (mDrmSystem != NULL)
{
strcpy(mDrmSystem, drmID);
}
else
{
MW_LOG_ERR("Memory allocation failed for mDrmSystem\n");
}
mDrmSystem = drmID;
}
}

Expand Down Expand Up @@ -2208,7 +2194,7 @@ void InterfacePlayerRDK::InitializeSourceForPlayer(void *PlayerInstance, void *
if (stream->codecInfo.mIsEncrypted && IsElementaryStreamFormat(static_cast<GstStreamOutputFormat>(stream->format)))
{
MW_LOG_DEBUG("Applying encrypted caps during source configuration for type[%d] format[%d]", mediaType, stream->format);
TransformToEncryptedCaps(caps, mDrmSystem);
TransformToEncryptedCaps(caps, mDrmSystem.empty() ? NULL : mDrmSystem.c_str());
}
gchar *capsStr = gst_caps_to_string(caps);
MW_LOG_MIL("Setting caps for source[type:%d]: %s", mediaType, capsStr);
Expand Down Expand Up @@ -2607,7 +2593,10 @@ int InterfacePlayerRDK::SetupStream(int streamId, void *playerInstance, std::st
auto subtitlebin = gst_bin_new("subtitlebin");
auto vipertransform = gst_element_factory_make("vipertransform", NULL);
gst_bin_add_many(GST_BIN(subtitlebin),vipertransform,textsink,NULL);
gst_element_link(vipertransform, textsink);
if (!gst_element_link(vipertransform, textsink))
{
MW_LOG_ERR("Failed to link vipertransform to rialtomsesubtitlesink; subtitles will not render");
}
gst_element_add_pad(subtitlebin, gst_ghost_pad_new("sink", gst_element_get_static_pad(vipertransform, "sink")));

g_object_set(stream->sinkbin, "text-sink", subtitlebin, NULL);
Expand Down Expand Up @@ -3160,14 +3149,13 @@ long InterfacePlayerRDK::GetDurationMilliseconds(void)
*/
void InterfacePlayerRDK::GetVideoSize(int &width, int &height)
{
int x;
int y;
int w = 0;
int h = 0;
if ((4 == sscanf(interfacePlayerPriv->gstPrivateContext->videoRectangle, "%d,%d,%d,%d", &x, &y, &w, &h)) && (w > 0) && (h > 0))
// Use the dimensions cached by SetVideoRectangle() instead of re-parsing
// the "x,y,w,h" string on every call.
if (interfacePlayerPriv->gstPrivateContext->videoRectangleWidth > 0 &&
interfacePlayerPriv->gstPrivateContext->videoRectangleHeight > 0)
{
width = w;
height = h;
width = interfacePlayerPriv->gstPrivateContext->videoRectangleWidth;
height = interfacePlayerPriv->gstPrivateContext->videoRectangleHeight;
}
}

Expand Down Expand Up @@ -3206,6 +3194,8 @@ void InterfacePlayerRDK::SetVideoRectangle(int x, int y, int w, int h)
return;
}
snprintf(interfacePlayerPriv->gstPrivateContext->videoRectangle, sizeof(interfacePlayerPriv->gstPrivateContext->videoRectangle), "%d,%d,%d,%d", x,y,w,h);
interfacePlayerPriv->gstPrivateContext->videoRectangleWidth = w;
interfacePlayerPriv->gstPrivateContext->videoRectangleHeight = h;
MW_LOG_MIL("Rect %s, video_sink =%p",
interfacePlayerPriv->gstPrivateContext->videoRectangle, interfacePlayerPriv->gstPrivateContext->video_sink);
if (m_gstConfigParam->enableRectPropertyCfg)
Expand Down Expand Up @@ -5702,10 +5692,10 @@ static GstBusSyncReply bus_sync_handler(GstBus * bus, GstMessage * msg, Interfac
gst_message_parse_context_type(msg, &contextType);
if (!g_strcmp0(contextType, "drm-preferred-decryption-system-id"))
{
MW_LOG_MIL("Setting %s as preferred drm",pInterfacePlayerRDK->mDrmSystem);
MW_LOG_MIL("Setting %s as preferred drm", pInterfacePlayerRDK->mDrmSystem.c_str());
GstContext* context = gst_context_new("drm-preferred-decryption-system-id", FALSE);
GstStructure* contextStructure = gst_context_writable_structure(context);
gst_structure_set(contextStructure, "decryption-system-id", G_TYPE_STRING, pInterfacePlayerRDK->mDrmSystem, NULL);
gst_structure_set(contextStructure, "decryption-system-id", G_TYPE_STRING, pInterfacePlayerRDK->mDrmSystem.empty() ? NULL : pInterfacePlayerRDK->mDrmSystem.c_str(), NULL);
gst_element_set_context(GST_ELEMENT(GST_MESSAGE_SRC(msg)), context);
}

Expand Down Expand Up @@ -6192,7 +6182,7 @@ void InterfacePlayerRDK::SetStreamCaps(GstMediaType type, MediaCodecInfo&& codec
}
if (codecInfo.mIsEncrypted)
{
TransformToEncryptedCaps(caps, mDrmSystem);
TransformToEncryptedCaps(caps, mDrmSystem.empty() ? NULL : mDrmSystem.c_str());
}
gchar* capsStr = gst_caps_to_string(caps);
MW_LOG_MIL("Setting stream caps for type[%d] format[%d]: %s", type, codecInfo.mCodecFormat, capsStr);
Expand Down
3 changes: 2 additions & 1 deletion InterfacePlayerRDK.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include <map>
#include <cstdint>
#include <string>
#include <string.h>
#include <vector>
#include <mutex>
Expand Down Expand Up @@ -166,7 +167,7 @@ class InterfacePlayerRDK

public:
Configs *m_gstConfigParam;
char *mDrmSystem;
std::string mDrmSystem;
void *mEncrypt;
void *mDRMSessionManager;
std::map<InterfaceCB, std::function<void()>> callbackMap;
Expand Down
16 changes: 6 additions & 10 deletions drm/DrmSessionManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ KeyIdEntries::KeyIdEntries() : creationTime(0), isFailedKeyEntries(false), isPri
/**
* @brief DrmSessionManager constructor.
*/
DrmSessionManager::DrmSessionManager(int maxDrmSessions, void *player, std::function<void(uint32_t, uint32_t, const std::string&)> watermarkSessionUpdateCallback, DrmSessionCreator creator) : drmSessionContexts(NULL),
cachedKeyIDs(NULL), accessToken(NULL),
DrmSessionManager::DrmSessionManager(int maxDrmSessions, void *player, std::function<void(uint32_t, uint32_t, const std::string&)> watermarkSessionUpdateCallback, DrmSessionCreator creator) : drmSessionContexts(nullptr),
cachedKeyIDs(nullptr), accessToken(NULL),
accessTokenLen(0), sessionMgrState(SessionMgrState::eSESSIONMGR_ACTIVE), accessTokenMutex(),
cachedKeyMutex()
,mEnableAccessAttributes(true)
Expand All @@ -89,8 +89,8 @@ DrmSessionManager::DrmSessionManager(int maxDrmSessions, void *player, std::func
,mFirstFrameSeen(false)
,mPlayerSendWatermarkSessionUpdateEventCB(std::move(watermarkSessionUpdateCallback))
{
drmSessionContexts = new DrmSessionContext[mMaxDRMSessions];
cachedKeyIDs = new KeyIdEntries[mMaxDRMSessions];
drmSessionContexts = std::make_unique<DrmSessionContext[]>(mMaxDRMSessions);
cachedKeyIDs = std::make_unique<KeyIdEntries[]>(mMaxDRMSessions);
m_drmConfigParam = new configs();
playerSecInstance = new PlayerSecInterface();

Expand All @@ -106,8 +106,6 @@ DrmSessionManager::~DrmSessionManager()
{
clearAccessToken();
clearSessionData();
MW_SAFE_DELETE_ARRAY(drmSessionContexts);
MW_SAFE_DELETE_ARRAY(cachedKeyIDs);
MW_SAFE_DELETE(playerSecInstance);
MW_SAFE_DELETE(m_drmConfigParam);
ContentSecurityManager::setWatermarkSessionEvent_CB(nullptr);
Expand Down Expand Up @@ -1086,13 +1084,11 @@ void DrmSessionManager::UpdateMaxDRMSessions(int maxSessions)
{
// Clean up the current sessions
clearSessionData();
MW_SAFE_DELETE_ARRAY(drmSessionContexts);
MW_SAFE_DELETE_ARRAY(cachedKeyIDs);

//Update to new session count
mMaxDRMSessions = maxSessions;
drmSessionContexts = new DrmSessionContext[mMaxDRMSessions];
cachedKeyIDs = new KeyIdEntries[mMaxDRMSessions];
drmSessionContexts = std::make_unique<DrmSessionContext[]>(mMaxDRMSessions);
cachedKeyIDs = std::make_unique<KeyIdEntries[]>(mMaxDRMSessions);
MW_LOG_INFO("Updated DrmSessionManager MaxSession to:%d", mMaxDRMSessions);
}
}
Expand Down
4 changes: 2 additions & 2 deletions drm/DrmSessionManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,15 +168,15 @@ class DrmSessionManager
{
public:

DrmSessionContext *drmSessionContexts;
std::unique_ptr<DrmSessionContext[]> drmSessionContexts;
configs *m_drmConfigParam;
PlayerSecInterface *playerSecInstance;/** PlayerSecInterface instance **/
ContentSecurityManagerSession mContentSecurityManagerSession;
std::atomic<bool> mFirstFrameSeen;
std::atomic<bool> mIsVideoOnMute;
std::atomic<int> mCurrentSpeed;
protected:
KeyIdEntries *cachedKeyIDs;
std::unique_ptr<KeyIdEntries[]> cachedKeyIDs;
std::mutex cachedKeyMutex;
private:
char* accessToken;
Expand Down
6 changes: 1 addition & 5 deletions drm/helper/VerimatrixHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,8 @@ bool VerimatrixHelper::parsePssh(const uint8_t* initData, uint32_t initDataLen)

initData += VERIMATRIX_PSSH_DATA_POSITION;
initDataLen -= VERIMATRIX_PSSH_DATA_POSITION;
char *init = new char[initDataLen + 1];
memcpy(init, initData, initDataLen);
init[initDataLen] = 0;

std::string pssh(init);
delete []init;
std::string pssh(reinterpret_cast<const char*>(initData), initDataLen);

MW_LOG_WARN("pssh %s", pssh.c_str());

Expand Down
16 changes: 12 additions & 4 deletions drm/ocdm/opencdmsessionadapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@

#include <sys/time.h>
#include <set>
#include <thread>
#include <chrono>
#define LICENSE_RENEWAL_MESSAGE_TYPE "1"

/**
Expand Down Expand Up @@ -351,10 +353,16 @@ int OCDMSessionAdapter::processDRMKey(DrmData* key, uint32_t timeout)
}
}

// wait for 5sec for all the logs to be flushed
sleep(5);
// Now kill self
processHandler.SelfKill();
// Defer the self-kill by 5sec on a worker thread so the killed
// OCDM process can restart and logs can flush, without blocking
// this decrypt/key path which would otherwise stall playback.
std::thread([]()
Comment thread
Copilot marked this conversation as resolved.
Resolved
{
std::this_thread::sleep_for(std::chrono::seconds(5));
// Now kill self
ProcessHandler handler;
handler.SelfKill();
}).detach();
}
else {
#ifdef USE_THUNDER_OCDM_API_0_2
Expand Down
16 changes: 6 additions & 10 deletions drm/processProtectionHls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,19 +224,15 @@ shared_ptr<DrmHelper> ProcessContentProtection( std::string attrName, bool propa
}
if (PlayerLogManager::isLogLevelAllowed(mLOGLEVEL_TRACE))
{
MW_LOG_TRACE("content metadata from manifest; length %zu", dataLength);
printf("*****************************************************************\n");
string dump;
dump.reserve(dataLength * 3 + 1);
for (int i = 0; i < dataLength; i++)
{
printf("%c", data[i]);
char hexByte[4];
snprintf(hexByte, sizeof(hexByte), "%02x ", data[i]);
dump += hexByte;
}
printf("\n*****************************************************************\n");
for (int i = 0; i < dataLength; i++)
{
printf("%02x ", data[i]);
}
printf("\n*****************************************************************\n");

MW_LOG_TRACE("content metadata from manifest; length %zu data %s", dataLength, dump.c_str());
}
if (!drmHelper->parsePssh(data, (uint32_t)dataLength))
{
Expand Down
22 changes: 11 additions & 11 deletions externals/PlayerThunderAccessBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ struct PlayerAudioData{
int pk;
std::string mixType;

PlayerAudioData(std::string lang, std::string content_Type, std::string nm, std::string t, int pk_int, std::string mix_Type)
PlayerAudioData(const std::string& lang, const std::string& content_Type, const std::string& nm, const std::string& t, int pk_int, const std::string& mix_Type)
: language(std::move(lang)),
contentType(std::move(content_Type)),
name(std::move(nm)),
Expand Down Expand Up @@ -146,7 +146,7 @@ struct PlayerTextData{
std::string name;
int pk;

PlayerTextData(std::string t, std::string lang, int ccSer, std::string cc_Type, std::string nm, int pk_int)
PlayerTextData(const std::string& t, const std::string& lang, int ccSer, const std::string& cc_Type, const std::string& nm, int pk_int)
:type(std::move(t)),
language(std::move(lang)),
ccServiceNumber(ccSer),
Expand Down Expand Up @@ -204,7 +204,7 @@ class PlayerThunderAccessBase
* @retval true on success
* @retval false on failure
*/
virtual bool UnSubscribeEvent (std::string eventName) = 0;
virtual bool UnSubscribeEvent (const std::string& eventName) = 0;

/**
* @fn SetVideoRectangle
Expand All @@ -218,7 +218,7 @@ class PlayerThunderAccessBase
* @retval true if success
* @retval false if failure
*/
virtual bool SetVideoRectangle(int x, int y, int w, int h, std::string videoInputType, PlayerThunderAccessShim shim) = 0;
virtual bool SetVideoRectangle(int x, int y, int w, int h, const std::string& videoInputType, PlayerThunderAccessShim shim) = 0;

/**
* @fn SetPreferredAudioLanguages_OTA
Expand All @@ -244,12 +244,12 @@ class PlayerThunderAccessBase
* @param port port number
* @param videoInputType string video input type
*/
virtual void StartHelperVideoin(int port, std::string videoInputType) = 0;
virtual void StartHelperVideoin(int port, const std::string& videoInputType) = 0;
/**
* @fn StopHelper
* @param videoInputType string video input type
*/
virtual void StopHelperVideoin(std::string videoInputType) = 0;
virtual void StopHelperVideoin(const std::string& videoInputType) = 0;

/**
* @fn RegisterEventOnVideoStreamInfoUpdateHdmiin
Expand All @@ -276,7 +276,7 @@ class PlayerThunderAccessBase
* @param preferredRenditionString player's preferred rendition
* @param atsc_preferredRenditionString ATSC preferred rendition
*/
virtual void StartOta(std::string url, std::string waylandDisplay, std::string preferredLanguagesString, std::string atsc_preferredLanguagesString, std::string preferredRenditionString, std::string atsc_preferredRenditionString) = 0;
virtual void StartOta(const std::string& url, const std::string& waylandDisplay, const std::string& preferredLanguagesString, const std::string& atsc_preferredLanguagesString, const std::string& preferredRenditionString, const std::string& atsc_preferredRenditionString) = 0;

/**
* @fn StopOta
Expand All @@ -288,7 +288,7 @@ class PlayerThunderAccessBase
* @param audData vector to be filled with audio data
* @return string of current track pk
*/
virtual std::string GetAudioTracksOta(std::vector<PlayerAudioData> audData) = 0;
virtual std::string GetAudioTracksOta(std::vector<PlayerAudioData>& audData) = 0;

/**
* @fn SetAudioTrackOta
Expand All @@ -303,7 +303,7 @@ class PlayerThunderAccessBase
* @param txtData vector to be filled with text data
* @return true if successful, false if failed
*/
virtual bool GetTextTracksOta(std::vector<PlayerTextData> txtData) = 0;
virtual bool GetTextTracksOta(std::vector<PlayerTextData>& txtData) = 0;

/**
* @fn DisableContentRestrictionsOta
Expand Down Expand Up @@ -333,7 +333,7 @@ class PlayerThunderAccessBase
* @param onPlayerErrorHandlerCb player error handler callback
* @return true if successful, false if failed
*/
virtual bool StartRmf(std::string url, std::function<void(std::string)> onPlayerStatusHandlerCb, std::function<void(std::string)> onPlayerErrorHandlerCb) = 0;
virtual bool StartRmf(const std::string& url, std::function<void(std::string)> onPlayerStatusHandlerCb, std::function<void(std::string)> onPlayerErrorHandlerCb) = 0;

/**
* @fn StopRmf
Expand Down Expand Up @@ -389,7 +389,7 @@ class PlayerThunderAccessBase
* @param metaData metaData
* @return true if successful, false if failed
*/
virtual bool PersistentStoreSaveWatermark(const char* base64Image, std::string metaData) = 0;
virtual bool PersistentStoreSaveWatermark(const char* base64Image, const std::string& metaData) = 0;

/**
* @fn PersistentStoreLoadWatermark
Expand Down
Loading
Loading