Feature/hdmi switch8.4 test#508
Conversation
Summary: Change Wayland Display for TextTrack Type: Fix Test Plan: UT/ CT, Fullstack Jira: ENTDAI-2218
Summary: Removed gstreamer interaction during RemoveSource Type: Fix Test Plan: UT/CT, Fullstack Jira: LLAMA-18057 --------- Co-authored-by: Marcin Wojciechowski <marcin.wojciechowski@sky.uk>
Summary: Allow to switch audio codec, when audio is re-attached Type: Fix Test Plan: UT/CT, Fullstack Jira: LLAMA-18057
Summary: Asure correct data & flush order during multiple flushes Type: Fix Test Plan: UT/CT, Fullstack Jira: NO-JIRA
Summary: Removed blocking get_state calls from aml codec switch Type: Fix Test Plan: UT/CT, Fullstack Jira: RDKEMW-13606, DELIA-70194 Co-authored-by: Adam Czynszak <92790185+aczs@users.noreply.github.com>
#484) Summary: Fixed initialisation of playbackGroup elements in GenericPlayerContext. Added linking of typefind and the parser after the audio switch Type: Feature Test Plan: UT/CT, Fullstack Jira: RDKEMW-16807
Summary: Do not treat server as deadlocked when outdated acks are received Type: Fix Test Plan: UT/CT, Fullstack Jira: RDKEMW-18258
There was a problem hiding this comment.
Pull request overview
This PR updates Rialto’s media pipeline and DRM/decryption flow to better handle HDMI/HDCP output restriction scenarios and to support reporting whether play() is synchronous vs asynchronous across the IPC boundary. It also refactors flush-on-preroll handling (moving state tracking to the dispatcher thread), adds audio typefind/parser relinking support, and updates a large set of unit/component tests accordingly.
Changes:
- Add OUTPUT_RESTRICTED retry handling in the decryption path (OpenCDM wrapper + MediaKeys retry loop).
- Extend
play()API end-to-end to return anasyncflag (public API, IPC proto/service/client, mocks, tests). - Refactor flush-on-preroll flow (new controller interface/impl, dispatcher-thread integration), plus related generic-player task/test updates.
Reviewed changes
Copilot reviewed 118 out of 118 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| wrappers/source/OcdmSession.cpp | Adds optional _decrypt_buffer_once path with pre/post key-status checks and debug logging. |
| wrappers/interface/IGstWrapper.h | Adds wrapper APIs for element state queries and pad/bin operations. |
| wrappers/include/OcdmSession.h | Declares new OpenCDM decrypt function pointer typedef/static. |
| wrappers/include/GstWrapper.h | Implements newly added IGstWrapper methods. |
| wrappers/CMakeLists.txt | Adds common/logging include directories to wrappers target. |
| serverManager/common/source/HealthcheckService.h | Changes failed-ping tracking from counter to per-pingId set. |
| serverManager/common/source/HealthcheckService.cpp | Handles “late ack” by removing specific pingId from failure set. |
| tests/unittests/serverManager/unittests/common/HealthcheckServiceTests.cpp | Adds coverage for “late ack” behavior. |
| proto/mediapipelinemodule.proto | Adds async field to PlayResponse and updates docstring. |
| media/public/include/MediaCommon.h | Adds MediaKeyErrorStatus::OUTPUT_RESTRICTED. |
| media/public/include/IMediaPipeline.h | Changes play() signature to play(bool &async). |
| media/server/service/include/IMediaPipelineService.h | Updates play() signature to include async out param. |
| media/server/service/source/MediaPipelineService.h | Updates service interface implementation signature. |
| media/server/service/source/MediaPipelineService.cpp | Propagates async out param down to pipeline implementation. |
| media/server/ipc/source/MediaPipelineModuleService.cpp | Sets PlayResponse.async based on server-side result. |
| media/client/ipc/interface/IMediaPipelineIpc.h | Updates IPC interface play() to include async out param. |
| media/client/ipc/include/MediaPipelineIpc.h | Updates IPC class interface accordingly. |
| media/client/ipc/source/MediaPipelineIpc.cpp | Reads PlayResponse.async into caller-provided out param. |
| media/client/main/include/MediaPipeline.h | Updates client MediaPipeline::play() signature. |
| media/client/main/source/MediaPipeline.cpp | Forwards async from client API to IPC. |
| media/client/main/include/MediaPipelineProxy.h | Updates proxy play() signature. |
| media/server/main/include/MediaPipelineServerInternal.h | Updates server internal play() signature and docs. |
| media/server/main/source/MediaPipelineServerInternal.cpp | Makes play() priority enqueue + removes gst-player call from removeSource. |
| media/server/main/source/MediaKeysServerInternal.cpp | Adds OUTPUT_RESTRICTED retry loop with 1s sleep, 4s total timeout + debug logs. |
| media/server/main/source/MediaKeysCapabilities.cpp | Adds OUTPUT_RESTRICTED to status-to-string mapping. |
| media/server/ipc/source/MediaKeysModuleService.cpp | Adds OUTPUT_RESTRICTED conversion case (currently TODO). |
| media/server/gstplayer/include/IFlushOnPrerollController.h | Replaces “postpone flush” API with wait/target-state based API. |
| media/server/gstplayer/include/FlushOnPrerollController.h | Adds condition-variable based controller state. |
| media/server/gstplayer/source/FlushOnPrerollController.cpp | Implements wait/setFlushing/prerolling/target-state transitions + logging. |
| media/server/gstplayer/include/IGstDispatcherThread.h | Passes flush controller into dispatcher thread factory. |
| media/server/gstplayer/include/GstDispatcherThread.h | Stores flush controller and updates constructor. |
| media/server/gstplayer/source/GstDispatcherThread.cpp | Updates factory + reports pipeline state changes to flush controller. |
| media/server/gstplayer/include/GenericPlayerContext.h | Stores flush controller as shared_ptr instead of value member. |
| media/server/gstplayer/source/tasks/generic/Flush.cpp | Removes postponing logic; waits via controller and marks async flush. |
| media/server/gstplayer/include/tasks/IGenericPlayerTaskFactory.h | Extends createFlush() signature with isAsync. |
| media/server/gstplayer/include/tasks/generic/GenericPlayerTaskFactory.h | Updates factory interface (remove RemoveSource, extend Flush). |
| media/server/gstplayer/source/tasks/generic/GenericPlayerTaskFactory.cpp | Removes RemoveSource creation; adds isAsync into Flush creation. |
| media/server/gstplayer/include/tasks/generic/Flush.h | Adds isAsync to task state. |
| media/server/gstplayer/source/tasks/generic/UpdatePlaybackGroup.cpp | Optionally links typefind to parser when requested. |
| media/server/gstplayer/source/tasks/generic/DeepElementAdded.cpp | Uses Utils type checks; tracks playsink bin and audio elements more robustly. |
| media/server/gstplayer/source/tasks/generic/NeedData.cpp | Removes “audioSourceRemoved” suppression. |
| media/server/gstplayer/source/tasks/generic/HandleBusMessage.cpp | Removes flush controller state updates (moved to dispatcher thread). |
| media/server/gstplayer/source/tasks/generic/CheckAudioUnderflow.cpp | Underflow no longer depends on audioSourceRemoved flag. |
| media/server/gstplayer/source/tasks/generic/AttachSource.cpp | Always reattaches audio via reattach path; removes playbin-flag toggling/needdata forcing. |
| media/server/gstplayer/source/Utils.cpp | Adds isAudioParser() helper. |
| media/server/gstplayer/include/Utils.h | Declares isAudioParser(). |
| media/server/gstplayer/include/IGstGenericPlayerPrivate.h | Changes changePipelineState() to return GstStateChangeReturn; removes postponed flush/playbin flags API. |
| media/server/gstplayer/interface/IGstGenericPlayer.h | Changes play() to play(bool &async); removes removeSource() API. |
| media/server/gstplayer/include/GstGenericPlayer.h | Implements new play/flush/state-change patterns; adds large audio codec switch helpers + ongoing state-change counter. |
| media/server/gstplayer/source/GstGenericPlayer.cpp | Adds play async reporting, flush changes, and large on-the-fly audio codec switching logic. |
| media/server/gstplayer/source/GstWebAudioPlayer.cpp | Updates dispatcher thread factory call signature (adds flush controller arg). |
| media/server/gstplayer/source/GstTextTrackSink.cpp | Hardcodes subtitle display name instead of using WAYLAND_DISPLAY env var. |
| media/server/gstplayer/CMakeLists.txt | Removes RemoveSource task compilation unit. |
| media/server/gstplayer/source/tasks/generic/RemoveSource.cpp | Removes RemoveSource task implementation. |
| media/server/gstplayer/include/tasks/generic/RemoveSource.h | Removes RemoveSource task header. |
| tests/common/externalLibraryMocks/GstWrapperMock.h | Adds mocks for new IGstWrapper methods. |
| tests/unittests/media/server/gstplayer/dispatcherThread/GstDispatcherThreadTest.cpp | Updates dispatcher thread tests for flush controller integration + adds new state-change tests. |
| tests/unittests/media/server/gstplayer/genericPlayer/FlushOnPrerollControllerTest.cpp | Replaces postpone-flush tests with wait-based tests (includes a typo). |
| tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/UpdatePlaybackGroupTest.cpp | Adds coverage for linking typefind with parser. |
| tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/NeedDataTest.cpp | Removes test tied to audioSourceRemoved behavior. |
| tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/FlushTest.cpp | Removes postpone-flush test. |
| tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/RemoveSourceTest.cpp | Removes RemoveSource task tests. |
| tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/GenericPlayerTaskFactoryTest.cpp | Removes RemoveSource factory test; updates Flush signature usage. |
| tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/HandleBusMessageTest.cpp | Removes expectation for executePostponedFlushes(). |
| tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/AttachSourceTest.cpp | Updates audio source reattach/switch expectations. |
| tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.h | Removes RemoveSource helpers; adds typefind/parser link helpers. |
| tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp | Updates helpers for new flush/controller behavior and type checks. |
| tests/unittests/media/server/gstplayer/genericPlayer/common/GstGenericPlayerTestCommon.cpp | Updates dispatcher thread factory call signature. |
| tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerTest.cpp | Updates play tests to validate async out param and flush factory call signature. |
| tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerPrivateTest.cpp | Adds extensive tests for codec-switch paths and updated getSink behavior. |
| tests/unittests/media/server/gstplayer/mocks/gstplayer/GstDispatcherThreadFactoryMock.h | Updates mock signature with flush controller arg. |
| tests/unittests/media/server/gstplayer/mocks/gstplayer/FlushOnPrerollControllerMock.h | Updates mock interface to new controller methods. |
| tests/unittests/media/server/gstplayer/mocks/gstplayer/GstGenericPlayerMock.h | Updates play mock signature; removes removeSource mock. |
| tests/unittests/media/server/gstplayer/mocks/gstplayer/GstGenericPlayerPrivateMock.h | Updates changePipelineState return type; removes obsolete methods. |
| tests/unittests/media/server/gstplayer/mocks/gstplayer/GenericPlayerTaskFactoryMock.h | Updates Flush signature; removes RemoveSource mock. |
| tests/unittests/media/server/gstplayer/CMakeLists.txt | Drops RemoveSource test file from build. |
| tests/unittests/media/server/main/mediaPipeline/MiscellaneousFunctionsTest.cpp | Updates play path to priority task + async out param. |
| tests/unittests/media/server/main/mediaPipeline/base/MediaPipelineTestBase.h | Adds priority enqueue helper. |
| tests/unittests/media/server/main/mediaPipeline/base/MediaPipelineTestBase.cpp | Implements priority enqueue helper for tests. |
| tests/unittests/media/server/service/mediaPipelineService/MediaPipelineServiceTestsFixture.cpp | Updates play signature in fixture and expectations. |
| tests/unittests/media/server/mocks/service/MediaPipelineServiceMock.h | Updates play mock signature. |
| tests/unittests/media/server/mocks/main/MediaPipelineServerInternalMock.h | Updates play mock signature. |
| tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTestsFixture.cpp | Updates play expectations to include async out param. |
| tests/unittests/media/server/gstplayer/webAudioPlayer/CreateTest.cpp | Updates dispatcher thread factory mock invocation signature. |
| tests/unittests/media/server/gstplayer/webAudioPlayer/common/GstWebAudioPlayerTestCommon.cpp | Updates dispatcher thread factory expectation signature. |
| tests/unittests/media/client/mocks/ipc/MediaPipelineIpcMock.h | Updates play mock signature. |
| tests/unittests/media/client/mocks/main/MediaPipelineAndControlClientMock.h | Updates play mock signature. |
| tests/unittests/media/client/main/mediaPipeline/PlayPauseTest.cpp | Updates play tests to pass async out param. |
| tests/unittests/media/client/main/mediaPipeline/MediaPipelineProxyTest.cpp | Updates play passthrough test to pass async out param. |
| tests/unittests/media/client/ipc/mediaPipelineIpc/PlayPauseTest.cpp | Updates IPC play tests to pass async out param. |
| tests/componenttests/server/common/ExpectMessage.h | Increases default message timeout from 400ms to 600ms. |
| tests/componenttests/server/fixtures/MediaPipelineTest.h | Removes willRemoveAudioSource/willSetAudioAndVideoFlags helpers. |
| tests/componenttests/server/fixtures/MediaPipelineTest.cpp | Removes audio-source removal flush+flag logic; removeSource no longer waits worker. |
| tests/componenttests/server/tests/CMakeLists.txt | Replaces RemoveAudioPlaybackTest with SwitchAudioPlaybackTest. |
| tests/componenttests/server/tests/mediaPipeline/SwitchAudioPlaybackTest.cpp | Adds (disabled) component test for switching audio source mid-playback. |
| tests/componenttests/server/tests/mediaPipeline/AudioSourceSwitchTest.cpp | Updates to fetch audio-sink element and adds amlhalasink prefix handling in expectations. |
| tests/componenttests/server/tests/mediaPipeline/*.cpp (multiple) | Removes willRemoveAudioSource expectation calls across many pipeline tests. |
| tests/componenttests/client/tests/base/MediaPipelineTestMethods.cpp | Updates play helper to pass async out param. |
| media/client/ipc/source/MediaKeysIpc.cpp | Adds OUTPUT_RESTRICTED to toString(); minor formatting changes. |
| wrappers/include/GstWrapper.h / wrappers/interface/IGstWrapper.h | Adds low-level GStreamer accessors needed by new codec-switch code. |
Comments suppressed due to low confidence (1)
media/server/gstplayer/source/GstGenericPlayer.cpp:879
- Similar to firstTimeSwitchFromAC3toAAC(), gstPadGetPeer()/gstPadUnlink() are called with pad pointers that may be NULL (e.g., audioDecSrcPad/audioDecSinkPad/audioParseSrcPad/audioParseSinkPad). Please add null checks before calling these wrappers and before unref’ing pads/peers to avoid crashes when elements don’t expose the expected static pads.
// Get AudioDecoder Src Pads
if ((audioDecSrcPad = m_gstWrapper->gstElementGetStaticPad(m_context.playbackGroup.m_curAudioDecoder, "src")) !=
NULL) // Unref the Pad
RIALTO_SERVER_LOG_DEBUG("OTF -> Current AudioDecoder Src Pad = %p", audioDecSrcPad);
// Get AudioDecoder Sink Pads
if ((audioDecSinkPad = m_gstWrapper->gstElementGetStaticPad(m_context.playbackGroup.m_curAudioDecoder, "sink")) !=
NULL) // Unref the Pad
RIALTO_SERVER_LOG_DEBUG("OTF -> Current AudioDecoder Sink Pad = %p", audioDecSinkPad);
// Get AudioDecoder Src Peer i.e. Downstream Element Pad
if ((audioDecSrcPeerPad = m_gstWrapper->gstPadGetPeer(audioDecSrcPad)) != NULL) // Unref the Pad
RIALTO_SERVER_LOG_DEBUG("OTF -> Current AudioDecoder Src Downstream Element Pad = %p", audioDecSrcPeerPad);
// Get AudioDecoder Sink Peer i.e. Upstream Element Pad
if ((audioDecSinkPeerPad = m_gstWrapper->gstPadGetPeer(audioDecSinkPad)) != NULL) // Unref the Pad
RIALTO_SERVER_LOG_DEBUG("OTF -> Current AudioDecoder Sink Upstream Element Pad = %p", audioDecSinkPeerPad);
// Get AudioParser Src Pads
if ((audioParseSrcPad = m_gstWrapper->gstElementGetStaticPad(m_context.playbackGroup.m_curAudioParse, "src")) !=
NULL) // Unref the Pad
RIALTO_SERVER_LOG_DEBUG("OTF -> Current AudioParser Src Pad = %p", audioParseSrcPad);
// Get AudioParser Sink Pads
if ((audioParseSinkPad = m_gstWrapper->gstElementGetStaticPad(m_context.playbackGroup.m_curAudioParse, "sink")) !=
NULL) // Unref the Pad
RIALTO_SERVER_LOG_DEBUG("OTF -> Current AudioParser Sink Pad = %p", audioParseSinkPad);
// Get AudioParser Src Peer i.e. Downstream Element Pad
if ((audioParseSrcPeerPad = m_gstWrapper->gstPadGetPeer(audioParseSrcPad)) != NULL) // Unref the Peer Pad
RIALTO_SERVER_LOG_DEBUG("OTF -> Current AudioParser Src Downstream Element Pad = %p", audioParseSrcPeerPad);
// Get AudioParser Sink Peer i.e. Upstream Element Pad
if ((audioParseSinkPeerPad = m_gstWrapper->gstPadGetPeer(audioParseSinkPad)) != NULL) // Unref the Peer Pad
RIALTO_SERVER_LOG_DEBUG("OTF -> Current AudioParser Sink Upstream Element Pad = %p", audioParseSinkPeerPad);
// AudioDecoder Downstream Unlink
if (m_gstWrapper->gstPadUnlink(audioDecSrcPad, audioDecSrcPeerPad) == FALSE)
RIALTO_SERVER_LOG_DEBUG("OTF -> AudioDecoder Downstream Unlink Failed");
// AudioDecoder Upstream Unlink
if (m_gstWrapper->gstPadUnlink(audioDecSinkPeerPad, audioDecSinkPad) == FALSE)
RIALTO_SERVER_LOG_DEBUG("OTF -> AudioDecoder Upstream Unlink Failed");
// AudioParser Downstream Unlink
if (m_gstWrapper->gstPadUnlink(audioParseSrcPad, audioParseSrcPeerPad) == FALSE)
RIALTO_SERVER_LOG_DEBUG("OTF -> AudioParser Downstream Unlink Failed");
// AudioParser Upstream Unlink
if (m_gstWrapper->gstPadUnlink(audioParseSinkPeerPad, audioParseSinkPad) == FALSE)
RIALTO_SERVER_LOG_DEBUG("OTF -> AudioParser Upstream Unlink Failed");
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| void* handle = dlopen("libocdm.so", RTLD_LAZY); | ||
| m_ocdmGstSessionDecryptEx = | ||
| (OcdmGstSessionDecryptExFn)dlsym(RTLD_DEFAULT, "opencdm_gstreamer_session_decrypt_ex"); | ||
| m_ocdmGstSessionDecryptBufferOnce = (OcdmGstSessionDecryptBufferOnceFn)dlsym(handle,"opencdm_gstreamer_session_decrypt_buffer_once"); | ||
| if(m_ocdmGstSessionDecryptBufferOnce != NULL){ | ||
| RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : m_ocdmGstSessionDecryptBufferOnce exists\n"); | ||
| } |
| MediaKeyErrorStatus OcdmSession::decryptBuffer(GstBuffer *encrypted, GstCaps *caps) | ||
| { | ||
| RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer()\n"); | ||
| if (!m_session) | ||
| { |
| if (preStatus == OutputRestricted || preStatus == OutputRestrictedHDCP22) | ||
| { | ||
|
|
||
| RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer() : returning MediaKeyErrorStatus::OUTPUT_RESTRICTED(Pre decrypt)\n"); | ||
| return MediaKeyErrorStatus::OUTPUT_RESTRICTED; | ||
| } else { | ||
| RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer() : returning error(Pre decrypt)\n"); | ||
| } |
| MediaKeyErrorStatus MediaKeysServerInternal::decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) | ||
| { | ||
| RIALTO_SERVER_LOG_DEBUG("entry:"); | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: entry:decrypt"); | ||
|
|
||
| MediaKeyErrorStatus status; | ||
| auto task = [&]() { status = decryptInternal(keySessionId, encrypted, caps); }; | ||
| MediaKeyErrorStatus status{MediaKeyErrorStatus::FAIL}; | ||
| const auto deadline = std::chrono::steady_clock::now() + kOutputRestrictedRetryTimeout; | ||
| do | ||
| { | ||
| auto task = [&]() { status = decryptInternal(keySessionId, encrypted, caps); }; | ||
| m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session id :%d", keySessionId); | ||
| switch (status) | ||
| { | ||
| case firebolt::rialto::MediaKeyErrorStatus::OK: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : OK"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::FAIL: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : FAIL"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : BAD_SESSION_ID"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : INTERFACE_NOT_IMPLEMENTED"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : BUFFER_TOO_SMALL"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : NOT_SUPPORTED"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::INVALID_STATE: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : INVALID_STATE"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : OUTPUT_RESTRICTED"); | ||
| break; | ||
| } |
| MediaKeyErrorStatus status{MediaKeyErrorStatus::FAIL}; | ||
| const auto deadline = std::chrono::steady_clock::now() + kOutputRestrictedRetryTimeout; | ||
| do | ||
| { | ||
| auto task = [&]() { status = decryptInternal(keySessionId, encrypted, caps); }; | ||
| m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session id :%d", keySessionId); | ||
| switch (status) | ||
| { | ||
| case firebolt::rialto::MediaKeyErrorStatus::OK: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : OK"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::FAIL: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : FAIL"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : BAD_SESSION_ID"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : INTERFACE_NOT_IMPLEMENTED"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : BUFFER_TOO_SMALL"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : NOT_SUPPORTED"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::INVALID_STATE: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : INVALID_STATE"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : OUTPUT_RESTRICTED"); | ||
| break; | ||
| } | ||
|
|
||
| if (status != MediaKeyErrorStatus::OUTPUT_RESTRICTED) | ||
| { | ||
| break; | ||
| } | ||
| RIALTO_SERVER_LOG_WARN("Decrypt returned OUTPUT_RESTRICTED, retrying after delay"); | ||
| std::this_thread::sleep_for(kOutputRestrictedRetryInterval); | ||
| } while (std::chrono::steady_clock::now() < deadline); |
| return firebolt::rialto::ProtoMediaKeyErrorStatus::FAIL; | ||
| } | ||
| case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED: | ||
| { | ||
| // TODO | ||
| } | ||
| } | ||
| return firebolt::rialto::ProtoMediaKeyErrorStatus::FAIL; |
| if (pingId != m_currentPingId) | ||
| { | ||
| RIALTO_SERVER_MANAGER_LOG_WARN("Unexpected ack received from server id: %d. Current ping id: %d, received ping " | ||
| "id: %d", | ||
| serverId, m_currentPingId, pingId); | ||
| if (success && m_failedPings[serverId].find(pingId) != m_failedPings[serverId].end()) | ||
| { | ||
| RIALTO_SERVER_MANAGER_LOG_WARN("Late ack received for server id: %d, Current ping id: %d, received ping " | ||
| "id: %d. Removing from failed pings list", | ||
| serverId, m_currentPingId, pingId); | ||
| m_failedPings[serverId].erase(pingId); | ||
| } |
| bool MediaPipelineServerInternal::removeSourceInternal(int32_t id) | ||
| { | ||
| if (!m_gstPlayer) | ||
| { | ||
| RIALTO_SERVER_LOG_ERROR("Failed to remove source - Gstreamer player has not been loaded"); | ||
| return false; | ||
| } | ||
| auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(), | ||
| [id](const auto &src) { return src.second == id; }); | ||
| if (sourceIter == m_attachedSources.end()) | ||
| { | ||
| RIALTO_SERVER_LOG_ERROR("Failed to remove source with id %d- Source not found", id); | ||
| return false; | ||
| } | ||
|
|
||
| m_gstPlayer->removeSource(sourceIter->first); | ||
| m_needMediaDataTimers.erase(sourceIter->first); | ||
| m_attachedSources.erase(sourceIter); | ||
| return true; |
| if ((pTypfdSrcPad = m_gstWrapper->gstElementGetStaticPad(m_context.playbackGroup.m_curAudioTypefind, "src")) != | ||
| NULL) // Unref the Pad | ||
| RIALTO_SERVER_LOG_DEBUG("OTF -> Current Typefind SrcPad = %p", pTypfdSrcPad); | ||
| if ((pTypfdSrcPeerPad = m_gstWrapper->gstPadGetPeer(pTypfdSrcPad)) != NULL) // Unref the Pad | ||
| RIALTO_SERVER_LOG_DEBUG("OTF -> Current Typefind Src Downstream Element Pad = %p", pTypfdSrcPeerPad); | ||
| // AudioDecoder Downstream Unlink | ||
| if (m_gstWrapper->gstPadUnlink(pTypfdSrcPad, pTypfdSrcPeerPad) == FALSE) | ||
| RIALTO_SERVER_LOG_DEBUG("OTF -> Typefind Downstream Unlink Failed"); | ||
| newAudioParse = m_gstWrapper->gstElementFactoryMake("aacparse", "aacparse"); | ||
| newAudioDecoder = m_gstWrapper->gstElementFactoryMake("avdec_aac", "avdec_aac"); | ||
| newQueue = m_gstWrapper->gstElementFactoryMake("queue", "aqueue"); |
| }; | ||
|
|
||
| TEST_F(FlushOnPrerollControllerTest, shouldNotPostponeFlushWhenNoFlushSet) | ||
| TEST_F(FlushOnPrerollControllerTest, shouldNotWaithWhenNoFlushSet) |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 118 out of 118 changed files in this pull request and generated 14 comments.
Comments suppressed due to low confidence (1)
tests/componenttests/server/tests/mediaPipeline/SwitchAudioPlaybackTest.cpp:224
- The new component test is checked in as
DISABLED_SwitchAudio, so it won’t run in CI even though the file is added to the test target. If this scenario is important for the change, please enable the test (or add an active equivalent) or document why it must remain disabled to avoid losing coverage for audio switching.
| { | ||
| return firebolt::rialto::ProtoMediaKeyErrorStatus::FAIL; | ||
| } | ||
| case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED: | ||
| { | ||
| // TODO | ||
| } | ||
| } | ||
| return firebolt::rialto::ProtoMediaKeyErrorStatus::FAIL; |
| std::unique_lock<std::mutex> lock{m_mutex}; | ||
| if (pingId != m_currentPingId) | ||
| { | ||
| RIALTO_SERVER_MANAGER_LOG_WARN("Unexpected ack received from server id: %d. Current ping id: %d, received ping " | ||
| "id: %d", | ||
| serverId, m_currentPingId, pingId); | ||
| if (success && m_failedPings[serverId].find(pingId) != m_failedPings[serverId].end()) | ||
| { | ||
| RIALTO_SERVER_MANAGER_LOG_WARN("Late ack received for server id: %d, Current ping id: %d, received ping " | ||
| "id: %d. Removing from failed pings list", | ||
| serverId, m_currentPingId, pingId); | ||
| m_failedPings[serverId].erase(pingId); | ||
| } |
| /*namespace | ||
| { | ||
| const char *toString(const firebolt::rialto::MediaKeyErrorStatus &status) | ||
| { | ||
| switch (status) | ||
| { | ||
| case firebolt::rialto::MediaKeyErrorStatus::OK: | ||
| return "OK"; | ||
| case firebolt::rialto::MediaKeyErrorStatus::FAIL: | ||
| return "FAIL"; | ||
| case firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID: | ||
| return "BAD_SESSION_ID"; | ||
| case firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED: | ||
| return "INTERFACE_NOT_IMPLEMENTED"; | ||
| case firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL: | ||
| return "BUFFER_TOO_SMALL"; | ||
| case firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED: | ||
| return "NOT_SUPPORTED"; | ||
| case firebolt::rialto::MediaKeyErrorStatus::INVALID_STATE: | ||
| return "INVALID_STATE"; | ||
| case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED: | ||
| return "OUTPUT_RESTRICTED"; | ||
| } | ||
| return "Unknown"; | ||
| } | ||
| } */// namespace | ||
|
|
| MediaKeyErrorStatus MediaKeysServerInternal::decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) | ||
| { | ||
| RIALTO_SERVER_LOG_DEBUG("entry:"); | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: entry:decrypt"); | ||
|
|
||
| MediaKeyErrorStatus status; | ||
| auto task = [&]() { status = decryptInternal(keySessionId, encrypted, caps); }; | ||
| MediaKeyErrorStatus status{MediaKeyErrorStatus::FAIL}; | ||
| const auto deadline = std::chrono::steady_clock::now() + kOutputRestrictedRetryTimeout; | ||
| do | ||
| { | ||
| auto task = [&]() { status = decryptInternal(keySessionId, encrypted, caps); }; | ||
| m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session id :%d", keySessionId); | ||
| switch (status) | ||
| { | ||
| case firebolt::rialto::MediaKeyErrorStatus::OK: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : OK"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::FAIL: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : FAIL"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : BAD_SESSION_ID"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : INTERFACE_NOT_IMPLEMENTED"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : BUFFER_TOO_SMALL"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : NOT_SUPPORTED"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::INVALID_STATE: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : INVALID_STATE"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : OUTPUT_RESTRICTED"); | ||
| break; | ||
| } | ||
|
|
||
| if (status != MediaKeyErrorStatus::OUTPUT_RESTRICTED) | ||
| { | ||
| break; | ||
| } | ||
| RIALTO_SERVER_LOG_WARN("Decrypt returned OUTPUT_RESTRICTED, retrying after delay"); | ||
| std::this_thread::sleep_for(kOutputRestrictedRetryInterval); | ||
| } while (std::chrono::steady_clock::now() < deadline); |
| static std::once_flag flag; | ||
| std::call_once(flag, | ||
| []() | ||
| { | ||
| void* handle = dlopen("libocdm.so", RTLD_LAZY); | ||
| m_ocdmGstSessionDecryptEx = | ||
| (OcdmGstSessionDecryptExFn)dlsym(RTLD_DEFAULT, "opencdm_gstreamer_session_decrypt_ex"); | ||
| m_ocdmGstSessionDecryptBufferOnce = (OcdmGstSessionDecryptBufferOnceFn)dlsym(handle,"opencdm_gstreamer_session_decrypt_buffer_once"); | ||
| if(m_ocdmGstSessionDecryptBufferOnce != NULL){ | ||
| RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : m_ocdmGstSessionDecryptBufferOnce exists\n"); | ||
| } |
| m_gstWrapper->gstObjectUnref(pTypfdSrcPad); | ||
| m_gstWrapper->gstObjectUnref(pTypfdSrcPeerPad); | ||
| m_gstWrapper->gstObjectUnref(pNewAudioDecoderSrcPad); |
| // Get AudioDecoder Src Pads | ||
| if ((audioDecSrcPad = m_gstWrapper->gstElementGetStaticPad(m_context.playbackGroup.m_curAudioDecoder, "src")) != | ||
| NULL) // Unref the Pad | ||
| RIALTO_SERVER_LOG_DEBUG("OTF -> Current AudioDecoder Src Pad = %p", audioDecSrcPad); | ||
| // Get AudioDecoder Sink Pads | ||
| if ((audioDecSinkPad = m_gstWrapper->gstElementGetStaticPad(m_context.playbackGroup.m_curAudioDecoder, "sink")) != | ||
| NULL) // Unref the Pad | ||
| RIALTO_SERVER_LOG_DEBUG("OTF -> Current AudioDecoder Sink Pad = %p", audioDecSinkPad); | ||
| // Get AudioDecoder Src Peer i.e. Downstream Element Pad | ||
| if ((audioDecSrcPeerPad = m_gstWrapper->gstPadGetPeer(audioDecSrcPad)) != NULL) // Unref the Pad | ||
| RIALTO_SERVER_LOG_DEBUG("OTF -> Current AudioDecoder Src Downstream Element Pad = %p", audioDecSrcPeerPad); | ||
| // Get AudioDecoder Sink Peer i.e. Upstream Element Pad | ||
| if ((audioDecSinkPeerPad = m_gstWrapper->gstPadGetPeer(audioDecSinkPad)) != NULL) // Unref the Pad | ||
| RIALTO_SERVER_LOG_DEBUG("OTF -> Current AudioDecoder Sink Upstream Element Pad = %p", audioDecSinkPeerPad); |
| reconfigDelayMs = now.tv_nsec > ts.tv_nsec ? (now.tv_nsec - ts.tv_nsec) / 1000000 | ||
| : (1000 - (ts.tv_nsec - now.tv_nsec) / 1000000); |
|
|
||
| MediaKeyErrorStatus MediaKeysIpc::createKeySession(KeySessionType sessionType, std::weak_ptr<IMediaKeysClient> client, | ||
| bool isLDL, int32_t &keySessionId) | ||
| bool isLDL, int32_t &keySessionId) |
| }; | ||
|
|
||
| TEST_F(FlushOnPrerollControllerTest, shouldNotPostponeFlushWhenNoFlushSet) | ||
| TEST_F(FlushOnPrerollControllerTest, shouldNotWaithWhenNoFlushSet) |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 118 out of 118 changed files in this pull request and generated 6 comments.
Comments suppressed due to low confidence (3)
wrappers/source/OcdmSession.cpp:244
- These
RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE ...")calls add noisy ERROR-level logging on every decrypt (and include embedded newlines). Also theelsebranches log "returning error" but do not return, which is misleading during troubleshooting. Please remove or downgrade to DEBUG/TRACE and only log real error paths; consider removing the misleadingelselogs or returning an actual error when intended.
serverManager/common/source/HealthcheckService.cpp:158 handleError()also usesm_failedPings[serverId], which will create a new entry ifserverIdwas never registered viaonPingSent()(e.g., ifhandleErroris called for an untracked server). Consider guarding withfind()/try_emplace()to make it explicit when a server becomes tracked and avoid silent insertion on error paths.
tests/componenttests/server/tests/mediaPipeline/SwitchAudioPlaybackTest.cpp:3- The file now starts with a blank line before the license header comment. If tooling expects the header at line 1 (common for license scanners), this may cause false negatives. Consider removing the leading blank line so the header begins at the top of the file.
| void* handle = dlopen("libocdm.so", RTLD_LAZY); | ||
| m_ocdmGstSessionDecryptEx = | ||
| (OcdmGstSessionDecryptExFn)dlsym(RTLD_DEFAULT, "opencdm_gstreamer_session_decrypt_ex"); | ||
| m_ocdmGstSessionDecryptBufferOnce = (OcdmGstSessionDecryptBufferOnceFn)dlsym(handle,"opencdm_gstreamer_session_decrypt_buffer_once"); | ||
| if(m_ocdmGstSessionDecryptBufferOnce != NULL){ | ||
| RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : m_ocdmGstSessionDecryptBufferOnce exists\n"); | ||
| } |
| firebolt::rialto::ProtoMediaKeyErrorStatus | ||
| convertMediaKeyErrorStatus(const firebolt::rialto::MediaKeyErrorStatus &errorStatus) | ||
| { | ||
| switch (errorStatus) | ||
| { | ||
| case firebolt::rialto::MediaKeyErrorStatus::OK: | ||
| { | ||
| return firebolt::rialto::ProtoMediaKeyErrorStatus::OK; | ||
| } | ||
| case firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID: | ||
| { | ||
| return firebolt::rialto::ProtoMediaKeyErrorStatus::BAD_SESSION_ID; | ||
| } | ||
| case firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED: | ||
| { | ||
| return firebolt::rialto::ProtoMediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED; | ||
| } | ||
| case firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL: | ||
| { | ||
| return firebolt::rialto::ProtoMediaKeyErrorStatus::BUFFER_TOO_SMALL; | ||
| } | ||
| case firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED: | ||
| { | ||
| return firebolt::rialto::ProtoMediaKeyErrorStatus::NOT_SUPPORTED; | ||
| } | ||
| case firebolt::rialto::MediaKeyErrorStatus::INVALID_STATE: | ||
| { | ||
| return firebolt::rialto::ProtoMediaKeyErrorStatus::INVALID_STATE; | ||
| } | ||
| case firebolt::rialto::MediaKeyErrorStatus::FAIL: | ||
| { | ||
| return firebolt::rialto::ProtoMediaKeyErrorStatus::FAIL; | ||
| } | ||
| case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED: | ||
| { | ||
| // TODO | ||
| } | ||
| } | ||
| return firebolt::rialto::ProtoMediaKeyErrorStatus::FAIL; | ||
| } |
| MediaKeyErrorStatus MediaKeysServerInternal::decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) | ||
| { | ||
| RIALTO_SERVER_LOG_DEBUG("entry:"); | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: entry:decrypt"); | ||
|
|
||
| MediaKeyErrorStatus status; | ||
| auto task = [&]() { status = decryptInternal(keySessionId, encrypted, caps); }; | ||
| MediaKeyErrorStatus status{MediaKeyErrorStatus::FAIL}; | ||
| const auto deadline = std::chrono::steady_clock::now() + kOutputRestrictedRetryTimeout; | ||
| do | ||
| { | ||
| auto task = [&]() { status = decryptInternal(keySessionId, encrypted, caps); }; | ||
| m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session id :%d", keySessionId); | ||
| switch (status) | ||
| { | ||
| case firebolt::rialto::MediaKeyErrorStatus::OK: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : OK"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::FAIL: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : FAIL"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : BAD_SESSION_ID"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : INTERFACE_NOT_IMPLEMENTED"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : BUFFER_TOO_SMALL"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : NOT_SUPPORTED"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::INVALID_STATE: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : INVALID_STATE"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : OUTPUT_RESTRICTED"); | ||
| break; | ||
| } | ||
|
|
||
| if (status != MediaKeyErrorStatus::OUTPUT_RESTRICTED) | ||
| { | ||
| break; | ||
| } | ||
| RIALTO_SERVER_LOG_WARN("Decrypt returned OUTPUT_RESTRICTED, retrying after delay"); | ||
| std::this_thread::sleep_for(kOutputRestrictedRetryInterval); | ||
| } while (std::chrono::steady_clock::now() < deadline); |
| void HealthcheckService::onAckReceived(int serverId, int pingId, bool success) | ||
| { | ||
| std::unique_lock<std::mutex> lock{m_mutex}; | ||
| if (pingId != m_currentPingId) | ||
| { | ||
| RIALTO_SERVER_MANAGER_LOG_WARN("Unexpected ack received from server id: %d. Current ping id: %d, received ping " | ||
| "id: %d", | ||
| serverId, m_currentPingId, pingId); | ||
| if (success && m_failedPings[serverId].find(pingId) != m_failedPings[serverId].end()) | ||
| { | ||
| RIALTO_SERVER_MANAGER_LOG_WARN("Late ack received for server id: %d, Current ping id: %d, received ping " | ||
| "id: %d. Removing from failed pings list", | ||
| serverId, m_currentPingId, pingId); | ||
| m_failedPings[serverId].erase(pingId); | ||
| } | ||
| else | ||
| { | ||
| RIALTO_SERVER_MANAGER_LOG_ERROR("Unexpected ack received from server id: %d. Current ping id: %d, received " | ||
| "ping " | ||
| "id: %d", | ||
| serverId, m_currentPingId, pingId); | ||
| } |
| static gboolean gst_rialto_text_track_sink_start(GstBaseSink *sink) // NOLINT(build/function_format) | ||
| { | ||
| const char *wayland_display = std::getenv("WAYLAND_DISPLAY"); | ||
| if (!wayland_display) | ||
| { | ||
| GST_ERROR_OBJECT(sink, "Failed to get WAYLAND_DISPLAY env variable"); | ||
| return false; | ||
| } | ||
|
|
||
| std::string display{wayland_display}; | ||
| const std::string kDisplay{"westeros-asplayer-subtitles"}; | ||
| GstRialtoTextTrackSink *self = GST_RIALTO_TEXT_TRACK_SINK(sink); | ||
| try | ||
| { | ||
| self->priv->m_textTrackSession = | ||
| firebolt::rialto::server::ITextTrackSessionFactory::getFactory().createTextTrackSession(display); | ||
| firebolt::rialto::server::ITextTrackSessionFactory::getFactory().createTextTrackSession(kDisplay); | ||
| } |
| MediaKeyErrorStatus status{MediaKeyErrorStatus::FAIL}; | ||
| const auto deadline = std::chrono::steady_clock::now() + kOutputRestrictedRetryTimeout; | ||
| do | ||
| { | ||
| auto task = [&]() { status = decryptInternal(keySessionId, encrypted, caps); }; | ||
| m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session id :%d", keySessionId); | ||
| switch (status) | ||
| { | ||
| case firebolt::rialto::MediaKeyErrorStatus::OK: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : OK"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::FAIL: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : FAIL"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : BAD_SESSION_ID"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : INTERFACE_NOT_IMPLEMENTED"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : BUFFER_TOO_SMALL"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : NOT_SUPPORTED"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::INVALID_STATE: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : INVALID_STATE"); | ||
| break; | ||
| case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED: | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : OUTPUT_RESTRICTED"); | ||
| break; | ||
| } | ||
|
|
||
| if (status != MediaKeyErrorStatus::OUTPUT_RESTRICTED) | ||
| { | ||
| break; | ||
| } | ||
| RIALTO_SERVER_LOG_WARN("Decrypt returned OUTPUT_RESTRICTED, retrying after delay"); | ||
| std::this_thread::sleep_for(kOutputRestrictedRetryInterval); | ||
| } while (std::chrono::steady_clock::now() < deadline); |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 119 out of 119 changed files in this pull request and generated 9 comments.
Comments suppressed due to low confidence (2)
media/server/main/source/MediaKeysServerInternal.cpp:648
- decrypt() now performs a blocking sleep/retry loop on OUTPUT_RESTRICTED, potentially stalling the calling thread for up to the timeout duration. This can have significant playback/latency impact; consider making the retry non-blocking (e.g., schedule retries on the worker/main thread) or ensure the caller is explicitly designed to tolerate this delay.
media/server/main/source/MediaKeysServerInternal.cpp:640 - There are extensive "DEBUG PURPOSE" logs emitted at ERROR level for every decrypt attempt/status, which will be very noisy and misleading in production. Please remove these or downgrade to DEBUG with concise messages (and ideally avoid per-buffer logs unless behind a feature flag).
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: ping entry") | ||
| for (const auto &mediaKeyPair : m_mediaKeys) | ||
| { | ||
| auto &mediaKeys = mediaKeyPair.second; | ||
| mediaKeys->ping(heartbeatProcedure->createHandler()); | ||
| } | ||
| RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE: ping exit") | ||
| } |
| void* handle = dlopen("libocdm.so", RTLD_LAZY); | ||
| m_ocdmGstSessionDecryptEx = | ||
| (OcdmGstSessionDecryptExFn)dlsym(RTLD_DEFAULT, "opencdm_gstreamer_session_decrypt_ex"); | ||
| m_ocdmGstSessionDecryptBufferOnce = (OcdmGstSessionDecryptBufferOnceFn)dlsym(handle,"opencdm_gstreamer_session_decrypt_buffer_once"); | ||
| if(m_ocdmGstSessionDecryptBufferOnce != NULL){ | ||
| RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : m_ocdmGstSessionDecryptBufferOnce exists\n"); | ||
| } |
| RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer()\n"); | ||
| if (!m_session) | ||
| { |
| if (preStatus == OutputRestricted || preStatus == OutputRestrictedHDCP22) | ||
| { | ||
|
|
||
| RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer() : returning MediaKeyErrorStatus::OUTPUT_RESTRICTED(Pre decrypt)\n"); | ||
| return MediaKeyErrorStatus::OUTPUT_RESTRICTED; | ||
| } else { | ||
| RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer() : returning error(Pre decrypt)\n"); | ||
| } |
| constexpr std::chrono::milliseconds kOutputRestrictedRetryInterval{250}; | ||
| constexpr std::chrono::seconds kOutputRestrictedRetryTimeout{6}; | ||
|
|
| /*namespace | ||
| { | ||
| const char *toString(const firebolt::rialto::MediaKeyErrorStatus &status) | ||
| { | ||
| switch (status) | ||
| { | ||
| case firebolt::rialto::MediaKeyErrorStatus::OK: | ||
| return "OK"; | ||
| case firebolt::rialto::MediaKeyErrorStatus::FAIL: | ||
| return "FAIL"; | ||
| case firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID: | ||
| return "BAD_SESSION_ID"; | ||
| case firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED: | ||
| return "INTERFACE_NOT_IMPLEMENTED"; | ||
| case firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL: | ||
| return "BUFFER_TOO_SMALL"; | ||
| case firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED: | ||
| return "NOT_SUPPORTED"; | ||
| case firebolt::rialto::MediaKeyErrorStatus::INVALID_STATE: | ||
| return "INVALID_STATE"; | ||
| case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED: | ||
| return "OUTPUT_RESTRICTED"; | ||
| } | ||
| return "Unknown"; | ||
| } | ||
| } */// namespace | ||
|
|
| case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED: | ||
| { | ||
| // TODO | ||
| } | ||
| } | ||
| return firebolt::rialto::ProtoMediaKeyErrorStatus::FAIL; |
| }; | ||
|
|
||
| TEST_F(FlushOnPrerollControllerTest, shouldNotPostponeFlushWhenNoFlushSet) | ||
| TEST_F(FlushOnPrerollControllerTest, shouldNotWaithWhenNoFlushSet) |
| return false; | ||
| } | ||
| return true; | ||
| --m_ongoingStateChangesNumber; |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 119 out of 119 changed files in this pull request and generated 8 comments.
Comments suppressed due to low confidence (1)
media/client/ipc/source/MediaPipelineIpc.cpp:356
MediaPipelineIpc::play(bool &async)returns false here without assigningasync, so callers can observe an uninitialized/previous value. Please setasync = falseat the beginning of the method (and/or on each failure path).
{
if (!reattachChannelIfRequired())
{
RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
return false;
| constexpr std::chrono::milliseconds kOutputRestrictedRetryInterval{250}; | ||
| constexpr std::chrono::seconds kOutputRestrictedRetryTimeout{6}; | ||
|
|
||
| int32_t generateSessionId() | ||
| { |
| MediaKeyErrorStatus OcdmSession::decryptBuffer(GstBuffer *encrypted, GstCaps *caps) | ||
| { | ||
| RIALTO_COMMON_LOG_ERROR("DEBUG PURPOSE : OcdmSession::decryptBuffer()\n"); | ||
| if (!m_session) | ||
| { |
| void* handle = dlopen("libocdm.so", RTLD_LAZY); | ||
| m_ocdmGstSessionDecryptEx = | ||
| (OcdmGstSessionDecryptExFn)dlsym(RTLD_DEFAULT, "opencdm_gstreamer_session_decrypt_ex"); | ||
| m_ocdmGstSessionDecryptBufferOnce = (OcdmGstSessionDecryptBufferOnceFn)dlsym(handle,"opencdm_gstreamer_session_decrypt_buffer_once"); | ||
| if(m_ocdmGstSessionDecryptBufferOnce != NULL){ |
| RIALTO_SERVER_LOG_ERROR("Media keys handle for mksId: %d does not exist", keySessionId); | ||
| return MediaKeyErrorStatus::FAIL; | ||
| } | ||
| mediaKeys = m_mediaKeys[mediaKeysHandleIter->second.mediaKeysHandle].get(); | ||
| } |
| case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED: | ||
| { | ||
| // TODO | ||
| } | ||
| } |
| RIALTO_SERVER_LOG_DEBUG("FlushOnPrerollController: Waiting if required for %s source entry", | ||
| common::convertMediaSourceType(type)); | ||
| m_conditionVariable.wait(lock, [this, &type]() | ||
| // coverity[MISSING_LOCK:FALSE] | ||
| { return !m_isPrerolled || m_flushingSources.find(type) == m_flushingSources.end(); }); |
| if ((pTypfdSrcPad = m_gstWrapper->gstElementGetStaticPad(m_context.playbackGroup.m_curAudioTypefind, "src")) != | ||
| NULL) // Unref the Pad | ||
| RIALTO_SERVER_LOG_DEBUG("OTF -> Current Typefind SrcPad = %p", pTypfdSrcPad); | ||
| if ((pTypfdSrcPeerPad = m_gstWrapper->gstPadGetPeer(pTypfdSrcPad)) != NULL) // Unref the Pad | ||
| RIALTO_SERVER_LOG_DEBUG("OTF -> Current Typefind Src Downstream Element Pad = %p", pTypfdSrcPeerPad); |
| if ((audioDecSrcPeerPad = m_gstWrapper->gstPadGetPeer(audioDecSrcPad)) != NULL) // Unref the Pad | ||
| RIALTO_SERVER_LOG_DEBUG("OTF -> Current AudioDecoder Src Downstream Element Pad = %p", audioDecSrcPeerPad); | ||
| // Get AudioDecoder Sink Peer i.e. Upstream Element Pad | ||
| if ((audioDecSinkPeerPad = m_gstWrapper->gstPadGetPeer(audioDecSinkPad)) != NULL) // Unref the Pad | ||
| RIALTO_SERVER_LOG_DEBUG("OTF -> Current AudioDecoder Sink Upstream Element Pad = %p", audioDecSinkPeerPad); |
sleep for 1 sec and total wait for 4sec