Skip to content

Comments

Rialto Server profiling#441

Open
smudri85 wants to merge 8 commits intomasterfrom
feature/RDKEMW-11764
Open

Rialto Server profiling#441
smudri85 wants to merge 8 commits intomasterfrom
feature/RDKEMW-11764

Conversation

@smudri85
Copy link

@smudri85 smudri85 commented Feb 6, 2026

Summary: Add profiling to Rialto Server.
Type: Feature
Test Plan: UT/CT, Fullstack
Jira: RDKEMW-11764

Copilot AI review requested due to automatic review settings February 6, 2026 14:37
@github-actions
Copy link

github-actions bot commented Feb 6, 2026

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.

@github-actions
Copy link

github-actions bot commented Feb 6, 2026

common/source/Profiler.cpp:98:0: style: Consider using std::find_if algorithm instead of a raw loop. [useStlAlgorithm]
if (record.stage == stage)
^
common/source/Profiler.cpp:111:0: style: Consider using std::find_if algorithm instead of a raw loop. [useStlAlgorithm]
if (record.stage == stage && record.info == info)
^
common/source/Profiler.cpp:184:0: style: Consider using std::find_if algorithm instead of a raw loop. [useStlAlgorithm]
if (record.id == id)
^
nofile:0:0: information: Active checkers: 161/592 (use --checkers-report= to see details) [checkersReport]

@rdkcmf-jenkins
Copy link
Contributor

b'## Blackduck scan failure details

Summary: 0 violations, 0 files pending approval, 1 file pending identification.

  • Protex Server Path: /home/blackduck/github/rialto/441/rdkcentral/rialto

  • Commit: 282cf54

Report detail: gist'

Copy link

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 pull request adds profiling functionality to the Rialto Server to track performance metrics and pipeline events. The implementation includes a generic profiling interface in the common module and a GStreamer-specific profiler that integrates with the media player pipeline. The profiler records timestamped events at various stages of media playback and can be enabled via environment variable.

Changes:

  • Added core profiling infrastructure with IProfiler interface and Profiler implementation
  • Integrated GstProfiler into the media player pipeline to track key events
  • Added unit tests and mocks for the profiling functionality

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 25 comments.

Show a summary per file
File Description
common/interface/IProfiler.h Defines the profiler interface with methods for recording, finding, logging, and dumping profiling records
common/include/Profiler.h Declares the concrete Profiler class implementation with internal Record structure
common/source/Profiler.cpp Implements the profiler with thread-safe record storage, environment-based enabling, and file dumping
common/CMakeLists.txt Adds Profiler.cpp to the build configuration
media/server/gstplayer/include/GstProfiler.h Defines GStreamer-specific profiler wrapper for pipeline profiling
media/server/gstplayer/include/GenericPlayerContext.h Adds GstProfiler instance to player context
media/server/gstplayer/source/GstProfiler.cpp Implements GStreamer profiler with pad probe callbacks and element filtering
media/server/gstplayer/source/GstGenericPlayer.cpp Integrates profiler into pipeline lifecycle (creation, termination, segment handling)
media/server/gstplayer/source/tasks/generic/HandleBusMessage.cpp Records pipeline state changes
media/server/gstplayer/source/tasks/generic/FinishSetupSource.cpp Records when all sources are attached
media/server/gstplayer/source/tasks/generic/AttachSource.cpp Records AppSrc element creation
media/server/gstplayer/source/tasks/generic/DeepElementAdded.cpp Schedules profiling for dynamically added GStreamer elements
media/server/gstplayer/CMakeLists.txt Adds GstProfiler.cpp to build and includes common headers
tests/unittests/common/unittests/ProfilerTests.cpp Unit tests for core profiler functionality
tests/unittests/common/unittests/CMakeLists.txt Adds ProfilerTests.cpp to test build
tests/unittests/common/mocks/ProfilerMock.h Mock implementation of IProfiler for testing
tests/unittests/common/mocks/ProfilerFactoryMock.h Mock implementation of IProfilerFactory for testing

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

if (appSrc)
{
auto recordId = m_context.gstProfiler->createRecord("Created AppSrc Element", m_gstWrapper->gstElementGetName(appSrc));
if(recordId)
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

Inconsistent spacing with codebase conventions. The codebase predominantly uses 'if (' with a space after 'if'. This pattern appears throughout the codebase (e.g., media/server/gstplayer/source/GstGenericPlayer.cpp). The spacing should be consistent.

Suggested change
if(recordId)
if (recordId)

Copilot uses AI. Check for mistakes.
*
* @param[in] stage : Stage name of the record to be found
*
* @retval Record identificator for found record or std::nullopt.
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

Spelling error in documentation. 'identificator' should be 'identifier'. This typo appears in the documentation for the return value.

Copilot uses AI. Check for mistakes.
/**
* @brief Logs a record for given identificator.
*
* @param[in] id : Record identificator
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

Spelling error in documentation. 'identificator' should be 'identifier'. This typo appears in the documentation for the parameter.

Copilot uses AI. Check for mistakes.
if (!pad)
return;

auto* probeCtx = new ProbeCtx{this, stage.value_or(""), std::string(m_gstWrapper->gstElementGetName(element))};
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

Redundant use of value_or(""). Line 74 uses stage.value_or("") but this is unnecessary because stage has already been checked for has_value() on line 67, and the function returns early if stage is nullopt. At this point, stage is guaranteed to have a value, so stage.value() should be used instead.

Suggested change
auto* probeCtx = new ProbeCtx{this, stage.value_or(""), std::string(m_gstWrapper->gstElementGetName(element))};
auto* probeCtx = new ProbeCtx{this, stage.value(), std::string(m_gstWrapper->gstElementGetName(element))};

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,67 @@
#include "IProfiler.h"
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

Missing copyright header. Other test files in the codebase consistently include a copyright and license header at the top of the file. This header should be added to maintain consistency with the rest of the codebase.

Copilot uses AI. Check for mistakes.
std::lock_guard<std::mutex> lock(m_mutex);

const auto* record = findById(id);
if(record)
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

Inconsistent spacing with codebase conventions. The codebase predominantly uses 'if (' with a space after 'if'. This pattern appears throughout the codebase (e.g., media/server/gstplayer/source/GstGenericPlayer.cpp). The spacing should be consistent.

Suggested change
if(record)
if (record)

Copilot uses AI. Check for mistakes.

RIALTO_SERVER_LOG_MIL("RialtoServer's pipeline terminated");
auto recordId = m_context.gstProfiler->createRecord("Pipeline Terminated");
if(recordId)
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

Inconsistent spacing with codebase conventions. The codebase predominantly uses 'if (' with a space after 'if'. This pattern appears throughout the codebase (e.g., media/server/gstplayer/source/GstGenericPlayer.cpp). The spacing should be consistent.

Suggested change
if(recordId)
if (recordId)

Copilot uses AI. Check for mistakes.
Comment on lines 45 to 49
std::optional<GstProfiler::RecordId> GstProfiler::createRecord(std::string stage)
{
if (!m_enabled) return std::nullopt;

return m_profiler->record(stage);
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

Potential null pointer dereference. If m_profiler is null (which can happen if profilerFactory is null or createProfiler returns null), calling m_profiler->record() will cause a crash. The methods createRecord and logRecord check m_enabled but not m_profiler itself. Since m_enabled is only set to true if m_profiler is successfully created, the current implementation appears safe, but this creates a tight coupling that is not immediately obvious. Consider adding an explicit null check on m_profiler or documenting this invariant.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,16 @@
#include "IProfiler.h"
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

Missing copyright header. Other header files in the codebase consistently include a copyright and license header at the top of the file. This header should be added to maintain consistency with the rest of the codebase.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,60 @@
#ifndef FIREBOLT_RIALTO_SERVER_GST_PROFILER_H_
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

Missing copyright header. Other header files in the codebase consistently include a copyright and license header at the top of the file. This header should be added to maintain consistency with the rest of the codebase.

Copilot uses AI. Check for mistakes.
@rdkcmf-jenkins
Copy link
Contributor

rdkcmf-jenkins commented Feb 6, 2026

Coverity Issue - Uncaught exception

An exception of type "std::bad_optional_access" is thrown but the exception specification "/implicit/noexcept" doesn't allow it to be thrown. This will result in a call to terminate().

Medium Impact, CWE-248
UNCAUGHT_EXCEPT

Issue location

This issue was discovered outside the diff for this Pull Request. You can find it at:
media/server/gstplayer/source/GstGenericPlayer.cpp:210

: m_pipeline{pipeline},
m_gstWrapper{gstWrapper},
m_glibWrapper{glibWrapper},
m_profilerFactory{profilerFactory}
Copy link
Contributor

@rdkcmf-jenkins rdkcmf-jenkins Feb 6, 2026

Choose a reason for hiding this comment

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

Coverity issue no longer present as of: undefined

Show issue

Coverity Issue - Variable copied when it could be moved

"profilerFactory" is passed-by-value as parameter to "std::shared_ptrfirebolt::rialto::common::IProfilerFactory::shared_ptr(std::shared_ptrfirebolt::rialto::common::IProfilerFactory const &) /explicit =default/", when it could be moved instead.

Low Impact, CWE-none
COPY_INSTEAD_OF_MOVE

How to fix

Use "std::move(""profilerFactory"")" instead of "profilerFactory".

{
if (!m_enabled) return std::nullopt;

return m_profiler->record(stage);
Copy link
Contributor

@rdkcmf-jenkins rdkcmf-jenkins Feb 6, 2026

Choose a reason for hiding this comment

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

Coverity issue no longer present as of: undefined

Show issue

Coverity Issue - Variable copied when it could be moved

"stage" is passed-by-value as parameter to "std::__cxx11::basic_string<char, std::char_traits, std::allocator >::basic_string(std::__cxx11::basic_string<char, std::char_traits, std::allocator > const &)", when it could be moved instead.

Low Impact, CWE-none
COPY_INSTEAD_OF_MOVE

How to fix

Use "std::move(""stage"")" instead of "stage".

{
if (!m_enabled) return std::nullopt;

return m_profiler->record(stage, info);
Copy link
Contributor

@rdkcmf-jenkins rdkcmf-jenkins Feb 6, 2026

Choose a reason for hiding this comment

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

Coverity issue no longer present as of: undefined

Show issue

Coverity Issue - Variable copied when it could be moved

"stage" is passed-by-value as parameter to "std::__cxx11::basic_string<char, std::char_traits, std::allocator >::basic_string(std::__cxx11::basic_string<char, std::char_traits, std::allocator > const &)", when it could be moved instead.

Low Impact, CWE-none
COPY_INSTEAD_OF_MOVE

How to fix

Use "std::move(""stage"")" instead of "stage".

{
if (!m_enabled) return std::nullopt;

return m_profiler->record(stage, info);
Copy link
Contributor

@rdkcmf-jenkins rdkcmf-jenkins Feb 6, 2026

Choose a reason for hiding this comment

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

Coverity issue no longer present as of: undefined

Show issue

Coverity Issue - Variable copied when it could be moved

"info" is passed-by-value as parameter to "std::__cxx11::basic_string<char, std::char_traits, std::allocator >::basic_string(std::__cxx11::basic_string<char, std::char_traits, std::allocator > const &)", when it could be moved instead.

Low Impact, CWE-none
COPY_INSTEAD_OF_MOVE

How to fix

Use "std::move(""info"")" instead of "info".

@mhughesacn
Copy link

Hi @smudri85 : The blackduck issue is not a problem but all new code files should have proper headers please.

  • MartinH, RDK CMF Compliance Team

@rdkcmf-jenkins
Copy link
Contributor

b'## WARNING: A Blackduck scan failure has been waived

A prior failure has been upvoted

  • Upvote reason: ok

  • Commit: 282cf54
    '

Copilot AI review requested due to automatic review settings February 11, 2026 12:19
@smudri85 smudri85 force-pushed the feature/RDKEMW-11764 branch from 95cc046 to 43eb771 Compare February 11, 2026 12:19
Copy link

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 19 out of 19 changed files in this pull request and generated 10 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

if (!pad)
return;

auto *probeCtx = new ProbeCtx{this, stage.value(), std::string(m_gstWrapper->gstElementGetName(element))};
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

gstElementGetName() returns an allocated string that must be freed (and it can be NULL). Constructing std::string(...) directly from the return value can both leak and crash if NULL is returned. Store the returned gchar*, check for null, copy into std::string, then free it with m_glibWrapper->gFree(...).

Suggested change
auto *probeCtx = new ProbeCtx{this, stage.value(), std::string(m_gstWrapper->gstElementGetName(element))};
gchar *elementNameCStr = m_gstWrapper->gstElementGetName(element);
std::string elementName;
if (elementNameCStr)
{
elementName = elementNameCStr;
m_glibWrapper->gFree(elementNameCStr);
}
auto *probeCtx = new ProbeCtx{this, stage.value(), std::move(elementName)};

Copilot uses AI. Check for mistakes.
Comment on lines +96 to +97
gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, &GstProfiler::probeCb, probeCtx, &GstProfiler::probeCtxDestroy);

Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

gst_pad_add_probe returns a probe id, but it’s currently ignored. Without tracking/removing the probe in ~GstProfiler(), ProbeCtx can outlive GstProfiler and probeCb would then dereference a dangling self pointer (use-after-free risk). Store the probe id(s) and remove them during teardown (e.g., via gst_pad_remove_probe).

Copilot uses AI. Check for mistakes.
Comment on lines +145 to +149
for (auto token : kKlassTokens)
{
if (g_strrstr(klass, token.data()) != nullptr)
{
return std::string(token.data()) + " FB Exit";
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

This code calls g_strrstr directly even though the codebase consistently goes through IGlibWrapper for GLib APIs (e.g. DeepElementAdded.cpp uses m_glibWrapper->gStrrstr(...)). Using the wrapper keeps the gstplayer code unit-testable and consistent; prefer m_glibWrapper->gStrrstr(klass, token.data()) here.

Copilot uses AI. Check for mistakes.
#include "RialtoCommonLogging.h"

#include <algorithm>
#include <fstream>
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

Profiler.cpp uses std::getenv and std::tolower but doesn’t include the standard headers that declare them (<cstdlib> and <cctype>). This can fail to compile depending on toolchain/headers; add the missing includes explicitly.

Suggested change
#include <fstream>
#include <fstream>
#include <cstdlib>
#include <cctype>

Copilot uses AI. Check for mistakes.
Comment on lines 107 to 112
const char *name = m_gstWrapper->gstElementGetName(appSrc);
std::string info = name ? name : "<null>";

auto recordId = m_context.gstProfiler->createRecord("Created AppSrc Element", std::move(info));
if (recordId)
m_context.gstProfiler->logRecord(recordId.value());
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

gstElementGetName() returns a newly allocated gchar* that must be freed with g_free (per IGstWrapper contract). Here it’s treated as const char* and never freed, which will leak; also the type should match the wrapper signature. Capture the returned pointer, copy into std::string, then free it via m_glibWrapper->gFree(...).

Suggested change
const char *name = m_gstWrapper->gstElementGetName(appSrc);
std::string info = name ? name : "<null>";
auto recordId = m_context.gstProfiler->createRecord("Created AppSrc Element", std::move(info));
if (recordId)
m_context.gstProfiler->logRecord(recordId.value());
gchar *name = m_gstWrapper->gstElementGetName(appSrc);
std::string info = name ? name : "<null>";
auto recordId = m_context.gstProfiler->createRecord("Created AppSrc Element", std::move(info));
if (recordId)
m_context.gstProfiler->logRecord(recordId.value());
if (name)
{
m_glibWrapper->gFree(name);
}

Copilot uses AI. Check for mistakes.
#include "RialtoCommonLogging.h"

#include <mutex>
#include <string>
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

This file uses std::array and std::string_view (see kKlassTokens) but doesn’t include <array> / <string_view>. Relying on transitive includes is fragile and can break builds; add the missing standard headers (and consider dropping unused <mutex>).

Suggested change
#include <string>
#include <string>
#include <array>
#include <string_view>

Copilot uses AI. Check for mistakes.
Comment on lines 276 to 279
/**
* @brief Profiler for player pipeline
*/
std::unique_ptr<GstProfiler> gstProfiler;
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

GenericPlayerContext stores a std::unique_ptr<GstProfiler> (concrete type) and includes GstProfiler.h, but this PR also introduces IGstProfiler + a GstProfilerMock. With the current field type, you can’t inject the mock in unit tests and you force all includers of GenericPlayerContext.h to pull in the full GstProfiler definition. Prefer storing std::unique_ptr<IGstProfiler> (forward-declare IGstProfiler and include IGstProfiler.h instead).

Copilot uses AI. Check for mistakes.
$<TARGET_PROPERTY:RialtoWrappers,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:RialtoCommon,INTERFACE_INCLUDE_DIRECTORIES>
${GStreamerApp_INCLUDE_DIRS}
${CMAKE_CURRENT_LIST_DIR}/../../../common/include
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

Adding ${CMAKE_CURRENT_LIST_DIR}/../../../common/include exposes RialtoCommon’s private headers to gstplayer and risks accidental coupling / ODR issues. GstProfiler includes IProfiler.h (from RialtoCommon’s public interface), and gstplayer already consumes RialtoCommon’s interface include dirs, so this extra include path looks unnecessary and should be removed unless there’s a concrete include that requires it.

Suggested change
${CMAKE_CURRENT_LIST_DIR}/../../../common/include

Copilot uses AI. Check for mistakes.
Comment on lines +31 to +38
void SetUp() override
{
factory = IProfilerFactory::createFactory();
ASSERT_TRUE(factory);

profiler = factory->createProfiler("UnitTestModule");
ASSERT_TRUE(profiler);
}
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

These tests will typically be skipped because Profiler defaults to disabled unless PROFILER_ENABLED is set. To make the unit tests meaningful and deterministic, set PROFILER_ENABLED=1 in SetUp() (and restore/unset it in TearDown() to avoid leaking env changes across tests).

Copilot uses AI. Check for mistakes.
Comment on lines 77 to 81
const std::string path = "/tmp/rialto_profiler_ut_dump.txt";
ASSERT_TRUE(profiler->dump(path));

std::ifstream in(path);
ASSERT_TRUE(in.good());
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

DumpCreatesFile writes a fixed path in /tmp but doesn’t clean it up afterward. Consider removing the file in the test (and/or using a unique temp filename) to avoid leaving artifacts and reduce the chance of collisions when tests run in parallel.

Copilot uses AI. Check for mistakes.
@smudri85 smudri85 force-pushed the feature/RDKEMW-11764 branch from 43eb771 to e476ba7 Compare February 11, 2026 13:45
Copilot AI review requested due to automatic review settings February 11, 2026 14:06
@smudri85 smudri85 force-pushed the feature/RDKEMW-11764 branch from e476ba7 to 5862d6c Compare February 11, 2026 14:06
Sasa Mudri added 7 commits February 11, 2026 15:11
Summary: Add profiling to Rialto Server.
Type: Feature
Test Plan: UT/CT, Fullstack
Jira: RDKEMW-11764
Summary: Add profiling to Rialto Server.
Type: Feature
Test Plan: UT/CT, Fullstack
Jira: RDKEMW-117641
Summary: Add profiling to Rialto Server.
Type: Feature
Test Plan: UT/CT, Fullstack
Jira: RDKEMW-11764
Summary: Add profiling to Rialto Server.
Type: Feature
Test Plan: UT/CT, Fullstack
Jira: RDKEMW-11764
Summary: Add profiling to Rialto Server.
Type: Feature
Test Plan: UT/CT, Fullstack
Jira: RDKEMW-11764
Summary: Add profiling to Rialto Server.
Type: Feature
Test Plan: UT/CT, Fullstack
Jira: RDKEMW-11764
Summary: Add profiling to Rialto Server.
Type: Feature
Test Plan: UT/CT, Fullstack
Jira: RDKEMW-11764
Copy link

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 19 out of 19 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +78 to +82
const auto suffix = std::to_string(std::random_device{}());
const std::string path = std::string{"/tmp/rialto_profiler_ut_dump_"} + suffix + ".txt";
ASSERT_TRUE(profiler->dump(path));

std::ifstream in(path);
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

DumpCreatesFile writes a dump file under /tmp but never removes it. Consider deleting the file at the end of the test (or using a temp-file helper) to avoid leaving artifacts behind across repeated test runs.

Copilot uses AI. Check for mistakes.
Comment on lines +127 to +129
auto recordId = m_context.gstProfiler->createRecord("All Sources Attached");
if (recordId)
m_context.gstProfiler->logRecord(recordId.value());
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

m_context.gstProfiler is dereferenced unconditionally. Several existing unit tests construct GenericPlayerContext without a profiler; this will cause a null-deref when FinishSetupSource runs. Add a null check (or ensure the context always has a valid no-op profiler).

Suggested change
auto recordId = m_context.gstProfiler->createRecord("All Sources Attached");
if (recordId)
m_context.gstProfiler->logRecord(recordId.value());
if (m_context.gstProfiler)
{
auto recordId = m_context.gstProfiler->createRecord("All Sources Attached");
if (recordId)
m_context.gstProfiler->logRecord(recordId.value());
}

Copilot uses AI. Check for mistakes.
m_callbackRegistered = true;
}

m_context.gstProfiler->scheduleGstElementRecord(m_element);
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

m_context.gstProfiler is used without checking for null. Existing task unit tests build a GenericPlayerContext without initializing gstProfiler, so this new call can crash the tests. Add a null check around the profiler usage (or provide a default no-op profiler in the context).

Suggested change
m_context.gstProfiler->scheduleGstElementRecord(m_element);
if (m_context.gstProfiler)
{
m_context.gstProfiler->scheduleGstElementRecord(m_element);
}

Copilot uses AI. Check for mistakes.
Comment on lines +61 to +64
auto recordId = m_context.gstProfiler->createRecord("Pipeline State Changed",
m_gstWrapper->gstElementStateGetName(newState));
if (recordId)
m_context.gstProfiler->logRecord(recordId.value());
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

m_context.gstProfiler is dereferenced unconditionally here. In the unit-test suite (e.g. HandleBusMessageTest), GenericPlayerContext is constructed without initializing gstProfiler, so this will crash. Guard these calls with if (m_context.gstProfiler) (or initialize gstProfiler to a no-op implementation in the context).

Suggested change
auto recordId = m_context.gstProfiler->createRecord("Pipeline State Changed",
m_gstWrapper->gstElementStateGetName(newState));
if (recordId)
m_context.gstProfiler->logRecord(recordId.value());
if (m_context.gstProfiler)
{
auto recordId = m_context.gstProfiler->createRecord(
"Pipeline State Changed", m_gstWrapper->gstElementStateGetName(newState));
if (recordId)
{
m_context.gstProfiler->logRecord(recordId.value());
}
}

Copilot uses AI. Check for mistakes.
Comment on lines 107 to 108
const char *name = m_gstWrapper->gstElementGetName(appSrc);
std::string info = name ? name : "<null>";
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

gstElementGetName() (via IGstWrapper) is documented to return an allocated name that must be freed with g_free. Here it’s copied into a std::string but never freed, which will leak each time a source is attached. Free the returned name after copying (or wrap it in an RAII helper).

Suggested change
const char *name = m_gstWrapper->gstElementGetName(appSrc);
std::string info = name ? name : "<null>";
gchar *name = m_gstWrapper->gstElementGetName(appSrc);
std::string info = name ? name : "<null>";
m_glibWrapper->gFree(name);

Copilot uses AI. Check for mistakes.
Comment on lines +31 to +35
inline constexpr std::array kKlassTokens{
std::string_view{"Source"},
std::string_view{"Decryptor"},
std::string_view{"Decoder"},
};
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

kKlassTokens uses std::array/std::string_view, but the file doesn’t include <array> / <string_view>. Depending on transitive includes can break builds on other toolchains; add the missing standard headers (and consider removing the unused <mutex> include).

Copilot uses AI. Check for mistakes.
Comment on lines 276 to 280
/**
* @brief Profiler for player pipeline
*/
std::unique_ptr<GstProfiler> gstProfiler;
};
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

GenericPlayerContext stores the profiler as std::unique_ptr<GstProfiler> (concrete type). Since an IGstProfiler interface and GstProfilerMock exist, consider storing std::unique_ptr<IGstProfiler> instead to reduce coupling and allow mocking in unit tests.

Copilot uses AI. Check for mistakes.
Comment on lines +32 to +36
void SetUp() override
{
factory = IProfilerFactory::createFactory();
ASSERT_TRUE(factory);

Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

These tests are skipped whenever PROFILER_ENABLED is disabled in the environment, which means CI may not execute any assertions. Consider setting PROFILER_ENABLED=1 in SetUp() (and restoring/unsetting it in TearDown()) so the tests deterministically validate record/find/dump behavior.

Copilot uses AI. Check for mistakes.
@smudri85 smudri85 force-pushed the feature/RDKEMW-11764 branch 2 times, most recently from 3934f05 to 761b259 Compare February 12, 2026 09:18
Copilot AI review requested due to automatic review settings February 12, 2026 09:18
Copy link

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 19 out of 19 changed files in this pull request and generated 7 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +100 to +103
auto *probeCtx = new ProbeCtx{this, stage.value(), std::move(elementName)};
gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, &GstProfiler::probeCb, probeCtx, &GstProfiler::probeCtxDestroy);

m_gstWrapper->gstObjectUnref(pad);
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

ProbeCtx stores a raw this pointer and the pad-probe callback can run on a GStreamer streaming thread after GstProfiler is destroyed (e.g., during shutdown if a buffer arrives late), leading to a potential use-after-free. Consider making the callback independent of GstProfiler lifetime (e.g., store a shared_ptr<IProfiler> in ProbeCtx, or track probe IDs and remove probes/disable callbacks in ~GstProfiler() before releasing resources).

Copilot uses AI. Check for mistakes.
Comment on lines 23 to 25
#include "FlushOnPrerollController.h"
#include "GstProfiler.h"
#include "IGstSrc.h"
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

GenericPlayerContext includes the concrete GstProfiler.h, which forces any user of the context to pull in the implementation header. Prefer depending on the interface (IGstProfiler) and forward-declaring it here to reduce coupling and build impact.

Copilot uses AI. Check for mistakes.
Comment on lines +80 to 83
std::string profileriInfo;
gchar *capsStr = m_gstWrapper->gstCapsToString(caps);
GstElement *appSrc = nullptr;
if (m_attachedSource->getType() == MediaSourceType::AUDIO)
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

Typo in variable name: profileriInfo looks unintended and makes the code harder to read/search. Rename it to profilerInfo (and update the use at record creation).

Copilot uses AI. Check for mistakes.
Comment on lines +51 to +53
Profiler::Profiler(std::string module)
: m_module(std::move(module)), m_enabled(parseEnv(std::getenv(kProfilerEnv), false))
{
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

Profiler::Profiler calls std::getenv but <cstdlib> isn’t included in this translation unit. Add <cstdlib> explicitly to avoid build breaks from missing transitive includes.

Copilot uses AI. Check for mistakes.
Comment on lines +184 to +187
std::string stringValue(value);
std::transform(stringValue.begin(), stringValue.end(), stringValue.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });

Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

parseEnv uses std::tolower but <cctype> isn’t included here. Please include <cctype> (or otherwise ensure std::tolower is declared) rather than relying on indirect includes.

Copilot uses AI. Check for mistakes.
Comment on lines +79 to +83
const std::string path = std::string{"/tmp/rialto_profiler_ut_dump_"} + suffix + ".txt";
ASSERT_TRUE(profiler->dump(path));

std::ifstream in(path);
ASSERT_TRUE(in.good());
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

This test writes a dump file under /tmp but doesn’t clean it up, which can leave litter behind across repeated runs. Consider deleting the file at the end of the test (or using a scoped temp-file helper if available).

Copilot uses AI. Check for mistakes.
Comment on lines 44 to 49
enum class Stage
{
AppSrc,
Decryptor,
Decoder
};
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

Stage enum is currently unused (all stages are passed as strings). If it’s not needed imminently, please remove it to avoid dead code; otherwise wire it into the API to keep the type-safety benefit.

Suggested change
enum class Stage
{
AppSrc,
Decryptor,
Decoder
};

Copilot uses AI. Check for mistakes.
@smudri85 smudri85 force-pushed the feature/RDKEMW-11764 branch from 761b259 to 3d607f2 Compare February 12, 2026 13:28
Summary: Add profiling to Rialto Server.
Type: Feature
Test Plan: UT/CT, Fullstack
Jira: RDKEMW-11764
@github-actions
Copy link

Coverage statistics of your commit:
WARNING: Lines coverage decreased from: 85.2% to 84.6%
WARNING: Functions coverage decreased from: 92.5% to 91.9%

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.

3 participants