Skip to content

RDKEMW-23564: Media Capabilities from yaml file Implementation - #598

Merged
Usha2124 merged 50 commits into
masterfrom
feature/RDKEMW-23564
Sep 29, 2026
Merged

Usha2124 merged 50 commits into
masterfrom
feature/RDKEMW-23564

Conversation

@Usha2124

@Usha2124 Usha2124 commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

RDKEMW-23564: Media Capabilities from yaml file Implementation

Reason for change: Add AudioDecoderCapabilities and VideoDecoderCapabilities with YAML config parsing, IPC serialization and unit test coverage.
Test Procedure: https://ccp.sys.comcast.net/browse/RDKEMW-23564

Copilot AI lite review requested due to automatic review settings September 2, 2026 19:09
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

Pull request title must follow the pattern:
< JIRA TICKET >: < one line summary of change less than 65 characters >

Pull request description must follow the Commit message format for RDK-E:
https://etwiki.sys.comcast.net/spaces/RDKAR/pages/1407997180/Commit+Message+Format+For+RDKE

  1. Associated JIRA ticket in format : < JIRA TICKET >: < one line summary of change less than 65 characters >
  2. Detailed reason for change information
  3. Test procedure. Only references links to Jira ticket or sub tickets where test steps and references are captured.

< JIRA TICKET >: < one line summary of change less than 65 characters >
< empty line >
Reason for change:
Test Procedure: < https://ccp.sys.comcast.net/browse/JIRA TICKET/url/to/test_step_section>

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

media/server/main/source/MediaCapabilitiesServerFactory.cpp:78:0: style: The function 'createMediaCapabilitiesFactory' is never used. [unusedFunction]
std::shared_ptrfirebolt::rialto::IMediaCapabilitiesFactory createMediaCapabilitiesFactory() const override
^
serverManager/common/source/MediaCapabilitiesFactory.cpp:28:0: style: The function 'createMediaCapabilities' is never used. [unusedFunction]
std::unique_ptr createMediaCapabilities()
^
nofile:0:0: information: Active checkers: 161/592 (use --checkers-report= to see details) [checkersReport]

@Usha2124 Usha2124 changed the title Feature/rdkemw 23564 RDKEMW-23564: Media Capabilties from yaml file Sep 2, 2026
@Usha2124 Usha2124 changed the title RDKEMW-23564: Media Capabilties from yaml file RDKEMW-23564: Media Capabilities from yaml file Implementation Sep 2, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

It introduces broad cross-component IPC/proto/API changes and there are confirmed functional blockers (capabilities not wired through in ServerManager and capability RPC path returning empty data) that must be resolved.

Pull request overview

This PR introduces a new end-to-end “media capabilities” flow: decoder capabilities are parsed from HFP YAML via a new yaml-cpp wrapper, forwarded from ServerManager to the session server using typed protobuf fields in SetConfigurationRequest, and exposed to clients via a new IMediaCapabilities IPC module/API.

Changes:

  • Added yaml-cpp based YAML parsing wrapper (IYamlCppWrapper / YamlCppWrapper) for audio/video decoder capability structs.
  • Extended ServerManager → SessionServer IPC (SetConfigurationRequest) to optionally carry typed audio/video capability payloads and threaded those optionals through the ServerManager IPC stack.
  • Added new IMediaCapabilities interface and MediaCapabilities IPC module (server + client), plus build/proto wiring to support the new messages and RPC service.
File summaries
File Description
wrappers/source/YamlCppWrapperAccessor.cpp Factory accessor glue for the new yaml-cpp wrapper factory.
wrappers/source/YamlCppWrapper.cpp Implements YAML parsing for audio/video decoder capabilities using yaml-cpp.
wrappers/source/FactoryAccessor.cpp Registers/lazily constructs the new YamlCppWrapperFactory.
wrappers/interface/IYamlCppWrapper.h New wrappers interface for reading decoder capabilities from YAML.
wrappers/interface/IFactoryAccessor.h Adds accessor for IYamlCppWrapperFactory.
wrappers/include/YamlCppWrapper.h Concrete wrapper + factory declarations.
wrappers/include/FactoryAccessor.h Adds member for the yaml-cpp wrapper factory.
wrappers/CMakeLists.txt Links yaml-cpp and adds new wrapper sources/include paths.
serverManager/service/source/ServiceContext.cpp Threads IMediaCapabilities into SessionServerAppManager creation.
serverManager/service/source/ServerManagerServiceFactory.cpp Extends ServiceContext construction with a media capabilities parameter (currently passed as null).
serverManager/service/include/ServiceContext.h Adds IMediaCapabilities include and constructor parameter.
serverManager/service/CMakeLists.txt Adjusts include dirs for common public headers.
serverManager/public/include/MediaCapabilitiesFactory.h Declares factory function to create IMediaCapabilities.
serverManager/public/include/IMediaCapabilities.h New ServerManager-side capabilities interface.
serverManager/ipc/source/Controller.h Updates performSetConfiguration signatures to carry optional caps.
serverManager/ipc/source/Controller.cpp Forwards optional caps through controller → client calls.
serverManager/ipc/source/Client.h Adds optional caps params to configuration calls and required includes.
serverManager/ipc/source/Client.cpp Serialises optional caps into typed proto fields for SetConfiguration.
serverManager/ipc/include/IController.h Extends controller interface with optional caps parameters.
serverManager/ipc/CMakeLists.txt Adjusts includes and links (incl. protobuf exposure).
serverManager/common/source/SessionServerAppManagerFactory.cpp Threads IMediaCapabilities into SessionServerAppManager ctor.
serverManager/common/source/SessionServerAppManager.h Stores optional caps and updates constructor signature.
serverManager/common/source/SessionServerAppManager.cpp Loads caps once (via IMediaCapabilities) and forwards them on SetConfiguration.
serverManager/common/source/MediaCapabilitiesFactory.cpp Implements creation of MediaCapabilities backed by IYamlCppWrapper.
serverManager/common/source/MediaCapabilities.cpp Delegates capabilities load to IYamlCppWrapper with logging.
serverManager/common/include/SessionServerAppManagerFactory.h Updates factory signature to accept IMediaCapabilities.
serverManager/common/include/MediaCapabilitiesFactory.h Duplicate factory header added under common/.
serverManager/common/include/MediaCapabilities.h Concrete ServerManager capabilities implementation wrapper.
serverManager/common/CMakeLists.txt Adds MediaCapabilities sources to build.
proto/servermanagermodule.proto Adds typed audio/video capability fields to SetConfigurationRequest.
proto/mediacapabilitiesmodule.proto Adds new MediaCapabilities RPC service definition.
proto/mediaCapabilitiesCommon.proto Introduces shared typed AudioCapabilities/VideoCapabilities messages.
proto/CMakeLists.txt Updates protoc import dirs and generated targets for new protos.
openspec/changes/servermanager-media-capabilities/tasks.md Adds implementation checklist for ServerManager media capabilities.
openspec/changes/servermanager-media-capabilities/proposal.md Adds proposal/specification doc for the feature.
openspec/changes/servermanager-media-capabilities/design.md Adds design doc describing goals/decisions/risks.
openspec/changes/hfp-schema-v1-migration/tasks.md Adds HFP schema v1 migration tasks (incl. YAML parser updates).
openspec/changes/hfp-schema-v1-migration/specs/video-decoder-capabilities/spec.md Adds detailed video capability requirements/spec.
openspec/changes/hfp-schema-v1-migration/specs/audio-decoder-capabilities/spec.md Adds detailed audio capability requirements/spec.
openspec/changes/hfp-schema-v1-migration/proposal.md Adds HFP schema v1 migration proposal narrative.
openspec/changes/hfp-schema-v1-migration/design.md Adds HFP schema v1 migration design doc.
media/server/service/source/SessionServerManager.h Adds storage + API for preloaded caps in the session server manager.
media/server/service/source/SessionServerManager.cpp Implements storing of preloaded caps.
media/server/service/source/MediaPipelineService.h Adds capability getter APIs to the media pipeline service.
media/server/service/source/MediaPipelineService.cpp Adds placeholder capability getters (currently return empty).
media/server/service/include/ISessionServerManager.h Adds setPreloadedCapabilities to session server manager interface.
media/server/service/include/IMediaPipelineService.h Adds capability getters to the pipeline service interface.
media/server/main/source/YamlCapabilities.cpp Adds YAML-only capability reader for the session server.
media/server/main/source/MediaPipelineCapabilities.cpp Adjusts creation timing/logging for GstCapabilities.
media/server/main/source/MediaCapabilitiesServerFactory.cpp Adds server-side MediaCapabilities factory orchestrating YAML/GStreamer/preloaded.
media/server/main/source/MediaCapabilities.cpp Implements orchestration logic: preloaded → YAML → GStreamer fallback.
media/server/main/interface/MediaCapabilitiesServerFactory.h Declares server-side MediaCapabilities factory interfaces.
media/server/main/include/YamlCapabilities.h Declares YAML-only capability reader.
media/server/main/include/MediaPipelineCapabilities.h Adds forward declaration related to new capabilities types.
media/server/main/include/MediaCapabilities.h Declares server-side MediaCapabilities implementing IMediaCapabilities.
media/server/main/CMakeLists.txt Adds new capability source files to session server main build.
media/server/ipc/source/SessionManagementServer.cpp Registers the new MediaCapabilities module with session management server.
media/server/ipc/source/ServerManagerModuleService.cpp Deserialises typed caps from SetConfiguration and stores them in SessionServerManager.
media/server/ipc/source/MediaCapabilitiesModuleService.cpp Implements MediaCapabilities IPC service endpoints.
media/server/ipc/source/IpcFactory.cpp Wires in MediaCapabilities module factory creation.
media/server/ipc/include/SessionManagementServer.h Adds MediaCapabilities module member/factory parameter.
media/server/ipc/include/MediaCapabilitiesModuleService.h Declares server-side MediaCapabilities module service impl.
media/server/ipc/include/IMediaCapabilitiesModuleService.h Declares server-side MediaCapabilities module service interface/factory.
media/server/ipc/CMakeLists.txt Adds MediaCapabilitiesModuleService source.
media/server/gstplayer/source/GstCapabilities.cpp Adds capability getter methods and extra logging (returns stored members).
media/server/gstplayer/interface/IGstCapabilities.h Extends interface with audio/video capability getters.
media/server/gstplayer/include/GstCapabilities.h Adds stored capability members and getter declarations.
media/public/include/IMediaPipelineCapabilities.h Minor include style change.
media/public/include/IMediaCapabilities.h Adds new public client API for media capabilities + factory.
media/public/CMakeLists.txt Exposes new IMediaCapabilities.h in public headers list.
media/client/main/source/MediaCapabilities.cpp Implements client factory + wrapper delegating to IPC implementation.
media/client/main/include/MediaCapabilities.h Declares client-side factory and wrapper classes.
media/client/main/CMakeLists.txt Adds MediaCapabilities source to client main library.
media/client/ipc/source/MediaCapabilitiesIpc.cpp Implements client-side IPC calls to MediaCapabilitiesModule.
media/client/ipc/proto/mediacapabilitiesmodule.proto Adds client-side proto definition for MediaCapabilitiesModule.
media/client/ipc/interface/IMediaCapabilitiesIpcFactory.h Declares IPC factory interface for capabilities client.
media/client/ipc/include/MediaCapabilitiesIpc.h Declares IPC implementation for IMediaCapabilities.
media/client/ipc/CMakeLists.txt Adds MediaCapabilitiesIpc source to build.
ipc/common/include/CapabilityConverters.h Adds shared typed proto ↔ C++ struct conversion API.
ipc/common/CMakeLists.txt Adds CapabilityConverters implementation and common-public include dirs.
common/public/include/VideoDecoderCapabilities.h Adds/moves common video capability structs to common public API.
common/public/include/DecoderCapabilitiesCommon.h Adds/moves shared capability status enum to common public API.
common/public/include/AudioDecoderCapabilities.h Adds/moves common audio capability structs/enums to common public API.
common/public/CMakeLists.txt Exposes new common-public headers for install/include dirs.
common/CMakeLists.txt Links RialtoCommon publicly against RialtoCommonPublic.
.github/workflows/valgrind_ut.yml Installs yaml-cpp dev dependency in CI.
.github/workflows/actions/init_ut/action.yml Installs yaml-cpp dev dependency in CI init step.
Review details

Suppressed comments (2)

serverManager/common/include/MediaCapabilitiesFactory.h:32

  • Update the #endif comment to match the renamed include guard so the guard remains consistent.
    wrappers/source/YamlCppWrapper.cpp:723
  • Same issue as audio: YAML::LoadFile throws YAML::BadFile when the YAML file is missing, so missing files may be incorrectly returned as SCHEMA_VALIDATION_FAILED. Catch YAML::BadFile and map it to CONFIG_NOT_FOUND.
  • Files reviewed: 88/88 changed files
  • Comments generated: 6
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread media/server/service/source/MediaPipelineService.cpp Outdated
Comment thread serverManager/service/include/ServiceContext.h Outdated
Comment thread serverManager/service/source/ServiceContext.cpp Outdated
Comment thread serverManager/common/include/MediaCapabilitiesFactory.h Outdated
Comment thread serverManager/service/source/ServerManagerServiceFactory.cpp
Comment thread wrappers/source/YamlCppWrapper.cpp Outdated
Copilot AI review requested due to automatic review settings September 3, 2026 04:19
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

media/server/main/source/MediaCapabilitiesServerFactory.cpp:76:0: style: The function 'createMediaCapabilitiesFactory' is never used. [unusedFunction]
std::shared_ptrfirebolt::rialto::IMediaCapabilitiesFactory createMediaCapabilitiesFactory() const override
^
tests/componenttests/server/common/MessageBuilders.cpp:676:0: style: The function 'createGetSupportedAudioCapabilitiesRequest' is never used. [unusedFunction]
::firebolt::rialto::GetSupportedAudioCapabilitiesRequest createGetSupportedAudioCapabilitiesRequest()
^
tests/componenttests/server/common/MessageBuilders.cpp:682:0: style: The function 'createGetSupportedVideoCapabilitiesRequest' is never used. [unusedFunction]
::firebolt::rialto::GetSupportedVideoCapabilitiesRequest createGetSupportedVideoCapabilitiesRequest()
^
nofile:0:0: information: Active checkers: 161/592 (use --checkers-report= to see details) [checkersReport]

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

There are correctness issues in the new capability plumbing (broken public factory header type, non-clearing preloaded capability propagation, and GStreamer fallback methods returning never-populated capability data).

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 126/126 changed files
  • Comments generated: 5
  • Review effort level: Lite

Comment thread serverManager/public/include/MediaCapabilitiesFactory.h Outdated
Comment thread media/server/gstplayer/source/GstCapabilities.cpp
Comment thread media/server/ipc/source/ServerManagerModuleService.cpp Outdated
Comment thread media/server/service/source/SessionServerManager.cpp Outdated
Comment thread media/server/main/include/MediaCapabilities.h Outdated
Copilot AI review requested due to automatic review settings September 3, 2026 04:37
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

media/server/main/source/MediaCapabilitiesServerFactory.cpp:67:0: style: The function 'createMediaCapabilitiesFactory' is never used. [unusedFunction]
std::shared_ptrfirebolt::rialto::IMediaCapabilitiesFactory createMediaCapabilitiesFactory() const override
^
tests/componenttests/server/common/MessageBuilders.cpp:676:0: style: The function 'createGetSupportedAudioCapabilitiesRequest' is never used. [unusedFunction]
::firebolt::rialto::GetSupportedAudioCapabilitiesRequest createGetSupportedAudioCapabilitiesRequest()
^
tests/componenttests/server/common/MessageBuilders.cpp:682:0: style: The function 'createGetSupportedVideoCapabilitiesRequest' is never used. [unusedFunction]
::firebolt::rialto::GetSupportedVideoCapabilitiesRequest createGetSupportedVideoCapabilitiesRequest()
^
nofile:0:0: information: Active checkers: 161/592 (use --checkers-report= to see details) [checkersReport]

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

There are confirmed build-breaking test/mock issues and at least one functional gap where the intended GStreamer fallback path returns default/empty capabilities due to never-populated state.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (6)

tests/unittests/media/server/ipc/serverManagerModuleService/ServerManagerModuleServiceTestsFixture.cpp:167

  • setPreloadedCapabilities is a void method in ISessionServerManager, so this expectation cannot use WillOnce(Return(true)) (won't compile).
    media/server/ipc/source/ServerManagerModuleService.cpp:144
  • setPreloadedCapabilities() is only called when at least one capability field is present. If a previous setConfiguration supplied capabilities and a later one omits them, the session server will keep using stale preloaded capabilities. Consider always calling setPreloadedCapabilities(audioCaps, videoCaps) so nullopt clears state.
    media/server/service/source/SessionServerManager.cpp:208
  • SessionServerManager::setPreloadedCapabilities only forwards to MediaPipelineService when at least one optional has a value. If the caller passes nullopt optionals (to clear a previous preload), MediaPipelineService will keep stale capabilities. Forward the optionals unconditionally so downstream state is cleared.
    serverManager/public/include/MediaCapabilitiesFactory.h:30
  • This header declares createMediaCapabilities() returning std::unique_ptr<IMediaCapabilities>, but IMediaCapabilities is not declared anywhere in serverManager/public/include (the interface defined in IMediaCapabilities.h is IYamlCapabilities). This mismatch will break any consumer including this public header.
    media/server/gstplayer/source/GstCapabilities.cpp:476
  • GstCapabilities::getSupportedAudioCapabilities() / getSupportedVideoCapabilities() always return m_audioDecoderCapabilities / m_videoDecoderCapabilities, but these members are never populated anywhere in GstCapabilities.cpp (they're only default-constructed). That means the advertised "GStreamer fallback" path will return empty capabilities on config-absent platforms.
firebolt::rialto::common::AudioDecoderCapabilities GstCapabilities::getSupportedAudioCapabilities()
{
    waitForInitialisation();
    return m_audioDecoderCapabilities;
}

firebolt::rialto::common::VideoDecoderCapabilities GstCapabilities::getSupportedVideoCapabilities()
{
    waitForInitialisation();
    return m_videoDecoderCapabilities;
}

tests/unittests/media/server/main/mediaCapabilities/MediaCapabilitiesTests.cpp:71

  • This test claims it covers the "preload missing" (GStreamer fallback) case, but it calls m_mediaCapabilities which the fixture constructs with preloaded audio/video optionals, so it will not exercise the fallback path.
  • Files reviewed: 131/131 changed files
  • Comments generated: 3
  • Review effort level: Lite

Comment thread tests/unittests/media/server/main/mediaCapabilities/MediaCapabilitiesTests.cpp Outdated
@Usha2124 Usha2124 changed the title RDKEMW-23564: Media Capabilities from yaml file Implementation RDKEMW-23564: Media Capabilities from yaml file Implementation Sep 3, 2026
Copilot AI review requested due to automatic review settings September 3, 2026 07:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The GStreamer fallback path for decoder capabilities appears functionally incomplete (capability members never populated), and there are compile/test correctness issues that need resolving before this can be safely approved.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (6)

Previously missed (1) — in code that hasn't changed since the last review.

tests/unittests/media/server/main/mediaCapabilities/MediaCapabilitiesTests.cpp:58

  • This test claims to cover the "preload missing" path, but it calls m_mediaCapabilities which is constructed with both audio and video preloads in the fixture ctor. As written it cannot exercise the GStreamer fallback. Construct a MediaCapabilities instance with std::nullopt preloads and assert the returned values match the GStreamer path.

This issue also appears on line 66 of the same file.

serverManager/public/include/MediaCapabilitiesFactory.h:23

  • MediaCapabilitiesFactory.h includes IYamlCapabilities.h, but that header does not exist in the repository (the IYamlCapabilities interface is declared in IMediaCapabilities.h). This will break compilation for any TU including this factory header.
    serverManager/common/include/MediaCapabilitiesFactory.h:25
  • This header duplicates the include guard macro used by serverManager/public/include/MediaCapabilitiesFactory.h, so including both headers in the same TU can silently skip one of them. It also uses a fragile relative include path into public/include. Use a unique guard for the common header and include the public header via the include search path instead of a relative path.
    media/server/gstplayer/source/GstCapabilities.cpp:476
  • GstCapabilities::getSupportedAudioCapabilities()/getSupportedVideoCapabilities() return m_audioDecoderCapabilities/m_videoDecoderCapabilities, but these members are never assigned anywhere in GstCapabilities.cpp (no element-query population), so the GStreamer fallback path will always return empty capabilities when YAML/preload is absent.
firebolt::rialto::common::AudioDecoderCapabilities GstCapabilities::getSupportedAudioCapabilities()
{
    waitForInitialisation();
    return m_audioDecoderCapabilities;
}

firebolt::rialto::common::VideoDecoderCapabilities GstCapabilities::getSupportedVideoCapabilities()
{
    waitForInitialisation();
    return m_videoDecoderCapabilities;
}

tests/unittests/media/server/main/mediaCapabilities/MediaCapabilitiesTestsFixture.cpp:45

  • gstCapabilitiesWillNotBeQueried() is currently a no-op, so tests that claim to verify the preload path do not actually fail if the implementation unexpectedly queries GStreamer. Add explicit Times(0) expectations here.
    tests/unittests/media/server/main/mediaCapabilities/MediaCapabilitiesTests.cpp:66
  • This test claims to cover the "preload missing" path, but it calls m_mediaCapabilities which is constructed with both audio and video preloads in the fixture ctor. As written it cannot exercise the GStreamer fallback. Construct a MediaCapabilities instance with std::nullopt preloads and assert the returned values match the GStreamer path.
  • Files reviewed: 150/150 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread tests/common/misc/MediaSourceUtil.cpp Outdated
Copilot AI review requested due to automatic review settings September 3, 2026 08:43
@github-actions

Copy link
Copy Markdown

Coverage statistics of your commit:
WARNING: Lines coverage decreased from: 84.7% to 84.4%
WARNING: Functions coverage decreased from: 93.0% to 92.6%

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Note

Copilot was unable to run its full agentic suite in this review.

Pull request overview

Copilot reviewed 146 out of 150 changed files in this pull request and generated 4 comments.

Suppressed comments (3)

wrappers/CMakeLists.txt:1

  • yaml-cpp is linked unconditionally, but find_package(yaml-cpp REQUIRED) is only executed in the non-UnitTests/non-Stub build branch. This can break configurations where yaml-cpp isn't available/desired (e.g., UnitTests builds or environments without the dev package) because the linker will still be asked to link yaml-cpp. Align the target_link_libraries(... yaml-cpp) and find_package(yaml-cpp ...) scopes (e.g., guard both under the same if()/feature flag).
    wrappers/CMakeLists.txt:1
  • yaml-cpp is linked unconditionally, but find_package(yaml-cpp REQUIRED) is only executed in the non-UnitTests/non-Stub build branch. This can break configurations where yaml-cpp isn't available/desired (e.g., UnitTests builds or environments without the dev package) because the linker will still be asked to link yaml-cpp. Align the target_link_libraries(... yaml-cpp) and find_package(yaml-cpp ...) scopes (e.g., guard both under the same if()/feature flag).
    tests/unittests/common/CMakeLists.txt:1
  • This removes add_subdirectory(misc) from the unit-test common build, but other changes in this PR reference RialtoCommonMisc (e.g., via $<TARGET_PROPERTY:RialtoCommonMisc,...> in tests/common/matchers/CMakeLists.txt). If RialtoCommonMisc is no longer created in the unit-test build graph, those generator expressions can break CMake generation. Ensure the new misc location is added consistently for unit tests (or remove the target-property dependency).

Comment on lines +345 to +458
for (const auto &mimeType : m_supportedMimeTypes)
{
if (mimeType.find("audio/") == 0)
{
// Create audio capability with codec-specific fields based on MIME type
// Each capability MUST have at least one codec field populated to avoid empty serialization
firebolt::rialto::common::AudioDecoderCapability audioCap;

if (mimeType.find("audio/x-opus") != std::string::npos || mimeType == "audio/opus")
{
// Opus codec with default profile capability
audioCap.opus = firebolt::rialto::common::OpusCapability{
firebolt::rialto::common::AudioProfileCapability{0, 2, 48000, 16}};
}
else if (mimeType.find("audio/x-flac") != std::string::npos || mimeType == "audio/flac")
{
// FLAC codec with default profile capability
audioCap.flac = firebolt::rialto::common::FlacCapability{
firebolt::rialto::common::AudioProfileCapability{0, 8, 192000, 24}};
}
else if (mimeType.find("audio/aac") != std::string::npos)
{
// AAC codec with default profile capability
audioCap.aac = firebolt::rialto::common::AacCapability{};
audioCap.aac->profiles[firebolt::rialto::common::AacProfile::LC] =
firebolt::rialto::common::AudioProfileCapability{0, 2, 48000, 16};
}
else if (mimeType.find("audio/mp3") != std::string::npos)
{
// MP3 codec with default profile capability
audioCap.mp3 = firebolt::rialto::common::Mp3Capability{
firebolt::rialto::common::AudioProfileCapability{0, 2, 48000, 16}};
}
else if (mimeType.find("audio/x-eac3") != std::string::npos || mimeType == "audio/eac3")
{
// Dolby EAC3 codec with default profile capability
audioCap.dolbyEac3 = firebolt::rialto::common::DolbyEac3Capability{};
audioCap.dolbyEac3->profiles[firebolt::rialto::common::DolbyEac3Profile::PLUS] =
firebolt::rialto::common::AudioProfileCapability{0, 6, 48000, 16};
}
else if (mimeType.find("audio/x-ac3") != std::string::npos || mimeType == "audio/ac3")
{
// Dolby AC3 codec with default profile capability
audioCap.dolbyAc3 = firebolt::rialto::common::DolbyAc3Capability{};
audioCap.dolbyAc3->profiles[firebolt::rialto::common::DolbyAc3Profile::STANDARD] =
firebolt::rialto::common::AudioProfileCapability{0, 6, 48000, 16};
}
else if (mimeType.find("audio/x-vorbis") != std::string::npos || mimeType == "audio/vorbis")
{
// Vorbis codec with default profile capability
audioCap.vorbis = firebolt::rialto::common::VorbisCapability{
firebolt::rialto::common::AudioProfileCapability{0, 8, 192000, 16}};
}
else
{
RIALTO_SERVER_LOG_WARN("Unknown audio MIME type '%s'", mimeType.c_str());
}

audioCapabilities.push_back(std::move(audioCap));
}
else if (mimeType.find("video/") == 0)
{
// Create video capability with codec-specific data based on MIME type
// Initialize with empty codec capabilities - will be populated based on MIME type
firebolt::rialto::common::VideoDecoderCapability videoCap;

if (mimeType.find("video/h264") != std::string::npos)
{
// H.264 codec with default profile
firebolt::rialto::common::H264Profile profile;
profile.type = firebolt::rialto::common::H264ProfileType::H264_MAIN;
profile.maxLevel = firebolt::rialto::common::H264Level::H264_LEVEL_5_2;
profile.maxBitrateInBps = 0; // No bitrate limit
videoCap.codecCapabilities.h264 = firebolt::rialto::common::H264CodecCapability{};
videoCap.codecCapabilities.h264->profiles.push_back(profile);
}
else if (mimeType.find("video/h265") != std::string::npos || mimeType.find("video/hevc") != std::string::npos)
{
// H.265/HEVC codec with default profile
firebolt::rialto::common::H265Profile profile;
profile.type = firebolt::rialto::common::H265ProfileType::H265_MAIN;
profile.maxLevel = firebolt::rialto::common::H265Level::H265_LEVEL_5_2;
profile.maxBitrateInBps = 0; // No bitrate limit
videoCap.codecCapabilities.h265 = firebolt::rialto::common::H265CodecCapability{};
videoCap.codecCapabilities.h265->profiles.push_back(profile);
}
else if (mimeType.find("video/x-vp9") != std::string::npos || mimeType == "video/vp9")
{
// VP9 codec with default profile
firebolt::rialto::common::Vp9Profile profile;
profile.type = firebolt::rialto::common::Vp9ProfileType::VP9_PROFILE_0;
profile.maxLevel = firebolt::rialto::common::Vp9Level::VP9_LEVEL_5_2;
profile.maxBitrateInBps = 0; // No bitrate limit
videoCap.codecCapabilities.vp9 = firebolt::rialto::common::Vp9CodecCapability{};
videoCap.codecCapabilities.vp9->profiles.push_back(profile);
}
else if (mimeType.find("video/x-av1") != std::string::npos || mimeType == "video/av1")
{
// AV1 codec with default profile
firebolt::rialto::common::Av1Profile profile;
profile.type = firebolt::rialto::common::Av1ProfileType::AV1_MAIN;
profile.maxLevel = firebolt::rialto::common::Av1Level::AV1_LEVEL_6_2;
profile.maxBitrateInBps = 0; // No bitrate limit
videoCap.codecCapabilities.av1 = firebolt::rialto::common::Av1CodecCapability{};
videoCap.codecCapabilities.av1->profiles.push_back(profile);
}
else
{
RIALTO_SERVER_LOG_WARN("Unknown video MIME type '%s', using H.264 as fallback", mimeType.c_str());
}

videoCapabilities.push_back(std::move(videoCap));
}
}
Comment on lines +460 to +474
// Initialize audio decoder capabilities if we found audio MIME types
if (!audioCapabilities.empty())
{
m_audioDecoderCapabilities.capabilities = std::move(audioCapabilities);
RIALTO_SERVER_LOG_INFO("Populated %zu audio decoder capabilities from GStreamer",
m_audioDecoderCapabilities.capabilities.size());
}

// Initialize video decoder capabilities if we found video MIME types
if (!videoCapabilities.empty())
{
m_videoDecoderCapabilities.capabilities = std::move(videoCapabilities);
RIALTO_SERVER_LOG_INFO("Populated %zu video decoder capabilities from GStreamer",
m_videoDecoderCapabilities.capabilities.size());
}
return mediaCapabilities;
}

}; // namespace firebolt::rialto
return m_mediaCapabilitiesIpc->getSupportedVideoCapabilities();
}

}; // namespace firebolt::rialto::client

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Unresolved critical and moderate findings require fixes before approval.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (18)

media/server/gstplayer/source/GstCapabilities.cpp:403

  • This unconditional push runs even after the preceding branch logs an unknown audio MIME. Existing GStreamer-to-MIME mapping emits values such as audio/mp4, audio/b-wav, and audio/x-raw, none of which populate a codec here, so the fallback advertises empty AudioDecoderCapability entries. Skip unknown MIME types or populate a real codec before pushing.
            {
                RIALTO_SERVER_LOG_WARN("Unknown audio MIME type '%s'", mimeType.c_str());
            }

            audioCapabilities.push_back(std::move(audioCap));

media/server/gstplayer/source/GstCapabilities.cpp:456

  • This unconditional push runs even after the preceding branch logs an unknown video MIME. For example, the existing mapping emits video/mp4, but this branch only logs that H.264 is a fallback and never populates videoCap, so the response contains an unusable empty video capability. Skip the unknown MIME or actually populate the claimed fallback before pushing.
            {
                RIALTO_SERVER_LOG_WARN("Unknown video MIME type '%s', using H.264 as fallback", mimeType.c_str());
            }

            videoCapabilities.push_back(std::move(videoCap));

media/server/main/include/MediaCapabilitiesServerInternal.h:23

  • IGstCapabilities is used as the pointee type at the constructor and member declarations below, but this header neither includes its definition nor forward-declares it. It currently compiles only because each known translation unit includes IGstCapabilities.h first; a direct include of this header fails. Include the interface here so the header is self-contained.
    media/server/main/source/MediaCapabilitiesServerInternal.cpp:132
  • The documented Path A behavior is to return ServerManager's preloaded YAML capabilities directly, but this branch always queries GStreamer and appends codecs/profiles. That means a YAML file that intentionally omits a codec is expanded at runtime and the advertised capability set is no longer the configured one. Return the cached value directly when present and query GStreamer only when it is absent.
    media/server/main/source/MediaCapabilitiesServerInternal.cpp:404
  • When YAML and GStreamer both contain a video codec, this merge branch unions only profiles and never unions dynamicRanges. Ranges present only in GStreamer are therefore lost from the returned capability (the same pattern is repeated for H264, H265, VP9, and AV1); merge each per-codec dynamic-range vector as well.
    media/server/service/source/MediaPipelineService.cpp:727
  • If the new MediaCapabilitiesServerInternal factory cannot be created, this returns an empty result even though m_mediaPipelineCapabilities was successfully constructed and still provides the existing GStreamer query path. That turns a recoverable factory failure into a silent loss of all capabilities; fall back to m_mediaPipelineCapabilities->getSupportedAudioCapabilities() here (and likewise for video) when m_mediaCapabilities is null.
    media/server/service/source/MediaPipelineService.cpp:739
  • If the new MediaCapabilitiesServerInternal factory cannot be created, this returns an empty result even though m_mediaPipelineCapabilities was successfully constructed and still provides the existing GStreamer query path. That turns a recoverable factory failure into a silent loss of all capabilities; fall back to m_mediaPipelineCapabilities->getSupportedVideoCapabilities() here when m_mediaCapabilities is null.
    serverManager/common/source/SessionServerAppManager.cpp:47
  • Non-OK YAML statuses are silently discarded for both audio and video. This makes a missing HFP file indistinguishable from a schema/internal failure in production logs, despite the status enum distinguishing those cases; retain the returned status and log CONFIG_NOT_FOUND at INFO and other failures at WARN before leaving the corresponding optional unset.
    serverManager/common/source/SessionServerAppManagerFactory.cpp:51
  • The ServerManager path constructs and injects IYamlCppWrapper directly, bypassing the IMediaCapabilities abstraction described by the change contract. This couples SessionServerAppManager to YAML parsing, prevents injecting a status-aware capability service in production/tests, and is why the cache currently has no status-specific handling; create/inject the ServerManager IMediaCapabilities service and keep the wrapper behind that boundary.
    tests/componenttests/server/tests/mediaCapabilities/MediaCapabilitiesAppendCodecsIntegrationTest.cpp:84
  • These new MediaCapabilities scenarios send GetSupportedMimeTypes, which is the legacy MediaPipelineCapabilities RPC; they never invoke getSupportedAudioCapabilities/getSupportedVideoCapabilities or validate typed capability serialization and orchestration. Use the dedicated audio/video request builders and matching response actions for all capability scenarios in this file.
    tests/componenttests/server/tests/mediaCapabilities/MediaCapabilitiesOrchestrationTest.cpp:92
  • This orchestration test also sends the legacy GetSupportedMimeTypes request, so its fallback, consistency, and unknown-source assertions do not exercise the new MediaCapabilities IPC methods at all. Replace these requests and response matchers with the dedicated audio/video capability RPCs before counting this as coverage for the new path.
    tests/unittests/media/server/main/mediaCapabilities/CMakeLists.txt:27
  • This standalone target does not compile MediaCapabilitiesAppendCodecsTests.cpp, so running RialtoServerMediaCapabilitiesTests omits the new append/merge coverage even though the aggregate main target lists it. Add the source here so the component-specific target actually runs all of its tests.
    tests/unittests/serverManager/unittests/service/ServerManagerServiceTests.cpp:104
  • These tests invoke YamlCppWrapperMock directly, so they only verify that a GMock expectation can be set and do not exercise any production delegation, YAML parsing, status handling, caching, or IPC forwarding. They would pass even if the new implementation were completely disconnected. Replace them with tests that construct the relevant production class and assert wrapper calls/results (or add parser tests) to provide the promised coverage.
    wrappers/CMakeLists.txt:129
  • yaml-cpp is linked unconditionally, but find_package(yaml-cpp) and YamlCppWrapper.cpp are both skipped for UnitTests and ComponentTests. Those configurations still propagate -lyaml-cpp through the static RialtoWrappers target and can fail to link on environments that intentionally do not install yaml-cpp; keep this dependency under the same production-only condition as the source.
    wrappers/source/YamlCppWrapper.cpp:726
  • YAML::LoadFile raises YAML::BadFile when the video file is missing, but this catch maps every exception to SCHEMA_VALIDATION_FAILED. The audio implementation maps the same condition to CONFIG_NOT_FOUND, so a missing video YAML is reported as a schema error instead of taking the normal missing-config fallback. Handle YAML::BadFile before the generic catch.
    wrappers/source/YamlCppWrapper.cpp:670
  • The parser only treats a null document as missing, then returns OK when the required audiodecoder root is absent. SessionServerAppManager caches every OK result and forwards it as a present optional, so malformed YAML is accepted as an empty capability set rather than being reported as schema-invalid and falling back. Add a SCHEMA_VALIDATION_FAILED branch for a missing root node.
    wrappers/source/YamlCppWrapper.cpp:708
  • The parser only treats a null document as missing, then returns OK when the required videodecoder root is absent. SessionServerAppManager caches every OK result and forwards it as a present optional, so malformed YAML is accepted as an empty capability set rather than being reported as schema-invalid and falling back. Add a SCHEMA_VALIDATION_FAILED branch for a missing root node.
    wrappers/source/YamlCppWrapper.cpp:131
  • The named-profile helper silently returns an empty map when profiles is absent or has the wrong YAML type, while its caller still sets the codec optional and returns OK. That produces a capability entry with no usable profiles for AAC/DTS/etc. Treat a missing or non-sequence profiles node as schema validation failure instead of silently accepting it.
  • Files reviewed: 149/153 changed files
  • Comments generated: 4
  • Review effort level: Lite

Comment on lines +44 to +48
auto gstCapabilitiesUnique = gstCapabilitiesFactory->createGstCapabilities();
if (!gstCapabilitiesUnique)
{
throw std::runtime_error("Failed to create GstCapabilities");
}
Comment thread media/server/main/source/MediaCapabilitiesServerInternal.cpp Outdated
Comment on lines +103 to +117
if (codecData["profiles"] && codecData["profiles"].IsSequence())
{
for (const auto &entry : codecData["profiles"])
{
YAML::const_iterator it = entry.begin();
if (it != entry.end())
{
if (it->first.as<std::string>() != "BASE")
throw std::runtime_error("parseBaseProfileCapability: expected key 'BASE', got '" +
it->first.as<std::string>() + "'");
return parseAudioProfileCapability(it->second);
}
}
}
return {};
@github-actions

Copy link
Copy Markdown

media/server/main/source/MediaCapabilitiesServerInternal.cpp:411:17: style: Consider using std::any_of algorithm instead of a raw loop. [useStlAlgorithm]
{
^
media/server/main/source/MediaCapabilitiesServerInternal.cpp:440:17: style: Consider using std::any_of algorithm instead of a raw loop. [useStlAlgorithm]
{
^
media/server/main/source/MediaCapabilitiesServerInternal.cpp:469:17: style: Consider using std::any_of algorithm instead of a raw loop. [useStlAlgorithm]
{
^
media/server/main/source/MediaCapabilitiesServerInternal.cpp:498:17: style: Consider using std::any_of algorithm instead of a raw loop. [useStlAlgorithm]
{
^
media/server/main/source/MediaCapabilitiesServerInternal.cpp:527:17: style: Consider using std::any_of algorithm instead of a raw loop. [useStlAlgorithm]
{
^
media/server/service/source/MediaPipelineService.cpp:34:23: warning: Member variable 'MediaPipelineService::m_metricsService' is not initialized in the constructor. [uninitMemberVar]
MediaPipelineService::MediaPipelineService(
^
nofile:0:0: information: Active checkers: 161/592 (use --checkers-report= to see details) [checkersReport]

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Note

Copilot was unable to run its full agentic suite in this review.

Pull request overview

Copilot reviewed 149 out of 153 changed files in this pull request and generated 2 comments.

Suppressed comments (5)

media/server/service/source/MediaPipelineService.h:1

  • m_metricsService is a reference member but the constructor signature no longer accepts a IPrivateMetricsService &metricsService parameter, so this reference cannot be initialized. This is a compile-time error (and/or a functional regression if metrics were intended to remain). Either reintroduce IPrivateMetricsService &metricsService in the constructor and initialize m_metricsService, or remove m_metricsService (and any downstream usage) if metrics are no longer part of this service.
    media/server/service/source/MediaPipelineService.h:1
  • m_metricsService is a reference member but the constructor signature no longer accepts a IPrivateMetricsService &metricsService parameter, so this reference cannot be initialized. This is a compile-time error (and/or a functional regression if metrics were intended to remain). Either reintroduce IPrivateMetricsService &metricsService in the constructor and initialize m_metricsService, or remove m_metricsService (and any downstream usage) if metrics are no longer part of this service.
    media/server/main/CMakeLists.txt:1
  • This hunk appears to replace multiple existing source files (e.g., metrics-related .cpp files) with only source/MediaCapabilitiesServerInternal.cpp. If those removed sources are still referenced by the library, this will break the build and/or remove required functionality. MediaCapabilitiesServerInternal.cpp should be added without dropping unrelated sources unless the PR also removes all usages of those previously compiled translation units.
    proto/CMakeLists.txt:1
  • privatemetricsmodule.proto was present in the previous protobuf_generate_cpp(...) list but is no longer generated here. If any targets include/use privatemetricsmodule.pb.h/.cc (which is likely given existing PrivateMetrics IPC code), this will cause build failures. Re-add privatemetricsmodule.proto to the generation list or ensure it is generated by another target that all dependents link against.
    tests/common/matchers/CMakeLists.txt:1
  • This introduces tab/whitespace-only lines inside target_include_directories, which can fail style/lint checks and makes CMake formatting inconsistent. Remove the blank tabbed line and align indentation consistently (spaces), keeping only valid directory entries under INTERFACE.

Comment on lines +398 to +403
else
{
RIALTO_SERVER_LOG_WARN("Unknown audio MIME type '%s'", mimeType.c_str());
}

audioCapabilities.push_back(std::move(audioCap));
}
else
{
RIALTO_SERVER_LOG_WARN("Unknown video MIME type '%s', using H.264 as fallback", mimeType.c_str());

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Unresolved build, schema, YAML-validation, capability-selection, and test-configuration issues remain.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (21)

common/public/include/AudioDecoderCapabilities.h:72

  • The public enum exposes HE_V1/HE_V2, but the HFP v1 requirement in openspec/changes/hfp-schema-v1-migration/specs/audio-decoder-capabilities/spec.md:24-27 names these profiles HE_AAC_V1/HE_AAC_V2 and expects those enum keys. The YAML converter likewise only accepts HE_V1/HE_V2, so a schema-conformant HE_AAC_V1 entry is silently dropped and the public API does not satisfy the documented contract; align the enum/converter names or update the schema and all producers.
enum class AacProfile
{
    LC,    /**< Low Complexity profile */
    HE_V1, /**< High Efficiency v1 profile */
    HE_V2, /**< High Efficiency v2 profile */
    ELD,   /**< Enhanced Low Delay profile */
    X_HE   /**< Extended High Efficiency profile */

media/server/gstplayer/source/GstCapabilities.cpp:403

  • The else branch logs an unknown audio MIME type but still appends the empty audioCap to audioCapabilities. Since the supported MIME set includes decoder/sink caps beyond the handled codecs, fallback results can contain ranks with no codec at all; only append a rank after populating a supported codec or add the missing mappings.
            audioCapabilities.push_back(std::move(audioCap));

media/server/gstplayer/source/GstCapabilities.cpp:456

  • Unknown video MIME types are logged here, but the empty videoCap is still appended. This produces capability ranks with no codec (despite the comment that each rank must be populated) and can expose unusable entries from the GStreamer fallback; filter these ranks or implement the missing mappings before appending.
            videoCapabilities.push_back(std::move(videoCap));

media/server/main/source/MediaCapabilitiesServerInternal.cpp:107

  • Path A is specified to use the ServerManager/YAML capabilities directly and skip GStreamer when preloaded data is present (openspec/changes/servermanager-media-capabilities/tasks.md:46). Querying and appending GStreamer codecs here makes the YAML data non-authoritative and can advertise codecs excluded by the HFP configuration; return the preloaded value without the fallback query.
    media/server/main/source/MediaCapabilitiesServerInternal.cpp:135
  • The video Path A has the same contract violation: with preloaded YAML data, the implementation must not query or merge GStreamer capabilities (openspec/changes/servermanager-media-capabilities/tasks.md:46). The current merge can expose codecs that the HFP configuration deliberately omits; return the preloaded value directly.
    media/server/main/source/MediaCapabilitiesServerInternal.cpp:53
  • The factory unconditionally creates the GStreamer fallback before the ServerManager can provide preloaded capabilities. If the GStreamer factory or wrapper cannot be created, this returns null and later YAML data cannot be served, even though the documented preloaded path should not depend on GStreamer. Defer fallback creation until it is needed or support a preloaded-only instance.
    proto/mediaCapabilitiesCommon.proto:30
  • The protobuf wire field for audio max_bitrate_in_bps is uint64, while the HFP schema and the new public contract specify uint32_t for all audio profile fields. This mismatch can expose a different API/wire type than the declared schema; align the protobuf and converter types with the public contract.
    serverManager/common/source/SessionServerAppManager.cpp:55
  • The constructor ignores both non-OK statuses, so a malformed YAML file is silently treated exactly like an expected missing file and the cached optionals remain unset. The documented behavior distinguishes CONFIG_NOT_FOUND from schema/internal failures (including different log severity); preserve the status and log/report validation failures so a broken deployment is not hidden behind the GStreamer fallback.
    tests/unittests/media/server/main/mediaCapabilities/CMakeLists.txt:22
  • This CMake file is never reached: tests/unittests/media/server/main/CMakeLists.txt lists these sources directly but does not add the mediaCapabilities subdirectory, and no other CMake file references this target. Consequently RialtoServerMediaCapabilitiesTests is never configured. Add this subdirectory to the parent target setup or remove the orphan target.
    tests/unittests/media/server/main/mediaCapabilities/CMakeLists.txt:26
  • If this target is enabled, these paths are resolved relative to the current mediaCapabilities directory, so CMake looks for mediaCapabilities/mediaCapabilities/MediaCapabilitiesTests.cpp, which does not exist. The append-codec test source is also omitted from this target. Use paths relative to the current directory and include MediaCapabilitiesAppendCodecsTests.cpp.
    tests/unittests/media/server/main/mediaCapabilities/MediaCapabilitiesAppendCodecsTests.cpp:46
  • This test target is configured for C++17, but designated member initializers are a C++20 feature. With the repository's global -Werror, this new test is rejected by compilers that diagnose the extension; initialize AudioProfileCapability positionally (or assign its fields explicitly).
    tests/unittests/serverManager/unittests/service/ServerManagerServiceTests.cpp:96
  • These tests only invoke YamlCppWrapperMock and assert that GMock records the call; they never exercise YamlCppWrapper, YAML loading, schema validation, status mapping, or IPC serialization. As a result they pass even if the new production parser is completely broken, so add tests using representative valid, malformed, and missing YAML configurations (and the actual wrapper/converters) rather than only testing the mock interface.
    wrappers/source/YamlCppWrapper.cpp:727
  • YAML::BadFile derives from std::exception, but this function has no BadFile catch before the generic catch. A missing video YAML file therefore returns SCHEMA_VALIDATION_FAILED instead of the declared CONFIG_NOT_FOUND status, unlike the audio implementation above.
    wrappers/source/YamlCppWrapper.cpp:117
  • When profiles is missing or empty, this returns a zero-initialized AudioProfileCapability and the caller still marks the codec as present, so malformed YAML is reported as OK and serialized with zero limits. Since all base-profile fields are required, reject a missing BASE entry here so the public method returns SCHEMA_VALIDATION_FAILED.
    wrappers/source/YamlCppWrapper.cpp:665
  • An existing but empty YAML file produces a null node and is classified as CONFIG_NOT_FOUND here. That status is reserved for YAML::BadFile/missing configuration; an empty file is present but invalid and should return SCHEMA_VALIDATION_FAILED, otherwise ServerManager treats a malformed deployment as an expected platform without configuration.
    wrappers/source/YamlCppWrapper.cpp:703
  • An existing but empty video YAML file produces a null node and is classified as CONFIG_NOT_FOUND here. That status is reserved for YAML::BadFile/missing configuration; an empty file is present but invalid and should return SCHEMA_VALIDATION_FAILED, otherwise ServerManager treats a malformed deployment as an expected platform without configuration.
    wrappers/source/YamlCppWrapper.cpp:684
  • A non-empty document without an audiodecoder mapping (for example {} or {other: value}) falls through this conditional and returns OK with an empty capability object. That is a schema error, not a valid empty capability result; validate the required root and capability-node types and return SCHEMA_VALIDATION_FAILED when they are absent or malformed.
    wrappers/source/YamlCppWrapper.cpp:722
  • A non-empty document without a videodecoder mapping (for example {} or {other: value}) falls through this conditional and returns OK with an empty capability object. That is a schema error, not a valid empty capability result; validate the required root and capability-node types and return SCHEMA_VALIDATION_FAILED when they are absent or malformed.
    wrappers/source/YamlCppWrapper.cpp:114
  • This helper returns immediately after the first profile entry, so malformed single-profile data such as [{BASE: {...}}, {OTHER: {...}}] (or a map containing multiple keys) is silently accepted and the extra entries are discarded. The schema requires a single BASE profile; validate the sequence/map cardinality before returning so malformed files produce SCHEMA_VALIDATION_FAILED.
    wrappers/source/YamlCppWrapper.cpp:151
  • The HFP v1 schema names the AAC keys HE_AAC_V1 and HE_AAC_V2, but this converter only recognizes HE_V1 and HE_V2. A valid schema-compliant YAML file will therefore silently drop those profiles from the map; align the accepted names and the common enum/protobuf contract with the schema.
    wrappers/source/YamlCppWrapper.cpp:139
  • Named-profile codecs have the same validation hole: a missing/non-sequence profiles node returns an empty map, and unknown profile keys are silently skipped. The codec is still marked present and parsing returns OK, so malformed YAML can be reported as a valid capability; reject these cases as schema validation failures.
  • Files reviewed: 149/153 changed files
  • Comments generated: 8
  • Review effort level: Lite

Comment thread media/server/main/CMakeLists.txt
Comment thread media/server/main/source/MediaCapabilitiesServerInternal.cpp Outdated
Comment thread media/server/service/source/MediaPipelineService.cpp Outdated
Comment thread media/server/service/source/PlaybackService.cpp Outdated
Comment thread proto/CMakeLists.txt
Comment on lines +112 to +118
message Mpeg2Profile { optional Mpeg2ProfileType type = 1; optional Mpeg2Level max_level = 2; optional uint64 max_bitrate_in_bps = 3; }
message H264Profile { optional H264ProfileType type = 1; optional H264Level max_level = 2; optional uint64 max_bitrate_in_bps = 3; }
message H265Profile { optional H265ProfileType type = 1; optional H265Level max_level = 2; optional uint64 max_bitrate_in_bps = 3; }
message Vp9Profile { optional Vp9ProfileType type = 1; optional Vp9Level max_level = 2; optional uint64 max_bitrate_in_bps = 3; }
message Av1Profile { optional Av1ProfileType type = 1; optional Av1Level max_level = 2; optional uint64 max_bitrate_in_bps = 3; }

message Mpeg2CodecCapability { repeated Mpeg2Profile profiles = 1; repeated DynamicRange dynamic_ranges = 2; }
Comment thread tests/componenttests/client/tests/base/ClientComponentTest.cpp Outdated
*/
struct AudioProfileCapability
{
uint64_t maxBitrateInBps; /**< Maximum bitrate in bits per second */
@github-actions

Copy link
Copy Markdown

Coverage statistics of your commit:
WARNING: Lines coverage decreased from: 85.0% to 84.3%
WARNING: Functions coverage decreased from: 93.4% to 92.7%

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Unresolved schema, YAML validation, build/linkage, fallback, and capability-discovery issues block safe approval.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (27)

Previously missed (2) — in code that hasn't changed since the last review.

wrappers/source/YamlCppWrapper.cpp:130

  • The named-profile parser silently accepts a codec with no profiles node by returning an empty map, which is then wrapped in an optional and reported as OK. A malformed AAC/DTS/etc. entry therefore bypasses schema validation; reject a missing or non-sequence profiles node instead of treating it as an empty capability.
    media/public/include/IMediaCapabilities.h:63
  • This public API documentation says preloaded HFP YAML is returned directly, but the server implementation copies it and appends missing GStreamer codecs before returning. Please describe the enhancement behavior so consumers do not rely on YAML being an unmodified result.

common/public/include/AudioDecoderCapabilities.h:148

  • The HFP schema v1 contract requires all four audio profile limits to be uint32_t, but this new member—and the corresponding protobuf field—is uint64. That changes the public/IPC contract and does not match the schema; use uint32_t consistently or explicitly document and validate an intentional widening.
    uint64_t maxBitrateInBps;   /**< Maximum bitrate in bits per second */

media/server/gstplayer/source/GstCapabilities.cpp:403

  • Unknown audio MIME types are logged but still appended as empty AudioDecoderCapability entries. The supported-cap scan includes sink caps such as audio/x-raw and audio/b-wav, so the GStreamer fallback can return decoder entries with no codec fields. Skip unsupported MIME types (or populate a real codec) instead of pushing audioCap in this case.
            {
                RIALTO_SERVER_LOG_WARN("Unknown audio MIME type '%s'", mimeType.c_str());
            }

            audioCapabilities.push_back(std::move(audioCap));

media/server/gstplayer/source/GstCapabilities.cpp:456

  • The video unknown-MIME branch claims to use H.264 as a fallback, but it never populates videoCap before pushing it. Sink/parser caps such as video/mpeg can therefore produce empty video capability entries; either initialize the advertised H.264 fallback or skip the unsupported MIME type.
            else
            {
                RIALTO_SERVER_LOG_WARN("Unknown video MIME type '%s', using H.264 as fallback", mimeType.c_str());
            }

            videoCapabilities.push_back(std::move(videoCap));

media/server/gstplayer/source/GstCapabilities.cpp:376

  • The supported MIME set used by this class includes audio/mpeg, mpegversion=(int)4 and audio/mpeg, mpegversion=(int)1, layer=(int)3, but these branches only recognize audio/aac and audio/mp3. Those common GStreamer MIME forms fall into the unknown branch and become empty capability entries, so AAC/MP3 fallback support is lost; classify audio/mpeg by its version/layer before the unknown case.
            else if (mimeType.find("audio/aac") != std::string::npos)
            {
                // AAC codec with default profile capability
                audioCap.aac = firebolt::rialto::common::AacCapability{};
                audioCap.aac->profiles[firebolt::rialto::common::AacProfile::LC] =
                    firebolt::rialto::common::AudioProfileCapability{0, 2, 48000, 16};
            }
            else if (mimeType.find("audio/mp3") != std::string::npos)
            {
                // MP3 codec with default profile capability
                audioCap.mp3 = firebolt::rialto::common::Mp3Capability{
                    firebolt::rialto::common::AudioProfileCapability{0, 2, 48000, 16}};

media/server/main/source/MediaCapabilitiesServerInternal.cpp:107

  • When preloaded YAML is present, Path A still waits for GStreamer and merges its discovered codecs into the YAML result. This means a curated YAML file is not returned as configured, and the request can block on GStreamer initialization; the documented preloaded path should return the cached data directly and use GStreamer only when no preload is available.
    media/server/main/source/MediaCapabilitiesServerInternal.cpp:135
  • The video preloaded path has the same issue as audio: it queries and merges GStreamer results even when YAML data is available. This exposes codecs/profiles that are absent from the configured YAML and defeats the intended no-GStreamer Path A; return the preloaded value directly here.
    media/server/main/source/MediaCapabilitiesServerInternal.cpp:48
  • This creates a second GstCapabilities instance for every session server; MediaPipelineService already creates one through MediaPipelineCapabilities (media/server/main/source/MediaPipelineCapabilities.cpp:68-76). With YAML preloaded, this still launches the full GStreamer discovery thread even though Path A should not query GStreamer, adding startup work and resource usage per server. Reuse the existing capability provider or defer this fallback object until a no-preload query is needed.
    media/server/service/source/MediaPipelineService.cpp:42
  • The existing m_mediaPipelineCapabilities construction already creates a GstCapabilities and starts its discovery thread; the new m_mediaCapabilities construction creates a second one. Every server now duplicates GStreamer element queries and initialization work. Reuse one capability provider or combine the two interfaces around a shared instance.
    serverManager/common/source/SessionServerAppManager.cpp:49
  • The statuses returned by the YAML wrapper are discarded whenever they are not OK, so missing and invalid configurations are silently indistinguishable. The required behavior calls for INFO on CONFIG_NOT_FOUND and WARN on schema/internal failures; log the result before leaving the optionals unset.
    tests/componenttests/client/tests/base/MediaCapabilitiesTestMethods.cpp:106
  • This test is labelled as the IPC failure case, but the mock never calls SetFailed; it returns a successful RPC with an empty response. The MediaCapabilitiesIpc error branch that checks ipcController->Failed() is therefore untested, so set the controller failure in this lambda (and apply the same correction to the video failure test).
    tests/componenttests/client/tests/base/MediaCapabilitiesTestMethods.cpp:123
  • As with the audio case, this video failure test returns an empty successful response and never sets the RPC controller to failed. It does not cover the actual failure handling in MediaCapabilitiesIpc; make the mock call SetFailed() before running the closure.
    tests/componenttests/server/tests/mediaCapabilities/MediaCapabilitiesAppendCodecsIntegrationTest.cpp:89
  • This integration test (and the other tests in this file) calls the legacy GetSupportedMimeTypes RPC, so it never exercises MediaCapabilitiesServerInternal::getSupportedAudioCapabilities() or the YAML/GStreamer codec-append logic described by the test. It can pass even if the new capability path is completely broken; issue GetSupportedAudioCapabilitiesRequest/AudioCapabilities responses here and in the other append tests.
    tests/componenttests/server/tests/mediaCapabilities/MediaCapabilitiesAppendCodecsIntegrationTest.cpp:84
  • configureSutInActiveState() sends createGenericSetConfigurationReq(), which contains neither capability field; moreover the ComponentTests build does not compile the real YAML wrapper. Consequently these tests never install preloaded YAML capabilities, so even after switching to the new RPC they would only exercise GStreamer fallback, not the advertised append integration.
    tests/componenttests/server/tests/mediaCapabilities/MediaCapabilitiesOrchestrationTest.cpp:105
  • These orchestration tests query GetSupportedMimeTypes, the legacy media-pipeline RPC, rather than GetSupportedAudioCapabilities/GetSupportedVideoCapabilities. They therefore do not exercise the new MediaCapabilities IPC service or verify typed capability fallback/caching, despite the test names and expectations describing that behavior.
    tests/unittests/serverManager/unittests/service/ServerManagerServiceTests.cpp:111
  • This test only verifies that Google Mock can invoke a mock method and return OK; it never exercises YamlCppWrapper, parses a YAML document, or checks any capability fields. As a result, the newly added YAML parser has no unit coverage for its profile, codec, or schema-validation behavior (the same applies to the video test below).
    wrappers/CMakeLists.txt:129
  • yaml-cpp is linked unconditionally, but find_package(yaml-cpp REQUIRED) and YamlCppWrapper.cpp are enabled only for non-UnitTests/ComponentTests builds. Test configurations therefore still require a -lyaml-cpp library even though they do not compile any YAML implementation (and the test dependency is not guaranteed by this CMake file), causing otherwise valid wrapper/test builds to fail when yaml-cpp is absent. Keep this dependency inside the same WRAPPERS_ENABLED conditional, e.g. add it to WRAPPER_LIBS there instead of linking it here.
    wrappers/source/YamlCppWrapper.cpp:726
  • Unlike the audio loader, this catch-all also catches YAML::BadFile, so a missing or unreadable video YAML file is reported as SCHEMA_VALIDATION_FAILED rather than CONFIG_NOT_FOUND. Handle YAML::BadFile before the generic exception, matching getAudioDecoderCapabilities().
    wrappers/source/YamlCppWrapper.cpp:692
  • The new file-backed YAML parser has no dedicated unit tests in tests/unittests/wrappers (that target currently contains only mocks). The audio/video schema mapping and status handling are central to this PR, so malformed files, missing fields, and representative codec/profile mappings should be exercised directly rather than only through the wrapper mock.
    wrappers/source/YamlCppWrapper.cpp:117
  • When profiles is missing, not a sequence, or empty, this helper returns a default-constructed capability. The caller then wraps that zero/default value in an optional and returns OK, so malformed base-codec YAML is advertised as a valid capability instead of producing SCHEMA_VALIDATION_FAILED. Reject the missing/invalid profile node rather than returning {}.
    wrappers/source/YamlCppWrapper.cpp:667
  • A syntactically valid YAML document without the required audiodecoder/Capabilities nodes falls through to OK with an empty result. That causes the ServerManager to cache and transmit an unusable empty capability set instead of reporting schema failure and using the documented fallback; validate the required root and capability nodes before returning OK.
    wrappers/source/YamlCppWrapper.cpp:138
  • Unknown profile names are silently skipped here, so a misspelled or unsupported profile produces an empty codec capability while the surrounding parser still returns OK. This turns malformed YAML into an apparently valid configuration; reject an unrecognized profile (and similarly invalid profile entries) so the caller receives SCHEMA_VALIDATION_FAILED.
    wrappers/source/YamlCppWrapper.cpp:346
  • The video parser drops unknown dynamic-range names and returns OK, leaving the advertised codec with incomplete ranges instead of rejecting the invalid schema. Treat an unrecognized value (and a non-sequence node) as a schema error, consistent with the required-field validation used for audio profiles.
    wrappers/source/YamlCppWrapper.cpp:661
  • The output object is appended to without being reset. Reusing the same capabilities object for a second successful call duplicates every YAML rank (and stale version fields can survive failures), so this getter is not idempotent. Clear the output before loading/parsing.
    wrappers/source/YamlCppWrapper.cpp:699
  • The video getter also appends to the caller-provided vector without clearing it, so repeated reads of the same wrapper duplicate capabilities and can retain stale metadata. Reset the output object before loading the file, as required for a getter that fills an output reference.
    wrappers/source/YamlCppWrapper.cpp:704
  • An existing file without the required videodecoder node (or its Capabilities node) falls through to OK with an empty result. That treats a malformed document as a valid configuration; validate the required top-level structure and return SCHEMA_VALIDATION_FAILED instead.
  • Files reviewed: 149/153 changed files
  • Comments generated: 1
  • Review effort level: Lite

include/IClientLogHandler.h
include/IControl.h
include/IControlClient.h
include/IMediaCapabilities.h
@github-actions

Copy link
Copy Markdown

Coverage statistics of your commit:
WARNING: Lines coverage decreased from: 85.0% to 84.3%
WARNING: Functions coverage decreased from: 93.4% to 92.7%

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Multiple moderate issues remain in schema validation, capability precedence/serialization, fallback construction, build dependencies, and test coverage.

Review details

Suppressed comments (27)

Previously missed (2) — in code that hasn't changed since the last review.

media/server/main/source/MediaCapabilitiesServerInternal.cpp:138

  • The video Path 0 has the same authority problem as the audio path: it performs GStreamer discovery and merges the result into the configured YAML capabilities. This violates the documented preloaded-capabilities precedence and can return capabilities not present in YAML; return the cached video value directly when it exists.
    wrappers/source/YamlCppWrapper.cpp:429
  • If maxLevel is present but has an unrecognized value, this builder leaves the enum at its zero value and still appends the profile. The other video builders have the same behavior, so a bad level is silently converted to a different valid level; reject unknown level strings as schema errors.

common/public/include/AudioDecoderCapabilities.h:151

  • The HFP v1 task requires all four AudioProfileCapability fields to be uint32_t (openspec/changes/hfp-schema-v1-migration/tasks.md:9), but bitrate is declared as uint64_t here and the new protobuf/parser also use uint64. This widens the public API beyond the required contract; update the common type and all serialization/parsing sites together.
    uint64_t maxBitrateInBps;   /**< Maximum bitrate in bits per second */
    uint32_t maxChannels;       /**< Maximum number of channels */
    uint32_t maxSampleRateInHz; /**< Maximum sample rate in Hz */
    uint32_t maxBitDepth;       /**< Maximum bit depth */

media/server/gstplayer/source/GstCapabilities.cpp:403

  • Unknown audio MIME types are still appended as empty decoder capabilities after only logging a warning. The existing caps mapping produces values such as audio/mp4, audio/b-wav, and audio/x-raw, which reach this branch; the resulting empty ranks are then serialized and can be mistaken for supported codecs. Skip unknown types instead of pushing audioCap.
            {
                RIALTO_SERVER_LOG_WARN("Unknown audio MIME type '%s'", mimeType.c_str());
            }

            audioCapabilities.push_back(std::move(audioCap));

media/server/gstplayer/source/GstCapabilities.cpp:456

  • The unknown-video branch logs that it is using an H.264 fallback, but it never populates videoCap.codecCapabilities.h264; the next line pushes an empty capability instead. For mapped types such as video/mp4, this produces an empty serialized rank. Either populate the documented fallback or skip the unknown MIME type.
            videoCapabilities.push_back(std::move(videoCap));

media/server/gstplayer/source/GstCapabilities.cpp:349

  • This loop creates one decoder rank for every MIME type. AudioDecoderCapability represents a rank containing multiple codec optionals, and appendMissingAudioCodecsToYaml merges GStreamer and YAML by rank index; with AAC, MP3, and E-AC3 MIME types, the codecs are split across unrelated ranks (in arbitrary unordered_set order) instead of being combined. Build a single GStreamer rank containing all discovered codecs before appending.
    for (const auto &mimeType : m_supportedMimeTypes)
    {
        if (mimeType.find("audio/") == 0)
        {
            // Create audio capability with codec-specific fields based on MIME type

media/server/gstplayer/source/GstCapabilities.cpp:409

  • The video path repeats the per-MIME-to-rank split. appendMissingVideoCodecsToYaml pairs ranks by index, so multiple discovered codecs are distributed into separate ranks and may be merged with the wrong YAML rank; accumulate the discovered video codec optionals into a rank before appending.
        else if (mimeType.find("video/") == 0)
        {
            // Create video capability with codec-specific data based on MIME type
            // Initialize with empty codec capabilities - will be populated based on MIME type
            firebolt::rialto::common::VideoDecoderCapability videoCap;

media/server/main/source/MediaCapabilitiesServerInternal.cpp:107

  • When preloaded audio capabilities are present, this path still queries GStreamer and appends discovered codecs. The preloaded YAML is intended to be authoritative for Path 0, so this can expose codecs that the configuration deliberately omits; return the cached capabilities directly and reserve GStreamer for the no-preload path.
    media/server/main/source/MediaCapabilitiesServerInternal.cpp:44
  • Creating this fallback eagerly starts GstCapabilities' initialization thread, whose constructor performs GStreamer MIME/capability discovery before setPreloadedCapabilities() is called. Therefore even a fully configured Path 0 still incurs the GStreamer query that the design says to skip; make the fallback lazy or provide preload state before constructing it.
    serverManager/common/source/SessionServerAppManager.cpp:49
  • The new cache path is not exercised by the updated ServerManager tests: their SessionServerAppManager fixtures pass a null YAML wrapper, while the added mock tests invoke the mock directly. Add a test with a wrapper returning OK and assert that the resulting audio/video optionals are forwarded to performSetConfiguration().
    serverManager/ipc/source/Client.cpp:255
  • The two capability optionals are serialized independently here, so a configuration with only one YAML file sends a partial SetConfigurationRequest. The ServerManager capability contract requires both typed fields to be absent when either optional is missing (openspec/changes/servermanager-media-capabilities/proposal.md:193-197); otherwise audio and video can silently use different sources. Gate both serializations on audioCaps.has_value() && videoCaps.has_value() and log the else case.
    serverManager/ipc/source/Client.cpp:307
  • This overload also serializes whichever optional happens to be present, producing a partial capability payload. The documented contract says that if either audio or video is unavailable, neither field should be sent (openspec/changes/servermanager-media-capabilities/proposal.md:193-197); use one has_value() conjunction for both fields, consistently with the socket-name overload.
    tests/unittests/media/client/main/mediaCapabilities/MediaCapabilitiesTest.cpp:65
  • This new client IPC test file is not listed in tests/unittests/media/client/main/CMakeLists.txt; that target only includes MediaCapabilitiesTests.cpp. As a result, these tests are never compiled or run, so add this source to the client-main unit-test target.
    wrappers/CMakeLists.txt:129
  • yaml-cpp is linked unconditionally, but both find_package(yaml-cpp REQUIRED) and YamlCppWrapper.cpp are excluded for UnitTests/ComponentTests. Those builds now link RialtoWrappers, so environments without yaml-cpp fail at link time even though the YAML implementation is not compiled. Keep this dependency inside the same non-test conditional as the package/source.
    wrappers/source/YamlCppWrapper.cpp:727
  • YAML::BadFile derives from std::exception, so a missing video configuration is caught here and reported as SCHEMA_VALIDATION_FAILED instead of CONFIG_NOT_FOUND (the audio method already distinguishes this case). Add a BadFile catch before the generic exception handler.
    wrappers/source/YamlCppWrapper.cpp:692
  • The generic exception handler maps every non-BadFile failure to SCHEMA_VALIDATION_FAILED, and the video handler does the same, leaving the public INTERNAL_ERROR status unreachable. Distinguish schema/conversion failures from unexpected internal failures so callers can apply the documented status contract.
    wrappers/source/YamlCppWrapper.cpp:138
  • Unknown named profiles are silently discarded, so a misspelled profile produces an incomplete capability object while the wrapper still returns OK. This defeats strict schema validation and can advertise a codec without the requested profile; reject the unknown key instead.
    wrappers/source/YamlCppWrapper.cpp:346
  • An unknown dynamic-range value is silently dropped and the wrapper still returns OK. A typo such as a misspelled HDR value therefore changes the advertised capability without any validation error; reject unknown enum values as a schema failure.
    wrappers/source/YamlCppWrapper.cpp:661
  • The new parser and status behavior has no real-wrapper unit coverage: the added YAML tests call YamlCppWrapperMock directly, so they pass even if YAML loading, profile validation, or CONFIG_NOT_FOUND handling is broken. Add tests that exercise YamlCppWrapper with representative valid and invalid audio/video documents (or inject the file source) and cover the status cases.
    wrappers/source/YamlCppWrapper.cpp:322
  • An unrecognized audio codec key is silently ignored, so malformed YAML still produces an OK status with a missing codec. Since this parser is intended to enforce the HFP schema, reject unknown codec keys rather than returning an incomplete capability object.
    wrappers/source/YamlCppWrapper.cpp:641
  • Unknown video codec keys are also ignored and the wrapper returns OK. A typo in a codec name therefore silently removes that codec from the advertised capabilities instead of reporting schema validation failure; add an explicit unknown-key error.
    wrappers/source/YamlCppWrapper.cpp:408
  • The video profile builders use this pattern for every codec: unknown profile names are skipped. This lets invalid profile keys return OK with incomplete capability data, contrary to strict schema validation; reject unknown profile names instead of continuing.
    wrappers/source/YamlCppWrapper.cpp:117
  • A single-profile codec with no profiles sequence, an empty sequence, or an empty entry falls through to a zero-initialized capability and the wrapper returns OK. The HFP schema requires a BASE profile for these codecs, so missing BASE data must raise a schema-validation error rather than advertise all-zero limits.
    wrappers/source/YamlCppWrapper.cpp:684
  • If the YAML file exists but lacks the required audiodecoder root, execution reaches this OK return with an empty capability set; the video method has the same behavior. A malformed document then becomes a present-but-empty preloaded capability and suppresses the GStreamer fallback, so missing required roots must be reported as schema validation failure.
    wrappers/source/YamlCppWrapper.cpp:722
  • A present video YAML document without the videodecoder root also returns OK with empty capabilities, which is then treated as authoritative preloaded data. Validate the required root before returning success, as with the corresponding audio path.
    wrappers/source/YamlCppWrapper.cpp:660
  • This method appends parsed ranks to the caller-provided vector without clearing it first. Reusing an AudioDecoderCapabilities object for a second successful call duplicates every rank, unlike a fill-style output parameter; reset the output object (or at least its fields) before loading.
    wrappers/source/YamlCppWrapper.cpp:698
  • The video parser has the same accumulation problem: every successful call pushes onto the existing capabilities.capabilities vector. A caller that reuses the output object receives duplicate decoder ranks, so reset capabilities at the start of this method as well.
  • Files reviewed: 149/153 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

DouglasAdler
DouglasAdler previously approved these changes Sep 18, 2026
@github-actions

Copy link
Copy Markdown

media/server/service/source/MediaPipelineService.cpp:34:23: warning: Member variable 'MediaPipelineService::m_metricsService' is not initialized in the constructor. [uninitMemberVar]
MediaPipelineService::MediaPipelineService(
^
nofile:0:0: information: Active checkers: 161/592 (use --checkers-report= to see details) [checkersReport]

1 similar comment
@github-actions

Copy link
Copy Markdown

media/server/service/source/MediaPipelineService.cpp:34:23: warning: Member variable 'MediaPipelineService::m_metricsService' is not initialized in the constructor. [uninitMemberVar]
MediaPipelineService::MediaPipelineService(
^
nofile:0:0: information: Active checkers: 161/592 (use --checkers-report= to see details) [checkersReport]

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Unresolved compile/link, dependency, configuration-status, and test-coverage issues block approval.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 6 High severity · 9 Medium severity · 3 Low severity

Open (18)

Comment thread media/server/service/source/MediaPipelineService.h

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

One or more issues must be addressed before approval.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 8 High severity · 9 Medium severity · 3 Low severity

Open (20)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Reuse GstCapabilities discovery instead of duplicating initialization

media/​server/​service/​source/​MediaPipelineService.cpp:42

m_mediaPipelineCapabilities has already constructed a GstCapabilities immediately above, while this factory constructs a second one for the new orchestrator. Each instance starts its own initialization and performs the full registry/caps scan, so every session now duplicates expensive GStreamer discovery. Reuse the existing discovery/orchestrator or otherwise share one GstCapabilities instance.

Low severity Exercise MediaCapabilities IPC in the component test

tests/​componenttests/​server/​tests/​CMakeLists.txt:70

The newly registered component test does not exercise the new MediaCapabilities IPC at all: its requests are all GetSupportedMimeTypes, which belongs to the legacy pipeline-capabilities module. Replace these actions/builders with the audio/video MediaCapabilities RPCs so this test actually validates the feature it is named for.

Comment thread media/server/service/source/PlaybackService.cpp
Comment on lines +138 to +139
::firebolt::rialto::GetSupportedAudioCapabilitiesRequest createGetSupportedAudioCapabilitiesRequest();
::firebolt::rialto::GetSupportedVideoCapabilitiesRequest createGetSupportedVideoCapabilitiesRequest();

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

One or more issues must be addressed before approval.

Review effort: Lite
Findings: 6 High severity · 9 Medium severity · 3 Low severity

Open (18)
Resolved since last review (2)
Previously missed (1)

In code that hasn't changed since last review

Low severity Test MediaCapabilities fallback with the correct service

tests/​componenttests/​server/​tests/​mediaCapabilities/​MediaCapabilitiesOrchestrationTest.cpp:92

This test is described as validating the new MediaCapabilities fallback, but it sends GetSupportedMimeTypes requests through the legacy MediaPipelineCapabilities service. It therefore never exercises MediaCapabilitiesModuleService, the typed capability converters, or the new fallback result; use the new audio/video capability requests and assert their typed responses.

@github-actions

Copy link
Copy Markdown

Coverage statistics of your commit:
WARNING: Lines coverage decreased from: 85.0% to 84.6%
WARNING: Functions coverage decreased from: 93.4% to 92.8%

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

One or more issues must be addressed before approval.

Review effort: Lite
Findings: 9 High severity · 10 Medium severity · 4 Low severity

Open (23)

And 3 more that still need to be addressed.

Comment on lines +23 to +24
#include "AudioDecoderCapabilities.h"
#include "VideoDecoderCapabilities.h"
RialtoServerIpc
RialtoServerMain
RialtoServerService
RialtoServerManagerCommon
$<TARGET_PROPERTY:RialtoPlayerPublic,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:RialtoCommon,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:RialtoServerGstPlayer,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:RialtoServerManagerCommon,INTERFACE_INCLUDE_DIRECTORIES>
Comment on lines +46 to +50
if (yamlCppWrapper->getAudioDecoderCapabilities(audioCaps) ==
firebolt::rialto::common::DecoderCapabilitiesStatus::OK)
{
m_cachedAudioCapabilities = audioCaps;
}
Comment on lines +91 to +95
auto audioRequest{createGetSupportedMimeTypesRequest(ProtoMediaSourceType::AUDIO)};
ConfigureAction<GetSupportedMimeTypes>{m_clientStub}
.send(audioRequest)
.expectSuccess()
.matchResponse(
@github-actions

Copy link
Copy Markdown

Coverage statistics of your commit:
Congratulations, your commit improved lines coverage from: 84.4% to 84.5%
Congratulations, your commit improved functions coverage from: 92.7% to 92.8%

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants