From 65f18e852fafff11db812d62934e21ab50923603 Mon Sep 17 00:00:00 2001 From: Marcin Wojciechowski <105790697+skywojciechowskim@users.noreply.github.com> Date: Mon, 9 Jun 2025 14:29:25 +0200 Subject: [PATCH 01/15] Do not forward state change/eos bus messages when flush is queued (#380) Summary: Do not forward state change/eos bus messages when flush is queued Type: Fix Test Plan: UT/ CT, Fullstack Jira: ENTDAI-748 --- media/server/gstplayer/include/FlushWatcher.h | 7 +- .../gstplayer/include/GstGenericPlayer.h | 4 +- .../server/gstplayer/include/IFlushWatcher.h | 3 +- .../include/tasks/IGenericPlayerTaskFactory.h | 11 +- .../tasks/generic/GenericPlayerTaskFactory.h | 3 +- .../include/tasks/generic/HandleBusMessage.h | 11 +- .../gstplayer/interface/IGstGenericPlayer.h | 12 +- .../server/gstplayer/source/FlushWatcher.cpp | 12 +- .../gstplayer/source/GstGenericPlayer.cpp | 8 +- .../generic/GenericPlayerTaskFactory.cpp | 5 +- .../source/tasks/generic/HandleBusMessage.cpp | 31 +- .../source/MediaPipelineServerInternal.cpp | 3 +- .../flushWatcher/FlushWatcherTests.cpp | 8 +- .../GstDispatcherThreadClientTest.cpp | 4 +- .../genericPlayer/GstGenericPlayerTest.cpp | 31 +- .../GenericPlayerTaskFactoryTest.cpp | 8 +- .../tasksTests/HandleBusMessageTest.cpp | 448 ++++++++++++++---- .../server/main/mediaPipeline/FlushTest.cpp | 9 +- .../server/mocks/gstplayer/FlushWatcherMock.h | 3 +- .../gstplayer/GenericPlayerTaskFactoryMock.h | 3 +- .../mocks/gstplayer/GstGenericPlayerMock.h | 3 +- 21 files changed, 454 insertions(+), 173 deletions(-) diff --git a/media/server/gstplayer/include/FlushWatcher.h b/media/server/gstplayer/include/FlushWatcher.h index ce51d7b3a..5a43b5ded 100644 --- a/media/server/gstplayer/include/FlushWatcher.h +++ b/media/server/gstplayer/include/FlushWatcher.h @@ -21,8 +21,8 @@ #define FIREBOLT_RIALTO_SERVER_FLUSH_WATCHER_H_ #include "IFlushWatcher.h" +#include #include -#include namespace firebolt::rialto::server { @@ -32,13 +32,14 @@ class FlushWatcher : public IFlushWatcher FlushWatcher() = default; ~FlushWatcher() override = default; - void setFlushing(const MediaSourceType &type) override; + void setFlushing(const MediaSourceType &type, bool async) override; void setFlushed(const MediaSourceType &type) override; bool isFlushOngoing() const override; + bool isAsyncFlushOngoing() const override; private: mutable std::mutex m_mutex; - std::set m_flushingSources; + std::map m_flushingSources; }; } // namespace firebolt::rialto::server #endif // FIREBOLT_RIALTO_SERVER_FLUSH_WATCHER_H_ diff --git a/media/server/gstplayer/include/GstGenericPlayer.h b/media/server/gstplayer/include/GstGenericPlayer.h index bf4da0b1b..6b6f97197 100644 --- a/media/server/gstplayer/include/GstGenericPlayer.h +++ b/media/server/gstplayer/include/GstGenericPlayer.h @@ -124,7 +124,6 @@ class GstGenericPlayer : public IGstGenericPlayer, public IGstGenericPlayerPriva bool getVolume(double &volume) override; void setMute(const MediaSourceType &mediaSourceType, bool mute) override; bool getMute(const MediaSourceType &mediaSourceType, bool &mute) override; - bool isAsync(const MediaSourceType &mediaSourceType) const override; void setTextTrackIdentifier(const std::string &textTrackIdentifier) override; bool getTextTrackIdentifier(std::string &textTrackIdentifier) override; bool setLowLatency(bool lowLatency) override; @@ -134,7 +133,7 @@ class GstGenericPlayer : public IGstGenericPlayer, public IGstGenericPlayerPriva bool setStreamSyncMode(const MediaSourceType &mediaSourceType, int32_t streamSyncMode) override; bool getStreamSyncMode(int32_t &streamSyncMode) override; void ping(std::unique_ptr &&heartbeatHandler) override; - void flush(const MediaSourceType &mediaSourceType, bool resetTime) override; + void flush(const MediaSourceType &mediaSourceType, bool resetTime, bool &async) override; void setSourcePosition(const MediaSourceType &mediaSourceType, int64_t position, bool resetTime, double appliedRate, uint64_t stopPosition) override; void processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) override; @@ -185,6 +184,7 @@ class GstGenericPlayer : public IGstGenericPlayer, public IGstGenericPlayerPriva bool reattachSource(const std::unique_ptr &source) override; GstElement *getSink(const MediaSourceType &mediaSourceType) const override; void setSourceFlushed(const MediaSourceType &mediaSourceType) override; + bool isAsync(const MediaSourceType &mediaSourceType) const; private: /** diff --git a/media/server/gstplayer/include/IFlushWatcher.h b/media/server/gstplayer/include/IFlushWatcher.h index 7f6686bcf..e1386a7e6 100644 --- a/media/server/gstplayer/include/IFlushWatcher.h +++ b/media/server/gstplayer/include/IFlushWatcher.h @@ -29,9 +29,10 @@ class IFlushWatcher public: virtual ~IFlushWatcher() = default; - virtual void setFlushing(const MediaSourceType &type) = 0; + virtual void setFlushing(const MediaSourceType &type, bool async) = 0; virtual void setFlushed(const MediaSourceType &type) = 0; virtual bool isFlushOngoing() const = 0; + virtual bool isAsyncFlushOngoing() const = 0; }; } // namespace firebolt::rialto::server #endif // FIREBOLT_RIALTO_SERVER_I_FLUSH_WATCHER_H_ diff --git a/media/server/gstplayer/include/tasks/IGenericPlayerTaskFactory.h b/media/server/gstplayer/include/tasks/IGenericPlayerTaskFactory.h index 1544587e9..ea91604e2 100644 --- a/media/server/gstplayer/include/tasks/IGenericPlayerTaskFactory.h +++ b/media/server/gstplayer/include/tasks/IGenericPlayerTaskFactory.h @@ -22,6 +22,7 @@ #include "GenericPlayerContext.h" #include "IDataReader.h" +#include "IFlushWatcher.h" #include "IGstGenericPlayerPrivate.h" #include "IHeartbeatHandler.h" #include "IMediaPipeline.h" @@ -119,16 +120,16 @@ class IGenericPlayerTaskFactory /** * @brief Creates a HandleBusMessage task. * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstGenericPlayer instance - * @param[in] message : The message to be handled. - * @param[in] isFlushing : Current flushing state. True if flush for any source is queued + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstGenericPlayer instance + * @param[in] message : The message to be handled. + * @param[in] flushWatcher : Flush watcher instance * * @retval the new HandleBusMessage task instance. */ virtual std::unique_ptr createHandleBusMessage(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, GstMessage *message, - bool isFlushing) const = 0; + const IFlushWatcher &flushWatcher) const = 0; /** * @brief Creates a NeedData task. diff --git a/media/server/gstplayer/include/tasks/generic/GenericPlayerTaskFactory.h b/media/server/gstplayer/include/tasks/generic/GenericPlayerTaskFactory.h index a9bc236fd..be72f5136 100644 --- a/media/server/gstplayer/include/tasks/generic/GenericPlayerTaskFactory.h +++ b/media/server/gstplayer/include/tasks/generic/GenericPlayerTaskFactory.h @@ -55,7 +55,8 @@ class GenericPlayerTaskFactory : public IGenericPlayerTaskFactory std::unique_ptr createFinishSetupSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player) const override; std::unique_ptr createHandleBusMessage(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - GstMessage *message, bool isFlushing) const override; + GstMessage *message, + const IFlushWatcher &flushWatcher) const override; std::unique_ptr createNeedData(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, GstAppSrc *src) const override; std::unique_ptr createPause(GenericPlayerContext &context, diff --git a/media/server/gstplayer/include/tasks/generic/HandleBusMessage.h b/media/server/gstplayer/include/tasks/generic/HandleBusMessage.h index cec810699..0db969cf4 100644 --- a/media/server/gstplayer/include/tasks/generic/HandleBusMessage.h +++ b/media/server/gstplayer/include/tasks/generic/HandleBusMessage.h @@ -21,6 +21,7 @@ #define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_HANDLE_BUS_MESSAGE_H_ #include "GenericPlayerContext.h" +#include "IFlushWatcher.h" #include "IGlibWrapper.h" #include "IGstGenericPlayerClient.h" #include "IGstGenericPlayerPrivate.h" @@ -35,9 +36,9 @@ class HandleBusMessage : public IPlayerTask { public: HandleBusMessage(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, - std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, GstMessage *message, - bool isFlushOngoing); + const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper, GstMessage *message, + const IFlushWatcher &flushWatcher); ~HandleBusMessage() override; void execute() const override; @@ -50,7 +51,9 @@ class HandleBusMessage : public IPlayerTask std::shared_ptr m_gstWrapper; std::shared_ptr m_glibWrapper; GstMessage *m_message; - bool m_isFlushOngoing; + const IFlushWatcher &m_flushWatcher; + bool m_isFlushOngoingDuringCreation; + bool m_isAsyncFlushOngoingDuringCreation; }; } // namespace firebolt::rialto::server::tasks::generic diff --git a/media/server/gstplayer/interface/IGstGenericPlayer.h b/media/server/gstplayer/interface/IGstGenericPlayer.h index 9c11c07ef..a6c9532bf 100644 --- a/media/server/gstplayer/interface/IGstGenericPlayer.h +++ b/media/server/gstplayer/interface/IGstGenericPlayer.h @@ -275,15 +275,6 @@ class IGstGenericPlayer */ virtual bool getMute(const MediaSourceType &mediaSourceType, bool &mute) = 0; - /** - * @brief Checks if given source is asyncronous - * - * @param[in] mediaSourceType : The media source type - * - * @retval True if source is asynchronous. - */ - virtual bool isAsync(const MediaSourceType &mediaSourceType) const = 0; - /** * @brief Change Text Track Identifier * @@ -370,9 +361,10 @@ class IGstGenericPlayer * * @param[in] mediaSourceType : The media source type to flush. * @param[in] resetTime : True if time should be reset + * @param[out] async : True if flushed source is asynchronous (will preroll after flush) * */ - virtual void flush(const MediaSourceType &mediaSourceType, bool resetTime) = 0; + virtual void flush(const MediaSourceType &mediaSourceType, bool resetTime, bool &async) = 0; /** * @brief Set the source position in nanoseconds. diff --git a/media/server/gstplayer/source/FlushWatcher.cpp b/media/server/gstplayer/source/FlushWatcher.cpp index 203873f6e..5918b6e25 100644 --- a/media/server/gstplayer/source/FlushWatcher.cpp +++ b/media/server/gstplayer/source/FlushWatcher.cpp @@ -18,15 +18,16 @@ */ #include "FlushWatcher.h" +#include namespace firebolt::rialto::server { -void FlushWatcher::setFlushing(const MediaSourceType &type) +void FlushWatcher::setFlushing(const MediaSourceType &type, bool async) { std::unique_lock lock{m_mutex}; if (MediaSourceType::UNKNOWN != type) { - m_flushingSources.insert(type); + m_flushingSources[type] = async; } } @@ -41,4 +42,11 @@ bool FlushWatcher::isFlushOngoing() const std::unique_lock lock{m_mutex}; return !m_flushingSources.empty(); } + +bool FlushWatcher::isAsyncFlushOngoing() const +{ + std::unique_lock lock{m_mutex}; + return !m_flushingSources.empty() && std::any_of(m_flushingSources.begin(), m_flushingSources.end(), + [](const auto &source) { return source.second; }); +} } // namespace firebolt::rialto::server diff --git a/media/server/gstplayer/source/GstGenericPlayer.cpp b/media/server/gstplayer/source/GstGenericPlayer.cpp index 2dff7b4b0..cbdde9f7c 100644 --- a/media/server/gstplayer/source/GstGenericPlayer.cpp +++ b/media/server/gstplayer/source/GstGenericPlayer.cpp @@ -1881,11 +1881,12 @@ void GstGenericPlayer::ping(std::unique_ptr &&heartbeatHandle } } -void GstGenericPlayer::flush(const MediaSourceType &mediaSourceType, bool resetTime) +void GstGenericPlayer::flush(const MediaSourceType &mediaSourceType, bool resetTime, bool &async) { if (m_workerThread) { - m_flushWatcher->setFlushing(mediaSourceType); + async = isAsync(mediaSourceType); + m_flushWatcher->setFlushing(mediaSourceType, async); m_workerThread->enqueueTask(m_taskFactory->createFlush(m_context, *this, mediaSourceType, resetTime)); } } @@ -1986,8 +1987,7 @@ void GstGenericPlayer::switchSource(const std::unique_ptrenqueueTask( - m_taskFactory->createHandleBusMessage(m_context, *this, message, m_flushWatcher->isFlushOngoing())); + m_workerThread->enqueueTask(m_taskFactory->createHandleBusMessage(m_context, *this, message, *m_flushWatcher)); } void GstGenericPlayer::updatePlaybackGroup(GstElement *typefind, const GstCaps *caps) diff --git a/media/server/gstplayer/source/tasks/generic/GenericPlayerTaskFactory.cpp b/media/server/gstplayer/source/tasks/generic/GenericPlayerTaskFactory.cpp index 693708ea9..b7ea1622f 100644 --- a/media/server/gstplayer/source/tasks/generic/GenericPlayerTaskFactory.cpp +++ b/media/server/gstplayer/source/tasks/generic/GenericPlayerTaskFactory.cpp @@ -114,10 +114,11 @@ std::unique_ptr GenericPlayerTaskFactory::createFinishSetupSource(G std::unique_ptr GenericPlayerTaskFactory::createHandleBusMessage(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - GstMessage *message, bool isFlushing) const + GstMessage *message, + const IFlushWatcher &flushWatcher) const { return std::make_unique(context, player, m_client, m_gstWrapper, m_glibWrapper, - message, isFlushing); + message, flushWatcher); } std::unique_ptr GenericPlayerTaskFactory::createNeedData(GenericPlayerContext &context, diff --git a/media/server/gstplayer/source/tasks/generic/HandleBusMessage.cpp b/media/server/gstplayer/source/tasks/generic/HandleBusMessage.cpp index b4d09fab3..132ecc333 100644 --- a/media/server/gstplayer/source/tasks/generic/HandleBusMessage.cpp +++ b/media/server/gstplayer/source/tasks/generic/HandleBusMessage.cpp @@ -27,11 +27,13 @@ namespace firebolt::rialto::server::tasks::generic { HandleBusMessage::HandleBusMessage(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, - std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, - GstMessage *message, bool isFlushOngoing) + const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper, + GstMessage *message, const IFlushWatcher &flushWatcher) : m_context{context}, m_player{player}, m_gstPlayerClient{client}, m_gstWrapper{gstWrapper}, - m_glibWrapper{glibWrapper}, m_message{message}, m_isFlushOngoing{isFlushOngoing} + m_glibWrapper{glibWrapper}, m_message{message}, m_flushWatcher{flushWatcher}, + m_isFlushOngoingDuringCreation{flushWatcher.isFlushOngoing()}, + m_isAsyncFlushOngoingDuringCreation{flushWatcher.isAsyncFlushOngoing()} { RIALTO_SERVER_LOG_DEBUG("Constructing HandleBusMessage"); } @@ -76,6 +78,14 @@ void HandleBusMessage::execute() const { if (pending != GST_STATE_PAUSED) { + // If async flush was requested before HandleBusMessage task creation (but it was not executed yet) + // or if async flush was created after HandleBusMessage task creation (but before its execution) + // we can't report playback state, because async flush causes state loss - reported state is probably invalid. + if (m_isAsyncFlushOngoingDuringCreation || m_flushWatcher.isAsyncFlushOngoing()) + { + RIALTO_SERVER_LOG_WARN("Skip PAUSED notification - flush is ongoing"); + break; + } // newState==GST_STATE_PAUSED, pending==GST_STATE_PAUSED state transition is received as a result of // waiting for preroll after seek. // Subsequent newState==GST_STATE_PAUSED, pending!=GST_STATE_PAUSED transition will @@ -86,6 +96,14 @@ void HandleBusMessage::execute() const } case GST_STATE_PLAYING: { + // If async flush was requested before HandleBusMessage task creation (but it was not executed yet) + // or if async flush was created after HandleBusMessage task creation (but before its execution) + // we can't report playback state, because async flush causes state loss - reported state is probably invalid. + if (m_isAsyncFlushOngoingDuringCreation || m_flushWatcher.isAsyncFlushOngoing()) + { + RIALTO_SERVER_LOG_WARN("Skip PLAYING notification - flush is ongoing"); + break; + } if (m_context.pendingPlaybackRate != kNoPendingPlaybackRate) { m_player.setPendingPlaybackRate(); @@ -107,7 +125,10 @@ void HandleBusMessage::execute() const } case GST_MESSAGE_EOS: { - if (m_isFlushOngoing) + // If flush was requested before HandleBusMessage task creation (but it was not executed yet) + // or if flush was created after HandleBusMessage task creation (but before its execution) + // we can't report EOS, because flush clears EOS. + if (m_isFlushOngoingDuringCreation || m_flushWatcher.isFlushOngoing()) { RIALTO_SERVER_LOG_WARN("Skip EOS notification - flush is ongoing"); break; diff --git a/media/server/main/source/MediaPipelineServerInternal.cpp b/media/server/main/source/MediaPipelineServerInternal.cpp index 88ba70e12..e80808285 100644 --- a/media/server/main/source/MediaPipelineServerInternal.cpp +++ b/media/server/main/source/MediaPipelineServerInternal.cpp @@ -1151,8 +1151,7 @@ bool MediaPipelineServerInternal::flushInternal(int32_t sourceId, bool resetTime return false; } - async = m_gstPlayer->isAsync(sourceIter->first); - m_gstPlayer->flush(sourceIter->first, resetTime); + m_gstPlayer->flush(sourceIter->first, resetTime, async); // Reset Eos on flush auto it = m_isMediaTypeEosMap.find(sourceIter->first); diff --git a/tests/unittests/media/server/gstplayer/flushWatcher/FlushWatcherTests.cpp b/tests/unittests/media/server/gstplayer/flushWatcher/FlushWatcherTests.cpp index dae7893d3..2d93ba441 100644 --- a/tests/unittests/media/server/gstplayer/flushWatcher/FlushWatcherTests.cpp +++ b/tests/unittests/media/server/gstplayer/flushWatcher/FlushWatcherTests.cpp @@ -30,17 +30,21 @@ TEST(FlushWatcherTests, ShouldReturnCorrectValue) EXPECT_FALSE(watcher.isFlushOngoing()); // Flushing when flushing set for at least one source - watcher.setFlushing(MediaSourceType::AUDIO); + watcher.setFlushing(MediaSourceType::AUDIO, false); EXPECT_TRUE(watcher.isFlushOngoing()); + EXPECT_FALSE(watcher.isAsyncFlushOngoing()); - watcher.setFlushing(MediaSourceType::VIDEO); + watcher.setFlushing(MediaSourceType::VIDEO, true); EXPECT_TRUE(watcher.isFlushOngoing()); + EXPECT_TRUE(watcher.isAsyncFlushOngoing()); // Not flushing when all flush flags cleared watcher.setFlushed(MediaSourceType::AUDIO); EXPECT_TRUE(watcher.isFlushOngoing()); + EXPECT_TRUE(watcher.isAsyncFlushOngoing()); watcher.setFlushed(MediaSourceType::VIDEO); EXPECT_FALSE(watcher.isFlushOngoing()); + EXPECT_FALSE(watcher.isAsyncFlushOngoing()); } } // namespace firebolt::rialto::server diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/GstDispatcherThreadClientTest.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/GstDispatcherThreadClientTest.cpp index 617e4ba92..ed883ce93 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/GstDispatcherThreadClientTest.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/GstDispatcherThreadClientTest.cpp @@ -55,14 +55,12 @@ class GstDispatcherThreadClientTest : public GstGenericPlayerTestCommon TEST_F(GstDispatcherThreadClientTest, shouldHandleBusMessage) { - constexpr bool kIsFlushing{false}; GstMessage message{}; std::unique_ptr messageTask{std::make_unique>()}; - EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillOnce(Return(kIsFlushing)); EXPECT_CALL(dynamic_cast &>(*messageTask), execute()); EXPECT_CALL(m_workerThreadMock, enqueueTask(_)) .WillRepeatedly(Invoke([](std::unique_ptr &&task) { task->execute(); })); - EXPECT_CALL(m_taskFactoryMock, createHandleBusMessage(_, _, &message, kIsFlushing)) + EXPECT_CALL(m_taskFactoryMock, createHandleBusMessage(_, _, &message, _)) .WillOnce(Return(ByMove(std::move(messageTask)))); m_sut->handleBusMessage(&message); diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerTest.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerTest.cpp index 7e0c3c54c..e3ae84101 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerTest.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerTest.cpp @@ -843,13 +843,23 @@ TEST_F(GstGenericPlayerTest, shouldPing) TEST_F(GstGenericPlayerTest, shouldFlush) { constexpr bool kResetTime{true}; + bool isAsync{true}; std::unique_ptr task{std::make_unique>()}; - EXPECT_CALL(m_flushWatcherMock, setFlushing(MediaSourceType::AUDIO)); + EXPECT_CALL(m_flushWatcherMock, setFlushing(MediaSourceType::VIDEO, isAsync)); + expectGetSink(kVideoSinkStr, m_element); + EXPECT_CALL(*m_glibWrapperMock, gObjectGetStub(_, StrEq("async"), _)) + .WillOnce(Invoke( + [&](gpointer object, const gchar *first_property_name, void *val) + { + gboolean *returnVal = reinterpret_cast(val); + *returnVal = TRUE; + })); + EXPECT_CALL(*m_gstWrapperMock, gstObjectUnref(m_element)); EXPECT_CALL(dynamic_cast &>(*task), execute()); - EXPECT_CALL(m_taskFactoryMock, createFlush(_, _, MediaSourceType::AUDIO, kResetTime)) + EXPECT_CALL(m_taskFactoryMock, createFlush(_, _, MediaSourceType::VIDEO, kResetTime)) .WillOnce(Return(ByMove(std::move(task)))); - m_sut->flush(MediaSourceType::AUDIO, kResetTime); + m_sut->flush(MediaSourceType::VIDEO, kResetTime, isAsync); } TEST_F(GstGenericPlayerTest, shouldSetSourcePosition) @@ -1043,18 +1053,3 @@ TEST_F(GstGenericPlayerTest, shouldSwitchSource) m_sut->switchSource(source); } - -TEST_F(GstGenericPlayerTest, shouldCheckIfSinkIsAsync) -{ - expectGetSink(kVideoSinkStr, m_element); - EXPECT_CALL(*m_glibWrapperMock, gObjectGetStub(_, StrEq("async"), _)) - .WillOnce(Invoke( - [&](gpointer object, const gchar *first_property_name, void *val) - { - gboolean *returnVal = reinterpret_cast(val); - *returnVal = TRUE; - })); - EXPECT_CALL(*m_gstWrapperMock, gstObjectUnref(m_element)); - - EXPECT_TRUE(m_sut->isAsync(MediaSourceType::VIDEO)); -} diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/GenericPlayerTaskFactoryTest.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/GenericPlayerTaskFactoryTest.cpp index 64b628ac5..45d0fd48d 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/GenericPlayerTaskFactoryTest.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/GenericPlayerTaskFactoryTest.cpp @@ -19,6 +19,7 @@ #include +#include "FlushWatcherMock.h" #include "GenericPlayerContext.h" #include "GlibWrapperMock.h" #include "GstGenericPlayerClientMock.h" @@ -87,6 +88,7 @@ class GenericPlayerTaskFactoryTest : public testing::Test std::make_shared>()}; std::shared_ptr m_gstTextTrackSinkFactoryMock{ std::make_shared>()}; + StrictMock m_flushWatcherMock; firebolt::rialto::server::GenericPlayerTaskFactory m_sut{&m_gstPlayerClient, m_gstWrapper, m_glibWrapper, m_rdkGstreamerUtilsWrapper, m_gstTextTrackSinkFactoryMock}; }; @@ -141,7 +143,11 @@ TEST_F(GenericPlayerTaskFactoryTest, ShouldCreateFinishSetupSource) TEST_F(GenericPlayerTaskFactoryTest, ShouldCreateHandleBusMessage) { - auto task = m_sut.createHandleBusMessage(m_context, m_gstPlayer, nullptr, false); + constexpr bool kNoFlushOngoing{false}; + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + + auto task = m_sut.createHandleBusMessage(m_context, m_gstPlayer, nullptr, m_flushWatcherMock); EXPECT_NE(task, nullptr); EXPECT_NO_THROW(dynamic_cast(*task)); } diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/HandleBusMessageTest.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/HandleBusMessageTest.cpp index 6f5086de3..c06b47abe 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/HandleBusMessageTest.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/HandleBusMessageTest.cpp @@ -18,6 +18,7 @@ */ #include "tasks/generic/HandleBusMessage.h" +#include "FlushWatcherMock.h" #include "GenericPlayerContext.h" #include "GlibWrapperMock.h" #include "GstGenericPlayerClientMock.h" @@ -54,6 +55,7 @@ class HandleBusMessageTest : public testing::Test std::make_shared>()}; std::shared_ptr m_glibWrapper{ std::make_shared>()}; + StrictMock m_flushWatcherMock; GstElement m_pipeline{}; GstAppSrc m_audioSrc{}; GstAppSrc m_videoSrc{}; @@ -84,9 +86,12 @@ TEST_F(HandleBusMessageTest, shouldNotHandleMessageWithUnknownType) { GST_MESSAGE_SRC(&m_message) = GST_OBJECT(&m_pipeline); EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); } @@ -94,9 +99,12 @@ TEST_F(HandleBusMessageTest, shouldNotHandleEosMessageForAnotherPipeline) { EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); GST_MESSAGE_TYPE(&m_message) = GST_MESSAGE_EOS; - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); } @@ -106,9 +114,12 @@ TEST_F(HandleBusMessageTest, shouldNotHandleMessageEosWhenPipelineIsNull) GST_MESSAGE_SRC(&m_message) = GST_OBJECT(&m_pipeline); GST_MESSAGE_TYPE(&m_message) = GST_MESSAGE_EOS; EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); } @@ -118,21 +129,44 @@ TEST_F(HandleBusMessageTest, shouldNotHandleMessageEosWhenEosAlreadyNotified) GST_MESSAGE_SRC(&m_message) = GST_OBJECT(&m_pipeline); GST_MESSAGE_TYPE(&m_message) = GST_MESSAGE_EOS; EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); } -TEST_F(HandleBusMessageTest, shouldNotHandleEosMessageWhenFlushing) +TEST_F(HandleBusMessageTest, shouldNotHandleEosMessageWhenFlushRequestedBeforeTaskCreation) { constexpr bool kFlushOngoing{true}; GST_MESSAGE_SRC(&m_message) = GST_OBJECT(&m_pipeline); GST_MESSAGE_TYPE(&m_message) = GST_MESSAGE_EOS; EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kFlushOngoing}; + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillOnce(Return(kFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillOnce(Return(kFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; + task.execute(); + + EXPECT_FALSE(m_context.eosNotified); +} + +TEST_F(HandleBusMessageTest, shouldNotHandleEosMessageWhenFlushRequestedAfterTaskCreation) +{ + constexpr bool kFlushOngoing{true}; + GST_MESSAGE_SRC(&m_message) = GST_OBJECT(&m_pipeline); + GST_MESSAGE_TYPE(&m_message) = GST_MESSAGE_EOS; + EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillOnce(Return(kNoFlushOngoing)).WillOnce(Return(kFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillOnce(Return(kNoFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); EXPECT_FALSE(m_context.eosNotified); @@ -144,9 +178,12 @@ TEST_F(HandleBusMessageTest, shouldHandleEosMessage) GST_MESSAGE_TYPE(&m_message) = GST_MESSAGE_EOS; EXPECT_CALL(m_gstPlayerClient, notifyPlaybackState(firebolt::rialto::PlaybackState::END_OF_STREAM)); EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); EXPECT_TRUE(m_context.eosNotified); @@ -156,9 +193,12 @@ TEST_F(HandleBusMessageTest, shouldNotHandleStateChangedMessageForAnotherPipelin { EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); GST_MESSAGE_TYPE(&m_message) = GST_MESSAGE_STATE_CHANGED; - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); } @@ -168,9 +208,12 @@ TEST_F(HandleBusMessageTest, shouldNotHandleMessageStateChangedWhenPipelineIsNul GST_MESSAGE_SRC(&m_message) = GST_OBJECT(&m_pipeline); GST_MESSAGE_TYPE(&m_message) = GST_MESSAGE_STATE_CHANGED; EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); } @@ -189,9 +232,11 @@ TEST_F(HandleBusMessageTest, shouldNotHandleStateChangedMessageWhenGstPlayerClie EXPECT_CALL(*m_gstWrapper, gstElementStateGetName(pending)).WillOnce(Return("Void")); EXPECT_CALL(*m_gstWrapper, gstDebugBinToDotFileWithTs(GST_BIN(&m_pipeline), _, _)); EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, nullptr, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, nullptr, + m_gstWrapper, m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); } @@ -211,9 +256,12 @@ TEST_F(HandleBusMessageTest, shouldHandleStateChangedToNullMessage) EXPECT_CALL(*m_gstWrapper, gstDebugBinToDotFileWithTs(GST_BIN(&m_pipeline), _, _)); EXPECT_CALL(m_gstPlayerClient, notifyPlaybackState(firebolt::rialto::PlaybackState::STOPPED)); EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); } @@ -233,9 +281,91 @@ TEST_F(HandleBusMessageTest, shouldHandleStateChangedToPausedMessage) EXPECT_CALL(*m_gstWrapper, gstDebugBinToDotFileWithTs(GST_BIN(&m_pipeline), _, _)); EXPECT_CALL(m_gstPlayerClient, notifyPlaybackState(firebolt::rialto::PlaybackState::PAUSED)); EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; + task.execute(); +} + +TEST_F(HandleBusMessageTest, shouldHandleStateChangedToPausedMessageWhenSyncFlushIsOngoing) +{ + constexpr bool kFlushOngoing{true}; + + GST_MESSAGE_SRC(&m_message) = GST_OBJECT(&m_pipeline); + GST_MESSAGE_TYPE(&m_message) = GST_MESSAGE_STATE_CHANGED; + GstState oldState = GST_STATE_READY; + GstState newState = GST_STATE_PAUSED; + GstState pending = GST_STATE_VOID_PENDING; + + EXPECT_CALL(*m_gstWrapper, gstMessageParseStateChanged(&m_message, _, _, _)) + .WillRepeatedly(DoAll(SetArgPointee<1>(oldState), SetArgPointee<2>(newState), SetArgPointee<3>(pending))); + EXPECT_CALL(*m_gstWrapper, gstElementStateGetName(oldState)).Times(2).WillRepeatedly(Return("Ready")); + EXPECT_CALL(*m_gstWrapper, gstElementStateGetName(newState)).Times(2).WillRepeatedly(Return("Paused")); + EXPECT_CALL(*m_gstWrapper, gstElementStateGetName(pending)).WillOnce(Return("Void")); + EXPECT_CALL(*m_gstWrapper, gstDebugBinToDotFileWithTs(GST_BIN(&m_pipeline), _, _)); + EXPECT_CALL(m_gstPlayerClient, notifyPlaybackState(firebolt::rialto::PlaybackState::PAUSED)); + EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; + task.execute(); +} + +TEST_F(HandleBusMessageTest, shouldSkipHandlingStateChangedToPausedMessageWhenAsyncFlushWasQueuedBeforeHandleBusMessage) +{ + constexpr bool kFlushOngoing{true}; + + GST_MESSAGE_SRC(&m_message) = GST_OBJECT(&m_pipeline); + GST_MESSAGE_TYPE(&m_message) = GST_MESSAGE_STATE_CHANGED; + GstState oldState = GST_STATE_READY; + GstState newState = GST_STATE_PAUSED; + GstState pending = GST_STATE_VOID_PENDING; + + EXPECT_CALL(*m_gstWrapper, gstMessageParseStateChanged(&m_message, _, _, _)) + .WillRepeatedly(DoAll(SetArgPointee<1>(oldState), SetArgPointee<2>(newState), SetArgPointee<3>(pending))); + EXPECT_CALL(*m_gstWrapper, gstElementStateGetName(oldState)).Times(2).WillRepeatedly(Return("Ready")); + EXPECT_CALL(*m_gstWrapper, gstElementStateGetName(newState)).Times(2).WillRepeatedly(Return("Paused")); + EXPECT_CALL(*m_gstWrapper, gstElementStateGetName(pending)).WillOnce(Return("Void")); + EXPECT_CALL(*m_gstWrapper, gstDebugBinToDotFileWithTs(GST_BIN(&m_pipeline), _, _)); + EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillOnce(Return(kFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillOnce(Return(kFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; + task.execute(); +} + +TEST_F(HandleBusMessageTest, shouldSkipHandlingStateChangedToPausedMessageWhenAsyncFlushWasQueuedAfterHandleBusMessage) +{ + constexpr bool kFlushOngoing{true}; + + GST_MESSAGE_SRC(&m_message) = GST_OBJECT(&m_pipeline); + GST_MESSAGE_TYPE(&m_message) = GST_MESSAGE_STATE_CHANGED; + GstState oldState = GST_STATE_READY; + GstState newState = GST_STATE_PAUSED; + GstState pending = GST_STATE_VOID_PENDING; + + EXPECT_CALL(*m_gstWrapper, gstMessageParseStateChanged(&m_message, _, _, _)) + .WillRepeatedly(DoAll(SetArgPointee<1>(oldState), SetArgPointee<2>(newState), SetArgPointee<3>(pending))); + EXPECT_CALL(*m_gstWrapper, gstElementStateGetName(oldState)).Times(2).WillRepeatedly(Return("Ready")); + EXPECT_CALL(*m_gstWrapper, gstElementStateGetName(newState)).Times(2).WillRepeatedly(Return("Paused")); + EXPECT_CALL(*m_gstWrapper, gstElementStateGetName(pending)).WillOnce(Return("Void")); + EXPECT_CALL(*m_gstWrapper, gstDebugBinToDotFileWithTs(GST_BIN(&m_pipeline), _, _)); + EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillOnce(Return(kFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillOnce(Return(kNoFlushOngoing)).WillOnce(Return(kFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); } @@ -252,9 +382,12 @@ TEST_F(HandleBusMessageTest, shouldHandleStateChangedToPausedAndPendingPausedMes EXPECT_CALL(*m_gstWrapper, gstElementStateGetName(GST_STATE_PAUSED)).WillRepeatedly(Return("Paused")); EXPECT_CALL(*m_gstWrapper, gstDebugBinToDotFileWithTs(GST_BIN(&m_pipeline), _, _)); EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); } @@ -276,14 +409,102 @@ TEST_F(HandleBusMessageTest, shouldHandleStateChangedToPlayingMessage) EXPECT_CALL(m_gstPlayer, startPositionReportingAndCheckAudioUnderflowTimer()); EXPECT_CALL(m_gstPlayerClient, notifyPlaybackState(firebolt::rialto::PlaybackState::PLAYING)); EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); EXPECT_TRUE(m_context.isPlaying); } +TEST_F(HandleBusMessageTest, shouldHandleStateChangedToPlayingMessageWhenSyncFlushIsOngoing) +{ + constexpr bool kIsFlushOngoing{true}; + + m_context.isPlaying = false; + GST_MESSAGE_SRC(&m_message) = GST_OBJECT(&m_pipeline); + GST_MESSAGE_TYPE(&m_message) = GST_MESSAGE_STATE_CHANGED; + GstState oldState = GST_STATE_READY; + GstState newState = GST_STATE_PLAYING; + GstState pending = GST_STATE_VOID_PENDING; + + EXPECT_CALL(*m_gstWrapper, gstMessageParseStateChanged(&m_message, _, _, _)) + .WillRepeatedly(DoAll(SetArgPointee<1>(oldState), SetArgPointee<2>(newState), SetArgPointee<3>(pending))); + EXPECT_CALL(*m_gstWrapper, gstElementStateGetName(oldState)).Times(2).WillRepeatedly(Return("Ready")); + EXPECT_CALL(*m_gstWrapper, gstElementStateGetName(newState)).Times(2).WillRepeatedly(Return("Playing")); + EXPECT_CALL(*m_gstWrapper, gstElementStateGetName(pending)).WillOnce(Return("Void")); + EXPECT_CALL(*m_gstWrapper, gstDebugBinToDotFileWithTs(GST_BIN(&m_pipeline), _, _)); + EXPECT_CALL(m_gstPlayer, startPositionReportingAndCheckAudioUnderflowTimer()); + EXPECT_CALL(m_gstPlayerClient, notifyPlaybackState(firebolt::rialto::PlaybackState::PLAYING)); + EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kIsFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; + task.execute(); + + EXPECT_TRUE(m_context.isPlaying); +} + +TEST_F(HandleBusMessageTest, shouldSkipHandlingStateChangedToPlayingMessageWhenAsyncFlushIsQueuedBeforeHandleBusMessage) +{ + constexpr bool kIsFlushOngoing{true}; + + m_context.isPlaying = false; + GST_MESSAGE_SRC(&m_message) = GST_OBJECT(&m_pipeline); + GST_MESSAGE_TYPE(&m_message) = GST_MESSAGE_STATE_CHANGED; + GstState oldState = GST_STATE_READY; + GstState newState = GST_STATE_PLAYING; + GstState pending = GST_STATE_VOID_PENDING; + + EXPECT_CALL(*m_gstWrapper, gstMessageParseStateChanged(&m_message, _, _, _)) + .WillRepeatedly(DoAll(SetArgPointee<1>(oldState), SetArgPointee<2>(newState), SetArgPointee<3>(pending))); + EXPECT_CALL(*m_gstWrapper, gstElementStateGetName(oldState)).Times(2).WillRepeatedly(Return("Ready")); + EXPECT_CALL(*m_gstWrapper, gstElementStateGetName(newState)).Times(2).WillRepeatedly(Return("Playing")); + EXPECT_CALL(*m_gstWrapper, gstElementStateGetName(pending)).WillOnce(Return("Void")); + EXPECT_CALL(*m_gstWrapper, gstDebugBinToDotFileWithTs(GST_BIN(&m_pipeline), _, _)); + EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillOnce(Return(kIsFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillOnce(Return(kIsFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; + task.execute(); +} + +TEST_F(HandleBusMessageTest, shouldSkipHandlingStateChangedToPlayingMessageWhenAsyncFlushIsQueuedAfterHandleBusMessage) +{ + constexpr bool kIsFlushOngoing{true}; + + m_context.isPlaying = false; + GST_MESSAGE_SRC(&m_message) = GST_OBJECT(&m_pipeline); + GST_MESSAGE_TYPE(&m_message) = GST_MESSAGE_STATE_CHANGED; + GstState oldState = GST_STATE_READY; + GstState newState = GST_STATE_PLAYING; + GstState pending = GST_STATE_VOID_PENDING; + + EXPECT_CALL(*m_gstWrapper, gstMessageParseStateChanged(&m_message, _, _, _)) + .WillRepeatedly(DoAll(SetArgPointee<1>(oldState), SetArgPointee<2>(newState), SetArgPointee<3>(pending))); + EXPECT_CALL(*m_gstWrapper, gstElementStateGetName(oldState)).Times(2).WillRepeatedly(Return("Ready")); + EXPECT_CALL(*m_gstWrapper, gstElementStateGetName(newState)).Times(2).WillRepeatedly(Return("Playing")); + EXPECT_CALL(*m_gstWrapper, gstElementStateGetName(pending)).WillOnce(Return("Void")); + EXPECT_CALL(*m_gstWrapper, gstDebugBinToDotFileWithTs(GST_BIN(&m_pipeline), _, _)); + EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillOnce(Return(kIsFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillOnce(Return(kNoFlushOngoing)).WillOnce(Return(kIsFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; + task.execute(); +} + TEST_F(HandleBusMessageTest, shouldHandleStateChangedToPlayingMessageAndSetPendingPlaybackRate) { m_context.pendingPlaybackRate = 1.25; @@ -303,9 +524,12 @@ TEST_F(HandleBusMessageTest, shouldHandleStateChangedToPlayingMessageAndSetPendi EXPECT_CALL(m_gstPlayerClient, notifyPlaybackState(firebolt::rialto::PlaybackState::PLAYING)); EXPECT_CALL(m_gstPlayer, setPendingPlaybackRate()); EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); } @@ -324,10 +548,12 @@ TEST_F(HandleBusMessageTest, shouldNotHandleQosMessageForUnsupportedFormat) .WillOnce(DoAll(SetArgPointee<1>(format), SetArgPointee<2>(processed), SetArgPointee<3>(dropped))); EXPECT_CALL(*m_gstWrapper, gstFormatGetName(format)).WillOnce(Return("Undefined")); EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); - - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); } @@ -348,10 +574,12 @@ TEST_F(HandleBusMessageTest, shouldNotHandleQosMessageForUnknownSourceType) StrEq(GST_ELEMENT_METADATA_KLASS))) .WillOnce(Return("Unknown")); EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); - - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); } @@ -374,9 +602,12 @@ TEST_F(HandleBusMessageTest, shouldHandleQosMessageForVideo) EXPECT_CALL(m_gstPlayerClient, notifyQos(firebolt::rialto::MediaSourceType::VIDEO, QosInfoMatcher(processed, dropped))); EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); } @@ -399,9 +630,12 @@ TEST_F(HandleBusMessageTest, shouldHandleQosMessageForAudio) EXPECT_CALL(m_gstPlayerClient, notifyQos(firebolt::rialto::MediaSourceType::AUDIO, QosInfoMatcher(processed, dropped))); EXPECT_CALL(*m_gstWrapper, gstMessageUnref(&m_message)); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); } @@ -413,15 +647,17 @@ TEST_F(HandleBusMessageTest, shouldHandleErrorMessageNoEos) GST_MESSAGE_TYPE(&m_message) = GST_MESSAGE_ERROR; GST_MESSAGE_SRC(&m_message) = GST_OBJECT_CAST(&m_videoSrc); m_err.domain = GST_CORE_ERROR; - + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); EXPECT_CALL(*m_gstWrapper, gstMessageParseError(&m_message, _, _)) .WillRepeatedly(DoAll(SetArgPointee<1>(&m_err), SetArgPointee<2>(m_debug))); EXPECT_CALL(m_gstPlayerClient, notifyPlaybackState(firebolt::rialto::PlaybackState::FAILURE)); expectFreeErrorMessage(); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); } @@ -436,15 +672,17 @@ TEST_F(HandleBusMessageTest, shouldHandleErrorMessageWhenEosAllSources) m_context.endOfStreamInfo.emplace(firebolt::rialto::MediaSourceType::AUDIO, firebolt::rialto::server::EosState::SET); m_context.endOfStreamInfo.emplace(firebolt::rialto::MediaSourceType::VIDEO, firebolt::rialto::server::EosState::SET); - + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); EXPECT_CALL(*m_gstWrapper, gstMessageParseError(&m_message, _, _)) .WillRepeatedly(DoAll(SetArgPointee<1>(&m_err), SetArgPointee<2>(m_debug))); EXPECT_CALL(m_gstPlayerClient, notifyPlaybackState(firebolt::rialto::PlaybackState::FAILURE)); expectFreeErrorMessage(); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); } @@ -456,15 +694,17 @@ TEST_F(HandleBusMessageTest, shouldHandleStreamErrorMessageNoEos) GST_MESSAGE_TYPE(&m_message) = GST_MESSAGE_ERROR; GST_MESSAGE_SRC(&m_message) = GST_OBJECT_CAST(&m_videoSrc); m_err.domain = GST_STREAM_ERROR; - + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); EXPECT_CALL(*m_gstWrapper, gstMessageParseError(&m_message, _, _)) .WillRepeatedly(DoAll(SetArgPointee<1>(&m_err), SetArgPointee<2>(m_debug))); EXPECT_CALL(m_gstPlayerClient, notifyPlaybackState(firebolt::rialto::PlaybackState::FAILURE)); expectFreeErrorMessage(); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); } @@ -478,15 +718,17 @@ TEST_F(HandleBusMessageTest, shouldHandleStreamErrorMessageWhenEosSingleSource) m_err.domain = GST_STREAM_ERROR; m_context.endOfStreamInfo.emplace(firebolt::rialto::MediaSourceType::AUDIO, firebolt::rialto::server::EosState::SET); - + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); EXPECT_CALL(*m_gstWrapper, gstMessageParseError(&m_message, _, _)) .WillRepeatedly(DoAll(SetArgPointee<1>(&m_err), SetArgPointee<2>(m_debug))); EXPECT_CALL(m_gstPlayerClient, notifyPlaybackState(firebolt::rialto::PlaybackState::FAILURE)); expectFreeErrorMessage(); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); } @@ -501,15 +743,17 @@ TEST_F(HandleBusMessageTest, shouldHandleStreamErrorMessageWhenEosAllSources) m_context.endOfStreamInfo.emplace(firebolt::rialto::MediaSourceType::AUDIO, firebolt::rialto::server::EosState::SET); m_context.endOfStreamInfo.emplace(firebolt::rialto::MediaSourceType::VIDEO, firebolt::rialto::server::EosState::SET); - + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); EXPECT_CALL(*m_gstWrapper, gstMessageParseError(&m_message, _, _)) .WillRepeatedly(DoAll(SetArgPointee<1>(&m_err), SetArgPointee<2>(m_debug))); EXPECT_CALL(m_gstPlayerClient, notifyPlaybackState(firebolt::rialto::PlaybackState::END_OF_STREAM)); expectFreeErrorMessage(); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); EXPECT_TRUE(m_context.eosNotified); @@ -528,14 +772,16 @@ TEST_F(HandleBusMessageTest, shouldHandleStreamErrorMessageWhenEosAllSourcesAndE m_context.endOfStreamInfo.emplace(firebolt::rialto::MediaSourceType::AUDIO, firebolt::rialto::server::EosState::SET); m_context.endOfStreamInfo.emplace(firebolt::rialto::MediaSourceType::VIDEO, firebolt::rialto::server::EosState::SET); m_context.eosNotified = true; - + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); EXPECT_CALL(*m_gstWrapper, gstMessageParseError(&m_message, _, _)) .WillRepeatedly(DoAll(SetArgPointee<1>(&m_err), SetArgPointee<2>(m_debug))); expectFreeErrorMessage(); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); } @@ -552,16 +798,18 @@ TEST_F(HandleBusMessageTest, shouldHandleWarningMessageForAudioDecryption) GST_MESSAGE_SRC(&m_message) = decryptor; m_err.domain = GST_STREAM_ERROR; m_err.code = GST_STREAM_ERROR_DECRYPT; - + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); EXPECT_CALL(*m_gstWrapper, gstMessageParseWarning(&m_message, _, _)) .WillOnce(DoAll(SetArgPointee<1>(&m_err), SetArgPointee<2>(m_debug))); EXPECT_CALL(m_gstPlayerClient, notifyPlaybackError(firebolt::rialto::MediaSourceType::AUDIO, firebolt::rialto::PlaybackError::DECRYPTION)); expectFreeErrorMessage(); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); g_object_unref(decryptor); @@ -580,16 +828,18 @@ TEST_F(HandleBusMessageTest, shouldHandleWarningMessageForVideoDecryption) GST_MESSAGE_SRC(&m_message) = decryptor; m_err.domain = GST_STREAM_ERROR; m_err.code = GST_STREAM_ERROR_DECRYPT; - + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); EXPECT_CALL(*m_gstWrapper, gstMessageParseWarning(&m_message, _, _)) .WillOnce(DoAll(SetArgPointee<1>(&m_err), SetArgPointee<2>(m_debug))); EXPECT_CALL(m_gstPlayerClient, notifyPlaybackError(firebolt::rialto::MediaSourceType::VIDEO, firebolt::rialto::PlaybackError::DECRYPTION)); expectFreeErrorMessage(); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); g_object_unref(decryptor); @@ -607,14 +857,16 @@ TEST_F(HandleBusMessageTest, shouldHandleWarningMessageGeneric) GST_MESSAGE_TYPE(&m_message) = GST_MESSAGE_WARNING; GST_MESSAGE_SRC(&m_message) = element; m_err.domain = GST_CORE_ERROR; - + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); EXPECT_CALL(*m_gstWrapper, gstMessageParseWarning(&m_message, _, _)) .WillOnce(DoAll(SetArgPointee<1>(&m_err), SetArgPointee<2>(m_debug))); expectFreeErrorMessage(); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); g_object_unref(element); @@ -633,14 +885,16 @@ TEST_F(HandleBusMessageTest, shouldHandleWarningMessageForUnknownSrcTypeDecrypti GST_MESSAGE_SRC(&m_message) = element; m_err.domain = GST_STREAM_ERROR; m_err.code = GST_STREAM_ERROR_DECRYPT; - + EXPECT_CALL(m_flushWatcherMock, isFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); + EXPECT_CALL(m_flushWatcherMock, isAsyncFlushOngoing()).WillRepeatedly(Return(kNoFlushOngoing)); EXPECT_CALL(*m_gstWrapper, gstMessageParseWarning(&m_message, _, _)) .WillOnce(DoAll(SetArgPointee<1>(&m_err), SetArgPointee<2>(m_debug))); expectFreeErrorMessage(); - firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient, - m_gstWrapper, m_glibWrapper, &m_message, - kNoFlushOngoing}; + firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, + &m_gstPlayerClient, m_gstWrapper, + m_glibWrapper, &m_message, + m_flushWatcherMock}; task.execute(); g_object_unref(element); diff --git a/tests/unittests/media/server/main/mediaPipeline/FlushTest.cpp b/tests/unittests/media/server/main/mediaPipeline/FlushTest.cpp index 65762329d..a9ca62986 100644 --- a/tests/unittests/media/server/main/mediaPipeline/FlushTest.cpp +++ b/tests/unittests/media/server/main/mediaPipeline/FlushTest.cpp @@ -29,7 +29,6 @@ class RialtoServerMediaPipelineFlushTest : public MediaPipelineTestBase const char *m_kMimeType{"video/mpeg"}; const bool m_kResetTime{true}; const int m_kDummySourceId{123}; - const bool m_kIsAsync{true}; RialtoServerMediaPipelineFlushTest() { createMediaPipeline(); } @@ -53,10 +52,8 @@ TEST_F(RialtoServerMediaPipelineFlushTest, FlushSuccess) bool async{false}; mainThreadWillEnqueueTaskAndWait(); - EXPECT_CALL(*m_gstPlayerMock, isAsync(m_kType)).WillOnce(Return(m_kIsAsync)); - EXPECT_CALL(*m_gstPlayerMock, flush(m_kType, m_kResetTime)); + EXPECT_CALL(*m_gstPlayerMock, flush(m_kType, m_kResetTime, async)); EXPECT_TRUE(m_mediaPipeline->flush(sourceId, m_kResetTime, async)); - EXPECT_EQ(async, m_kIsAsync); } /** @@ -99,10 +96,8 @@ TEST_F(RialtoServerMediaPipelineFlushTest, FlushResetEos) setEos(firebolt::rialto::MediaSourceType::VIDEO); mainThreadWillEnqueueTaskAndWait(); - EXPECT_CALL(*m_gstPlayerMock, isAsync(m_kType)).WillOnce(Return(m_kIsAsync)); - EXPECT_CALL(*m_gstPlayerMock, flush(m_kType, m_kResetTime)); + EXPECT_CALL(*m_gstPlayerMock, flush(m_kType, m_kResetTime, async)); EXPECT_TRUE(m_mediaPipeline->flush(sourceId, m_kResetTime, async)); - EXPECT_EQ(async, m_kIsAsync); // Expect need data notified to client expectNotifyNeedData(firebolt::rialto::MediaSourceType::VIDEO, sourceId, 3); diff --git a/tests/unittests/media/server/mocks/gstplayer/FlushWatcherMock.h b/tests/unittests/media/server/mocks/gstplayer/FlushWatcherMock.h index 27d16a2bb..b3d0390f3 100644 --- a/tests/unittests/media/server/mocks/gstplayer/FlushWatcherMock.h +++ b/tests/unittests/media/server/mocks/gstplayer/FlushWatcherMock.h @@ -28,9 +28,10 @@ namespace firebolt::rialto::server class FlushWatcherMock : public IFlushWatcher { public: - MOCK_METHOD(void, setFlushing, (const MediaSourceType &type), (override)); + MOCK_METHOD(void, setFlushing, (const MediaSourceType &type, bool async), (override)); MOCK_METHOD(void, setFlushed, (const MediaSourceType &type), (override)); MOCK_METHOD(bool, isFlushOngoing, (), (const, override)); + MOCK_METHOD(bool, isAsyncFlushOngoing, (), (const, override)); }; } // namespace firebolt::rialto::server #endif // FIREBOLT_RIALTO_SERVER_FLUSH_WATCHER_MOCK_H_ diff --git a/tests/unittests/media/server/mocks/gstplayer/GenericPlayerTaskFactoryMock.h b/tests/unittests/media/server/mocks/gstplayer/GenericPlayerTaskFactoryMock.h index 815ed0520..656416104 100644 --- a/tests/unittests/media/server/mocks/gstplayer/GenericPlayerTaskFactoryMock.h +++ b/tests/unittests/media/server/mocks/gstplayer/GenericPlayerTaskFactoryMock.h @@ -50,7 +50,8 @@ class GenericPlayerTaskFactoryMock : public IGenericPlayerTaskFactory MOCK_METHOD(std::unique_ptr, createFinishSetupSource, (GenericPlayerContext & context, IGstGenericPlayerPrivate &player), (const, override)); MOCK_METHOD(std::unique_ptr, createHandleBusMessage, - (GenericPlayerContext & context, IGstGenericPlayerPrivate &player, GstMessage *message, bool isFlushing), + (GenericPlayerContext & context, IGstGenericPlayerPrivate &player, GstMessage *message, + const IFlushWatcher &flushWatcher), (const, override)); MOCK_METHOD(std::unique_ptr, createNeedData, (GenericPlayerContext & context, IGstGenericPlayerPrivate &player, GstAppSrc *src), (const, override)); diff --git a/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerMock.h b/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerMock.h index b03de8f81..224147f1d 100644 --- a/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerMock.h +++ b/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerMock.h @@ -56,7 +56,6 @@ class GstGenericPlayerMock : public IGstGenericPlayer MOCK_METHOD(bool, getVolume, (double &volume), (override)); MOCK_METHOD(void, setMute, (const MediaSourceType &mediaSourceType, bool mute), (override)); MOCK_METHOD(bool, getMute, (const MediaSourceType &mediaSourceType, bool &mute), (override)); - MOCK_METHOD(bool, isAsync, (const MediaSourceType &mediaSourceType), (const, override)); MOCK_METHOD(void, setTextTrackIdentifier, (const std::string &textTrackIdentifier), (override)); MOCK_METHOD(bool, getTextTrackIdentifier, (std::string & textTrackIdentifier), (override)); MOCK_METHOD(bool, setLowLatency, (bool lowLatency), (override)); @@ -66,7 +65,7 @@ class GstGenericPlayerMock : public IGstGenericPlayer MOCK_METHOD(bool, setStreamSyncMode, (const MediaSourceType &mediaSourceType, int32_t streamSyncMode), (override)); MOCK_METHOD(bool, getStreamSyncMode, (int32_t & streamSyncMode), (override)); MOCK_METHOD(void, ping, (std::unique_ptr && heartbeatHandler), (override)); - MOCK_METHOD(void, flush, (const MediaSourceType &mediaSourceType, bool resetTime), (override)); + MOCK_METHOD(void, flush, (const MediaSourceType &mediaSourceType, bool resetTime, bool &async), (override)); MOCK_METHOD(void, setSourcePosition, (const MediaSourceType &mediaSourceType, int64_t position, bool resetTime, double appliedRate, uint64_t stopPosition), From 10b155635cbaed541da22e5307c08620fd0cf2c0 Mon Sep 17 00:00:00 2001 From: Yurii Yakubin <144821088+yurii-yakubin@users.noreply.github.com> Date: Wed, 11 Jun 2025 10:55:44 +0100 Subject: [PATCH 02/15] Removed WorkerThread.join method (#382) Summary: Removed WorkerThread.join method Type: Fix Test Plan: UT/ CT, Fullstack Jira: ENTDAI-464 --- media/server/gstplayer/CMakeLists.txt | 2 - .../gstplayer/include/GstGenericPlayer.h | 1 - .../gstplayer/include/GstWebAudioPlayer.h | 1 - .../include/IGstGenericPlayerPrivate.h | 5 --- .../include/IGstWebAudioPlayerPrivate.h | 5 --- .../server/gstplayer/include/IWorkerThread.h | 5 --- media/server/gstplayer/include/WorkerThread.h | 1 - .../include/tasks/IGenericPlayerTaskFactory.h | 9 ---- .../tasks/IWebAudioPlayerTaskFactory.h | 9 ---- .../tasks/generic/GenericPlayerTaskFactory.h | 1 - .../include/tasks/generic/Shutdown.h | 45 ------------------- .../include/tasks/webAudio/Shutdown.h | 45 ------------------- .../webAudio/WebAudioPlayerTaskFactory.h | 1 - .../gstplayer/source/GstGenericPlayer.cpp | 11 ----- .../gstplayer/source/GstWebAudioPlayer.cpp | 10 ----- .../server/gstplayer/source/WorkerThread.cpp | 15 +++---- .../generic/GenericPlayerTaskFactory.cpp | 6 --- .../source/tasks/generic/Shutdown.cpp | 41 ----------------- .../source/tasks/webAudio/Shutdown.cpp | 41 ----------------- .../webAudio/WebAudioPlayerTaskFactory.cpp | 6 --- .../media/server/gstplayer/CMakeLists.txt | 2 - .../gstplayer/genericPlayer/CreateTest.cpp | 1 - .../GstGenericPlayerPrivateTest.cpp | 6 --- .../common/GenericTasksTestsBase.cpp | 12 ----- .../common/GenericTasksTestsBase.h | 4 -- .../common/GstGenericPlayerTestCommon.cpp | 9 ---- .../common/GstGenericPlayerTestCommon.h | 1 - .../GenericPlayerTaskFactoryTest.cpp | 8 ---- .../genericPlayer/tasksTests/ShutdownTest.cpp | 30 ------------- .../gstplayer/webAudioPlayer/CreateTest.cpp | 5 --- .../GstWebAudioPlayerPrivateTest.cpp | 6 --- .../common/GstWebAudioPlayerTestCommon.cpp | 10 ----- .../common/GstWebAudioPlayerTestCommon.h | 1 - .../common/WebAudioTasksTestsBase.cpp | 12 ----- .../common/WebAudioTasksTestsBase.h | 4 -- .../webAudioPlayer/taskTests/ShutdownTest.cpp | 30 ------------- .../WebAudioPlayerTaskFactoryTest.cpp | 8 ---- .../gstplayer/GenericPlayerTaskFactoryMock.h | 1 - .../gstplayer/GstGenericPlayerPrivateMock.h | 1 - .../gstplayer/GstWebAudioPlayerPrivateMock.h | 1 - .../gstplayer/WebAudioPlayerTaskFactoryMock.h | 1 - .../server/mocks/gstplayer/WorkerThreadMock.h | 1 - 42 files changed, 5 insertions(+), 409 deletions(-) delete mode 100644 media/server/gstplayer/include/tasks/generic/Shutdown.h delete mode 100644 media/server/gstplayer/include/tasks/webAudio/Shutdown.h delete mode 100644 media/server/gstplayer/source/tasks/generic/Shutdown.cpp delete mode 100644 media/server/gstplayer/source/tasks/webAudio/Shutdown.cpp delete mode 100644 tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/ShutdownTest.cpp delete mode 100644 tests/unittests/media/server/gstplayer/webAudioPlayer/taskTests/ShutdownTest.cpp diff --git a/media/server/gstplayer/CMakeLists.txt b/media/server/gstplayer/CMakeLists.txt index 1a49fde59..1ab652fff 100644 --- a/media/server/gstplayer/CMakeLists.txt +++ b/media/server/gstplayer/CMakeLists.txt @@ -68,7 +68,6 @@ add_library( source/tasks/generic/SetVolume.cpp source/tasks/generic/SetupElement.cpp source/tasks/generic/SetupSource.cpp - source/tasks/generic/Shutdown.cpp source/tasks/generic/Stop.cpp source/tasks/generic/SwitchSource.cpp source/tasks/generic/Underflow.cpp @@ -81,7 +80,6 @@ add_library( source/tasks/webAudio/Play.cpp source/tasks/webAudio/SetCaps.cpp source/tasks/webAudio/SetVolume.cpp - source/tasks/webAudio/Shutdown.cpp source/tasks/webAudio/Stop.cpp source/tasks/webAudio/WebAudioPlayerTaskFactory.cpp source/tasks/webAudio/WriteBuffer.cpp diff --git a/media/server/gstplayer/include/GstGenericPlayer.h b/media/server/gstplayer/include/GstGenericPlayer.h index 6b6f97197..1ad8b2a41 100644 --- a/media/server/gstplayer/include/GstGenericPlayer.h +++ b/media/server/gstplayer/include/GstGenericPlayer.h @@ -168,7 +168,6 @@ class GstGenericPlayer : public IGstGenericPlayer, public IGstGenericPlayerPriva bool changePipelineState(GstState newState) override; void startPositionReportingAndCheckAudioUnderflowTimer() override; void stopPositionReportingAndCheckAudioUnderflowTimer() override; - void stopWorkerThread() override; void cancelUnderflow(firebolt::rialto::MediaSourceType mediaSource) override; void setPendingPlaybackRate() override; void renderFrame() override; diff --git a/media/server/gstplayer/include/GstWebAudioPlayer.h b/media/server/gstplayer/include/GstWebAudioPlayer.h index ccc3ce627..8d3d87dd4 100644 --- a/media/server/gstplayer/include/GstWebAudioPlayer.h +++ b/media/server/gstplayer/include/GstWebAudioPlayer.h @@ -94,7 +94,6 @@ class GstWebAudioPlayer : public IGstWebAudioPlayer, public IGstWebAudioPlayerPr uint64_t getQueuedBytes() override; bool changePipelineState(GstState newState) override; - void stopWorkerThread() override; void handleBusMessage(GstMessage *message) override; void ping(std::unique_ptr &&heartbeatHandler) override; diff --git a/media/server/gstplayer/include/IGstGenericPlayerPrivate.h b/media/server/gstplayer/include/IGstGenericPlayerPrivate.h index 8df30e1a4..b0ccfa75f 100644 --- a/media/server/gstplayer/include/IGstGenericPlayerPrivate.h +++ b/media/server/gstplayer/include/IGstGenericPlayerPrivate.h @@ -181,11 +181,6 @@ class IGstGenericPlayerPrivate */ virtual void stopPositionReportingAndCheckAudioUnderflowTimer() = 0; - /** - * @brief Stops worker thread. Called by the worker thread. - */ - virtual void stopWorkerThread() = 0; - /** * @brief Restores playback after underflow. Called by the worker thread. * diff --git a/media/server/gstplayer/include/IGstWebAudioPlayerPrivate.h b/media/server/gstplayer/include/IGstWebAudioPlayerPrivate.h index 216b4653e..a0e7362ae 100644 --- a/media/server/gstplayer/include/IGstWebAudioPlayerPrivate.h +++ b/media/server/gstplayer/include/IGstWebAudioPlayerPrivate.h @@ -43,11 +43,6 @@ class IGstWebAudioPlayerPrivate * @retval true on success. */ virtual bool changePipelineState(GstState newState) = 0; - - /** - * @brief Stops worker thread. Called by the worker thread. - */ - virtual void stopWorkerThread() = 0; }; } // namespace firebolt::rialto::server diff --git a/media/server/gstplayer/include/IWorkerThread.h b/media/server/gstplayer/include/IWorkerThread.h index 011fc7bb6..12ce64835 100644 --- a/media/server/gstplayer/include/IWorkerThread.h +++ b/media/server/gstplayer/include/IWorkerThread.h @@ -50,11 +50,6 @@ class IWorkerThread */ virtual void stop() = 0; - /** - * @brief Joins the task thread - */ - virtual void join() = 0; - /** * @brief Queues a task in the task queue. */ diff --git a/media/server/gstplayer/include/WorkerThread.h b/media/server/gstplayer/include/WorkerThread.h index 0a3ed3204..74c11e9e8 100644 --- a/media/server/gstplayer/include/WorkerThread.h +++ b/media/server/gstplayer/include/WorkerThread.h @@ -43,7 +43,6 @@ class WorkerThread : public IWorkerThread ~WorkerThread() override; void stop() override; - void join() override; void enqueueTask(std::unique_ptr &&task) override; private: diff --git a/media/server/gstplayer/include/tasks/IGenericPlayerTaskFactory.h b/media/server/gstplayer/include/tasks/IGenericPlayerTaskFactory.h index ea91604e2..f5a8dc358 100644 --- a/media/server/gstplayer/include/tasks/IGenericPlayerTaskFactory.h +++ b/media/server/gstplayer/include/tasks/IGenericPlayerTaskFactory.h @@ -355,15 +355,6 @@ class IGenericPlayerTaskFactory const firebolt::rialto::MediaSourceType &type, int32_t streamSyncMode) const = 0; - /** - * @brief Creates a Shutdown task. - * - * @param[in] context : The GstGenericPlayer context - * - * @retval the new Shutdown task instance. - */ - virtual std::unique_ptr createShutdown(IGstGenericPlayerPrivate &player) const = 0; - /** * @brief Creates a Stop task. * diff --git a/media/server/gstplayer/include/tasks/IWebAudioPlayerTaskFactory.h b/media/server/gstplayer/include/tasks/IWebAudioPlayerTaskFactory.h index 439d9f990..f68187132 100644 --- a/media/server/gstplayer/include/tasks/IWebAudioPlayerTaskFactory.h +++ b/media/server/gstplayer/include/tasks/IWebAudioPlayerTaskFactory.h @@ -38,15 +38,6 @@ class IWebAudioPlayerTaskFactory IWebAudioPlayerTaskFactory() = default; virtual ~IWebAudioPlayerTaskFactory() = default; - /** - * @brief Creates a Shutdown task. - * - * @param[in] player : The GstWebAudioPlayer instance - * - * @retval the new Shutdown task instance. - */ - virtual std::unique_ptr createShutdown(IGstWebAudioPlayerPrivate &player) const = 0; - /** * @brief Creates a Stop task. * diff --git a/media/server/gstplayer/include/tasks/generic/GenericPlayerTaskFactory.h b/media/server/gstplayer/include/tasks/generic/GenericPlayerTaskFactory.h index be72f5136..f330edfe7 100644 --- a/media/server/gstplayer/include/tasks/generic/GenericPlayerTaskFactory.h +++ b/media/server/gstplayer/include/tasks/generic/GenericPlayerTaskFactory.h @@ -95,7 +95,6 @@ class GenericPlayerTaskFactory : public IGenericPlayerTaskFactory std::unique_ptr createSetStreamSyncMode(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, const firebolt::rialto::MediaSourceType &type, int32_t streamSyncMode) const override; - std::unique_ptr createShutdown(IGstGenericPlayerPrivate &player) const override; std::unique_ptr createStop(GenericPlayerContext &context, IGstGenericPlayerPrivate &player) const override; std::unique_ptr createUnderflow(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, diff --git a/media/server/gstplayer/include/tasks/generic/Shutdown.h b/media/server/gstplayer/include/tasks/generic/Shutdown.h deleted file mode 100644 index d055c8e8c..000000000 --- a/media/server/gstplayer/include/tasks/generic/Shutdown.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SHUTDOWN_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SHUTDOWN_H_ - -#include "IPlayerTask.h" -#include - -namespace firebolt::rialto::server -{ -class IGstGenericPlayerPrivate; -} // namespace firebolt::rialto::server - -namespace firebolt::rialto::server::tasks::generic -{ -class Shutdown : public IPlayerTask -{ -public: - explicit Shutdown(IGstGenericPlayerPrivate &player); - ~Shutdown() override; - void execute() const override; - -private: - IGstGenericPlayerPrivate &m_player; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SHUTDOWN_H_ diff --git a/media/server/gstplayer/include/tasks/webAudio/Shutdown.h b/media/server/gstplayer/include/tasks/webAudio/Shutdown.h deleted file mode 100644 index c019ec27c..000000000 --- a/media/server/gstplayer/include/tasks/webAudio/Shutdown.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SHUTDOWN_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SHUTDOWN_H_ - -#include "IPlayerTask.h" -#include - -namespace firebolt::rialto::server -{ -class IGstWebAudioPlayerPrivate; -} // namespace firebolt::rialto::server - -namespace firebolt::rialto::server::tasks::webaudio -{ -class Shutdown : public IPlayerTask -{ -public: - explicit Shutdown(IGstWebAudioPlayerPrivate &player); - ~Shutdown() override; - void execute() const override; - -private: - IGstWebAudioPlayerPrivate &m_player; -}; -} // namespace firebolt::rialto::server::tasks::webaudio - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SHUTDOWN_H_ diff --git a/media/server/gstplayer/include/tasks/webAudio/WebAudioPlayerTaskFactory.h b/media/server/gstplayer/include/tasks/webAudio/WebAudioPlayerTaskFactory.h index 44af6aaff..d6923b153 100644 --- a/media/server/gstplayer/include/tasks/webAudio/WebAudioPlayerTaskFactory.h +++ b/media/server/gstplayer/include/tasks/webAudio/WebAudioPlayerTaskFactory.h @@ -37,7 +37,6 @@ class WebAudioPlayerTaskFactory : public IWebAudioPlayerTaskFactory const std::shared_ptr &glibWrapper); ~WebAudioPlayerTaskFactory() override = default; - std::unique_ptr createShutdown(IGstWebAudioPlayerPrivate &player) const override; std::unique_ptr createStop(IGstWebAudioPlayerPrivate &player) const override; std::unique_ptr createPlay(IGstWebAudioPlayerPrivate &player) const override; std::unique_ptr createPause(IGstWebAudioPlayerPrivate &player) const override; diff --git a/media/server/gstplayer/source/GstGenericPlayer.cpp b/media/server/gstplayer/source/GstGenericPlayer.cpp index cbdde9f7c..070fa677b 100644 --- a/media/server/gstplayer/source/GstGenericPlayer.cpp +++ b/media/server/gstplayer/source/GstGenericPlayer.cpp @@ -247,9 +247,6 @@ void GstGenericPlayer::initMsePipeline() void GstGenericPlayer::resetWorkerThread() { - // Shutdown task thread - m_workerThread->enqueueTask(m_taskFactory->createShutdown(*this)); - m_workerThread->join(); m_workerThread.reset(); } @@ -1607,14 +1604,6 @@ void GstGenericPlayer::stopPositionReportingAndCheckAudioUnderflowTimer() } } -void GstGenericPlayer::stopWorkerThread() -{ - if (m_workerThread) - { - m_workerThread->stop(); - } -} - void GstGenericPlayer::setPendingPlaybackRate() { RIALTO_SERVER_LOG_INFO("Setting pending playback rate"); diff --git a/media/server/gstplayer/source/GstWebAudioPlayer.cpp b/media/server/gstplayer/source/GstWebAudioPlayer.cpp index 7a632bb4c..71f6ccce7 100644 --- a/media/server/gstplayer/source/GstWebAudioPlayer.cpp +++ b/media/server/gstplayer/source/GstWebAudioPlayer.cpp @@ -354,8 +354,6 @@ void GstWebAudioPlayer::termWebAudioPipeline() void GstWebAudioPlayer::resetWorkerThread() { - m_workerThread->enqueueTask(m_taskFactory->createShutdown(*this)); - m_workerThread->join(); m_workerThread.reset(); } @@ -426,14 +424,6 @@ bool GstWebAudioPlayer::changePipelineState(GstState newState) return true; } -void GstWebAudioPlayer::stopWorkerThread() -{ - if (m_workerThread) - { - m_workerThread->stop(); - } -} - void GstWebAudioPlayer::handleBusMessage(GstMessage *message) { if (m_workerThread) diff --git a/media/server/gstplayer/source/WorkerThread.cpp b/media/server/gstplayer/source/WorkerThread.cpp index 7c065051f..49afc7259 100644 --- a/media/server/gstplayer/source/WorkerThread.cpp +++ b/media/server/gstplayer/source/WorkerThread.cpp @@ -62,8 +62,11 @@ WorkerThread::WorkerThread() WorkerThread::~WorkerThread() { - stop(); - join(); + if (m_taskThread.joinable()) + { + stop(); + m_taskThread.join(); + } } void WorkerThread::stop() @@ -74,14 +77,6 @@ void WorkerThread::stop() enqueueTask(std::make_unique(std::move(shutdownTask))); } -void WorkerThread::join() -{ - if (m_taskThread.joinable()) - { - m_taskThread.join(); - } -} - void WorkerThread::enqueueTask(std::unique_ptr &&task) { if (task) diff --git a/media/server/gstplayer/source/tasks/generic/GenericPlayerTaskFactory.cpp b/media/server/gstplayer/source/tasks/generic/GenericPlayerTaskFactory.cpp index b7ea1622f..ec0e35c5e 100644 --- a/media/server/gstplayer/source/tasks/generic/GenericPlayerTaskFactory.cpp +++ b/media/server/gstplayer/source/tasks/generic/GenericPlayerTaskFactory.cpp @@ -52,7 +52,6 @@ #include "tasks/generic/SetVolume.h" #include "tasks/generic/SetupElement.h" #include "tasks/generic/SetupSource.h" -#include "tasks/generic/Shutdown.h" #include "tasks/generic/Stop.h" #include "tasks/generic/SwitchSource.h" #include "tasks/generic/Underflow.h" @@ -250,11 +249,6 @@ GenericPlayerTaskFactory::createSetStreamSyncMode(GenericPlayerContext &context, return std::make_unique(context, player, type, streamSyncMode); } -std::unique_ptr GenericPlayerTaskFactory::createShutdown(IGstGenericPlayerPrivate &player) const -{ - return std::make_unique(player); -} - std::unique_ptr GenericPlayerTaskFactory::createStop(GenericPlayerContext &context, IGstGenericPlayerPrivate &player) const { diff --git a/media/server/gstplayer/source/tasks/generic/Shutdown.cpp b/media/server/gstplayer/source/tasks/generic/Shutdown.cpp deleted file mode 100644 index b3bb41a82..000000000 --- a/media/server/gstplayer/source/tasks/generic/Shutdown.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/Shutdown.h" -#include "IGstGenericPlayerPrivate.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::tasks::generic -{ -Shutdown::Shutdown(IGstGenericPlayerPrivate &player) : m_player{player} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing Shutdown"); -} - -Shutdown::~Shutdown() -{ - RIALTO_SERVER_LOG_DEBUG("Shutdown finished"); -} - -void Shutdown::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing Shutdown"); - m_player.stopWorkerThread(); -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/media/server/gstplayer/source/tasks/webAudio/Shutdown.cpp b/media/server/gstplayer/source/tasks/webAudio/Shutdown.cpp deleted file mode 100644 index 1fa57f51e..000000000 --- a/media/server/gstplayer/source/tasks/webAudio/Shutdown.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/webAudio/Shutdown.h" -#include "IGstWebAudioPlayerPrivate.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::tasks::webaudio -{ -Shutdown::Shutdown(IGstWebAudioPlayerPrivate &player) : m_player{player} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing Shutdown"); -} - -Shutdown::~Shutdown() -{ - RIALTO_SERVER_LOG_DEBUG("Shutdown finished"); -} - -void Shutdown::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing Shutdown"); - m_player.stopWorkerThread(); -} -} // namespace firebolt::rialto::server::tasks::webaudio diff --git a/media/server/gstplayer/source/tasks/webAudio/WebAudioPlayerTaskFactory.cpp b/media/server/gstplayer/source/tasks/webAudio/WebAudioPlayerTaskFactory.cpp index 2e1c392a4..e8cc5f0c8 100644 --- a/media/server/gstplayer/source/tasks/webAudio/WebAudioPlayerTaskFactory.cpp +++ b/media/server/gstplayer/source/tasks/webAudio/WebAudioPlayerTaskFactory.cpp @@ -24,7 +24,6 @@ #include "tasks/webAudio/Play.h" #include "tasks/webAudio/SetCaps.h" #include "tasks/webAudio/SetVolume.h" -#include "tasks/webAudio/Shutdown.h" #include "tasks/webAudio/Stop.h" #include "tasks/webAudio/WriteBuffer.h" @@ -37,11 +36,6 @@ WebAudioPlayerTaskFactory::WebAudioPlayerTaskFactory( { } -std::unique_ptr WebAudioPlayerTaskFactory::createShutdown(IGstWebAudioPlayerPrivate &player) const -{ - return std::make_unique(player); -} - std::unique_ptr WebAudioPlayerTaskFactory::createStop(IGstWebAudioPlayerPrivate &player) const { return std::make_unique(player); diff --git a/tests/unittests/media/server/gstplayer/CMakeLists.txt b/tests/unittests/media/server/gstplayer/CMakeLists.txt index 94e79529c..69429fc27 100644 --- a/tests/unittests/media/server/gstplayer/CMakeLists.txt +++ b/tests/unittests/media/server/gstplayer/CMakeLists.txt @@ -63,7 +63,6 @@ add_gtests(RialtoServerGstPlayerUnitTests genericPlayer/tasksTests/SetVolumeTest.cpp genericPlayer/tasksTests/SetupElementTest.cpp genericPlayer/tasksTests/SetupSourceTest.cpp - genericPlayer/tasksTests/ShutdownTest.cpp genericPlayer/tasksTests/StopTest.cpp genericPlayer/tasksTests/SwitchSourceTest.cpp genericPlayer/tasksTests/UnderflowTest.cpp @@ -86,7 +85,6 @@ add_gtests(RialtoServerGstPlayerUnitTests webAudioPlayer/taskTests/EosTest.cpp webAudioPlayer/taskTests/HandleBusMessageTest.cpp webAudioPlayer/taskTests/SetVolumeTest.cpp - webAudioPlayer/taskTests/ShutdownTest.cpp webAudioPlayer/taskTests/StopTest.cpp webAudioPlayer/taskTests/SetCapsTest.cpp webAudioPlayer/taskTests/WriteBufferTest.cpp diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/CreateTest.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/CreateTest.cpp index d94251132..d134b3664 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/CreateTest.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/CreateTest.cpp @@ -408,7 +408,6 @@ TEST_F(RialtoServerCreateGstGenericPlayerTest, UnknownMediaType) { EXPECT_CALL(m_gstInitialiserMock, waitForInitialisation()); initFactories(); - expectShutdown(); executeTaskWhenEnqueued(); EXPECT_CALL(*m_gstSrcMock, initSrc()); EXPECT_CALL(m_workerThreadFactoryMock, createWorkerThread()).WillOnce(Return(ByMove(std::move(workerThread)))); diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerPrivateTest.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerPrivateTest.cpp index ead4576bd..63ff3e5a7 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerPrivateTest.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerPrivateTest.cpp @@ -1677,12 +1677,6 @@ TEST_F(GstGenericPlayerPrivateTest, shouldNotStopInactivePositionReportingTimerW m_sut->stopPositionReportingAndCheckAudioUnderflowTimer(); } -TEST_F(GstGenericPlayerPrivateTest, shouldStopWorkerThread) -{ - EXPECT_CALL(m_workerThreadMock, stop()); - m_sut->stopWorkerThread(); -} - TEST_F(GstGenericPlayerPrivateTest, shouldUpdatePlaybackGroup) { GstElement typefind; diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp index ffac46908..69081a751 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp @@ -57,7 +57,6 @@ #include "tasks/generic/SetVolume.h" #include "tasks/generic/SetupElement.h" #include "tasks/generic/SetupSource.h" -#include "tasks/generic/Shutdown.h" #include "tasks/generic/Stop.h" #include "tasks/generic/SwitchSource.h" #include "tasks/generic/Underflow.h" @@ -2355,17 +2354,6 @@ void GenericTasksTestsBase::shouldNotifyVideoUnderflow() EXPECT_CALL(testContext->m_gstPlayerClient, notifyBufferUnderflow(firebolt::rialto::MediaSourceType::VIDEO)); } -void GenericTasksTestsBase::shouldStopWorkerThread() -{ - EXPECT_CALL(testContext->m_gstPlayer, stopWorkerThread()); -} - -void GenericTasksTestsBase::triggerShutdown() -{ - firebolt::rialto::server::tasks::generic::Shutdown task{testContext->m_gstPlayer}; - task.execute(); -} - void GenericTasksTestsBase::shouldSetVideoMute() { EXPECT_CALL(testContext->m_gstPlayer, getSink(firebolt::rialto::MediaSourceType::VIDEO)) diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.h b/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.h index 9ccae0315..2ce54436a 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.h +++ b/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.h @@ -258,10 +258,6 @@ class GenericTasksTestsBase : public ::testing::Test void triggerVideoUnderflow(); void shouldNotifyVideoUnderflow(); - // Shutdown test methods - void shouldStopWorkerThread(); - void triggerShutdown(); - // SetMute test methods void triggerSetAudioMute(); void triggerSetVideoMute(); diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/common/GstGenericPlayerTestCommon.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/common/GstGenericPlayerTestCommon.cpp index 4f423a12e..e0f0de0a3 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/common/GstGenericPlayerTestCommon.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/common/GstGenericPlayerTestCommon.cpp @@ -50,7 +50,6 @@ void GstGenericPlayerTestCommon::gstPlayerWillBeCreated() void GstGenericPlayerTestCommon::gstPlayerWillBeDestroyed() { - expectShutdown(); expectStop(); EXPECT_CALL(*m_gstWrapperMock, gstPipelineGetBus(GST_PIPELINE(&m_pipeline))).WillOnce(Return(&m_bus)); EXPECT_CALL(*m_gstWrapperMock, gstBusSetSyncHandler(&m_bus, nullptr, nullptr, nullptr)); @@ -58,14 +57,6 @@ void GstGenericPlayerTestCommon::gstPlayerWillBeDestroyed() EXPECT_CALL(*m_gstWrapperMock, gstObjectUnref(&m_pipeline)); } -void GstGenericPlayerTestCommon::expectShutdown() -{ - std::unique_ptr shutdownTask{std::make_unique>()}; - EXPECT_CALL(dynamic_cast &>(*shutdownTask), execute()); - EXPECT_CALL(m_taskFactoryMock, createShutdown(_)).WillOnce(Return(ByMove(std::move(shutdownTask)))); - EXPECT_CALL(m_workerThreadMock, join()); -} - void GstGenericPlayerTestCommon::expectStop() { std::unique_ptr stopTask{std::make_unique>()}; diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/common/GstGenericPlayerTestCommon.h b/tests/unittests/media/server/gstplayer/genericPlayer/common/GstGenericPlayerTestCommon.h index acc6da04c..efba04800 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/common/GstGenericPlayerTestCommon.h +++ b/tests/unittests/media/server/gstplayer/genericPlayer/common/GstGenericPlayerTestCommon.h @@ -106,7 +106,6 @@ class GstGenericPlayerTestCommon : public ::testing::Test protected: void gstPlayerWillBeCreated(); void gstPlayerWillBeDestroyed(); - void expectShutdown(); void expectStop(); void executeTaskWhenEnqueued(); void initFactories(); diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/GenericPlayerTaskFactoryTest.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/GenericPlayerTaskFactoryTest.cpp index 45d0fd48d..bdf89cb95 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/GenericPlayerTaskFactoryTest.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/GenericPlayerTaskFactoryTest.cpp @@ -64,7 +64,6 @@ #include "tasks/generic/SetVolume.h" #include "tasks/generic/SetupElement.h" #include "tasks/generic/SetupSource.h" -#include "tasks/generic/Shutdown.h" #include "tasks/generic/Stop.h" #include "tasks/generic/SwitchSource.h" #include "tasks/generic/Underflow.h" @@ -280,13 +279,6 @@ TEST_F(GenericPlayerTaskFactoryTest, ShouldCreateSetStreamSyncMode) EXPECT_NO_THROW(dynamic_cast(*task)); } -TEST_F(GenericPlayerTaskFactoryTest, ShouldCreateShutdown) -{ - auto task = m_sut.createShutdown(m_gstPlayer); - EXPECT_NE(task, nullptr); - EXPECT_NO_THROW(dynamic_cast(*task)); -} - TEST_F(GenericPlayerTaskFactoryTest, ShouldCreateStop) { auto task = m_sut.createStop(m_context, m_gstPlayer); diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/ShutdownTest.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/ShutdownTest.cpp deleted file mode 100644 index 4ed09f284..000000000 --- a/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/ShutdownTest.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "GenericTasksTestsBase.h" - -class ShutdownTest : public GenericTasksTestsBase -{ -}; - -TEST_F(ShutdownTest, shouldShutdown) -{ - shouldStopWorkerThread(); - triggerShutdown(); -} diff --git a/tests/unittests/media/server/gstplayer/webAudioPlayer/CreateTest.cpp b/tests/unittests/media/server/gstplayer/webAudioPlayer/CreateTest.cpp index ccfb2a55a..89e07e79b 100644 --- a/tests/unittests/media/server/gstplayer/webAudioPlayer/CreateTest.cpp +++ b/tests/unittests/media/server/gstplayer/webAudioPlayer/CreateTest.cpp @@ -184,9 +184,6 @@ TEST_F(RialtoServerCreateGstWebAudioPlayerTest, createPipelineFailure) expectInitWorkerThread(); EXPECT_CALL(*m_gstWrapperMock, gstPipelineNew(_)).WillOnce(Return(nullptr)); - // Reset worker thread on failure - expectResetWorkerThread(); - EXPECT_THROW(m_gstPlayer = std::make_unique(&m_gstPlayerClient, m_priority, m_gstWrapperMock, m_glibWrapperMock, m_gstInitialiserMock, m_gstSrcFactoryMock, std::move(m_taskFactory), @@ -211,7 +208,6 @@ TEST_F(RialtoServerCreateGstWebAudioPlayerTest, createAppSrcFailure) EXPECT_CALL(*m_gstWrapperMock, gstPipelineGetBus(GST_PIPELINE(&m_pipeline))).WillOnce(Return(nullptr)); EXPECT_CALL(*m_gstWrapperMock, gstObjectUnref(&m_pipeline)); expectTaskStop(); - expectResetWorkerThread(); EXPECT_THROW(m_gstPlayer = std::make_unique(&m_gstPlayerClient, m_priority, m_gstWrapperMock, m_glibWrapperMock, m_gstInitialiserMock, @@ -490,7 +486,6 @@ TEST_F(RialtoServerCreateGstWebAudioPlayerTest, createGstDispatcherAfterFailureT expectTaskStop(); expectTermPipeline(); - expectResetWorkerThread(); EXPECT_THROW(m_gstPlayer = std::make_unique(&m_gstPlayerClient, m_priority, m_gstWrapperMock, m_glibWrapperMock, m_gstInitialiserMock, diff --git a/tests/unittests/media/server/gstplayer/webAudioPlayer/GstWebAudioPlayerPrivateTest.cpp b/tests/unittests/media/server/gstplayer/webAudioPlayer/GstWebAudioPlayerPrivateTest.cpp index 57c131f6d..d31c8199c 100644 --- a/tests/unittests/media/server/gstplayer/webAudioPlayer/GstWebAudioPlayerPrivateTest.cpp +++ b/tests/unittests/media/server/gstplayer/webAudioPlayer/GstWebAudioPlayerPrivateTest.cpp @@ -52,9 +52,3 @@ TEST_F(GstWebAudioPlayerPrivateTest, shouldChangePlaybackState) EXPECT_CALL(*m_gstWrapperMock, gstElementSetState(_, GST_STATE_PLAYING)).WillOnce(Return(GST_STATE_CHANGE_SUCCESS)); EXPECT_TRUE(m_sut->changePipelineState(GST_STATE_PLAYING)); } - -TEST_F(GstWebAudioPlayerPrivateTest, shouldStopWorkerThread) -{ - EXPECT_CALL(m_workerThreadMock, stop()); - m_sut->stopWorkerThread(); -} diff --git a/tests/unittests/media/server/gstplayer/webAudioPlayer/common/GstWebAudioPlayerTestCommon.cpp b/tests/unittests/media/server/gstplayer/webAudioPlayer/common/GstWebAudioPlayerTestCommon.cpp index b6b50076d..3f87fe55f 100644 --- a/tests/unittests/media/server/gstplayer/webAudioPlayer/common/GstWebAudioPlayerTestCommon.cpp +++ b/tests/unittests/media/server/gstplayer/webAudioPlayer/common/GstWebAudioPlayerTestCommon.cpp @@ -55,20 +55,10 @@ void GstWebAudioPlayerTestCommon::gstPlayerWillBeCreatedForGenericPlatform() void GstWebAudioPlayerTestCommon::gstPlayerWillBeDestroyed() { - expectResetWorkerThread(); expectTaskStop(); expectTermPipeline(); } -void GstWebAudioPlayerTestCommon::expectResetWorkerThread() -{ - std::unique_ptr shutdownTask{std::make_unique>()}; - EXPECT_CALL(dynamic_cast &>(*shutdownTask), execute()); - EXPECT_CALL(m_taskFactoryMock, createShutdown(_)).WillOnce(Return(ByMove(std::move(shutdownTask)))); - EXPECT_CALL(m_workerThreadMock, join()); - executeTaskWhenEnqueued(); -} - void GstWebAudioPlayerTestCommon::expectTermPipeline() { EXPECT_CALL(*m_gstWrapperMock, gstPipelineGetBus(GST_PIPELINE(&m_pipeline))).WillOnce(Return(&m_bus)); diff --git a/tests/unittests/media/server/gstplayer/webAudioPlayer/common/GstWebAudioPlayerTestCommon.h b/tests/unittests/media/server/gstplayer/webAudioPlayer/common/GstWebAudioPlayerTestCommon.h index 787b57a86..6971c09b3 100644 --- a/tests/unittests/media/server/gstplayer/webAudioPlayer/common/GstWebAudioPlayerTestCommon.h +++ b/tests/unittests/media/server/gstplayer/webAudioPlayer/common/GstWebAudioPlayerTestCommon.h @@ -100,7 +100,6 @@ class GstWebAudioPlayerTestCommon : public ::testing::Test void expectAddBinFailure(); void expectLinkElementFailure(); void expectTermPipeline(); - void expectResetWorkerThread(); void expectTaskStop(); GstElement m_pipeline{}; diff --git a/tests/unittests/media/server/gstplayer/webAudioPlayer/common/WebAudioTasksTestsBase.cpp b/tests/unittests/media/server/gstplayer/webAudioPlayer/common/WebAudioTasksTestsBase.cpp index c4f3cd1f4..7e6374c3e 100644 --- a/tests/unittests/media/server/gstplayer/webAudioPlayer/common/WebAudioTasksTestsBase.cpp +++ b/tests/unittests/media/server/gstplayer/webAudioPlayer/common/WebAudioTasksTestsBase.cpp @@ -30,7 +30,6 @@ #include "tasks/webAudio/Play.h" #include "tasks/webAudio/SetCaps.h" #include "tasks/webAudio/SetVolume.h" -#include "tasks/webAudio/Shutdown.h" #include "tasks/webAudio/Stop.h" #include "tasks/webAudio/WriteBuffer.h" @@ -126,17 +125,6 @@ void WebAudioTasksTestsBase::triggerSetVolume() task.execute(); } -void WebAudioTasksTestsBase::shouldStopWorkerThread() -{ - EXPECT_CALL(testContext->m_gstPlayer, stopWorkerThread()); -} - -void WebAudioTasksTestsBase::triggerShutdown() -{ - firebolt::rialto::server::tasks::webaudio::Shutdown task{testContext->m_gstPlayer}; - task.execute(); -} - void WebAudioTasksTestsBase::shouldChangePlayerStateNull() { EXPECT_CALL(testContext->m_gstPlayer, changePipelineState(GST_STATE_NULL)); diff --git a/tests/unittests/media/server/gstplayer/webAudioPlayer/common/WebAudioTasksTestsBase.h b/tests/unittests/media/server/gstplayer/webAudioPlayer/common/WebAudioTasksTestsBase.h index ec122f4db..7998e65e9 100644 --- a/tests/unittests/media/server/gstplayer/webAudioPlayer/common/WebAudioTasksTestsBase.h +++ b/tests/unittests/media/server/gstplayer/webAudioPlayer/common/WebAudioTasksTestsBase.h @@ -68,10 +68,6 @@ class WebAudioTasksTestsBase : public ::testing::Test void shouldGstSetVolume(); void triggerSetVolume(); - // Shutdown test methods - void shouldStopWorkerThread(); - void triggerShutdown(); - // Stop test methods void shouldChangePlayerStateNull(); void triggerStop(); diff --git a/tests/unittests/media/server/gstplayer/webAudioPlayer/taskTests/ShutdownTest.cpp b/tests/unittests/media/server/gstplayer/webAudioPlayer/taskTests/ShutdownTest.cpp deleted file mode 100644 index 412265ada..000000000 --- a/tests/unittests/media/server/gstplayer/webAudioPlayer/taskTests/ShutdownTest.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "WebAudioTasksTestsBase.h" - -class WebAudioShutdownTest : public WebAudioTasksTestsBase -{ -}; - -TEST_F(WebAudioShutdownTest, shouldShutdown) -{ - shouldStopWorkerThread(); - triggerShutdown(); -} diff --git a/tests/unittests/media/server/gstplayer/webAudioPlayer/taskTests/WebAudioPlayerTaskFactoryTest.cpp b/tests/unittests/media/server/gstplayer/webAudioPlayer/taskTests/WebAudioPlayerTaskFactoryTest.cpp index 503a2839a..3d41c91d8 100644 --- a/tests/unittests/media/server/gstplayer/webAudioPlayer/taskTests/WebAudioPlayerTaskFactoryTest.cpp +++ b/tests/unittests/media/server/gstplayer/webAudioPlayer/taskTests/WebAudioPlayerTaskFactoryTest.cpp @@ -32,7 +32,6 @@ #include "tasks/webAudio/Play.h" #include "tasks/webAudio/SetCaps.h" #include "tasks/webAudio/SetVolume.h" -#include "tasks/webAudio/Shutdown.h" #include "tasks/webAudio/Stop.h" #include "tasks/webAudio/WriteBuffer.h" #include @@ -91,13 +90,6 @@ TEST_F(WebAudioPlayerTaskFactoryTest, ShouldStop) EXPECT_NO_THROW(dynamic_cast(*task)); } -TEST_F(WebAudioPlayerTaskFactoryTest, ShouldShutdown) -{ - auto task = m_sut.createShutdown(m_gstPlayer); - EXPECT_NE(task, nullptr); - EXPECT_NO_THROW(dynamic_cast(*task)); -} - TEST_F(WebAudioPlayerTaskFactoryTest, ShouldSetVolume) { auto task = m_sut.createSetVolume(m_context, {}); diff --git a/tests/unittests/media/server/mocks/gstplayer/GenericPlayerTaskFactoryMock.h b/tests/unittests/media/server/mocks/gstplayer/GenericPlayerTaskFactoryMock.h index 656416104..43bc6da08 100644 --- a/tests/unittests/media/server/mocks/gstplayer/GenericPlayerTaskFactoryMock.h +++ b/tests/unittests/media/server/mocks/gstplayer/GenericPlayerTaskFactoryMock.h @@ -101,7 +101,6 @@ class GenericPlayerTaskFactoryMock : public IGenericPlayerTaskFactory (GenericPlayerContext & context, IGstGenericPlayerPrivate &player, const firebolt::rialto::MediaSourceType &type, int32_t streamSyncMode), (const, override)); - MOCK_METHOD(std::unique_ptr, createShutdown, (IGstGenericPlayerPrivate & player), (const, override)); MOCK_METHOD(std::unique_ptr, createStop, (GenericPlayerContext & context, IGstGenericPlayerPrivate &player), (const, override)); MOCK_METHOD(std::unique_ptr, createUnderflow, diff --git a/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerPrivateMock.h b/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerPrivateMock.h index 3697e3deb..b8e15348f 100644 --- a/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerPrivateMock.h +++ b/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerPrivateMock.h @@ -57,7 +57,6 @@ class GstGenericPlayerPrivateMock : public IGstGenericPlayerPrivate MOCK_METHOD(bool, changePipelineState, (GstState newState), (override)); MOCK_METHOD(void, startPositionReportingAndCheckAudioUnderflowTimer, (), (override)); MOCK_METHOD(void, stopPositionReportingAndCheckAudioUnderflowTimer, (), (override)); - MOCK_METHOD(void, stopWorkerThread, (), (override)); MOCK_METHOD(void, cancelUnderflow, (firebolt::rialto::MediaSourceType mediaSource), (override)); MOCK_METHOD(void, setPendingPlaybackRate, (), (override)); MOCK_METHOD(void, updatePlaybackGroup, (GstElement * typefind, const GstCaps *caps), (override)); diff --git a/tests/unittests/media/server/mocks/gstplayer/GstWebAudioPlayerPrivateMock.h b/tests/unittests/media/server/mocks/gstplayer/GstWebAudioPlayerPrivateMock.h index 7b1da65fb..0604a10fc 100644 --- a/tests/unittests/media/server/mocks/gstplayer/GstWebAudioPlayerPrivateMock.h +++ b/tests/unittests/media/server/mocks/gstplayer/GstWebAudioPlayerPrivateMock.h @@ -29,7 +29,6 @@ class GstWebAudioPlayerPrivateMock : public IGstWebAudioPlayerPrivate { public: MOCK_METHOD(bool, changePipelineState, (GstState newState), (override)); - MOCK_METHOD(void, stopWorkerThread, (), (override)); }; } // namespace firebolt::rialto::server diff --git a/tests/unittests/media/server/mocks/gstplayer/WebAudioPlayerTaskFactoryMock.h b/tests/unittests/media/server/mocks/gstplayer/WebAudioPlayerTaskFactoryMock.h index ba57e1f92..31251367b 100644 --- a/tests/unittests/media/server/mocks/gstplayer/WebAudioPlayerTaskFactoryMock.h +++ b/tests/unittests/media/server/mocks/gstplayer/WebAudioPlayerTaskFactoryMock.h @@ -29,7 +29,6 @@ namespace firebolt::rialto::server class WebAudioPlayerTaskFactoryMock : public IWebAudioPlayerTaskFactory { public: - MOCK_METHOD(std::unique_ptr, createShutdown, (IGstWebAudioPlayerPrivate & player), (const, override)); MOCK_METHOD(std::unique_ptr, createStop, (IGstWebAudioPlayerPrivate & player), (const, override)); MOCK_METHOD(std::unique_ptr, createPlay, (IGstWebAudioPlayerPrivate & player), (const, override)); MOCK_METHOD(std::unique_ptr, createPause, (IGstWebAudioPlayerPrivate & player), (const, override)); diff --git a/tests/unittests/media/server/mocks/gstplayer/WorkerThreadMock.h b/tests/unittests/media/server/mocks/gstplayer/WorkerThreadMock.h index 7b0071a78..095aa9a17 100644 --- a/tests/unittests/media/server/mocks/gstplayer/WorkerThreadMock.h +++ b/tests/unittests/media/server/mocks/gstplayer/WorkerThreadMock.h @@ -30,7 +30,6 @@ class WorkerThreadMock : public IWorkerThread { public: MOCK_METHOD(void, stop, (), (override)); - MOCK_METHOD(void, join, (), (override)); MOCK_METHOD(void, enqueueTask, (std::unique_ptr && task), (override)); }; } // namespace firebolt::rialto::server From 9820fd34b3a5efc7e65e77efcefadb94afa9a330 Mon Sep 17 00:00:00 2001 From: Marcin Wojciechowski <105790697+skywojciechowskim@users.noreply.github.com> Date: Fri, 13 Jun 2025 12:59:09 +0200 Subject: [PATCH 03/15] Add support for GST_BUFFER_OFFSET for subtitles source (#384) Summary: Add support for GST_BUFFER_OFFSET for subtitles source Type: Fix Test Plan: UT/ CT, Fullstack Jira: ENTDAI-1382 --------- Co-authored-by: Adam Czynszak --- .../valgrind_server_component_test.yml | 2 +- media/common/source/MediaFrameWriterV2.cpp | 4 ++++ media/public/include/IMediaPipeline.h | 22 ++++++++++++++++++- .../gstplayer/source/GstTextTrackSink.cpp | 7 +++++- .../generic/ReadShmDataAndAttachSamples.cpp | 8 ++++++- media/server/main/source/DataReaderV2.cpp | 4 ++++ .../server/main/source/TextTrackAccessor.cpp | 3 ++- proto/metadata.proto | 1 + .../mediaFrameWriterV2/WriteFrameTest.cpp | 3 +++ .../common/GenericTasksTestsBase.cpp | 3 +++ .../main/dataReader/DataReaderV2Tests.cpp | 3 +++ 11 files changed, 55 insertions(+), 5 deletions(-) diff --git a/.github/workflows/valgrind_server_component_test.yml b/.github/workflows/valgrind_server_component_test.yml index 76eaee4aa..01ca012ab 100644 --- a/.github/workflows/valgrind_server_component_test.yml +++ b/.github/workflows/valgrind_server_component_test.yml @@ -45,7 +45,7 @@ jobs: runs-on: ubuntu-24.04 # Timeout after - timeout-minutes: 10 + timeout-minutes: 20 # Steps represent a sequence of tasks that will be executed as part of the job steps: diff --git a/media/common/source/MediaFrameWriterV2.cpp b/media/common/source/MediaFrameWriterV2.cpp index c4fc48016..808d0b470 100644 --- a/media/common/source/MediaFrameWriterV2.cpp +++ b/media/common/source/MediaFrameWriterV2.cpp @@ -148,6 +148,10 @@ MediaSegmentMetadata MediaFrameWriterV2::buildMetadata(const std::unique_ptrgetTimeStamp()); metadata.set_sample_duration(data->getDuration()); metadata.set_stream_id(static_cast(data->getId())); + if (data->getDisplayOffset()) + { + metadata.set_display_offset(data->getDisplayOffset().value()); + } if (MediaSourceType::AUDIO == data->getType()) { IMediaPipeline::MediaSegmentAudio &audioSegment = dynamic_cast(*data); diff --git a/media/public/include/IMediaPipeline.h b/media/public/include/IMediaPipeline.h index d63c3cc84..61b992b86 100644 --- a/media/public/include/IMediaPipeline.h +++ b/media/public/include/IMediaPipeline.h @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -460,7 +461,7 @@ class IMediaPipeline : m_sourceId(sourceId), m_type(type), m_data(nullptr), m_dataLength(0u), m_timeStamp(timeStamp), m_duration(duration), m_encrypted(false), m_mediaKeySessionId(0), m_initWithLast15(0), m_alignment(SegmentAlignment::UNDEFINED), m_cipherMode(CipherMode::UNKNOWN), m_crypt(0), m_skip(0), - m_encryptionPatternSet(false) + m_encryptionPatternSet(false), m_displayOffset(std::nullopt) { } @@ -608,6 +609,13 @@ class IMediaPipeline return m_encryptionPatternSet; } + /** + * @brief Gets the display offset + * + * @retval The offset in the source file of the beginning of the media segment. + */ + std::optional getDisplayOffset() const { return m_displayOffset; } + protected: /** * @brief The source id. @@ -705,6 +713,11 @@ class IMediaPipeline */ bool m_encryptionPatternSet; + /** + * @brief The offset in the source file of the beginning of the media segment. + */ + std::optional m_displayOffset; + public: /** * @brief Sets the segment data. @@ -818,6 +831,13 @@ class IMediaPipeline m_encryptionPatternSet = true; } + /** + * @brief Sets the display offset + * + * @param[in] displayOffset : The offset in the source file of the beginning of the media segment. + */ + void setDisplayOffset(uint64_t displayOffset) { m_displayOffset = displayOffset; } + /** * @brief Copies the data from other to this. */ diff --git a/media/server/gstplayer/source/GstTextTrackSink.cpp b/media/server/gstplayer/source/GstTextTrackSink.cpp index 543947159..d85d6d61a 100644 --- a/media/server/gstplayer/source/GstTextTrackSink.cpp +++ b/media/server/gstplayer/source/GstTextTrackSink.cpp @@ -188,7 +188,12 @@ static GstFlowReturn gst_rialto_text_track_sink_render(GstBaseSink *sink, GstBuf if (gst_buffer_map(buffer, &info, GST_MAP_READ)) { std::string data(reinterpret_cast(info.data), info.size); - textTrackSink->priv->m_textTrackSession->sendData(data); + int32_t displayOffset{0}; + if (GST_BUFFER_OFFSET_NONE != GST_BUFFER_OFFSET(buffer)) + { + displayOffset = static_cast(GST_BUFFER_OFFSET(buffer)); + } + textTrackSink->priv->m_textTrackSession->sendData(data, 0 - displayOffset); gst_buffer_unmap(buffer, &info); } diff --git a/media/server/gstplayer/source/tasks/generic/ReadShmDataAndAttachSamples.cpp b/media/server/gstplayer/source/tasks/generic/ReadShmDataAndAttachSamples.cpp index 0839468a1..6e220449a 100644 --- a/media/server/gstplayer/source/tasks/generic/ReadShmDataAndAttachSamples.cpp +++ b/media/server/gstplayer/source/tasks/generic/ReadShmDataAndAttachSamples.cpp @@ -85,7 +85,13 @@ void ReadShmDataAndAttachSamples::execute() const RIALTO_SERVER_LOG_ERROR("Failed to get the audio segment, reason: %s", e.what()); } } - // no special action for SUBTITLE needed, just attach the buffer + else if (mediaSegment->getType() == firebolt::rialto::MediaSourceType::SUBTITLE) + { + if (mediaSegment->getDisplayOffset()) + { + GST_BUFFER_OFFSET(gstBuffer) = mediaSegment->getDisplayOffset().value(); + } + } attachData(mediaSegment->getType(), gstBuffer); } diff --git a/media/server/main/source/DataReaderV2.cpp b/media/server/main/source/DataReaderV2.cpp index 88a7b2722..5659045f0 100644 --- a/media/server/main/source/DataReaderV2.cpp +++ b/media/server/main/source/DataReaderV2.cpp @@ -187,6 +187,10 @@ createSegment(const firebolt::rialto::MediaSegmentMetadata &metadata, const fire { segment->setEncryptionPattern(metadata.crypt(), metadata.skip()); } + if (metadata.has_display_offset()) + { + segment->setDisplayOffset(metadata.display_offset()); + } for (const auto &info : metadata.sub_sample_info()) { diff --git a/media/server/main/source/TextTrackAccessor.cpp b/media/server/main/source/TextTrackAccessor.cpp index 2d41d644d..177173dd0 100644 --- a/media/server/main/source/TextTrackAccessor.cpp +++ b/media/server/main/source/TextTrackAccessor.cpp @@ -182,7 +182,8 @@ bool TextTrackAccessor::sendData(uint32_t sessionId, const std::string &data, Da const uint32_t result = m_textTrackWrapper->sendSessionData(sessionId, wrapperDataType, displayOffsetMs, data); if (m_thunderWrapper->isSuccessful(result)) { - RIALTO_SERVER_LOG_DEBUG("Sending data to TextTrack session %u was successful", sessionId); + RIALTO_SERVER_LOG_DEBUG("Sending data to TextTrack session %u was successful; offset %d, size %zu", sessionId, + displayOffsetMs, data.size()); return true; } diff --git a/proto/metadata.proto b/proto/metadata.proto index 2587fb5ec..59d68f231 100644 --- a/proto/metadata.proto +++ b/proto/metadata.proto @@ -78,4 +78,5 @@ message MediaSegmentMetadata { optional Fraction frame_rate = 20; /* Fractional frame rate of the video segments */ optional uint64 clipping_start = 21; /* The amount of audio to clip from start of buffer */ optional uint64 clipping_end = 22; /* The amount of audio to clip from end of buffer */ + optional uint64 display_offset = 23; /* The offset in the source file of the beginning of the media segment. */ } diff --git a/tests/unittests/media/common/mediaFrameWriterV2/WriteFrameTest.cpp b/tests/unittests/media/common/mediaFrameWriterV2/WriteFrameTest.cpp index cae30412b..ff83078c2 100644 --- a/tests/unittests/media/common/mediaFrameWriterV2/WriteFrameTest.cpp +++ b/tests/unittests/media/common/mediaFrameWriterV2/WriteFrameTest.cpp @@ -50,6 +50,7 @@ const std::vector kInitVector{34, 53, 54, 62, 56}; constexpr size_t kNumClearBytes{2}; constexpr size_t kNumEncryptedBytes{7}; constexpr uint32_t kInitWithLast15{1}; +constexpr uint64_t kDisplayOffset{35}; uint32_t readLEUint32(const uint8_t *buffer) { @@ -78,6 +79,7 @@ void addOptionalData(std::unique_ptr &segment) segment->setSegmentAlignment(SegmentAlignment::NAL); segment->setExtraData(kExtraData); segment->setCodecData(std::make_shared(CodecData{kCodecDataVector, CodecDataType::BUFFER})); + segment->setDisplayOffset(kDisplayOffset); } void addEncryptionData(std::unique_ptr &segment) @@ -133,6 +135,7 @@ void checkOptionalMetadataPresent(const MediaSegmentMetadata &metadata) EXPECT_TRUE(metadata.has_codec_data()); EXPECT_EQ(metadata.codec_data().data(), std::string(kCodecDataVector.begin(), kCodecDataVector.end())); EXPECT_EQ(metadata.codec_data().type(), MediaSegmentMetadata_CodecData_Type_BUFFER); + EXPECT_EQ(metadata.display_offset(), kDisplayOffset); } void checkEncryptionMetadataNotPresent(const MediaSegmentMetadata &metadata) diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp index 69081a751..40cf6f80b 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp @@ -136,6 +136,7 @@ constexpr bool kIsAudioAac{false}; constexpr uint64_t kStopPosition{4523}; const std::vector kStreamHeaderVector{1, 2, 3, 4}; constexpr bool kFramed{true}; +constexpr uint64_t kDisplayOffset{35}; firebolt::rialto::IMediaPipeline::MediaSegmentVector buildAudioSamples() { @@ -172,10 +173,12 @@ firebolt::rialto::IMediaPipeline::MediaSegmentVector buildSubtitleSamples() std::make_unique(kSubtitleSourceId, firebolt::rialto::MediaSourceType::SUBTITLE, kItHappenedInThePast, kDuration)); + dataVec.back()->setDisplayOffset(kDisplayOffset); dataVec.emplace_back( std::make_unique(kSubtitleSourceId, firebolt::rialto::MediaSourceType::SUBTITLE, kItWillHappenInTheFuture, kDuration)); + dataVec.back()->setDisplayOffset(kDisplayOffset); return dataVec; } diff --git a/tests/unittests/media/server/main/dataReader/DataReaderV2Tests.cpp b/tests/unittests/media/server/main/dataReader/DataReaderV2Tests.cpp index 001f6b0de..c2824b425 100644 --- a/tests/unittests/media/server/main/dataReader/DataReaderV2Tests.cpp +++ b/tests/unittests/media/server/main/dataReader/DataReaderV2Tests.cpp @@ -64,6 +64,7 @@ constexpr SegmentAlignment kSegmentAlignment{SegmentAlignment::AU}; constexpr uint32_t kCryptBlocks{131}; constexpr uint32_t kSkipBlocks{242}; +constexpr uint64_t kDisplayOffset{35}; class Check { @@ -115,6 +116,7 @@ class Check EXPECT_TRUE(m_segment->getCodecData()); EXPECT_EQ(m_segment->getCodecData()->data, kCodecData.data); EXPECT_EQ(m_segment->getCodecData()->type, kCodecData.type); + EXPECT_EQ(m_segment->getDisplayOffset().value(), kDisplayOffset); return *this; } @@ -230,6 +232,7 @@ class Build m_segment->setExtraData(kExtraData); m_segment->setSegmentAlignment(kSegmentAlignment); m_segment->setCodecData(std::make_shared(kCodecData)); + m_segment->setDisplayOffset(kDisplayOffset); return *this; } From 866abf972705b2be5968eb1499fe5c1a21698584 Mon Sep 17 00:00:00 2001 From: Marcin Wojciechowski <105790697+skywojciechowskim@users.noreply.github.com> Date: Tue, 17 Jun 2025 11:25:05 +0200 Subject: [PATCH 04/15] GstQueue element added to WebAudio pipeline (#385) Summary: GstQueue element added to WebAudio pipeline Type: Fix Test Plan: UT/ CT, Fullstack Jira: ENTDAI-513 --- .../gstplayer/source/GstWebAudioPlayer.cpp | 19 ++++++++- .../tests/webAudio/WebAudioTestMethods.cpp | 6 ++- .../tests/webAudio/WebAudioTestMethods.h | 1 + .../gstplayer/webAudioPlayer/CreateTest.cpp | 40 +++++++++++++++++++ .../common/GstWebAudioPlayerTestCommon.cpp | 15 ++++++- 5 files changed, 78 insertions(+), 3 deletions(-) diff --git a/media/server/gstplayer/source/GstWebAudioPlayer.cpp b/media/server/gstplayer/source/GstWebAudioPlayer.cpp index 71f6ccce7..81d585683 100644 --- a/media/server/gstplayer/source/GstWebAudioPlayer.cpp +++ b/media/server/gstplayer/source/GstWebAudioPlayer.cpp @@ -255,6 +255,7 @@ bool GstWebAudioPlayer::linkElementsToSrc(GstElement *sink) GstElement *convert{nullptr}; GstElement *resample{nullptr}; GstElement *volume{nullptr}; + GstElement *queue{nullptr}; convert = m_gstWrapper->gstElementFactoryMake("audioconvert", NULL); if (!convert) @@ -282,6 +283,20 @@ bool GstWebAudioPlayer::linkElementsToSrc(GstElement *sink) status = false; } } + if (status) + { + queue = m_gstWrapper->gstElementFactoryMake("queue", NULL); + if (!queue) + { + RIALTO_SERVER_LOG_ERROR("Failed create the queue"); + status = false; + } + else + { + constexpr guint kWebAudioQueueSize{8192}; + m_glibWrapper->gObjectSet(queue, "max-size-bytes", kWebAudioQueueSize, nullptr); + } + } std::queue elementsToAdd; elementsToAdd.push(m_context.source); @@ -291,6 +306,8 @@ bool GstWebAudioPlayer::linkElementsToSrc(GstElement *sink) elementsToAdd.push(resample); if (volume) elementsToAdd.push(volume); + if (queue) + elementsToAdd.push(queue); elementsToAdd.push(sink); if (status) @@ -314,7 +331,7 @@ bool GstWebAudioPlayer::linkElementsToSrc(GstElement *sink) { if ((!m_gstWrapper->gstElementLink(m_context.source, convert)) || (!m_gstWrapper->gstElementLink(convert, resample)) || (!m_gstWrapper->gstElementLink(resample, volume)) || - (!m_gstWrapper->gstElementLink(volume, sink))) + (!m_gstWrapper->gstElementLink(volume, queue)) || (!m_gstWrapper->gstElementLink(queue, sink))) { RIALTO_SERVER_LOG_ERROR("Failed to link elements"); status = false; diff --git a/tests/componenttests/server/tests/webAudio/WebAudioTestMethods.cpp b/tests/componenttests/server/tests/webAudio/WebAudioTestMethods.cpp index d7876715e..1d34fe7e3 100644 --- a/tests/componenttests/server/tests/webAudio/WebAudioTestMethods.cpp +++ b/tests/componenttests/server/tests/webAudio/WebAudioTestMethods.cpp @@ -199,15 +199,19 @@ void WebAudioTestMethods::willCreateWebAudioPlayer() EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("audioconvert"), _)).WillOnce(Return(&m_convert)); EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("audioresample"), _)).WillOnce(Return(&m_resample)); EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("volume"), _)).WillOnce(Return(&m_volume)); + EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("queue"), _)).WillOnce(Return(&m_queue)); + EXPECT_CALL(*m_glibWrapperMock, gObjectSetStub(&m_queue, StrEq("max-size-bytes"))); EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), GST_ELEMENT(&m_appSrc))).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &m_convert)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &m_resample)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &m_volume)).WillOnce(Return(TRUE)); + EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &m_queue)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &m_sink)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstElementLink(GST_ELEMENT(&m_appSrc), &m_convert)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstElementLink(&m_convert, &m_resample)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstElementLink(&m_resample, &m_volume)).WillOnce(Return(TRUE)); - EXPECT_CALL(*m_gstWrapperMock, gstElementLink(&m_volume, &m_sink)).WillOnce(Return(TRUE)); + EXPECT_CALL(*m_gstWrapperMock, gstElementLink(&m_volume, &m_queue)).WillOnce(Return(TRUE)); + EXPECT_CALL(*m_gstWrapperMock, gstElementLink(&m_queue, &m_sink)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstCapsNewEmptySimple(StrEq(kAudioMimeType))).WillOnce(Return(&m_gstCaps1)); EXPECT_CALL(*m_gstWrapperMock, gstCapsSetSimpleIntStub(&m_gstCaps1, StrEq("channels"), G_TYPE_INT, kPcmChannels)); diff --git a/tests/componenttests/server/tests/webAudio/WebAudioTestMethods.h b/tests/componenttests/server/tests/webAudio/WebAudioTestMethods.h index 166b47ea8..cd3cc7f32 100644 --- a/tests/componenttests/server/tests/webAudio/WebAudioTestMethods.h +++ b/tests/componenttests/server/tests/webAudio/WebAudioTestMethods.h @@ -109,6 +109,7 @@ class WebAudioTestMethods : public RialtoServerComponentTest GstElement m_convert; GstElement m_resample; GstElement m_volume; + GstElement m_queue; GstBuffer m_buffer; gchar m_capsStr; diff --git a/tests/unittests/media/server/gstplayer/webAudioPlayer/CreateTest.cpp b/tests/unittests/media/server/gstplayer/webAudioPlayer/CreateTest.cpp index 89e07e79b..d3d9bd0e5 100644 --- a/tests/unittests/media/server/gstplayer/webAudioPlayer/CreateTest.cpp +++ b/tests/unittests/media/server/gstplayer/webAudioPlayer/CreateTest.cpp @@ -365,6 +365,46 @@ TEST_F(RialtoServerCreateGstWebAudioPlayerTest, createAudioResampleFailure) EXPECT_EQ(m_gstPlayer, nullptr); } +/** + * Test that a GstWebAudioPlayer throws an exception if there is a failure to create queue. + */ +TEST_F(RialtoServerCreateGstWebAudioPlayerTest, createAudioQueueFailure) +{ + EXPECT_CALL(m_gstInitialiserMock, waitForInitialisation()); + expectInitRialtoSrc(); + expectMakeRtkAudioSink(); + expectCreatePipeline(); + expectInitAppSrc(); + expectInitWorkerThread(); + EXPECT_CALL(*m_glibWrapperMock, gObjectSetStub(G_OBJECT(&m_sink), StrEq("media-tunnel"))); + EXPECT_CALL(*m_glibWrapperMock, gObjectSetStub(G_OBJECT(&m_sink), StrEq("audio-service"))); + + GstElement convert{}; + GstElement resample{}; + GstElement volume{}; + + EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("audioconvert"), _)).WillOnce(Return(&convert)); + EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("audioresample"), _)).WillOnce(Return(&resample)); + EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("volume"), _)).WillOnce(Return(&volume)); + EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("queue"), _)).WillOnce(Return(nullptr)); + EXPECT_CALL(*m_gstWrapperMock, gstObjectUnref(&convert)); + + // Reset worker thread and pipeline on failure + gstPlayerWillBeDestroyed(); + EXPECT_CALL(*m_gstWrapperMock, gstObjectUnref(&resample)); + EXPECT_CALL(*m_gstWrapperMock, gstObjectUnref(&volume)); + EXPECT_CALL(*m_gstWrapperMock, gstObjectUnref(&m_sink)); + EXPECT_CALL(*m_gstWrapperMock, gstObjectUnref(&m_appSrc)); + + EXPECT_THROW(m_gstPlayer = std::make_unique(&m_gstPlayerClient, m_priority, m_gstWrapperMock, + m_glibWrapperMock, m_gstInitialiserMock, + m_gstSrcFactoryMock, std::move(m_taskFactory), + std::move(workerThreadFactory), + std::move(gstDispatcherThreadFactory)), + std::runtime_error); + EXPECT_EQ(m_gstPlayer, nullptr); +} + /** * Test that a GstWebAudioPlayer throws an exception if there is a failure to add the audio sink elements to the bin. */ diff --git a/tests/unittests/media/server/gstplayer/webAudioPlayer/common/GstWebAudioPlayerTestCommon.cpp b/tests/unittests/media/server/gstplayer/webAudioPlayer/common/GstWebAudioPlayerTestCommon.cpp index 3f87fe55f..3ed48f72d 100644 --- a/tests/unittests/media/server/gstplayer/webAudioPlayer/common/GstWebAudioPlayerTestCommon.cpp +++ b/tests/unittests/media/server/gstplayer/webAudioPlayer/common/GstWebAudioPlayerTestCommon.cpp @@ -187,19 +187,24 @@ void GstWebAudioPlayerTestCommon::expectLinkElements() GstElement convert{}; GstElement resample{}; memset(&m_volume, 0x00, sizeof(m_volume)); + GstElement queue{}; EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("audioconvert"), _)).WillOnce(Return(&convert)); EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("audioresample"), _)).WillOnce(Return(&resample)); EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("volume"), _)).WillOnce(Return(&m_volume)); + EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("queue"), _)).WillOnce(Return(&queue)); + EXPECT_CALL(*m_glibWrapperMock, gObjectSetStub(G_OBJECT(&queue), StrEq("max-size-bytes"))); EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &m_appSrc)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &convert)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &resample)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &m_volume)).WillOnce(Return(TRUE)); + EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &queue)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &m_sink)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstElementLink(&m_appSrc, &convert)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstElementLink(&convert, &resample)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstElementLink(&resample, &m_volume)).WillOnce(Return(TRUE)); - EXPECT_CALL(*m_gstWrapperMock, gstElementLink(&m_volume, &m_sink)).WillOnce(Return(TRUE)); + EXPECT_CALL(*m_gstWrapperMock, gstElementLink(&m_volume, &queue)).WillOnce(Return(TRUE)); + EXPECT_CALL(*m_gstWrapperMock, gstElementLink(&queue, &m_sink)).WillOnce(Return(TRUE)); } void GstWebAudioPlayerTestCommon::expectLinkElementsExceptVolume() @@ -221,14 +226,18 @@ void GstWebAudioPlayerTestCommon::expectAddBinFailure() GstElement convert{}; GstElement resample{}; memset(&m_volume, 0x00, sizeof(m_volume)); + GstElement queue{}; EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("audioconvert"), _)).WillOnce(Return(&convert)); EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("audioresample"), _)).WillOnce(Return(&resample)); EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("volume"), _)).WillOnce(Return(&m_volume)); + EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("queue"), _)).WillOnce(Return(&queue)); + EXPECT_CALL(*m_glibWrapperMock, gObjectSetStub(G_OBJECT(&queue), StrEq("max-size-bytes"))); EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &m_appSrc)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &convert)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &resample)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &m_volume)).WillOnce(Return(TRUE)); + EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &queue)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &m_sink)).WillOnce(Return(FALSE)); EXPECT_CALL(*m_gstWrapperMock, gstObjectUnref(&m_sink)); } @@ -238,14 +247,18 @@ void GstWebAudioPlayerTestCommon::expectLinkElementFailure() GstElement convert{}; GstElement resample{}; memset(&m_volume, 0x00, sizeof(m_volume)); + GstElement queue{}; EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("audioconvert"), _)).WillOnce(Return(&convert)); EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("audioresample"), _)).WillOnce(Return(&resample)); EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("volume"), _)).WillOnce(Return(&m_volume)); + EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("queue"), _)).WillOnce(Return(&queue)); + EXPECT_CALL(*m_glibWrapperMock, gObjectSetStub(G_OBJECT(&queue), StrEq("max-size-bytes"))); EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &m_appSrc)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &convert)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &resample)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &m_volume)).WillOnce(Return(TRUE)); + EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &queue)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstBinAdd(GST_BIN(&m_pipeline), &m_sink)).WillOnce(Return(TRUE)); EXPECT_CALL(*m_gstWrapperMock, gstElementLink(&m_appSrc, &convert)).WillOnce(Return(FALSE)); } From 92816c10536e851c5a12dcc3971c30d9160e2afd Mon Sep 17 00:00:00 2001 From: Yurii Yakubin <144821088+yurii-yakubin@users.noreply.github.com> Date: Wed, 25 Jun 2025 10:01:42 +0100 Subject: [PATCH 05/15] Valgrind on native (#388) Summary: Valgrind on native Type: Feature Test Plan: UT/CT, Fullstack Jira: ENTDAI-464 --------- Co-authored-by: Adam Czynszak Co-authored-by: Philip Proudman --- .gitignore | 1 + CMakeLists.txt | 26 +- build_ct.py | 5 +- build_ut.py | 3 +- common/CMakeLists.txt | 8 - media/client/main/CMakeLists.txt | 9 - media/server/CMakeLists.txt | 1 + .../server/gstplayer/include/GstInitialiser.h | 3 + media/server/gstplayer/include/GstSrc.h | 2 +- media/server/gstplayer/include/IGstSrc.h | 2 +- .../gstplayer/source/GstInitialiser.cpp | 22 +- media/server/gstplayer/source/GstSrc.cpp | 2 +- .../tasks/generic/FinishSetupSource.cpp | 2 +- media/server/service/source/main.cpp | 10 +- rialto.supp | 996 ++++++++++++++++++ scripts/gtest/generate_coverage.py | 30 +- .../serverManagerSim/commands/SetLog.cpp | 5 + serverManager/service/CMakeLists.txt | 8 - .../externalLibraryMocks/GstWrapperMock.h | 1 + tests/componenttests/client/CMakeLists.txt | 10 - .../server/tests/CMakeLists.txt | 8 - .../unittests/common/unittests/CMakeLists.txt | 11 +- tests/unittests/ipc/CMakeLists.txt | 10 - tests/unittests/logging/CMakeLists.txt | 9 - .../unittests/media/client/ipc/CMakeLists.txt | 8 - .../media/client/main/CMakeLists.txt | 10 - tests/unittests/media/common/CMakeLists.txt | 9 - .../media/server/gstplayer/CMakeLists.txt | 8 - .../common/GenericTasksTestsBase.cpp | 4 +- .../server/gstplayer/rialtoSrc/AppSrcTest.cpp | 18 +- .../unittests/media/server/ipc/CMakeLists.txt | 9 - .../media/server/main/CMakeLists.txt | 8 - .../media/server/mocks/gstplayer/GstSrcMock.h | 2 +- .../media/server/service/CMakeLists.txt | 8 - tests/unittests/serverManager/CMakeLists.txt | 8 - wrappers/CMakeLists.txt | 8 - wrappers/include/GstWrapper.h | 2 + wrappers/interface/IGstWrapper.h | 6 + 38 files changed, 1092 insertions(+), 200 deletions(-) diff --git a/.gitignore b/.gitignore index 0a8ded2b9..59e2214ab 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ /cmake/ocdm-config.cmake *__pycache__ /.vscode/* +/CMakeUserPresets.json # These files are fetched by cmake during building rialto for the native platform /stubs/opencdm/third-party/* diff --git a/CMakeLists.txt b/CMakeLists.txt index 234db9ea4..eb66410b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,8 @@ add_compile_definitions(PROJECT_VER_PATCH="${PROJECT_VERSION_PATCH}") set(CMAKE_CXX_STANDARD 17) if ( COVERAGE_ENABLED ) - add_compile_options(-coverage -fprofile-update=atomic) + add_compile_options(--coverage -fprofile-update=atomic) + add_link_options(--coverage) endif() add_compile_options(-Wall -Werror) @@ -55,7 +56,7 @@ else() option(RIALTO_LOG_DEBUG_ENABLED "Enable debug logging for RialtoServer" OFF) endif() -if (NOT RIALTO_LOG_FATAL_ENABLED OR +if (NOT RIALTO_LOG_FATAL_ENABLED OR NOT RIALTO_LOG_ERROR_ENABLED OR NOT RIALTO_LOG_WARN_ENABLED OR NOT RIALTO_LOG_MIL_ENABLED OR @@ -66,7 +67,7 @@ if (NOT RIALTO_LOG_FATAL_ENABLED OR add_compile_options(-Wno-error=unused-function -Wno-error=unused-variable) endif() - + if ( RIALTO_LOG_FATAL_ENABLED ) message("RIALTO_LOG_FATAL IS ENABLED") add_compile_definitions( RIALTO_LOG_FATAL_ENABLED ) @@ -104,13 +105,13 @@ if (TEXT_TRACK_INCLUDE_DIR) add_compile_definitions(RIALTO_ENABLE_TEXT_TRACK) endif() -# Retrieve the commit ID +# Retrieve the commit ID execute_process( COMMAND git rev-parse HEAD - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - RESULT_VARIABLE RESULT - OUTPUT_VARIABLE SRCREV - OUTPUT_STRIP_TRAILING_WHITESPACE + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + RESULT_VARIABLE RESULT + OUTPUT_VARIABLE SRCREV + OUTPUT_STRIP_TRAILING_WHITESPACE ) if(RESULT) @@ -120,15 +121,15 @@ endif() # Retrieve release tag execute_process( COMMAND bash -c "git tag --points-at ${SRCREV} | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$'" - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE TAGS - OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_STRIP_TRAILING_WHITESPACE ) string(REPLACE "\n" ", " TAGS "${TAGS}") if(NOT TAGS STREQUAL "") set(TAGS ${TAGS}) -endif() +endif() # Preprocesser Variable add_compile_definitions(SRCREV="${SRCREV}") @@ -213,6 +214,9 @@ if( NATIVE_BUILD ) add_subdirectory( stubs/wpeframework-core ) add_subdirectory( stubs/wpeframework-com ) + add_compile_options(-DFREE_MEM_BEFORE_EXIT) + add_compile_options(-ggdb) + include( GNUInstallDirs ) configure_file( pkg-config/RialtoClient.in.pc ${CMAKE_BINARY_DIR}/RialtoClient.pc @ONLY ) install ( diff --git a/build_ct.py b/build_ct.py index 7ecfb96f3..21ca9f730 100755 --- a/build_ct.py +++ b/build_ct.py @@ -21,6 +21,7 @@ # Entry script for running rialto componenttests import argparse +import os from scripts.gtest.build_and_run_tests import getGenericArguments, buildAndRunGTests from scripts.gtest.utils import getSuitesToRun, getOutputFile from scripts.gtest.generate_coverage import generateCoverageReport, generateSpecificCoverageStats @@ -50,8 +51,8 @@ # Generate coverage if args['coverage'] == True: - generateCoverageReport(args['output'], outputFile, suitesToRun) + generateCoverageReport(os.getcwd(), args['output'], outputFile) # Also generate coverage stats for public interfaces source files = ["*/main/source/*"] - generateSpecificCoverageStats(args['output'], outputFile, files, "coverage_statistics_public_apis") + generateSpecificCoverageStats(os.getcwd(), args['output'], outputFile, files, "coverage_statistics_public_apis") diff --git a/build_ut.py b/build_ut.py index f4d408e02..e34173c45 100755 --- a/build_ut.py +++ b/build_ut.py @@ -21,6 +21,7 @@ # Entry script for running rialto unittests import argparse +import os from scripts.gtest.build_and_run_tests import getGenericArguments, buildAndRunGTests from scripts.gtest.utils import getSuitesToRun, getOutputFile from scripts.gtest.generate_coverage import generateCoverageReport @@ -58,4 +59,4 @@ buildAndRunGTests(args, outputFile, buildDefines, suitesToRun) if args['coverage'] == True: - generateCoverageReport(args['output'], outputFile, suitesToRun) + generateCoverageReport(os.getcwd(), args['output'], outputFile) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index f5df87f31..42d7a115f 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -56,11 +56,3 @@ target_link_libraries ( PRIVATE RialtoLogging ) - -if ( COVERAGE_ENABLED ) - target_link_libraries( - RialtoCommon - PRIVATE - gcov - ) -endif() diff --git a/media/client/main/CMakeLists.txt b/media/client/main/CMakeLists.txt index d201d84cb..73f891086 100644 --- a/media/client/main/CMakeLists.txt +++ b/media/client/main/CMakeLists.txt @@ -88,15 +88,6 @@ target_link_libraries( Threads::Threads ) -if ( COVERAGE_ENABLED ) - target_link_libraries( - RialtoClient - - PRIVATE - gcov - ) -endif() - include( GNUInstallDirs ) diff --git a/media/server/CMakeLists.txt b/media/server/CMakeLists.txt index ab25f78c7..05d4ec2a2 100644 --- a/media/server/CMakeLists.txt +++ b/media/server/CMakeLists.txt @@ -61,6 +61,7 @@ target_link_libraries( RialtoServerIpc RialtoServerMain RialtoServerService + protobuf::libprotobuf ) if( NATIVE_BUILD ) diff --git a/media/server/gstplayer/include/GstInitialiser.h b/media/server/gstplayer/include/GstInitialiser.h index 58dad9de0..cab3a9a6c 100644 --- a/media/server/gstplayer/include/GstInitialiser.h +++ b/media/server/gstplayer/include/GstInitialiser.h @@ -21,7 +21,9 @@ #define FIREBOLT_RIALTO_SERVER_GST_INITIALISER_H_ #include "IGstInitialiser.h" +#include "IGstWrapper.h" #include +#include #include #include @@ -41,6 +43,7 @@ class GstInitialiser : public IGstInitialiser mutable std::mutex m_mutex; mutable std::condition_variable m_cv; std::thread m_thread; + std::shared_ptr m_gstWrapper; }; }; // namespace firebolt::rialto::server diff --git a/media/server/gstplayer/include/GstSrc.h b/media/server/gstplayer/include/GstSrc.h index 968f888ce..84f8f19de 100644 --- a/media/server/gstplayer/include/GstSrc.h +++ b/media/server/gstplayer/include/GstSrc.h @@ -122,7 +122,7 @@ class GstSrc : public IGstSrc void initSrc() override; - void setupAndAddAppArc(IDecryptionService *decryptionService, GstElement *source, StreamInfo &streamInfo, + void setupAndAddAppSrc(IDecryptionService *decryptionService, GstElement *source, StreamInfo &streamInfo, GstAppSrcCallbacks *callbacks, gpointer userData, firebolt::rialto::MediaSourceType type) override; diff --git a/media/server/gstplayer/include/IGstSrc.h b/media/server/gstplayer/include/IGstSrc.h index 0a83e2cac..76325e5e7 100644 --- a/media/server/gstplayer/include/IGstSrc.h +++ b/media/server/gstplayer/include/IGstSrc.h @@ -106,7 +106,7 @@ class IGstSrc * @param[in] userData : Data to be passed to the callbacks. * @param[in] type : The media type of the source. */ - virtual void setupAndAddAppArc(IDecryptionService *decryptionService, GstElement *source, StreamInfo &streamInfo, + virtual void setupAndAddAppSrc(IDecryptionService *decryptionService, GstElement *source, StreamInfo &streamInfo, GstAppSrcCallbacks *callbacks, gpointer userData, firebolt::rialto::MediaSourceType type) = 0; diff --git a/media/server/gstplayer/source/GstInitialiser.cpp b/media/server/gstplayer/source/GstInitialiser.cpp index b43b2d506..b701ed318 100644 --- a/media/server/gstplayer/source/GstInitialiser.cpp +++ b/media/server/gstplayer/source/GstInitialiser.cpp @@ -19,7 +19,6 @@ #include "GstInitialiser.h" #include "GstLogForwarding.h" -#include "IGstWrapper.h" #include "RialtoServerLogging.h" namespace firebolt::rialto::server @@ -30,6 +29,14 @@ GstInitialiser::~GstInitialiser() { m_thread.join(); } + +#ifdef FREE_MEM_BEFORE_EXIT + if (m_gstWrapper) + { + m_gstWrapper->gstDeinit(); + m_gstWrapper.reset(); + } +#endif } IGstInitialiser &IGstInitialiser::instance() @@ -51,22 +58,23 @@ void GstInitialiser::initialise(int *argc, char ***argv) { std::shared_ptr factory = firebolt::rialto::wrappers::IGstWrapperFactory::getFactory(); - std::shared_ptr gstWrapper = factory->getGstWrapper(); + m_gstWrapper = factory->getGstWrapper(); - if (!gstWrapper) + if (!m_gstWrapper) { RIALTO_SERVER_LOG_ERROR("Failed to create the gst wrapper"); return; } - gstWrapper->gstInit(argc, argv); + m_gstWrapper->gstInit(argc, argv); // remove rialto sinks from the registry - GstPlugin *rialtoPlugin = gstWrapper->gstRegistryFindPlugin(gstWrapper->gstRegistryGet(), "rialtosinks"); + GstPlugin *rialtoPlugin = + m_gstWrapper->gstRegistryFindPlugin(m_gstWrapper->gstRegistryGet(), "rialtosinks"); if (rialtoPlugin) { - gstWrapper->gstRegistryRemovePlugin(gstWrapper->gstRegistryGet(), rialtoPlugin); - gstWrapper->gstObjectUnref(rialtoPlugin); + m_gstWrapper->gstRegistryRemovePlugin(m_gstWrapper->gstRegistryGet(), rialtoPlugin); + m_gstWrapper->gstObjectUnref(rialtoPlugin); } enableGstLogForwarding(); diff --git a/media/server/gstplayer/source/GstSrc.cpp b/media/server/gstplayer/source/GstSrc.cpp index c8e753d09..d570ba671 100644 --- a/media/server/gstplayer/source/GstSrc.cpp +++ b/media/server/gstplayer/source/GstSrc.cpp @@ -389,7 +389,7 @@ void GstSrc::setDefaultStreamFormatIfNeeded(GstElement *appSrc) m_gstWrapper->gstCapsUnref(currentCaps); } -void GstSrc::setupAndAddAppArc(IDecryptionService *decryptionService, GstElement *source, StreamInfo &streamInfo, +void GstSrc::setupAndAddAppSrc(IDecryptionService *decryptionService, GstElement *source, StreamInfo &streamInfo, GstAppSrcCallbacks *callbacks, gpointer userData, firebolt::rialto::MediaSourceType type) { // Configure and add appsrc diff --git a/media/server/gstplayer/source/tasks/generic/FinishSetupSource.cpp b/media/server/gstplayer/source/tasks/generic/FinishSetupSource.cpp index f7e46621a..7ae44a486 100644 --- a/media/server/gstplayer/source/tasks/generic/FinishSetupSource.cpp +++ b/media/server/gstplayer/source/tasks/generic/FinishSetupSource.cpp @@ -109,7 +109,7 @@ void FinishSetupSource::execute() const } StreamInfo &streamInfo = elem.second; - m_context.gstSrc->setupAndAddAppArc(m_context.decryptionService, m_context.source, streamInfo, &callbacks, + m_context.gstSrc->setupAndAddAppSrc(m_context.decryptionService, m_context.source, streamInfo, &callbacks, &m_player, sourceType); m_player.notifyNeedMediaData(sourceType); } diff --git a/media/server/service/source/main.cpp b/media/server/service/source/main.cpp index 19e987d71..94c7e5138 100644 --- a/media/server/service/source/main.cpp +++ b/media/server/service/source/main.cpp @@ -17,10 +17,12 @@ * limitations under the License. */ +#include +#include + #include "IApplicationSessionServer.h" #include "IGstInitialiser.h" #include "RialtoServerLogging.h" -#include // NOLINT(build/filename_format) @@ -55,5 +57,11 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } appSessionServer->startService(); + +#ifdef FREE_MEM_BEFORE_EXIT + RIALTO_SERVER_LOG_INFO("Calling ShutdownProtobufLibrary"); + google::protobuf::ShutdownProtobufLibrary(); +#endif + return EXIT_SUCCESS; } diff --git a/rialto.supp b/rialto.supp index 17a07d536..ccbef7bad 100644 --- a/rialto.supp +++ b/rialto.supp @@ -134,6 +134,455 @@ fun:gst_debug_add_log_function ... } +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:__vasprintf_internal + fun:g_vasprintf + fun:g_strdup_vprintf + fun:g_strdup_printf + obj:*/libgstreamer-1.0.so* + obj:*/libgobject-2.0.so* + obj:*/libgobject-2.0.so* + fun:g_object_new_with_properties + fun:gst_element_factory_create_with_properties + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/libffi.so* + obj:*/libffi.so* + fun:g_cclosure_marshal_generic + fun:g_closure_invoke + obj:*/libgobject-2.0.so* + fun:g_signal_emit_valist + fun:g_signal_emit + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/libffi.so* + obj:*/libffi.so* + fun:g_cclosure_marshal_generic + fun:g_closure_invoke + obj:*/libgobject-2.0.so* + fun:g_signal_emit_valist + fun:g_signal_emit + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/libffi.so* + obj:*/libffi.so* + fun:g_cclosure_marshal_generic + fun:g_closure_invoke + obj:*/libgobject-2.0.so* + fun:g_signal_emit_valist + fun:g_signal_emit + obj:*/gstreamer-1.0/libgstcoreelements.so + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/gstreamer-1.0/libgstcoreelements.so + obj:*/libgstreamer-1.0.so* + obj:*/libglib-2.0.so* + obj:*/libglib-2.0.so* + fun:start_thread + fun:clone +} +{ + + Memcheck:Leak + match-leak-kinds: possible + fun:calloc + fun:calloc + fun:allocate_dtv + fun:_dl_allocate_tls + fun:allocate_stack + fun:pthread_create* + obj:*/libglib-2.0.so* + obj:*/libglib-2.0.so* + fun:g_thread_pool_push + ... + fun:gst_element_change_state + fun:gst_element_change_state + obj:*/libgstreamer-1.0.so* + fun:gst_element_sync_state_with_parent + fun:_ZN8firebolt6rialto8wrappers10GstWrapper29gstElementSyncStateWithParentEP11_GstElement + fun:_ZN8firebolt6rialto6server6GstSrc17setupAndAddAppSrcEPNS1_18IDecryptionServiceEP11_GstElementRNS1_10StreamInfoEP18GstAppSrcCallbacksPvNS0_15MediaSourceTypeE +} +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:__vasprintf_internal + fun:g_vasprintf + fun:g_strdup_vprintf + fun:g_strdup_printf + obj:*/libgstreamer-1.0.so* + obj:*/libgobject-2.0.so* + obj:*/libgobject-2.0.so* + fun:g_object_new_with_properties + fun:gst_element_factory_create_with_properties + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/libffi.so* + obj:*/libffi.so* + fun:g_cclosure_marshal_generic + fun:g_closure_invoke + obj:*/libgobject-2.0.so* + fun:g_signal_emit_valist + fun:g_signal_emit + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/libffi.so* + obj:*/libffi.so* + fun:g_cclosure_marshal_generic + fun:g_closure_invoke + obj:*/libgobject-2.0.so* + fun:g_signal_emit_valist + fun:g_signal_emit + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/libffi.so* + obj:*/libffi.so* + fun:g_cclosure_marshal_generic + fun:g_closure_invoke + obj:*/libgobject-2.0.so* + fun:g_signal_emit_valist + fun:g_signal_emit + obj:*/gstreamer-1.0/libgstcoreelements.so + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/gstreamer-1.0/libgstcoreelements.so + obj:*/libgstreamer-1.0.so* + obj:*/libglib-2.0.so* + obj:*/libglib-2.0.so* + fun:start_thread + fun:clone +} +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:g_malloc + obj:*/libglib-2.0.so* + obj:*/libgobject-2.0.so* + fun:g_object_unref + obj:*/gstreamer-1.0/libgstplayback.so + fun:g_object_unref + obj:*/libgstreamer-1.0.so* + fun:gst_bin_remove + obj:*/libgstreamer-1.0.so* + fun:g_object_unref + fun:_ZN8firebolt6rialto8wrappers10GstWrapper14gstObjectUnrefEPv + fun:_ZN8firebolt6rialto6server16GstGenericPlayer12termPipelineEv + ... + fun:_ZNKSt14default_deleteIN8firebolt6rialto6server17IGstGenericPlayerEEclEPS3_ + fun:_ZNSt10unique_ptrIN8firebolt6rialto6server17IGstGenericPlayerESt14default_deleteIS3_EED1Ev + ... + fun:_ZNKSt14default_deleteIN8firebolt6rialto6server28IMediaPipelineServerInternalEEclEPS3_ + fun:_ZNSt10unique_ptrIN8firebolt6rialto6server28IMediaPipelineServerInternalESt14default_deleteIS3_EED1Ev +} +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + obj:*/libglib-2.0.so* + fun:g_rec_mutex_init + obj:*/libgstreamer-1.0.so* + fun:g_type_create_instance + obj:*/libgobject-2.0.so* + fun:g_object_new_with_properties + fun:gst_element_factory_create_with_properties + obj:*/gstreamer-1.0/libgstplayback.so + ... + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + ... + fun:gst_pad_push_event + ... + fun:gst_pad_push_event + obj:*/gstreamer-1.0/libgstcoreelements.so + obj:*/libgstreamer-1.0.so* + obj:*/libglib-2.0.so* + obj:*/libglib-2.0.so* + fun:start_thread + fun:clone +} +{ + + Memcheck:Leak + match-leak-kinds: possible + fun:calloc + fun:calloc + fun:allocate_dtv + fun:_dl_allocate_tls + fun:allocate_stack + fun:pthread_create* + obj:*/libglib-2.0.so* + obj:*/libglib-2.0.so* + fun:g_thread_pool_push + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_task_set_state + fun:gst_pad_start_task + obj:*/gstreamer-1.0/libgstcoreelements.so + obj:*/libgstreamer-1.0.so* + fun:gst_pad_set_active + obj:*/libgstreamer-1.0.so* + fun:gst_iterator_fold + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_element_change_state + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_element_change_state + fun:gst_element_change_state + obj:*/libgstreamer-1.0.so* + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/libgstreamer-1.0.so* + fun:g_hook_list_marshal + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + ... + fun:gst_pad_push_event + obj:*/libffi.so* + obj:*/libffi.so* + fun:g_cclosure_marshal_generic + fun:g_closure_invoke + obj:*/libgobject-2.0.so* + fun:g_signal_emit_valist + fun:g_signal_emit + ... + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + ... + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + ... + fun:gst_pad_push_event + obj:*/gstreamer-1.0/libgstcoreelements.so + obj:*/libgstreamer-1.0.so* + obj:*/libglib-2.0.so* + obj:*/libglib-2.0.so* + fun:start_thread + fun:clone +} +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:calloc + fun:g_malloc0 + obj:*/libgstreamer-1.0.so* + fun:gst_structure_new_id + fun:gst_event_new_seek + fun:gst_element_seek + fun:_ZN8firebolt6rialto8wrappers10GstWrapper14gstElementSeekEP11_GstElementd9GstFormat12GstSeekFlags11GstSeekTypelS7_l + fun:_ZNK8firebolt6rialto6server5tasks7generic15SetPlaybackRate7executeEv + fun:_ZN8firebolt6rialto6server12WorkerThread11taskHandlerEv + fun:_ZSt13__invoke_implIvMN8firebolt6rialto6server12WorkerThreadEFvvEPS3_JEET_St21__invoke_memfun_derefOT0_OT1_DpOT2_ + fun:_ZSt8__invokeIMN8firebolt6rialto6server12WorkerThreadEFvvEJPS3_EENSt15__invoke_resultIT_JDpT0_EE4typeEOS8_DpOS9_ + fun:_ZNSt6thread8_InvokerISt5tupleIJMN8firebolt6rialto6server12WorkerThreadEFvvEPS5_EEE9_M_invokeIJLm0ELm1EEEEvSt12_Index_tupleIJXspT_EEE + fun:_ZNSt6thread8_InvokerISt5tupleIJMN8firebolt6rialto6server12WorkerThreadEFvvEPS5_EEEclEv + fun:_ZNSt6thread11_State_implINS_8_InvokerISt5tupleIJMN8firebolt6rialto6server12WorkerThreadEFvvEPS6_EEEEE6_M_runEv + obj:*/libstdc++.so* + fun:start_thread + fun:clone +} +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:gst_event_new_custom + fun:gst_element_seek + fun:_ZN8firebolt6rialto8wrappers10GstWrapper14gstElementSeekEP11_GstElementd9GstFormat12GstSeekFlags11GstSeekTypelS7_l + fun:_ZNK8firebolt6rialto6server5tasks7generic15SetPlaybackRate7executeEv + fun:_ZN8firebolt6rialto6server12WorkerThread11taskHandlerEv + fun:_ZSt13__invoke_implIvMN8firebolt6rialto6server12WorkerThreadEFvvEPS3_JEET_St21__invoke_memfun_derefOT0_OT1_DpOT2_ + fun:_ZSt8__invokeIMN8firebolt6rialto6server12WorkerThreadEFvvEJPS3_EENSt15__invoke_resultIT_JDpT0_EE4typeEOS8_DpOS9_ + fun:_ZNSt6thread8_InvokerISt5tupleIJMN8firebolt6rialto6server12WorkerThreadEFvvEPS5_EEE9_M_invokeIJLm0ELm1EEEEvSt12_Index_tupleIJXspT_EEE + fun:_ZNSt6thread8_InvokerISt5tupleIJMN8firebolt6rialto6server12WorkerThreadEFvvEPS5_EEEclEv + fun:_ZNSt6thread11_State_implINS_8_InvokerISt5tupleIJMN8firebolt6rialto6server12WorkerThreadEFvvEPS6_EEEEE6_M_runEv + obj:*/libstdc++.so* + fun:start_thread + fun:clone +} + + +{ + + Helgrind:Race + ... + fun:gst_* +} +{ + + Helgrind:Race + ... + fun:g_* +} +{ + + Helgrind:Race + ... + obj:*/libglib-2.0.so* +} +{ + + Helgrind:Race + ... + obj:*/libgstcoreelements.so +} +{ + + Helgrind:Race + ... + obj:*/libgstreamer-1.0.so* +} +{ + + Helgrind:Race + ... + obj:*/libgstapp-1.0.so* +} +{ + + Helgrind:Race + ... + obj:*/libgstbase-1.0.so* +} +{ + + Helgrind:LockOrder + ... + obj:*/libgstreamer-1.0.so* +} + + +{ + + Helgrind:Race + ... + fun:_ZNK6google8protobuf* +} + + +{ + + Helgrind:Misc + obj:*/libexec/valgrind/vgpreload_helgrind-amd64-linux.so + fun:_ZN8firebolt6rialto6server10MainThread11enqueueTaskEjSt8functionIFvvEE +} +{ + + Helgrind:Misc + obj:*/libexec/valgrind/vgpreload_helgrind-amd64-linux.so + fun:_ZN8firebolt6rialto6server10MainThread18enqueueTaskAndWaitEjSt8functionIFvvEE +} +{ + + Helgrind:Misc + obj:*/libexec/valgrind/vgpreload_helgrind-amd64-linux.so + fun:_ZN8firebolt6rialto6server12WorkerThread11enqueueTaskEOSt10unique_ptrINS1_11IPlayerTaskESt14default_deleteIS4_EE +} +{ + + Helgrind:Race + fun:_ZN8firebolt6rialto6server19GstDispatcherThread18gstBusEventHandlerEP11_GstElement +} +{ + + Helgrind:Race + fun:_ZNK8firebolt6rialto6server5tasks7generic16HandleBusMessage7executeEv +} +{ + + Helgrind:Misc + ... + fun:_ZN8firebolt6rialto6common5Timer6cancelEv +} +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:__vasprintf_internal + fun:g_vasprintf + fun:g_strdup_vprintf + fun:g_error_new_valist + fun:g_error_new +} { ignore_protobuf_internal_parse_possibly_lost Memcheck:Leak @@ -164,3 +613,550 @@ fun:gst_update_registry ... } +{ + + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + fun:malloc + fun:allocate_dtv_entry + fun:allocate_and_init + fun:tls_get_addr_tail + fun:__tls_get_addr + obj:*/libgnutls.so* + fun:_dl_call_fini + fun:_dl_fini + fun:__run_exit_handlers + fun:exit + ... +} +{ + + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + fun:malloc + fun:_dl_resize_dtv + fun:_dl_update_slotinfo + fun:update_get_addr + fun:__tls_get_addr + obj:*/libgnutls.so* + fun:_dl_call_fini + fun:_dl_fini + fun:__run_exit_handlers + fun:exit + ... +} +{ + + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + fun:_dl_resize_dtv + fun:_dl_update_slotinfo + fun:update_get_addr + fun:__tls_get_addr + obj:*/libgnutls.so* + fun:_dl_call_fini + fun:_dl_fini + fun:__run_exit_handlers + fun:exit + ... +} +{ + + Memcheck:Leak + match-leak-kinds: possible + fun:calloc + fun:calloc + fun:allocate_dtv + fun:_dl_allocate_tls + fun:allocate_stack + fun:pthread_create@@GLIBC_2.34 + obj:*/libglib-2.0.so* + obj:*/libglib-2.0.so* + obj:*/libglib-2.0.so* + fun:start_thread + fun:clone +} +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:__vasprintf_internal + fun:g_vasprintf + fun:g_strdup_vprintf + fun:g_strdup_printf + obj:*/libgstreamer-1.0.so* + obj:*/libgobject-2.0.so* + obj:*/libgobject-2.0.so* + fun:g_object_new_with_properties + fun:gst_element_factory_create_with_properties + ... +} +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:g_rec_mutex_init + obj:*/libgstreamer-1.0.so* + fun:g_type_create_instance + obj:*/libgobject-2.0.so* + fun:g_object_new_with_properties + fun:gst_element_factory_create_with_properties + ... +} +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:malloc + fun:resize_scopes + fun:dl_open_worker_begin + fun:_dl_catch_exception + fun:dl_open_worker + fun:_dl_catch_exception + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_exception + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen_implementation + fun:dlopen@@GLIBC_2.34 + fun:g_module_open_full + obj:*/libgstreamer-1.0.so* + fun:gst_plugin_load_by_name + fun:gst_plugin_feature_load + fun:gst_element_factory_create_with_properties + ... +} +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:g_malloc + obj:*/libglib-2.0.so* + obj:*/libglib-2.0.so* + obj:*/libgobject-2.0.so* + fun:g_object_unref + ... +} +{ + + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + fun:g_malloc + fun:g_atomic_rc_box_alloc + obj:*/libgstreamer-1.0.so* + fun:g_type_create_instance + obj:*/libgobject-2.0.so* + fun:g_object_new_valist + fun:g_object_new + fun:gst_system_clock_obtain + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/gstreamer-1.0/libgstplayback.so + fun:gst_element_change_state + obj:*/libgstreamer-1.0.so* + ... +} +{ + + Memcheck:Leak + match-leak-kinds: possible + fun:calloc + fun:calloc + fun:allocate_dtv + fun:_dl_allocate_tls + fun:allocate_stack + fun:pthread_create@@GLIBC_2.34 + obj:*/libglib-2.0.so* + fun:g_thread_new + fun:g_thread_pool_new_full + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:g_type_create_instance + obj:*/libgobject-2.0.so* + fun:g_object_new_with_properties + fun:g_object_new + fun:gst_task_new + fun:gst_pad_start_task + obj:*/gstreamer-1.0/libgstcoreelements.so + obj:*/libgstreamer-1.0.so* + fun:gst_pad_set_active + obj:*/libgstreamer-1.0.so* + fun:gst_iterator_fold + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_element_change_state + fun:gst_element_change_state + obj:*/libgstreamer-1.0.so* + fun:gst_element_sync_state_with_parent + ... +} +{ + + Memcheck:Leak + match-leak-kinds: definite + ... + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/libgstreamer-1.0.so* + fun:g_hook_list_marshal + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libffi.so* + obj:*/libffi.so* + fun:ffi_call + fun:g_cclosure_marshal_generic + fun:g_closure_invoke + obj:*/libgobject-2.0.so* + obj:*/libgobject-2.0.so* + fun:g_signal_emit_valist + fun:g_signal_emit + obj:*/gstreamer-1.0/libgstcoreelements.so + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/gstreamer-1.0/libgstcoreelements.so + obj:*/libgstreamer-1.0.so* + obj:*/libglib-2.0.so* + obj:*/libglib-2.0.so* + fun:start_thread + fun:clone +} +{ + + Memcheck:Leak + match-leak-kinds: possible + ... + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/libgstreamer-1.0.so* + fun:g_hook_list_marshal + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libffi.so* + obj:*/libffi.so* + fun:ffi_call + fun:g_cclosure_marshal_generic + fun:g_closure_invoke + obj:*/libgobject-2.0.so* + obj:*/libgobject-2.0.so* + fun:g_signal_emit_valist + fun:g_signal_emit + obj:*/gstreamer-1.0/libgstcoreelements.so + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/gstreamer-1.0/libgstcoreelements.so + obj:*/libgstreamer-1.0.so* + obj:*/libglib-2.0.so* + obj:*/libglib-2.0.so* + fun:start_thread + fun:clone +} +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + ... + obj:*/libgobject-2.0.so* + fun:g_object_new_with_properties + fun:gst_element_factory_create_with_properties + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/libffi.so* + obj:*/libffi.so* + fun:ffi_call + fun:g_cclosure_marshal_generic + fun:g_closure_invoke + obj:*/libgobject-2.0.so* + obj:*/libgobject-2.0.so* + fun:g_signal_emit_valist + fun:g_signal_emit + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/libffi.so* + obj:*/libffi.so* + fun:ffi_call + fun:g_cclosure_marshal_generic + fun:g_closure_invoke + obj:*/libgobject-2.0.so* + obj:*/libgobject-2.0.so* + fun:g_signal_emit_valist + fun:g_signal_emit + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/libffi.so* + obj:*/libffi.so* + fun:ffi_call + fun:g_cclosure_marshal_generic + fun:g_closure_invoke + obj:*/libgobject-2.0.so* + obj:*/libgobject-2.0.so* + fun:g_signal_emit_valist + fun:g_signal_emit + obj:*/gstreamer-1.0/libgstcoreelements.so + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/gstreamer-1.0/libgstcoreelements.so + obj:*/libgstreamer-1.0.so* + obj:*/libglib-2.0.so* + obj:*/libglib-2.0.so* + fun:start_thread + fun:clone +} +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:g_type_create_instance + obj:*/libgobject-2.0.so* + fun:g_object_new_with_properties + fun:gst_element_factory_create_with_properties + fun:gst_element_factory_create_valist + fun:gst_element_factory_make_valist + fun:gst_element_factory_make_full + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/libgstreamer-1.0.so* + fun:g_hook_list_marshal + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libffi.so* + fun:ffi_call + fun:g_cclosure_marshal_generic + fun:g_closure_invoke + obj:*/libgobject-2.0.so* + fun:g_signal_emit_valist + fun:g_signal_emit + obj:*/gstreamer-1.0/libgstcoreelements.so + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/libgstreamer-1.0.so* + fun:gst_pad_forward + fun:gst_pad_event_default + obj:*/libgstreamer-1.0.so* + fun:gst_pad_push_event + obj:*/gstreamer-1.0/libgstcoreelements.so + obj:*/libgstreamer-1.0.so* + obj:*/libglib-2.0.so* + fun:start_thread + fun:clone +} +{ + + Memcheck:Leak + match-leak-kinds: possible + ... + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/libgstreamer-1.0.so* + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/gstreamer-1.0/libgstplayback.so + fun:g_cclosure_marshal_VOID__OBJECTv + obj:*/libgobject-2.0.so* + fun:g_signal_emit_valist + fun:g_signal_emit + fun:gst_element_remove_pad + fun:g_cclosure_marshal_VOID__OBJECTv + obj:*/libgobject-2.0.so* + fun:g_signal_emit_valist + fun:g_signal_emit + fun:gst_element_remove_pad + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/gstreamer-1.0/libgstplayback.so + fun:gst_element_change_state + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/gstreamer-1.0/libgstplayback.so + fun:gst_element_change_state + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/gstreamer-1.0/libgstplayback.so + fun:gst_element_change_state + ... +} +{ + + Memcheck:Leak + match-leak-kinds: definite + ... + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/libgstreamer-1.0.so* + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/gstreamer-1.0/libgstplayback.so + fun:g_cclosure_marshal_VOID__OBJECTv + obj:*/libgobject-2.0.so* + fun:g_signal_emit_valist + fun:g_signal_emit + fun:gst_element_remove_pad + fun:g_cclosure_marshal_VOID__OBJECTv + obj:*/libgobject-2.0.so* + fun:g_signal_emit_valist + fun:g_signal_emit + fun:gst_element_remove_pad + obj:*/gstreamer-1.0/libgstplayback.so + obj:*/gstreamer-1.0/libgstplayback.so + fun:gst_element_change_state + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/gstreamer-1.0/libgstplayback.so + fun:gst_element_change_state + obj:*/libgstreamer-1.0.so* + obj:*/libgstreamer-1.0.so* + obj:*/gstreamer-1.0/libgstplayback.so + fun:gst_element_change_state + ... +} diff --git a/scripts/gtest/generate_coverage.py b/scripts/gtest/generate_coverage.py index ce6356bc6..e73e2a397 100644 --- a/scripts/gtest/generate_coverage.py +++ b/scripts/gtest/generate_coverage.py @@ -27,10 +27,10 @@ from .utils import runcmd # Generates the coverage stats and produces html github pages for all files in the src tree -def generateCoverageReport(outputDir, resultsFile, suites): +def generateCoverageReport(baseDir, outputDir, resultsFile): lcovCommon = [] lcovCommon.extend(["--exclude", "/usr/*"]) - lcovCommon.extend(["--exclude", "*build/*", "--exclude", "*tests/*", "--exclude", "*wrappers/*", "--filter", "brace,function,trivial"]) + lcovCommon.extend(["--exclude", "*build*/*", "--exclude", "*tests/*", "--exclude", "*wrappers/*", "--filter", "brace,function,trivial"]) lcovCommon.extend(["--parallel", str(multiprocessing.cpu_count())]) # the following line tells lcov to ignore any errors caused by include/exclude/erase/omit/substitute pattern which did not match any file pathnames @@ -40,18 +40,18 @@ def generateCoverageReport(outputDir, resultsFile, suites): lcovBaseCmd.extend(lcovCommon) if resultsFile: - lcovBaseStatus = runcmd(lcovBaseCmd, cwd=os.getcwd() + '/' + outputDir, stdout=resultsFile, stderr=subprocess.STDOUT) + lcovBaseStatus = runcmd(lcovBaseCmd, cwd=baseDir + '/' + outputDir, stdout=resultsFile, stderr=subprocess.STDOUT) else: - lcovBaseStatus = runcmd(lcovBaseCmd, cwd=os.getcwd() + '/' + outputDir, stderr=subprocess.STDOUT) + lcovBaseStatus = runcmd(lcovBaseCmd, cwd=baseDir + '/' + outputDir, stderr=subprocess.STDOUT) if not lcovBaseStatus: return False lcovTestCmd = ["lcov", "-c", "-d", ".", "--output-file", "coverage_test.info"] lcovTestCmd.extend(lcovCommon) if resultsFile: - lcovTestStatus = runcmd(lcovTestCmd, cwd=os.getcwd() + '/' + outputDir, stdout=resultsFile, stderr=subprocess.STDOUT) + lcovTestStatus = runcmd(lcovTestCmd, cwd=baseDir + '/' + outputDir, stdout=resultsFile, stderr=subprocess.STDOUT) else: - lcovTestStatus = runcmd(lcovTestCmd, cwd=os.getcwd() + '/' + outputDir, stderr=subprocess.STDOUT) + lcovTestStatus = runcmd(lcovTestCmd, cwd=baseDir + '/' + outputDir, stderr=subprocess.STDOUT) if not lcovTestStatus: return False @@ -59,24 +59,24 @@ def generateCoverageReport(outputDir, resultsFile, suites): "brace,function,trivial"] lcovCombineCmd.extend(["--ignore-errors", "empty"]) if resultsFile: - lcovCombineStatus = runcmd(lcovCombineCmd, cwd=os.getcwd() + '/' + outputDir, stdout=resultsFile, stderr=subprocess.STDOUT) + lcovCombineStatus = runcmd(lcovCombineCmd, cwd=baseDir + '/' + outputDir, stdout=resultsFile, stderr=subprocess.STDOUT) else: - lcovCombineStatus = runcmd(lcovCombineCmd, cwd=os.getcwd() + '/' + outputDir, stderr=subprocess.STDOUT) + lcovCombineStatus = runcmd(lcovCombineCmd, cwd=baseDir + '/' + outputDir, stderr=subprocess.STDOUT) if not lcovCombineStatus: return False genHtmlCmd = ["genhtml", "coverage.info", "--output-directory", "gh_pages/coverage_report", "--filter", "brace,function,trivial"] genHtmlCmd.extend(["--ignore-errors", "empty"]) if resultsFile: - genHtmlStatus = runcmd(genHtmlCmd, cwd=os.getcwd() + '/' + outputDir, stdout=resultsFile, stderr=subprocess.STDOUT) + genHtmlStatus = runcmd(genHtmlCmd, cwd=baseDir + '/' + outputDir, stdout=resultsFile, stderr=subprocess.STDOUT) else: - genHtmlStatus = runcmd(genHtmlCmd, cwd=os.getcwd() + '/' + outputDir, stderr=subprocess.STDOUT) + genHtmlStatus = runcmd(genHtmlCmd, cwd=baseDir + '/' + outputDir, stderr=subprocess.STDOUT) genStatsCmd = ["lcov", "--summary", "coverage.info", "--filter", "brace,function,trivial"] genStatsCmd.extend(["--ignore-errors", "empty"]) - statsFile = open(os.getcwd() + '/' + outputDir + '/' + "coverage_statistics.txt", "w") + statsFile = open(baseDir + '/' + outputDir + '/' + "coverage_statistics.txt", "w") if statsFile: - genStatsStatus = runcmd(genStatsCmd, cwd=os.getcwd() + '/' + outputDir, stdout=statsFile, stderr=subprocess.STDOUT) + genStatsStatus = runcmd(genStatsCmd, cwd=baseDir + '/' + outputDir, stdout=statsFile, stderr=subprocess.STDOUT) else: genStatsStatus = False statsFile.close() @@ -84,16 +84,16 @@ def generateCoverageReport(outputDir, resultsFile, suites): return genHtmlStatus and genStatsStatus # Generates a stats file based on the file patterns given in includeFiles. generateCoverageReport must have been run first. -def generateSpecificCoverageStats(outputDir, resultsFile, includeFiles, statsFileName): +def generateSpecificCoverageStats(baseDir, outputDir, resultsFile, includeFiles, statsFileName): genStatsCmd = ["lcov", "--summary", "coverage.info", "--filter", "brace,function,trivial"] genStatsCmd.extend(["--ignore-errors", "empty"]) for file in includeFiles: genStatsCmd.extend(["--include", file]) - statsFile = open(os.getcwd() + '/' + outputDir + '/' + statsFileName + '.txt', "w") + statsFile = open(baseDir + '/' + outputDir + '/' + statsFileName + '.txt', "w") if statsFile: - genStatsStatus = runcmd(genStatsCmd, cwd=os.getcwd() + '/' + outputDir, stdout=statsFile, stderr=subprocess.STDOUT) + genStatsStatus = runcmd(genStatsCmd, cwd=baseDir + '/' + outputDir, stdout=statsFile, stderr=subprocess.STDOUT) else: genStatsStatus = False statsFile.close() diff --git a/serverManager/serverManagerSim/commands/SetLog.cpp b/serverManager/serverManagerSim/commands/SetLog.cpp index 95d6615c9..cfe258957 100644 --- a/serverManager/serverManagerSim/commands/SetLog.cpp +++ b/serverManager/serverManagerSim/commands/SetLog.cpp @@ -59,12 +59,17 @@ rialto::servermanager::service::LoggingLevels convert(const std::string &compone auto loggingLevel{convert(level)}; if ("all" == component) { + levels.defaultLoggingLevel = loggingLevel; levels.clientLoggingLevel = loggingLevel; levels.sessionServerLoggingLevel = loggingLevel; levels.ipcLoggingLevel = loggingLevel; levels.serverManagerLoggingLevel = loggingLevel; levels.commonLoggingLevel = loggingLevel; } + else if ("default" == component) + { + levels.defaultLoggingLevel = loggingLevel; + } else if ("client" == component) { levels.clientLoggingLevel = loggingLevel; diff --git a/serverManager/service/CMakeLists.txt b/serverManager/service/CMakeLists.txt index dedb42e95..3f5004699 100644 --- a/serverManager/service/CMakeLists.txt +++ b/serverManager/service/CMakeLists.txt @@ -77,14 +77,6 @@ if( RIALTO_ENABLE_CONFIG_FILE ) ) endif() -if ( COVERAGE_ENABLED ) - target_link_libraries( - RialtoServerManager - PRIVATE - gcov - ) -endif() - if( NOT CMAKE_BUILD_TYPE STREQUAL "UnitTests" ) include( GNUInstallDirs ) install ( diff --git a/tests/common/externalLibraryMocks/GstWrapperMock.h b/tests/common/externalLibraryMocks/GstWrapperMock.h index 476bbdab6..10e76256a 100644 --- a/tests/common/externalLibraryMocks/GstWrapperMock.h +++ b/tests/common/externalLibraryMocks/GstWrapperMock.h @@ -33,6 +33,7 @@ class GstWrapperMock : public IGstWrapper virtual ~GstWrapperMock() = default; MOCK_METHOD(void, gstInit, (int *argc, char ***argv), (override)); + MOCK_METHOD(void, gstDeinit, (), (override)); MOCK_METHOD(GstPlugin *, gstRegistryFindPlugin, (GstRegistry * registry, const gchar *name), (override)); MOCK_METHOD(void, gstRegistryRemovePlugin, (GstRegistry * registry, GstPlugin *plugin), (override)); MOCK_METHOD(void, gstObjectUnref, (gpointer object), (override)); diff --git a/tests/componenttests/client/CMakeLists.txt b/tests/componenttests/client/CMakeLists.txt index ca850f953..35ac239f3 100644 --- a/tests/componenttests/client/CMakeLists.txt +++ b/tests/componenttests/client/CMakeLists.txt @@ -127,13 +127,3 @@ target_link_libraries( RialtoPlayerCommon RialtoProtobuf ) - -if ( COVERAGE_ENABLED ) - target_link_libraries( - RialtoClientComponentTests - - gcov - ) -endif() - - diff --git a/tests/componenttests/server/tests/CMakeLists.txt b/tests/componenttests/server/tests/CMakeLists.txt index 04d368646..9fe1d15bb 100644 --- a/tests/componenttests/server/tests/CMakeLists.txt +++ b/tests/componenttests/server/tests/CMakeLists.txt @@ -98,11 +98,3 @@ target_link_libraries( RialtoServerComponentTestsFixtures RialtoTestCommonUtils ) - -if ( COVERAGE_ENABLED ) - target_link_libraries( - RialtoServerComponentTests - - gcov - ) -endif() diff --git a/tests/unittests/common/unittests/CMakeLists.txt b/tests/unittests/common/unittests/CMakeLists.txt index 63df0a217..b9d1ab2a8 100644 --- a/tests/unittests/common/unittests/CMakeLists.txt +++ b/tests/unittests/common/unittests/CMakeLists.txt @@ -18,7 +18,8 @@ # if ( COVERAGE_ENABLED ) - add_compile_options(-coverage) + add_compile_options(--coverage) + add_link_options(--coverage) endif() add_gtests ( @@ -41,11 +42,3 @@ target_link_libraries( RialtoCommonUnitTests RialtoCommon ) - -if ( COVERAGE_ENABLED ) - target_link_libraries( - RialtoCommonUnitTests - - gcov - ) -endif() diff --git a/tests/unittests/ipc/CMakeLists.txt b/tests/unittests/ipc/CMakeLists.txt index ec517eec4..a170c44d0 100644 --- a/tests/unittests/ipc/CMakeLists.txt +++ b/tests/unittests/ipc/CMakeLists.txt @@ -64,13 +64,3 @@ target_link_libraries( RialtoIpcStub RialtoProtobuf ) - -if ( COVERAGE_ENABLED ) - target_link_libraries( - RialtoIpcUnitTests - - gcov - ) -endif() - - diff --git a/tests/unittests/logging/CMakeLists.txt b/tests/unittests/logging/CMakeLists.txt index 2811f5836..57bdc177a 100644 --- a/tests/unittests/logging/CMakeLists.txt +++ b/tests/unittests/logging/CMakeLists.txt @@ -40,12 +40,3 @@ target_link_libraries( # # Link application source RialtoLogging ) - -if ( COVERAGE_ENABLED ) - target_link_libraries( - RialtoLoggingUnitTests - - gcov - ) -endif() - diff --git a/tests/unittests/media/client/ipc/CMakeLists.txt b/tests/unittests/media/client/ipc/CMakeLists.txt index a2fcca219..d00f5d6cf 100644 --- a/tests/unittests/media/client/ipc/CMakeLists.txt +++ b/tests/unittests/media/client/ipc/CMakeLists.txt @@ -145,11 +145,3 @@ target_link_libraries( RialtoIpcClient RialtoProtobuf ) - -if ( COVERAGE_ENABLED ) - target_link_libraries( - RialtoClientIpcUnitTests - - gcov - ) -endif() diff --git a/tests/unittests/media/client/main/CMakeLists.txt b/tests/unittests/media/client/main/CMakeLists.txt index acb66b743..d0ae9c218 100644 --- a/tests/unittests/media/client/main/CMakeLists.txt +++ b/tests/unittests/media/client/main/CMakeLists.txt @@ -121,13 +121,3 @@ target_link_libraries( # # Link application source RialtoClient ) - -if ( COVERAGE_ENABLED ) - target_link_libraries( - RialtoClientUnitTests - - gcov - ) -endif() - - diff --git a/tests/unittests/media/common/CMakeLists.txt b/tests/unittests/media/common/CMakeLists.txt index 88726d5e7..c129e0d3e 100644 --- a/tests/unittests/media/common/CMakeLists.txt +++ b/tests/unittests/media/common/CMakeLists.txt @@ -53,12 +53,3 @@ target_link_libraries( RialtoPlayerCommon RialtoProtobuf ) - -if ( COVERAGE_ENABLED ) - target_link_libraries( - RialtoPlayerCommonUnitTests - - gcov - ) -endif() - diff --git a/tests/unittests/media/server/gstplayer/CMakeLists.txt b/tests/unittests/media/server/gstplayer/CMakeLists.txt index 69429fc27..56a0b5d70 100644 --- a/tests/unittests/media/server/gstplayer/CMakeLists.txt +++ b/tests/unittests/media/server/gstplayer/CMakeLists.txt @@ -145,12 +145,4 @@ target_link_libraries(RialtoServerGstPlayerUnitTests RialtoTestCommonUtils ) -if ( COVERAGE_ENABLED ) - target_link_libraries( - RialtoServerGstPlayerUnitTests - - gcov - ) -endif() - set_target_properties(RialtoServerGstPlayerUnitTests PROPERTIES COMPILE_FLAGS "-Wno-write-strings") diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp index 40cf6f80b..496b30df8 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp @@ -2618,7 +2618,7 @@ void GenericTasksTestsBase::shouldFailToReportPosition() void GenericTasksTestsBase::shouldFinishSetupSource() { EXPECT_CALL(*testContext->m_gstSrc, - setupAndAddAppArc(std::dynamic_pointer_cast( + setupAndAddAppSrc(std::dynamic_pointer_cast( testContext->m_decryptionServiceMock) .get(), testContext->m_element, testContext->m_streamInfoAudio, _, &testContext->m_gstPlayer, @@ -2633,7 +2633,7 @@ void GenericTasksTestsBase::shouldFinishSetupSource() })); EXPECT_CALL(testContext->m_gstPlayer, notifyNeedMediaData(MediaSourceType::AUDIO)); EXPECT_CALL(*testContext->m_gstSrc, - setupAndAddAppArc(std::dynamic_pointer_cast( + setupAndAddAppSrc(std::dynamic_pointer_cast( testContext->m_decryptionServiceMock) .get(), testContext->m_element, testContext->m_streamInfoVideo, _, &testContext->m_gstPlayer, diff --git a/tests/unittests/media/server/gstplayer/rialtoSrc/AppSrcTest.cpp b/tests/unittests/media/server/gstplayer/rialtoSrc/AppSrcTest.cpp index 64af525f7..48e126df8 100644 --- a/tests/unittests/media/server/gstplayer/rialtoSrc/AppSrcTest.cpp +++ b/tests/unittests/media/server/gstplayer/rialtoSrc/AppSrcTest.cpp @@ -227,7 +227,7 @@ TEST_F(RialtoServerAppSrcGstSrcTest, SetupVideo) expectLinkQueue(&m_payloader); expectSetupPad(&m_queue); - m_gstSrc->setupAndAddAppArc(m_decryptionServiceMock.get(), GST_ELEMENT(&m_rialtoSrc), m_streamInfo, &m_callbacks, + m_gstSrc->setupAndAddAppSrc(m_decryptionServiceMock.get(), GST_ELEMENT(&m_rialtoSrc), m_streamInfo, &m_callbacks, this, MediaSourceType::VIDEO); } @@ -247,7 +247,7 @@ TEST_F(RialtoServerAppSrcGstSrcTest, SetupVideoH264WithoutStreamFormat) expectLinkQueue(&m_payloader); expectSetupPad(&m_queue); - m_gstSrc->setupAndAddAppArc(m_decryptionServiceMock.get(), GST_ELEMENT(&m_rialtoSrc), m_streamInfo, &m_callbacks, + m_gstSrc->setupAndAddAppSrc(m_decryptionServiceMock.get(), GST_ELEMENT(&m_rialtoSrc), m_streamInfo, &m_callbacks, this, MediaSourceType::VIDEO); } @@ -273,7 +273,7 @@ TEST_F(RialtoServerAppSrcGstSrcTest, SetupVideoWithStreamFormat) expectLinkQueue(&m_payloader); expectSetupPad(&m_queue); - m_gstSrc->setupAndAddAppArc(m_decryptionServiceMock.get(), GST_ELEMENT(&m_rialtoSrc), m_streamInfo, &m_callbacks, + m_gstSrc->setupAndAddAppSrc(m_decryptionServiceMock.get(), GST_ELEMENT(&m_rialtoSrc), m_streamInfo, &m_callbacks, this, MediaSourceType::VIDEO); } @@ -299,7 +299,7 @@ TEST_F(RialtoServerAppSrcGstSrcTest, SetupVideoWithCodecData) expectLinkQueue(&m_payloader); expectSetupPad(&m_queue); - m_gstSrc->setupAndAddAppArc(m_decryptionServiceMock.get(), GST_ELEMENT(&m_rialtoSrc), m_streamInfo, &m_callbacks, + m_gstSrc->setupAndAddAppSrc(m_decryptionServiceMock.get(), GST_ELEMENT(&m_rialtoSrc), m_streamInfo, &m_callbacks, this, MediaSourceType::VIDEO); } @@ -328,7 +328,7 @@ TEST_F(RialtoServerAppSrcGstSrcTest, SetupAudio) expectLinkQueue(&m_decryptor); expectSetupPad(&m_queue); - m_gstSrc->setupAndAddAppArc(m_decryptionServiceMock.get(), GST_ELEMENT(&m_rialtoSrc), m_streamInfo, &m_callbacks, + m_gstSrc->setupAndAddAppSrc(m_decryptionServiceMock.get(), GST_ELEMENT(&m_rialtoSrc), m_streamInfo, &m_callbacks, this, MediaSourceType::AUDIO); } @@ -354,7 +354,7 @@ TEST_F(RialtoServerAppSrcGstSrcTest, DecryptorFailure) expectLinkQueue(&m_payloader); expectSetupPad(&m_queue); - m_gstSrc->setupAndAddAppArc(m_decryptionServiceMock.get(), GST_ELEMENT(&m_rialtoSrc), m_streamInfo, &m_callbacks, + m_gstSrc->setupAndAddAppSrc(m_decryptionServiceMock.get(), GST_ELEMENT(&m_rialtoSrc), m_streamInfo, &m_callbacks, this, MediaSourceType::VIDEO); } @@ -379,7 +379,7 @@ TEST_F(RialtoServerAppSrcGstSrcTest, PayloaderFailure) expectLinkQueue(&m_decryptor); expectSetupPad(&m_queue); - m_gstSrc->setupAndAddAppArc(m_decryptionServiceMock.get(), GST_ELEMENT(&m_rialtoSrc), m_streamInfo, &m_callbacks, + m_gstSrc->setupAndAddAppSrc(m_decryptionServiceMock.get(), GST_ELEMENT(&m_rialtoSrc), m_streamInfo, &m_callbacks, this, MediaSourceType::VIDEO); } @@ -400,7 +400,7 @@ TEST_F(RialtoServerAppSrcGstSrcTest, QueueFailure) expectAddDefaultStreamFormat(); expectSetupPad(&m_payloader); - m_gstSrc->setupAndAddAppArc(m_decryptionServiceMock.get(), GST_ELEMENT(&m_rialtoSrc), m_streamInfo, &m_callbacks, + m_gstSrc->setupAndAddAppSrc(m_decryptionServiceMock.get(), GST_ELEMENT(&m_rialtoSrc), m_streamInfo, &m_callbacks, this, MediaSourceType::VIDEO); } @@ -417,7 +417,7 @@ TEST_F(RialtoServerAppSrcGstSrcTest, NotDrm) expectSyncElement(m_streamInfo.appSrc); expectSetupPad(m_streamInfo.appSrc); - m_gstSrc->setupAndAddAppArc(m_decryptionServiceMock.get(), GST_ELEMENT(&m_rialtoSrc), m_streamInfo, &m_callbacks, + m_gstSrc->setupAndAddAppSrc(m_decryptionServiceMock.get(), GST_ELEMENT(&m_rialtoSrc), m_streamInfo, &m_callbacks, this, MediaSourceType::VIDEO); } diff --git a/tests/unittests/media/server/ipc/CMakeLists.txt b/tests/unittests/media/server/ipc/CMakeLists.txt index d08cb21bf..ac1d8856c 100644 --- a/tests/unittests/media/server/ipc/CMakeLists.txt +++ b/tests/unittests/media/server/ipc/CMakeLists.txt @@ -99,15 +99,6 @@ target_link_libraries( RialtoProtobuf ) -if ( COVERAGE_ENABLED ) - target_link_libraries( - RialtoServerIpcUnitTests - - gcov - ) -endif() - - set_target_properties( RialtoServerIpcUnitTests PROPERTIES COMPILE_FLAGS "-Wno-write-strings" diff --git a/tests/unittests/media/server/main/CMakeLists.txt b/tests/unittests/media/server/main/CMakeLists.txt index 995e79ea8..ec242bc4f 100644 --- a/tests/unittests/media/server/main/CMakeLists.txt +++ b/tests/unittests/media/server/main/CMakeLists.txt @@ -143,11 +143,3 @@ target_link_libraries( RialtoPlayerCommon RialtoCommonMisc ) - -if ( COVERAGE_ENABLED ) - target_link_libraries( - RialtoServerMainUnitTests - - gcov - ) -endif() diff --git a/tests/unittests/media/server/mocks/gstplayer/GstSrcMock.h b/tests/unittests/media/server/mocks/gstplayer/GstSrcMock.h index b9554a5ad..774cb8e2d 100644 --- a/tests/unittests/media/server/mocks/gstplayer/GstSrcMock.h +++ b/tests/unittests/media/server/mocks/gstplayer/GstSrcMock.h @@ -32,7 +32,7 @@ class GstSrcMock : public IGstSrc virtual ~GstSrcMock() = default; MOCK_METHOD(void, initSrc, (), (override)); - MOCK_METHOD(void, setupAndAddAppArc, + MOCK_METHOD(void, setupAndAddAppSrc, (IDecryptionService * decryptionService, GstElement *element, StreamInfo &streamInfo, GstAppSrcCallbacks *callbacks, gpointer userData, firebolt::rialto::MediaSourceType type), (override)); diff --git a/tests/unittests/media/server/service/CMakeLists.txt b/tests/unittests/media/server/service/CMakeLists.txt index 87710b501..e2fab6d94 100644 --- a/tests/unittests/media/server/service/CMakeLists.txt +++ b/tests/unittests/media/server/service/CMakeLists.txt @@ -64,11 +64,3 @@ target_link_libraries( # # Link application source RialtoServerService ) - -if ( COVERAGE_ENABLED ) - target_link_libraries( - RialtoServerServiceUnitTests - - gcov - ) -endif() diff --git a/tests/unittests/serverManager/CMakeLists.txt b/tests/unittests/serverManager/CMakeLists.txt index 3bdc94aa9..7a6c930ef 100644 --- a/tests/unittests/serverManager/CMakeLists.txt +++ b/tests/unittests/serverManager/CMakeLists.txt @@ -83,11 +83,3 @@ target_link_libraries( RialtoServerManager Threads::Threads ) - -if ( COVERAGE_ENABLED ) - target_link_libraries( - RialtoServerManagerUnitTests - - gcov - ) -endif() diff --git a/wrappers/CMakeLists.txt b/wrappers/CMakeLists.txt index 37a472e23..3be841fd1 100644 --- a/wrappers/CMakeLists.txt +++ b/wrappers/CMakeLists.txt @@ -130,11 +130,3 @@ if( RIALTO_ENABLE_CONFIG_FILE ) JsonCpp::JsonCpp ) endif() - -if ( COVERAGE_ENABLED ) - target_link_libraries( - RialtoWrappers - PRIVATE - gcov - ) -endif() diff --git a/wrappers/include/GstWrapper.h b/wrappers/include/GstWrapper.h index 275a056c9..05e829417 100644 --- a/wrappers/include/GstWrapper.h +++ b/wrappers/include/GstWrapper.h @@ -73,6 +73,8 @@ class GstWrapper : public IGstWrapper void gstInit(int *argc, char ***argv) override { gst_init(argc, argv); } + void gstDeinit() override { gst_deinit(); } + GstPlugin *gstRegistryFindPlugin(GstRegistry *registry, const gchar *name) override { return gst_registry_find_plugin(registry, name); diff --git a/wrappers/interface/IGstWrapper.h b/wrappers/interface/IGstWrapper.h index 6237e792d..847128d54 100644 --- a/wrappers/interface/IGstWrapper.h +++ b/wrappers/interface/IGstWrapper.h @@ -78,6 +78,12 @@ class IGstWrapper */ virtual void gstInit(int *argc, char ***argv) = 0; + /** + * @brief Deinitalise gstreamer. + * + */ + virtual void gstDeinit() = 0; + /** * @brief Finds the plugin with the given name. * From 8ecf4922165d4554d720e2ddeea64cfbd18821dc Mon Sep 17 00:00:00 2001 From: Marcin Wojciechowski <105790697+skywojciechowskim@users.noreply.github.com> Date: Mon, 30 Jun 2025 11:30:36 +0200 Subject: [PATCH 06/15] Add support for pending video mute if sink is not present (#390) Summary: Add support for pending video mute if sink is not present Type: Fix Test Plan: UT/CT, Fullstack Jira: VPLAY-10045 --------- Co-authored-by: Yurii Yakubin <144821088+yurii-yakubin@users.noreply.github.com> --- .../gstplayer/include/GenericPlayerContext.h | 5 +++ .../gstplayer/include/GstGenericPlayer.h | 1 + .../include/IGstGenericPlayerPrivate.h | 7 ++++ .../gstplayer/source/GstGenericPlayer.cpp | 29 ++++++++++++++ .../source/tasks/generic/SetMute.cpp | 17 +------- .../source/tasks/generic/SetupElement.cpp | 4 ++ .../GstGenericPlayerPrivateTest.cpp | 35 +++++++++++++++++ .../common/GenericTasksTestsBase.cpp | 39 ++++++++----------- .../common/GenericTasksTestsBase.h | 3 +- .../genericPlayer/tasksTests/SetMuteTest.cpp | 12 ------ .../tasksTests/SetupElementTest.cpp | 6 +++ .../gstplayer/GstGenericPlayerPrivateMock.h | 1 + 12 files changed, 108 insertions(+), 51 deletions(-) diff --git a/media/server/gstplayer/include/GenericPlayerContext.h b/media/server/gstplayer/include/GenericPlayerContext.h index 71383ead0..59187c865 100644 --- a/media/server/gstplayer/include/GenericPlayerContext.h +++ b/media/server/gstplayer/include/GenericPlayerContext.h @@ -179,6 +179,11 @@ struct GenericPlayerContext */ bool pendingRenderFrame{false}; + /** + * @brief Pending show video window + */ + std::optional pendingShowVideoWindow{}; + /** * @brief Last audio sample timestamps * TODO(LLDEV-31012) Needed to detect audio stream underflow diff --git a/media/server/gstplayer/include/GstGenericPlayer.h b/media/server/gstplayer/include/GstGenericPlayer.h index 1ad8b2a41..da06ea918 100644 --- a/media/server/gstplayer/include/GstGenericPlayer.h +++ b/media/server/gstplayer/include/GstGenericPlayer.h @@ -151,6 +151,7 @@ class GstGenericPlayer : public IGstGenericPlayer, public IGstGenericPlayerPriva void scheduleAllSourcesAttached() override; bool setVideoSinkRectangle() override; bool setImmediateOutput() override; + bool setShowVideoWindow() override; bool setLowLatency() override; bool setSync() override; bool setSyncOff() override; diff --git a/media/server/gstplayer/include/IGstGenericPlayerPrivate.h b/media/server/gstplayer/include/IGstGenericPlayerPrivate.h index b0ccfa75f..f9c6ba776 100644 --- a/media/server/gstplayer/include/IGstGenericPlayerPrivate.h +++ b/media/server/gstplayer/include/IGstGenericPlayerPrivate.h @@ -129,6 +129,13 @@ class IGstGenericPlayerPrivate */ virtual bool setUseBuffering() = 0; + /** + * @brief Sets Show Video Window property. Called by the worker thread. + * + * @retval true on success. + */ + virtual bool setShowVideoWindow() = 0; + /** * @brief Sends NeedMediaData notification. Called by the worker thread. */ diff --git a/media/server/gstplayer/source/GstGenericPlayer.cpp b/media/server/gstplayer/source/GstGenericPlayer.cpp index 070fa677b..d75ca99d0 100644 --- a/media/server/gstplayer/source/GstGenericPlayer.cpp +++ b/media/server/gstplayer/source/GstGenericPlayer.cpp @@ -1255,6 +1255,35 @@ bool GstGenericPlayer::setImmediateOutput() return result; } +bool GstGenericPlayer::setShowVideoWindow() +{ + if (!m_context.pendingShowVideoWindow.has_value()) + { + RIALTO_SERVER_LOG_WARN("No show video window value to be set. Aborting..."); + return false; + } + + GstElement *videoSink{getSink(MediaSourceType::VIDEO)}; + if (!videoSink) + { + RIALTO_SERVER_LOG_DEBUG("Setting show video window queued. Video sink is NULL"); + return false; + } + bool result{false}; + if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(videoSink), "show-video-window")) + { + m_glibWrapper->gObjectSet(videoSink, "show-video-window", m_context.pendingShowVideoWindow.value(), nullptr); + result = true; + } + else + { + RIALTO_SERVER_LOG_ERROR("Setting show video window failed. Property does not exist"); + } + m_context.pendingShowVideoWindow.reset(); + m_gstWrapper->gstObjectUnref(GST_OBJECT(videoSink)); + return result; +} + bool GstGenericPlayer::setLowLatency() { bool result{false}; diff --git a/media/server/gstplayer/source/tasks/generic/SetMute.cpp b/media/server/gstplayer/source/tasks/generic/SetMute.cpp index 89096e9f9..b8ed1b04c 100644 --- a/media/server/gstplayer/source/tasks/generic/SetMute.cpp +++ b/media/server/gstplayer/source/tasks/generic/SetMute.cpp @@ -62,21 +62,8 @@ void SetMute::execute() const } else if (m_mediaSourceType == MediaSourceType::VIDEO) { - GstElement *videoSink{m_player.getSink(MediaSourceType::VIDEO)}; - if (!videoSink) - { - RIALTO_SERVER_LOG_ERROR("Setting mute failed. Video sink is NULL"); - return; - } - if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(videoSink), "show-video-window")) - { - m_glibWrapper->gObjectSet(videoSink, "show-video-window", m_mute, nullptr); - } - else - { - RIALTO_SERVER_LOG_ERROR("Setting mute failed. Property does not exist"); - } - m_gstWrapper->gstObjectUnref(GST_OBJECT(videoSink)); + m_context.pendingShowVideoWindow = !m_mute; + m_player.setShowVideoWindow(); } else { diff --git a/media/server/gstplayer/source/tasks/generic/SetupElement.cpp b/media/server/gstplayer/source/tasks/generic/SetupElement.cpp index d4d1e79d9..57c14914a 100644 --- a/media/server/gstplayer/source/tasks/generic/SetupElement.cpp +++ b/media/server/gstplayer/source/tasks/generic/SetupElement.cpp @@ -255,6 +255,10 @@ void SetupElement::execute() const { m_player.setRenderFrame(); } + if (m_context.pendingShowVideoWindow.has_value()) + { + m_player.setShowVideoWindow(); + } } else if (isAudioDecoder(*m_gstWrapper, m_element)) { diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerPrivateTest.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerPrivateTest.cpp index 63ff3e5a7..f9ad47d57 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerPrivateTest.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerPrivateTest.cpp @@ -79,6 +79,7 @@ const std::string kSyncModeStreamingStr{"syncmode-streaming"}; const std::string kBufferingLimitStr{"limit-buffering-ms"}; const std::string kUseBufferingStr{"use-buffering"}; const std::string kFrameStepOnPrerollStr{"frame-step-on-preroll"}; +constexpr bool kShowVideoWindow{true}; } // namespace bool operator==(const GstRialtoProtectionData &lhs, const GstRialtoProtectionData &rhs) @@ -97,6 +98,7 @@ class GstGenericPlayerPrivateTest : public GstGenericPlayerTestCommon GstElement *m_realElement; GstElement m_element{}; GParamSpec m_rectangleSpec{}; + GParamSpec m_showVideoWindowSpec{}; GstEvent m_event{}; GstGenericPlayerPrivateTest() @@ -1983,3 +1985,36 @@ TEST_F(GstGenericPlayerPrivateTest, shouldSetSourceFlushed) EXPECT_CALL(m_flushWatcherMock, setFlushed(MediaSourceType::AUDIO)); m_sut->setSourceFlushed(MediaSourceType::AUDIO); } + +TEST_F(GstGenericPlayerPrivateTest, failToSetShowVideoWindowNoValue) +{ + EXPECT_FALSE(m_sut->setShowVideoWindow()); +} + +TEST_F(GstGenericPlayerPrivateTest, failToSetShowVideoWindowNoSink) +{ + modifyContext([&](GenericPlayerContext &context) { context.pendingShowVideoWindow = true; }); + EXPECT_CALL(*m_glibWrapperMock, gObjectGetStub(_, StrEq(kVideoSinkStr.c_str()), _)); + EXPECT_FALSE(m_sut->setShowVideoWindow()); +} + +TEST_F(GstGenericPlayerPrivateTest, failToSetShowVideoWindowNoProperty) +{ + modifyContext([&](GenericPlayerContext &context) { context.pendingShowVideoWindow = true; }); + expectGetSink(kVideoSinkStr, m_realElement); + EXPECT_CALL(*m_glibWrapperMock, gObjectClassFindProperty(_, StrEq("show-video-window"))).WillOnce(Return(nullptr)); + EXPECT_CALL(*m_gstWrapperMock, gstObjectUnref(m_realElement)); + EXPECT_FALSE(m_sut->setShowVideoWindow()); +} + +TEST_F(GstGenericPlayerPrivateTest, shouldSetShowVideoWindow) +{ + modifyContext([&](GenericPlayerContext &context) { context.pendingShowVideoWindow = true; }); + + expectGetSink(kVideoSinkStr, m_realElement); + EXPECT_CALL(*m_glibWrapperMock, gObjectClassFindProperty(_, StrEq("show-video-window"))) + .WillOnce(Return(&m_showVideoWindowSpec)); + EXPECT_CALL(*m_glibWrapperMock, gObjectSetStub(m_realElement, StrEq("show-video-window"))); + EXPECT_CALL(*m_gstWrapperMock, gstObjectUnref(m_realElement)); + EXPECT_TRUE(m_sut->setShowVideoWindow()); +} diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp index 496b30df8..896519a6a 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp @@ -800,6 +800,21 @@ void GenericTasksTestsBase::shouldSetupVideoSinkElementWithPendingRenderFrame() expectSetupVideoSinkElement(); } +void GenericTasksTestsBase::shouldSetupVideoSinkElementWithPendingShowVideoWindow() +{ + testContext->m_context.pendingShowVideoWindow = true; + EXPECT_CALL(*testContext->m_glibWrapper, gTypeName(G_OBJECT_TYPE(testContext->m_element))) + .WillOnce(Return(kElementTypeName.c_str())); + EXPECT_CALL(*testContext->m_glibWrapper, gStrHasPrefix(_, StrEq("amlhalasink"))).WillOnce(Return(FALSE)); + EXPECT_CALL(*testContext->m_glibWrapper, gStrHasPrefix(_, StrEq("brcmaudiosink"))).WillOnce(Return(FALSE)); + EXPECT_CALL(*testContext->m_glibWrapper, gStrHasPrefix(_, StrEq("rialtotexttracksink"))).WillOnce(Return(FALSE)); + EXPECT_CALL(*testContext->m_gstWrapper, gstIsBaseParse(_)).WillOnce(Return(FALSE)); + + // This is the extra EXPECT caused by setting pendingShowVideoWindow... + EXPECT_CALL(testContext->m_gstPlayer, setShowVideoWindow()).WillOnce(Return(true)); + expectSetupVideoSinkElement(); +} + void GenericTasksTestsBase::shouldSetupAudioElementAmlhalasinkWhenVideoExists() { setContextStreamInfo(firebolt::rialto::MediaSourceType::VIDEO); @@ -2359,28 +2374,7 @@ void GenericTasksTestsBase::shouldNotifyVideoUnderflow() void GenericTasksTestsBase::shouldSetVideoMute() { - EXPECT_CALL(testContext->m_gstPlayer, getSink(firebolt::rialto::MediaSourceType::VIDEO)) - .WillOnce(Return(&testContext->m_videoSink)); - EXPECT_CALL(*testContext->m_glibWrapper, - gObjectClassFindProperty(G_OBJECT_GET_CLASS(&testContext->m_videoSink), StrEq("show-video-window"))) - .WillOnce(Return(&testContext->m_paramSpec)); - EXPECT_CALL(*testContext->m_glibWrapper, gObjectSetStub(&testContext->m_videoSink, StrEq("show-video-window"))); - EXPECT_CALL(*testContext->m_gstWrapper, gstObjectUnref(&testContext->m_videoSink)); -} - -void GenericTasksTestsBase::shouldFailToSetVideoMuteNoSink() -{ - EXPECT_CALL(testContext->m_gstPlayer, getSink(firebolt::rialto::MediaSourceType::VIDEO)).WillOnce(Return(nullptr)); -} - -void GenericTasksTestsBase::shouldFailToSetVideoMuteNoProperty() -{ - EXPECT_CALL(testContext->m_gstPlayer, getSink(firebolt::rialto::MediaSourceType::VIDEO)) - .WillOnce(Return(&testContext->m_videoSink)); - EXPECT_CALL(*testContext->m_glibWrapper, - gObjectClassFindProperty(G_OBJECT_GET_CLASS(&testContext->m_videoSink), StrEq("show-video-window"))) - .WillOnce(Return(nullptr)); - EXPECT_CALL(*testContext->m_gstWrapper, gstObjectUnref(&testContext->m_videoSink)); + EXPECT_CALL(testContext->m_gstPlayer, setShowVideoWindow()).WillOnce(Return(true)); } void GenericTasksTestsBase::triggerSetAudioMute() @@ -2408,6 +2402,7 @@ void GenericTasksTestsBase::triggerSetVideoMute() testContext->m_gstWrapper, testContext->m_glibWrapper, MediaSourceType::VIDEO, kMute}; task.execute(); + EXPECT_EQ(testContext->m_context.pendingShowVideoWindow, !kMute); } void GenericTasksTestsBase::triggerSetSubtitleMute() diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.h b/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.h index 2ce54436a..fac0fc76c 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.h +++ b/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.h @@ -88,6 +88,7 @@ class GenericTasksTestsBase : public ::testing::Test void shouldSetupVideoParserElementWithPendingStreamSyncMode(); void shouldSetupAudioDecoderElementWithPendingBufferingLimit(); void shouldSetupVideoSinkElementWithPendingRenderFrame(); + void shouldSetupVideoSinkElementWithPendingShowVideoWindow(); void shouldSetupAudioElementAmlhalasinkWhenNoVideo(); void shouldSetupAudioElementAmlhalasinkWhenVideoExists(); void shouldSetupAudioElementBrcmAudioSink(); @@ -265,8 +266,6 @@ class GenericTasksTestsBase : public ::testing::Test void triggerSetUnknownMute(); void setContextSubtitleSink(); void shouldSetAudioMute(); - void shouldFailToSetVideoMuteNoSink(); - void shouldFailToSetVideoMuteNoProperty(); void shouldSetVideoMute(); void shouldSetSubtitleMute(); diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/SetMuteTest.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/SetMuteTest.cpp index 7ea55907a..5bccd8bb0 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/SetMuteTest.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/SetMuteTest.cpp @@ -34,18 +34,6 @@ TEST_F(SetMuteTest, shouldSetVideoMute) triggerSetVideoMute(); } -TEST_F(SetMuteTest, shouldFailToSetVideoMuteNoSink) -{ - shouldFailToSetVideoMuteNoSink(); - triggerSetVideoMute(); -} - -TEST_F(SetMuteTest, shouldFailToSetVideoMuteNoProperty) -{ - shouldFailToSetVideoMuteNoProperty(); - triggerSetVideoMute(); -} - TEST_F(SetMuteTest, shouldFailToSetAudioMuteWhenPipelineIsNull) { setContextPipelineNull(); diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/SetupElementTest.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/SetupElementTest.cpp index 6eec00361..d572a59d0 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/SetupElementTest.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/SetupElementTest.cpp @@ -83,6 +83,12 @@ TEST_F(SetupElementTest, shouldSetupVideoElementWithPendingRenderFrame) triggerSetupElement(); } +TEST_F(SetupElementTest, shouldSetupVideoElementWithPendingShowVideoWindow) +{ + shouldSetupVideoSinkElementWithPendingShowVideoWindow(); + triggerSetupElement(); +} + TEST_F(SetupElementTest, shouldSetupAudioElementAmlhalasinkWhenNoVideo) { shouldSetupAudioElementAmlhalasinkWhenNoVideo(); diff --git a/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerPrivateMock.h b/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerPrivateMock.h index b8e15348f..45f6728b2 100644 --- a/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerPrivateMock.h +++ b/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerPrivateMock.h @@ -46,6 +46,7 @@ class GstGenericPlayerPrivateMock : public IGstGenericPlayerPrivate MOCK_METHOD(bool, setRenderFrame, (), (override)); MOCK_METHOD(bool, setBufferingLimit, (), (override)); MOCK_METHOD(bool, setUseBuffering, (), (override)); + MOCK_METHOD(bool, setShowVideoWindow, (), (override)); MOCK_METHOD(void, notifyNeedMediaData, (const MediaSourceType mediaSource), (override)); MOCK_METHOD(GstBuffer *, createBuffer, (const IMediaPipeline::MediaSegment &mediaSegment), (const, override)); MOCK_METHOD(void, attachData, (const firebolt::rialto::MediaSourceType mediaType), (override)); From 6baf3e61323862f31218afbc58ab5a715d0fc0b3 Mon Sep 17 00:00:00 2001 From: Yurii Yakubin <144821088+yurii-yakubin@users.noreply.github.com> Date: Mon, 7 Jul 2025 17:28:12 +0100 Subject: [PATCH 07/15] RialtoClient logging to EthanLog (#391) Summary: RialtoClient logging to EthanLog Type: Feature Test Plan: UT/ CT, Fullstack Jira: ENTDAI-1404 --- cmake/FindEthanLog.cmake | 43 +++++++++++++++++++++++++ logging/CMakeLists.txt | 54 ++++++++++++++++++-------------- logging/source/RialtoLogging.cpp | 41 +++++++++++++++++++----- media/client/ipc/CMakeLists.txt | 3 +- media/client/main/CMakeLists.txt | 3 +- 5 files changed, 108 insertions(+), 36 deletions(-) create mode 100644 cmake/FindEthanLog.cmake diff --git a/cmake/FindEthanLog.cmake b/cmake/FindEthanLog.cmake new file mode 100644 index 000000000..e66fe6f21 --- /dev/null +++ b/cmake/FindEthanLog.cmake @@ -0,0 +1,43 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2025 Sky UK +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +find_path(EthanLog_INCLUDE_DIR + NAMES ethanlog.h + ) + +find_library(EthanLog_LIBRARY + NAMES ethanlog + ) + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(EthanLog DEFAULT_MSG EthanLog_INCLUDE_DIR EthanLog_LIBRARY) + +mark_as_advanced(EthanLog_INCLUDE_DIR EthanLog_LIBRARY) + +if (ETHANLOG_FOUND OR EthanLog_FOUND) + set(EthanLog_INCLUDE_DIRS "${EthanLog_INCLUDE_DIR}") + set(EthanLog_LIBRARIES "${EthanLog_LIBRARY}") + set(EthanLog_FOUND TRUE) +endif() + +if (EthanLog_FOUND AND NOT TARGET EthanLog::EthanLog) + add_library(EthanLog::EthanLog INTERFACE IMPORTED) + set_property(TARGET EthanLog::EthanLog PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${EthanLog_INCLUDE_DIR}") + set_property(TARGET EthanLog::EthanLog PROPERTY INTERFACE_LINK_LIBRARIES "${EthanLog_LIBRARY}") +endif() diff --git a/logging/CMakeLists.txt b/logging/CMakeLists.txt index 33ec074b2..cbc02ea2d 100644 --- a/logging/CMakeLists.txt +++ b/logging/CMakeLists.txt @@ -2,7 +2,7 @@ # If not stated otherwise in this file or this component's LICENSE file the # following copyright and licenses apply: # -# Copyright 2022 Sky UK +# Copyright 2025 Sky UK # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,30 +17,36 @@ # limitations under the License. # -set(CMAKE_C_STANDARD 99) -set(CMAKE_CXX_STANDARD 17) +set(RialtoLogging_HEADERS + include/RialtoLogging.h + ) -set( CMAKE_CXX_STANDARD_REQUIRED ON ) -set( CMAKE_POSITION_INDEPENDENT_CODE ON ) -include( CheckCCompilerFlag ) -include( CheckCXXCompilerFlag ) +set(RialtoLogging_SOURCES + source/EnvVariableParser.cpp + source/EnvVariableParser.h + source/LogFileHandle.cpp + source/LogFileHandle.h + source/RialtoLogging.cpp + ) -set(LIB_RIALTO_LOGGING_SOURCES - source/EnvVariableParser.cpp - source/LogFileHandle.cpp - source/RialtoLogging.cpp - ) +set(RialtoLogging_INCLUDES + "${CMAKE_CURRENT_SOURCE_DIR}/include" + ) -set(LIB_RIALTO_LOGGING_PUBLIC_HEADERS - include/RialtoLogging.h - ) +add_library(RialtoLogging STATIC ${RialtoLogging_HEADERS} ${RialtoLogging_SOURCES}) +target_include_directories(RialtoLogging PUBLIC "$") +set_target_properties(RialtoLogging PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF) +set_target_properties(RialtoLogging PROPERTIES POSITION_INDEPENDENT_CODE ON) -add_library(RialtoLogging STATIC ${LIB_RIALTO_LOGGING_SOURCES}) - -target_include_directories( - RialtoLogging - - PUBLIC - $ - $ - ) +find_package(EthanLog) +if (EthanLog_FOUND) + add_library(RialtoEthanLog STATIC ${RialtoLogging_HEADERS} ${RialtoLogging_SOURCES}) + target_include_directories(RialtoEthanLog PUBLIC "$") + target_compile_definitions(RialtoEthanLog PRIVATE USE_ETHANLOG) + target_link_libraries(RialtoEthanLog PUBLIC EthanLog::EthanLog) + set_target_properties(RialtoEthanLog PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF) + set_target_properties(RialtoEthanLog PROPERTIES POSITION_INDEPENDENT_CODE ON) +else () + message(STATUS "EthanLog is disabled") + add_library(RialtoEthanLog ALIAS RialtoLogging) +endif () diff --git a/logging/source/RialtoLogging.cpp b/logging/source/RialtoLogging.cpp index 802b852d2..099599a69 100644 --- a/logging/source/RialtoLogging.cpp +++ b/logging/source/RialtoLogging.cpp @@ -25,13 +25,38 @@ #include #include #include -#include #include #include "EnvVariableParser.h" #include "LogFileHandle.h" #include "RialtoLogging.h" +#ifdef USE_ETHANLOG + +#include + +#define SYSTEM_LOG_FATAL(filename, function, line, ...) ethanlog(ETHAN_LOG_FATAL, filename, function, line, __VA_ARGS__) +#define SYSTEM_LOG_ERROR(filename, function, line, ...) ethanlog(ETHAN_LOG_ERROR, filename, function, line, __VA_ARGS__) +#define SYSTEM_LOG_WARN(filename, function, line, ...) \ + ethanlog(ETHAN_LOG_WARNING, filename, function, line, __VA_ARGS__) +#define SYSTEM_LOG_MIL(filename, function, line, ...) \ + ethanlog(ETHAN_LOG_MILESTONE, filename, function, line, __VA_ARGS__) +#define SYSTEM_LOG_INFO(filename, function, line, ...) ethanlog(ETHAN_LOG_INFO, filename, function, line, __VA_ARGS__) +#define SYSTEM_LOG_DEBUG(filename, function, line, ...) ethanlog(ETHAN_LOG_DEBUG, filename, function, line, __VA_ARGS__) + +#else + +#include + +#define SYSTEM_LOG_FATAL(filename, function, line, ...) syslog(LOG_CRIT, __VA_ARGS__) +#define SYSTEM_LOG_ERROR(filename, function, line, ...) syslog(LOG_ERR, __VA_ARGS__) +#define SYSTEM_LOG_WARN(filename, function, line, ...) syslog(LOG_WARNING, __VA_ARGS__) +#define SYSTEM_LOG_MIL(filename, function, line, ...) syslog(LOG_NOTICE, __VA_ARGS__) +#define SYSTEM_LOG_INFO(filename, function, line, ...) syslog(LOG_INFO, __VA_ARGS__) +#define SYSTEM_LOG_DEBUG(filename, function, line, ...) syslog(LOG_DEBUG, __VA_ARGS__) + +#endif + namespace { /** @@ -203,25 +228,25 @@ void journaldLogHandler(RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL level, co switch (level) { case RIALTO_DEBUG_LEVEL_FATAL: - syslog(LOG_CRIT, "%s %s", fbuf, message); + SYSTEM_LOG_FATAL(file, function, line, "%s %s", fbuf, message); break; case RIALTO_DEBUG_LEVEL_ERROR: - syslog(LOG_ERR, "%s %s", fbuf, message); + SYSTEM_LOG_ERROR(file, function, line, "%s %s", fbuf, message); break; case RIALTO_DEBUG_LEVEL_WARNING: - syslog(LOG_WARNING, "%s %s", fbuf, message); + SYSTEM_LOG_WARN(file, function, line, "%s %s", fbuf, message); break; case RIALTO_DEBUG_LEVEL_MILESTONE: - syslog(LOG_NOTICE, "%s %s", fbuf, message); + SYSTEM_LOG_MIL(file, function, line, "%s %s", fbuf, message); break; case RIALTO_DEBUG_LEVEL_INFO: - syslog(LOG_INFO, "%s %s", fbuf, message); + SYSTEM_LOG_INFO(file, function, line, "%s %s", fbuf, message); break; case RIALTO_DEBUG_LEVEL_DEBUG: - syslog(LOG_DEBUG, "%s %s", fbuf, message); + SYSTEM_LOG_DEBUG(file, function, line, "%s %s", fbuf, message); break; case RIALTO_DEBUG_LEVEL_EXTERNAL: - syslog(LOG_INFO, "%s %s", fbuf, message); + SYSTEM_LOG_INFO(file, function, line, "%s %s", fbuf, message); break; default: break; diff --git a/media/client/ipc/CMakeLists.txt b/media/client/ipc/CMakeLists.txt index 9c2db8796..97d09750e 100644 --- a/media/client/ipc/CMakeLists.txt +++ b/media/client/ipc/CMakeLists.txt @@ -55,7 +55,6 @@ target_include_directories ( $ $ $ - $ ) target_link_libraries ( @@ -66,6 +65,6 @@ target_link_libraries ( RialtoIpcCommon RialtoCommon RialtoPlayerCommon - RialtoLogging + RialtoEthanLog RialtoProtobuf ) diff --git a/media/client/main/CMakeLists.txt b/media/client/main/CMakeLists.txt index 73f891086..814f717d6 100644 --- a/media/client/main/CMakeLists.txt +++ b/media/client/main/CMakeLists.txt @@ -65,7 +65,6 @@ target_include_directories( $ $ $ - $ ) @@ -83,7 +82,7 @@ target_link_libraries( RialtoPlayerCommon RialtoClientIpcImpl RialtoCommon - RialtoLogging + RialtoEthanLog Threads::Threads From cc6296c0d2a3fdbf659a2d19d5e92e07b3a07f74 Mon Sep 17 00:00:00 2001 From: Yurii Yakubin <144821088+yurii-yakubin@users.noreply.github.com> Date: Tue, 8 Jul 2025 16:17:32 +0100 Subject: [PATCH 08/15] The changes fix Jenkins job for testing rialto with valgrind on native (#392) Summary: The changes fix Jenkins job for testing rialto with valgrind on native Type: Fix Test Plan: UT/ CT, Fullstack Jira: ENTDAI-462 --- .gitignore | 1 + rialto.supp | 58 ++++++++++++++++++- .../common/source/SessionServerApp.cpp | 2 +- .../common/SessionServerAppTestsFixture.cpp | 2 +- .../unittests/service/ConfigReaderTests.cpp | 14 ++--- 5 files changed, 66 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 59e2214ab..aca35095f 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ *__pycache__ /.vscode/* /CMakeUserPresets.json +/CMakeLists.txt.user* # These files are fetched by cmake during building rialto for the native platform /stubs/opencdm/third-party/* diff --git a/rialto.supp b/rialto.supp index ccbef7bad..65e2603cc 100644 --- a/rialto.supp +++ b/rialto.supp @@ -672,7 +672,7 @@ fun:allocate_dtv fun:_dl_allocate_tls fun:allocate_stack - fun:pthread_create@@GLIBC_2.34 + fun:pthread_create* obj:*/libglib-2.0.so* obj:*/libglib-2.0.so* obj:*/libglib-2.0.so* @@ -774,7 +774,7 @@ fun:allocate_dtv fun:_dl_allocate_tls fun:allocate_stack - fun:pthread_create@@GLIBC_2.34 + fun:pthread_create* obj:*/libglib-2.0.so* fun:g_thread_new fun:g_thread_pool_new_full @@ -1160,3 +1160,57 @@ fun:gst_element_change_state ... } +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:g_type_create_instance + fun:g_param_spec_internal + fun:* + fun:* + fun:ipatch_init + fun:new_fluid_synth + obj:*/gstreamer-1.0/libgstfluidsynthmidi.so + fun:g_type_create_instance + obj:*/libgobject-2.0.so* + fun:g_object_new_with_properties + fun:gst_element_factory_create_with_properties + ... +} +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + obj:*/libglib-2.0.so* + fun:g_rec_mutex_init + obj:*/libgstreamer-1.0.so* + fun:g_type_create_instance + obj:*/libgobject-2.0.so* + fun:g_object_new_with_properties + fun:gst_element_factory_create_with_properties + ... +} +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:g_malloc + obj:*/libglib-2.0.so* + obj:*/libgobject-2.0.so* + fun:g_object_unref + ... +} +{ + + Memcheck:Leak + match-leak-kinds: possible + fun:calloc + fun:calloc + fun:allocate_dtv + fun:_dl_allocate_tls + fun:allocate_stack + fun:pthread_create* + ... +} diff --git a/serverManager/common/source/SessionServerApp.cpp b/serverManager/common/source/SessionServerApp.cpp index 8b69838f1..46363d9da 100644 --- a/serverManager/common/source/SessionServerApp.cpp +++ b/serverManager/common/source/SessionServerApp.cpp @@ -421,7 +421,7 @@ void SessionServerApp::waitForChildProcess() return; } auto killTimer = - m_timerFactory->createTimer(std::chrono::milliseconds{1000}, + m_timerFactory->createTimer(std::chrono::milliseconds{1500}, [this]() { RIALTO_SERVER_MANAGER_LOG_ERROR("Waitpid timeout. Killing: %d", m_kServerId); diff --git a/tests/unittests/serverManager/unittests/common/SessionServerAppTestsFixture.cpp b/tests/unittests/serverManager/unittests/common/SessionServerAppTestsFixture.cpp index cf843d8b2..01d487eb4 100644 --- a/tests/unittests/serverManager/unittests/common/SessionServerAppTestsFixture.cpp +++ b/tests/unittests/serverManager/unittests/common/SessionServerAppTestsFixture.cpp @@ -28,7 +28,7 @@ const std::list kEnvironmentVariablesWithLogPath{"var1", "RIALTO_LO const std::list kEnvironmentVariables{"var1", "var2"}; const std::string kSessionServerPath{"/usr/bin/RialtoServer"}; constexpr std::chrono::milliseconds kSessionServerStartupTimeout{100}; -constexpr std::chrono::milliseconds kKillTimeout{1000}; +constexpr std::chrono::milliseconds kKillTimeout{1500}; constexpr unsigned int kSocketPermissions{0777}; // Empty strings for kSocketOwner and kSocketGroup means that chown() won't be called. This will leave the created // socket being owned by the user executing the code (and the group would be their primary group) diff --git a/tests/unittests/serverManager/unittests/service/ConfigReaderTests.cpp b/tests/unittests/serverManager/unittests/service/ConfigReaderTests.cpp index a876dd59b..eff8204dc 100644 --- a/tests/unittests/serverManager/unittests/service/ConfigReaderTests.cpp +++ b/tests/unittests/serverManager/unittests/service/ConfigReaderTests.cpp @@ -129,7 +129,7 @@ TEST_F(ConfigReaderTests, thereWillBeNothing) EXPECT_CALL(*m_rootJsonValueMock, isMember(_)).WillRepeatedly(Return(false)); EXPECT_TRUE(m_sut->read()); - EXPECT_EQ(m_sut->getEnvironmentVariables().size(), 0); + EXPECT_EQ(m_sut->getEnvironmentVariables().size(), 0u); EXPECT_EQ(m_sut->getSessionServerPath().has_value(), false); EXPECT_EQ(m_sut->getSessionServerStartupTimeout().has_value(), false); EXPECT_EQ(m_sut->getHealthcheckInterval().has_value(), false); @@ -150,7 +150,7 @@ TEST_F(ConfigReaderTests, envVariablesNotArray) EXPECT_CALL(*m_rootJsonValueMock, isMember(StrNe("environmentVariables"))).WillRepeatedly(Return(false)); EXPECT_TRUE(m_sut->read()); - EXPECT_EQ(m_sut->getEnvironmentVariables().size(), 0); + EXPECT_EQ(m_sut->getEnvironmentVariables().size(), 0u); } TEST_F(ConfigReaderTests, envVariablesEmptyArray) @@ -165,7 +165,7 @@ TEST_F(ConfigReaderTests, envVariablesEmptyArray) EXPECT_CALL(*m_rootJsonValueMock, isMember(StrNe("environmentVariables"))).WillRepeatedly(Return(false)); EXPECT_TRUE(m_sut->read()); - EXPECT_EQ(m_sut->getEnvironmentVariables().size(), 0); + EXPECT_EQ(m_sut->getEnvironmentVariables().size(), 0u); } TEST_F(ConfigReaderTests, envVariablesOneElementArrayNotString) @@ -185,7 +185,7 @@ TEST_F(ConfigReaderTests, envVariablesOneElementArrayNotString) EXPECT_CALL(*m_rootJsonValueMock, isMember(StrNe("environmentVariables"))).WillRepeatedly(Return(false)); EXPECT_TRUE(m_sut->read()); - EXPECT_EQ(m_sut->getEnvironmentVariables().size(), 0); + EXPECT_EQ(m_sut->getEnvironmentVariables().size(), 0u); } TEST_F(ConfigReaderTests, envVariablesMultipleElementArray) @@ -431,7 +431,7 @@ TEST_F(ConfigReaderTests, extraEnvVariablesNotArray) EXPECT_CALL(*m_rootJsonValueMock, isMember(StrNe("extraEnvVariables"))).WillRepeatedly(Return(false)); EXPECT_TRUE(m_sut->read()); - EXPECT_EQ(m_sut->getExtraEnvVariables().size(), 0); + EXPECT_EQ(m_sut->getExtraEnvVariables().size(), 0u); } TEST_F(ConfigReaderTests, extraEnvVariablesEmptyArray) @@ -446,7 +446,7 @@ TEST_F(ConfigReaderTests, extraEnvVariablesEmptyArray) EXPECT_CALL(*m_rootJsonValueMock, isMember(StrNe("extraEnvVariables"))).WillRepeatedly(Return(false)); EXPECT_TRUE(m_sut->read()); - EXPECT_EQ(m_sut->getExtraEnvVariables().size(), 0); + EXPECT_EQ(m_sut->getExtraEnvVariables().size(), 0u); } TEST_F(ConfigReaderTests, extraEnvVariablesOneElementArrayNotString) @@ -466,7 +466,7 @@ TEST_F(ConfigReaderTests, extraEnvVariablesOneElementArrayNotString) EXPECT_CALL(*m_rootJsonValueMock, isMember(StrNe("extraEnvVariables"))).WillRepeatedly(Return(false)); EXPECT_TRUE(m_sut->read()); - EXPECT_EQ(m_sut->getExtraEnvVariables().size(), 0); + EXPECT_EQ(m_sut->getExtraEnvVariables().size(), 0u); } TEST_F(ConfigReaderTests, extraEnvVariablesMultipleElementArray) From 324bbcb80fbf9d9db4badff29cb9356e694af855 Mon Sep 17 00:00:00 2001 From: Marcin Wojciechowski <105790697+skywojciechowskim@users.noreply.github.com> Date: Wed, 16 Jul 2025 12:41:00 +0200 Subject: [PATCH 09/15] Fix RialtoServer deadlock during pipeline shutdown. (#394) Summary: Fix RialtoServer deadlock during pipeline shutdown. Type: Fix Test Plan: UT/ CT, Fullstack Jira: ENTDAI-748 --- media/server/gstplayer/CMakeLists.txt | 2 + .../gstplayer/include/GstGenericPlayer.h | 1 + .../gstplayer/include/GstWebAudioPlayer.h | 1 + .../include/IGstGenericPlayerPrivate.h | 5 +++ .../include/IGstWebAudioPlayerPrivate.h | 5 +++ .../server/gstplayer/include/IWorkerThread.h | 5 +++ media/server/gstplayer/include/WorkerThread.h | 1 + .../include/tasks/IGenericPlayerTaskFactory.h | 9 ++++ .../tasks/IWebAudioPlayerTaskFactory.h | 9 ++++ .../tasks/generic/GenericPlayerTaskFactory.h | 1 + .../include/tasks/generic/Shutdown.h | 45 +++++++++++++++++++ .../include/tasks/webAudio/Shutdown.h | 45 +++++++++++++++++++ .../webAudio/WebAudioPlayerTaskFactory.h | 1 + .../gstplayer/source/GstGenericPlayer.cpp | 11 +++++ .../gstplayer/source/GstWebAudioPlayer.cpp | 10 +++++ .../server/gstplayer/source/WorkerThread.cpp | 15 ++++--- .../generic/GenericPlayerTaskFactory.cpp | 6 +++ .../source/tasks/generic/Shutdown.cpp | 41 +++++++++++++++++ .../source/tasks/webAudio/Shutdown.cpp | 41 +++++++++++++++++ .../webAudio/WebAudioPlayerTaskFactory.cpp | 6 +++ .../media/server/gstplayer/CMakeLists.txt | 2 + .../gstplayer/genericPlayer/CreateTest.cpp | 1 + .../GstGenericPlayerPrivateTest.cpp | 6 +++ .../common/GenericTasksTestsBase.cpp | 12 +++++ .../common/GenericTasksTestsBase.h | 4 ++ .../common/GstGenericPlayerTestCommon.cpp | 9 ++++ .../common/GstGenericPlayerTestCommon.h | 1 + .../GenericPlayerTaskFactoryTest.cpp | 8 ++++ .../genericPlayer/tasksTests/ShutdownTest.cpp | 30 +++++++++++++ .../gstplayer/webAudioPlayer/CreateTest.cpp | 5 +++ .../GstWebAudioPlayerPrivateTest.cpp | 6 +++ .../common/GstWebAudioPlayerTestCommon.cpp | 10 +++++ .../common/GstWebAudioPlayerTestCommon.h | 1 + .../common/WebAudioTasksTestsBase.cpp | 12 +++++ .../common/WebAudioTasksTestsBase.h | 4 ++ .../webAudioPlayer/taskTests/ShutdownTest.cpp | 30 +++++++++++++ .../WebAudioPlayerTaskFactoryTest.cpp | 8 ++++ .../gstplayer/GenericPlayerTaskFactoryMock.h | 1 + .../gstplayer/GstGenericPlayerPrivateMock.h | 1 + .../gstplayer/GstWebAudioPlayerPrivateMock.h | 1 + .../gstplayer/WebAudioPlayerTaskFactoryMock.h | 1 + .../server/mocks/gstplayer/WorkerThreadMock.h | 1 + 42 files changed, 409 insertions(+), 5 deletions(-) create mode 100644 media/server/gstplayer/include/tasks/generic/Shutdown.h create mode 100644 media/server/gstplayer/include/tasks/webAudio/Shutdown.h create mode 100644 media/server/gstplayer/source/tasks/generic/Shutdown.cpp create mode 100644 media/server/gstplayer/source/tasks/webAudio/Shutdown.cpp create mode 100644 tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/ShutdownTest.cpp create mode 100644 tests/unittests/media/server/gstplayer/webAudioPlayer/taskTests/ShutdownTest.cpp diff --git a/media/server/gstplayer/CMakeLists.txt b/media/server/gstplayer/CMakeLists.txt index 1ab652fff..1a49fde59 100644 --- a/media/server/gstplayer/CMakeLists.txt +++ b/media/server/gstplayer/CMakeLists.txt @@ -68,6 +68,7 @@ add_library( source/tasks/generic/SetVolume.cpp source/tasks/generic/SetupElement.cpp source/tasks/generic/SetupSource.cpp + source/tasks/generic/Shutdown.cpp source/tasks/generic/Stop.cpp source/tasks/generic/SwitchSource.cpp source/tasks/generic/Underflow.cpp @@ -80,6 +81,7 @@ add_library( source/tasks/webAudio/Play.cpp source/tasks/webAudio/SetCaps.cpp source/tasks/webAudio/SetVolume.cpp + source/tasks/webAudio/Shutdown.cpp source/tasks/webAudio/Stop.cpp source/tasks/webAudio/WebAudioPlayerTaskFactory.cpp source/tasks/webAudio/WriteBuffer.cpp diff --git a/media/server/gstplayer/include/GstGenericPlayer.h b/media/server/gstplayer/include/GstGenericPlayer.h index da06ea918..91548b7bb 100644 --- a/media/server/gstplayer/include/GstGenericPlayer.h +++ b/media/server/gstplayer/include/GstGenericPlayer.h @@ -169,6 +169,7 @@ class GstGenericPlayer : public IGstGenericPlayer, public IGstGenericPlayerPriva bool changePipelineState(GstState newState) override; void startPositionReportingAndCheckAudioUnderflowTimer() override; void stopPositionReportingAndCheckAudioUnderflowTimer() override; + void stopWorkerThread() override; void cancelUnderflow(firebolt::rialto::MediaSourceType mediaSource) override; void setPendingPlaybackRate() override; void renderFrame() override; diff --git a/media/server/gstplayer/include/GstWebAudioPlayer.h b/media/server/gstplayer/include/GstWebAudioPlayer.h index 8d3d87dd4..ccc3ce627 100644 --- a/media/server/gstplayer/include/GstWebAudioPlayer.h +++ b/media/server/gstplayer/include/GstWebAudioPlayer.h @@ -94,6 +94,7 @@ class GstWebAudioPlayer : public IGstWebAudioPlayer, public IGstWebAudioPlayerPr uint64_t getQueuedBytes() override; bool changePipelineState(GstState newState) override; + void stopWorkerThread() override; void handleBusMessage(GstMessage *message) override; void ping(std::unique_ptr &&heartbeatHandler) override; diff --git a/media/server/gstplayer/include/IGstGenericPlayerPrivate.h b/media/server/gstplayer/include/IGstGenericPlayerPrivate.h index f9c6ba776..056f5177c 100644 --- a/media/server/gstplayer/include/IGstGenericPlayerPrivate.h +++ b/media/server/gstplayer/include/IGstGenericPlayerPrivate.h @@ -188,6 +188,11 @@ class IGstGenericPlayerPrivate */ virtual void stopPositionReportingAndCheckAudioUnderflowTimer() = 0; + /** + * @brief Stops worker thread. Called by the worker thread. + */ + virtual void stopWorkerThread() = 0; + /** * @brief Restores playback after underflow. Called by the worker thread. * diff --git a/media/server/gstplayer/include/IGstWebAudioPlayerPrivate.h b/media/server/gstplayer/include/IGstWebAudioPlayerPrivate.h index a0e7362ae..216b4653e 100644 --- a/media/server/gstplayer/include/IGstWebAudioPlayerPrivate.h +++ b/media/server/gstplayer/include/IGstWebAudioPlayerPrivate.h @@ -43,6 +43,11 @@ class IGstWebAudioPlayerPrivate * @retval true on success. */ virtual bool changePipelineState(GstState newState) = 0; + + /** + * @brief Stops worker thread. Called by the worker thread. + */ + virtual void stopWorkerThread() = 0; }; } // namespace firebolt::rialto::server diff --git a/media/server/gstplayer/include/IWorkerThread.h b/media/server/gstplayer/include/IWorkerThread.h index 12ce64835..011fc7bb6 100644 --- a/media/server/gstplayer/include/IWorkerThread.h +++ b/media/server/gstplayer/include/IWorkerThread.h @@ -50,6 +50,11 @@ class IWorkerThread */ virtual void stop() = 0; + /** + * @brief Joins the task thread + */ + virtual void join() = 0; + /** * @brief Queues a task in the task queue. */ diff --git a/media/server/gstplayer/include/WorkerThread.h b/media/server/gstplayer/include/WorkerThread.h index 74c11e9e8..0a3ed3204 100644 --- a/media/server/gstplayer/include/WorkerThread.h +++ b/media/server/gstplayer/include/WorkerThread.h @@ -43,6 +43,7 @@ class WorkerThread : public IWorkerThread ~WorkerThread() override; void stop() override; + void join() override; void enqueueTask(std::unique_ptr &&task) override; private: diff --git a/media/server/gstplayer/include/tasks/IGenericPlayerTaskFactory.h b/media/server/gstplayer/include/tasks/IGenericPlayerTaskFactory.h index f5a8dc358..ea91604e2 100644 --- a/media/server/gstplayer/include/tasks/IGenericPlayerTaskFactory.h +++ b/media/server/gstplayer/include/tasks/IGenericPlayerTaskFactory.h @@ -355,6 +355,15 @@ class IGenericPlayerTaskFactory const firebolt::rialto::MediaSourceType &type, int32_t streamSyncMode) const = 0; + /** + * @brief Creates a Shutdown task. + * + * @param[in] context : The GstGenericPlayer context + * + * @retval the new Shutdown task instance. + */ + virtual std::unique_ptr createShutdown(IGstGenericPlayerPrivate &player) const = 0; + /** * @brief Creates a Stop task. * diff --git a/media/server/gstplayer/include/tasks/IWebAudioPlayerTaskFactory.h b/media/server/gstplayer/include/tasks/IWebAudioPlayerTaskFactory.h index f68187132..439d9f990 100644 --- a/media/server/gstplayer/include/tasks/IWebAudioPlayerTaskFactory.h +++ b/media/server/gstplayer/include/tasks/IWebAudioPlayerTaskFactory.h @@ -38,6 +38,15 @@ class IWebAudioPlayerTaskFactory IWebAudioPlayerTaskFactory() = default; virtual ~IWebAudioPlayerTaskFactory() = default; + /** + * @brief Creates a Shutdown task. + * + * @param[in] player : The GstWebAudioPlayer instance + * + * @retval the new Shutdown task instance. + */ + virtual std::unique_ptr createShutdown(IGstWebAudioPlayerPrivate &player) const = 0; + /** * @brief Creates a Stop task. * diff --git a/media/server/gstplayer/include/tasks/generic/GenericPlayerTaskFactory.h b/media/server/gstplayer/include/tasks/generic/GenericPlayerTaskFactory.h index f330edfe7..be72f5136 100644 --- a/media/server/gstplayer/include/tasks/generic/GenericPlayerTaskFactory.h +++ b/media/server/gstplayer/include/tasks/generic/GenericPlayerTaskFactory.h @@ -95,6 +95,7 @@ class GenericPlayerTaskFactory : public IGenericPlayerTaskFactory std::unique_ptr createSetStreamSyncMode(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, const firebolt::rialto::MediaSourceType &type, int32_t streamSyncMode) const override; + std::unique_ptr createShutdown(IGstGenericPlayerPrivate &player) const override; std::unique_ptr createStop(GenericPlayerContext &context, IGstGenericPlayerPrivate &player) const override; std::unique_ptr createUnderflow(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, diff --git a/media/server/gstplayer/include/tasks/generic/Shutdown.h b/media/server/gstplayer/include/tasks/generic/Shutdown.h new file mode 100644 index 000000000..d055c8e8c --- /dev/null +++ b/media/server/gstplayer/include/tasks/generic/Shutdown.h @@ -0,0 +1,45 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SHUTDOWN_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SHUTDOWN_H_ + +#include "IPlayerTask.h" +#include + +namespace firebolt::rialto::server +{ +class IGstGenericPlayerPrivate; +} // namespace firebolt::rialto::server + +namespace firebolt::rialto::server::tasks::generic +{ +class Shutdown : public IPlayerTask +{ +public: + explicit Shutdown(IGstGenericPlayerPrivate &player); + ~Shutdown() override; + void execute() const override; + +private: + IGstGenericPlayerPrivate &m_player; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SHUTDOWN_H_ diff --git a/media/server/gstplayer/include/tasks/webAudio/Shutdown.h b/media/server/gstplayer/include/tasks/webAudio/Shutdown.h new file mode 100644 index 000000000..c019ec27c --- /dev/null +++ b/media/server/gstplayer/include/tasks/webAudio/Shutdown.h @@ -0,0 +1,45 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SHUTDOWN_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SHUTDOWN_H_ + +#include "IPlayerTask.h" +#include + +namespace firebolt::rialto::server +{ +class IGstWebAudioPlayerPrivate; +} // namespace firebolt::rialto::server + +namespace firebolt::rialto::server::tasks::webaudio +{ +class Shutdown : public IPlayerTask +{ +public: + explicit Shutdown(IGstWebAudioPlayerPrivate &player); + ~Shutdown() override; + void execute() const override; + +private: + IGstWebAudioPlayerPrivate &m_player; +}; +} // namespace firebolt::rialto::server::tasks::webaudio + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SHUTDOWN_H_ diff --git a/media/server/gstplayer/include/tasks/webAudio/WebAudioPlayerTaskFactory.h b/media/server/gstplayer/include/tasks/webAudio/WebAudioPlayerTaskFactory.h index d6923b153..44af6aaff 100644 --- a/media/server/gstplayer/include/tasks/webAudio/WebAudioPlayerTaskFactory.h +++ b/media/server/gstplayer/include/tasks/webAudio/WebAudioPlayerTaskFactory.h @@ -37,6 +37,7 @@ class WebAudioPlayerTaskFactory : public IWebAudioPlayerTaskFactory const std::shared_ptr &glibWrapper); ~WebAudioPlayerTaskFactory() override = default; + std::unique_ptr createShutdown(IGstWebAudioPlayerPrivate &player) const override; std::unique_ptr createStop(IGstWebAudioPlayerPrivate &player) const override; std::unique_ptr createPlay(IGstWebAudioPlayerPrivate &player) const override; std::unique_ptr createPause(IGstWebAudioPlayerPrivate &player) const override; diff --git a/media/server/gstplayer/source/GstGenericPlayer.cpp b/media/server/gstplayer/source/GstGenericPlayer.cpp index d75ca99d0..f0363de95 100644 --- a/media/server/gstplayer/source/GstGenericPlayer.cpp +++ b/media/server/gstplayer/source/GstGenericPlayer.cpp @@ -247,6 +247,9 @@ void GstGenericPlayer::initMsePipeline() void GstGenericPlayer::resetWorkerThread() { + // Shutdown task thread + m_workerThread->enqueueTask(m_taskFactory->createShutdown(*this)); + m_workerThread->join(); m_workerThread.reset(); } @@ -1633,6 +1636,14 @@ void GstGenericPlayer::stopPositionReportingAndCheckAudioUnderflowTimer() } } +void GstGenericPlayer::stopWorkerThread() +{ + if (m_workerThread) + { + m_workerThread->stop(); + } +} + void GstGenericPlayer::setPendingPlaybackRate() { RIALTO_SERVER_LOG_INFO("Setting pending playback rate"); diff --git a/media/server/gstplayer/source/GstWebAudioPlayer.cpp b/media/server/gstplayer/source/GstWebAudioPlayer.cpp index 81d585683..d71b51ddc 100644 --- a/media/server/gstplayer/source/GstWebAudioPlayer.cpp +++ b/media/server/gstplayer/source/GstWebAudioPlayer.cpp @@ -371,6 +371,8 @@ void GstWebAudioPlayer::termWebAudioPipeline() void GstWebAudioPlayer::resetWorkerThread() { + m_workerThread->enqueueTask(m_taskFactory->createShutdown(*this)); + m_workerThread->join(); m_workerThread.reset(); } @@ -441,6 +443,14 @@ bool GstWebAudioPlayer::changePipelineState(GstState newState) return true; } +void GstWebAudioPlayer::stopWorkerThread() +{ + if (m_workerThread) + { + m_workerThread->stop(); + } +} + void GstWebAudioPlayer::handleBusMessage(GstMessage *message) { if (m_workerThread) diff --git a/media/server/gstplayer/source/WorkerThread.cpp b/media/server/gstplayer/source/WorkerThread.cpp index 49afc7259..7c065051f 100644 --- a/media/server/gstplayer/source/WorkerThread.cpp +++ b/media/server/gstplayer/source/WorkerThread.cpp @@ -62,11 +62,8 @@ WorkerThread::WorkerThread() WorkerThread::~WorkerThread() { - if (m_taskThread.joinable()) - { - stop(); - m_taskThread.join(); - } + stop(); + join(); } void WorkerThread::stop() @@ -77,6 +74,14 @@ void WorkerThread::stop() enqueueTask(std::make_unique(std::move(shutdownTask))); } +void WorkerThread::join() +{ + if (m_taskThread.joinable()) + { + m_taskThread.join(); + } +} + void WorkerThread::enqueueTask(std::unique_ptr &&task) { if (task) diff --git a/media/server/gstplayer/source/tasks/generic/GenericPlayerTaskFactory.cpp b/media/server/gstplayer/source/tasks/generic/GenericPlayerTaskFactory.cpp index ec0e35c5e..b7ea1622f 100644 --- a/media/server/gstplayer/source/tasks/generic/GenericPlayerTaskFactory.cpp +++ b/media/server/gstplayer/source/tasks/generic/GenericPlayerTaskFactory.cpp @@ -52,6 +52,7 @@ #include "tasks/generic/SetVolume.h" #include "tasks/generic/SetupElement.h" #include "tasks/generic/SetupSource.h" +#include "tasks/generic/Shutdown.h" #include "tasks/generic/Stop.h" #include "tasks/generic/SwitchSource.h" #include "tasks/generic/Underflow.h" @@ -249,6 +250,11 @@ GenericPlayerTaskFactory::createSetStreamSyncMode(GenericPlayerContext &context, return std::make_unique(context, player, type, streamSyncMode); } +std::unique_ptr GenericPlayerTaskFactory::createShutdown(IGstGenericPlayerPrivate &player) const +{ + return std::make_unique(player); +} + std::unique_ptr GenericPlayerTaskFactory::createStop(GenericPlayerContext &context, IGstGenericPlayerPrivate &player) const { diff --git a/media/server/gstplayer/source/tasks/generic/Shutdown.cpp b/media/server/gstplayer/source/tasks/generic/Shutdown.cpp new file mode 100644 index 000000000..b3bb41a82 --- /dev/null +++ b/media/server/gstplayer/source/tasks/generic/Shutdown.cpp @@ -0,0 +1,41 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/Shutdown.h" +#include "IGstGenericPlayerPrivate.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::tasks::generic +{ +Shutdown::Shutdown(IGstGenericPlayerPrivate &player) : m_player{player} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing Shutdown"); +} + +Shutdown::~Shutdown() +{ + RIALTO_SERVER_LOG_DEBUG("Shutdown finished"); +} + +void Shutdown::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing Shutdown"); + m_player.stopWorkerThread(); +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/media/server/gstplayer/source/tasks/webAudio/Shutdown.cpp b/media/server/gstplayer/source/tasks/webAudio/Shutdown.cpp new file mode 100644 index 000000000..1fa57f51e --- /dev/null +++ b/media/server/gstplayer/source/tasks/webAudio/Shutdown.cpp @@ -0,0 +1,41 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/webAudio/Shutdown.h" +#include "IGstWebAudioPlayerPrivate.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::tasks::webaudio +{ +Shutdown::Shutdown(IGstWebAudioPlayerPrivate &player) : m_player{player} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing Shutdown"); +} + +Shutdown::~Shutdown() +{ + RIALTO_SERVER_LOG_DEBUG("Shutdown finished"); +} + +void Shutdown::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing Shutdown"); + m_player.stopWorkerThread(); +} +} // namespace firebolt::rialto::server::tasks::webaudio diff --git a/media/server/gstplayer/source/tasks/webAudio/WebAudioPlayerTaskFactory.cpp b/media/server/gstplayer/source/tasks/webAudio/WebAudioPlayerTaskFactory.cpp index e8cc5f0c8..2e1c392a4 100644 --- a/media/server/gstplayer/source/tasks/webAudio/WebAudioPlayerTaskFactory.cpp +++ b/media/server/gstplayer/source/tasks/webAudio/WebAudioPlayerTaskFactory.cpp @@ -24,6 +24,7 @@ #include "tasks/webAudio/Play.h" #include "tasks/webAudio/SetCaps.h" #include "tasks/webAudio/SetVolume.h" +#include "tasks/webAudio/Shutdown.h" #include "tasks/webAudio/Stop.h" #include "tasks/webAudio/WriteBuffer.h" @@ -36,6 +37,11 @@ WebAudioPlayerTaskFactory::WebAudioPlayerTaskFactory( { } +std::unique_ptr WebAudioPlayerTaskFactory::createShutdown(IGstWebAudioPlayerPrivate &player) const +{ + return std::make_unique(player); +} + std::unique_ptr WebAudioPlayerTaskFactory::createStop(IGstWebAudioPlayerPrivate &player) const { return std::make_unique(player); diff --git a/tests/unittests/media/server/gstplayer/CMakeLists.txt b/tests/unittests/media/server/gstplayer/CMakeLists.txt index 56a0b5d70..f3da20901 100644 --- a/tests/unittests/media/server/gstplayer/CMakeLists.txt +++ b/tests/unittests/media/server/gstplayer/CMakeLists.txt @@ -63,6 +63,7 @@ add_gtests(RialtoServerGstPlayerUnitTests genericPlayer/tasksTests/SetVolumeTest.cpp genericPlayer/tasksTests/SetupElementTest.cpp genericPlayer/tasksTests/SetupSourceTest.cpp + genericPlayer/tasksTests/ShutdownTest.cpp genericPlayer/tasksTests/StopTest.cpp genericPlayer/tasksTests/SwitchSourceTest.cpp genericPlayer/tasksTests/UnderflowTest.cpp @@ -85,6 +86,7 @@ add_gtests(RialtoServerGstPlayerUnitTests webAudioPlayer/taskTests/EosTest.cpp webAudioPlayer/taskTests/HandleBusMessageTest.cpp webAudioPlayer/taskTests/SetVolumeTest.cpp + webAudioPlayer/taskTests/ShutdownTest.cpp webAudioPlayer/taskTests/StopTest.cpp webAudioPlayer/taskTests/SetCapsTest.cpp webAudioPlayer/taskTests/WriteBufferTest.cpp diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/CreateTest.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/CreateTest.cpp index d134b3664..d94251132 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/CreateTest.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/CreateTest.cpp @@ -408,6 +408,7 @@ TEST_F(RialtoServerCreateGstGenericPlayerTest, UnknownMediaType) { EXPECT_CALL(m_gstInitialiserMock, waitForInitialisation()); initFactories(); + expectShutdown(); executeTaskWhenEnqueued(); EXPECT_CALL(*m_gstSrcMock, initSrc()); EXPECT_CALL(m_workerThreadFactoryMock, createWorkerThread()).WillOnce(Return(ByMove(std::move(workerThread)))); diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerPrivateTest.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerPrivateTest.cpp index f9ad47d57..b9ea88135 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerPrivateTest.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerPrivateTest.cpp @@ -1679,6 +1679,12 @@ TEST_F(GstGenericPlayerPrivateTest, shouldNotStopInactivePositionReportingTimerW m_sut->stopPositionReportingAndCheckAudioUnderflowTimer(); } +TEST_F(GstGenericPlayerPrivateTest, shouldStopWorkerThread) +{ + EXPECT_CALL(m_workerThreadMock, stop()); + m_sut->stopWorkerThread(); +} + TEST_F(GstGenericPlayerPrivateTest, shouldUpdatePlaybackGroup) { GstElement typefind; diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp index 896519a6a..e7231dccb 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp @@ -57,6 +57,7 @@ #include "tasks/generic/SetVolume.h" #include "tasks/generic/SetupElement.h" #include "tasks/generic/SetupSource.h" +#include "tasks/generic/Shutdown.h" #include "tasks/generic/Stop.h" #include "tasks/generic/SwitchSource.h" #include "tasks/generic/Underflow.h" @@ -2372,6 +2373,17 @@ void GenericTasksTestsBase::shouldNotifyVideoUnderflow() EXPECT_CALL(testContext->m_gstPlayerClient, notifyBufferUnderflow(firebolt::rialto::MediaSourceType::VIDEO)); } +void GenericTasksTestsBase::shouldStopWorkerThread() +{ + EXPECT_CALL(testContext->m_gstPlayer, stopWorkerThread()); +} + +void GenericTasksTestsBase::triggerShutdown() +{ + firebolt::rialto::server::tasks::generic::Shutdown task{testContext->m_gstPlayer}; + task.execute(); +} + void GenericTasksTestsBase::shouldSetVideoMute() { EXPECT_CALL(testContext->m_gstPlayer, setShowVideoWindow()).WillOnce(Return(true)); diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.h b/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.h index fac0fc76c..45b4cfa95 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.h +++ b/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.h @@ -259,6 +259,10 @@ class GenericTasksTestsBase : public ::testing::Test void triggerVideoUnderflow(); void shouldNotifyVideoUnderflow(); + // Shutdown test methods + void shouldStopWorkerThread(); + void triggerShutdown(); + // SetMute test methods void triggerSetAudioMute(); void triggerSetVideoMute(); diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/common/GstGenericPlayerTestCommon.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/common/GstGenericPlayerTestCommon.cpp index e0f0de0a3..4f423a12e 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/common/GstGenericPlayerTestCommon.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/common/GstGenericPlayerTestCommon.cpp @@ -50,6 +50,7 @@ void GstGenericPlayerTestCommon::gstPlayerWillBeCreated() void GstGenericPlayerTestCommon::gstPlayerWillBeDestroyed() { + expectShutdown(); expectStop(); EXPECT_CALL(*m_gstWrapperMock, gstPipelineGetBus(GST_PIPELINE(&m_pipeline))).WillOnce(Return(&m_bus)); EXPECT_CALL(*m_gstWrapperMock, gstBusSetSyncHandler(&m_bus, nullptr, nullptr, nullptr)); @@ -57,6 +58,14 @@ void GstGenericPlayerTestCommon::gstPlayerWillBeDestroyed() EXPECT_CALL(*m_gstWrapperMock, gstObjectUnref(&m_pipeline)); } +void GstGenericPlayerTestCommon::expectShutdown() +{ + std::unique_ptr shutdownTask{std::make_unique>()}; + EXPECT_CALL(dynamic_cast &>(*shutdownTask), execute()); + EXPECT_CALL(m_taskFactoryMock, createShutdown(_)).WillOnce(Return(ByMove(std::move(shutdownTask)))); + EXPECT_CALL(m_workerThreadMock, join()); +} + void GstGenericPlayerTestCommon::expectStop() { std::unique_ptr stopTask{std::make_unique>()}; diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/common/GstGenericPlayerTestCommon.h b/tests/unittests/media/server/gstplayer/genericPlayer/common/GstGenericPlayerTestCommon.h index efba04800..acc6da04c 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/common/GstGenericPlayerTestCommon.h +++ b/tests/unittests/media/server/gstplayer/genericPlayer/common/GstGenericPlayerTestCommon.h @@ -106,6 +106,7 @@ class GstGenericPlayerTestCommon : public ::testing::Test protected: void gstPlayerWillBeCreated(); void gstPlayerWillBeDestroyed(); + void expectShutdown(); void expectStop(); void executeTaskWhenEnqueued(); void initFactories(); diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/GenericPlayerTaskFactoryTest.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/GenericPlayerTaskFactoryTest.cpp index bdf89cb95..45d0fd48d 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/GenericPlayerTaskFactoryTest.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/GenericPlayerTaskFactoryTest.cpp @@ -64,6 +64,7 @@ #include "tasks/generic/SetVolume.h" #include "tasks/generic/SetupElement.h" #include "tasks/generic/SetupSource.h" +#include "tasks/generic/Shutdown.h" #include "tasks/generic/Stop.h" #include "tasks/generic/SwitchSource.h" #include "tasks/generic/Underflow.h" @@ -279,6 +280,13 @@ TEST_F(GenericPlayerTaskFactoryTest, ShouldCreateSetStreamSyncMode) EXPECT_NO_THROW(dynamic_cast(*task)); } +TEST_F(GenericPlayerTaskFactoryTest, ShouldCreateShutdown) +{ + auto task = m_sut.createShutdown(m_gstPlayer); + EXPECT_NE(task, nullptr); + EXPECT_NO_THROW(dynamic_cast(*task)); +} + TEST_F(GenericPlayerTaskFactoryTest, ShouldCreateStop) { auto task = m_sut.createStop(m_context, m_gstPlayer); diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/ShutdownTest.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/ShutdownTest.cpp new file mode 100644 index 000000000..4ed09f284 --- /dev/null +++ b/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/ShutdownTest.cpp @@ -0,0 +1,30 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "GenericTasksTestsBase.h" + +class ShutdownTest : public GenericTasksTestsBase +{ +}; + +TEST_F(ShutdownTest, shouldShutdown) +{ + shouldStopWorkerThread(); + triggerShutdown(); +} diff --git a/tests/unittests/media/server/gstplayer/webAudioPlayer/CreateTest.cpp b/tests/unittests/media/server/gstplayer/webAudioPlayer/CreateTest.cpp index d3d9bd0e5..0a61ceeb5 100644 --- a/tests/unittests/media/server/gstplayer/webAudioPlayer/CreateTest.cpp +++ b/tests/unittests/media/server/gstplayer/webAudioPlayer/CreateTest.cpp @@ -184,6 +184,9 @@ TEST_F(RialtoServerCreateGstWebAudioPlayerTest, createPipelineFailure) expectInitWorkerThread(); EXPECT_CALL(*m_gstWrapperMock, gstPipelineNew(_)).WillOnce(Return(nullptr)); + // Reset worker thread on failure + expectResetWorkerThread(); + EXPECT_THROW(m_gstPlayer = std::make_unique(&m_gstPlayerClient, m_priority, m_gstWrapperMock, m_glibWrapperMock, m_gstInitialiserMock, m_gstSrcFactoryMock, std::move(m_taskFactory), @@ -208,6 +211,7 @@ TEST_F(RialtoServerCreateGstWebAudioPlayerTest, createAppSrcFailure) EXPECT_CALL(*m_gstWrapperMock, gstPipelineGetBus(GST_PIPELINE(&m_pipeline))).WillOnce(Return(nullptr)); EXPECT_CALL(*m_gstWrapperMock, gstObjectUnref(&m_pipeline)); expectTaskStop(); + expectResetWorkerThread(); EXPECT_THROW(m_gstPlayer = std::make_unique(&m_gstPlayerClient, m_priority, m_gstWrapperMock, m_glibWrapperMock, m_gstInitialiserMock, @@ -526,6 +530,7 @@ TEST_F(RialtoServerCreateGstWebAudioPlayerTest, createGstDispatcherAfterFailureT expectTaskStop(); expectTermPipeline(); + expectResetWorkerThread(); EXPECT_THROW(m_gstPlayer = std::make_unique(&m_gstPlayerClient, m_priority, m_gstWrapperMock, m_glibWrapperMock, m_gstInitialiserMock, diff --git a/tests/unittests/media/server/gstplayer/webAudioPlayer/GstWebAudioPlayerPrivateTest.cpp b/tests/unittests/media/server/gstplayer/webAudioPlayer/GstWebAudioPlayerPrivateTest.cpp index d31c8199c..57c131f6d 100644 --- a/tests/unittests/media/server/gstplayer/webAudioPlayer/GstWebAudioPlayerPrivateTest.cpp +++ b/tests/unittests/media/server/gstplayer/webAudioPlayer/GstWebAudioPlayerPrivateTest.cpp @@ -52,3 +52,9 @@ TEST_F(GstWebAudioPlayerPrivateTest, shouldChangePlaybackState) EXPECT_CALL(*m_gstWrapperMock, gstElementSetState(_, GST_STATE_PLAYING)).WillOnce(Return(GST_STATE_CHANGE_SUCCESS)); EXPECT_TRUE(m_sut->changePipelineState(GST_STATE_PLAYING)); } + +TEST_F(GstWebAudioPlayerPrivateTest, shouldStopWorkerThread) +{ + EXPECT_CALL(m_workerThreadMock, stop()); + m_sut->stopWorkerThread(); +} diff --git a/tests/unittests/media/server/gstplayer/webAudioPlayer/common/GstWebAudioPlayerTestCommon.cpp b/tests/unittests/media/server/gstplayer/webAudioPlayer/common/GstWebAudioPlayerTestCommon.cpp index 3ed48f72d..96980db37 100644 --- a/tests/unittests/media/server/gstplayer/webAudioPlayer/common/GstWebAudioPlayerTestCommon.cpp +++ b/tests/unittests/media/server/gstplayer/webAudioPlayer/common/GstWebAudioPlayerTestCommon.cpp @@ -55,10 +55,20 @@ void GstWebAudioPlayerTestCommon::gstPlayerWillBeCreatedForGenericPlatform() void GstWebAudioPlayerTestCommon::gstPlayerWillBeDestroyed() { + expectResetWorkerThread(); expectTaskStop(); expectTermPipeline(); } +void GstWebAudioPlayerTestCommon::expectResetWorkerThread() +{ + std::unique_ptr shutdownTask{std::make_unique>()}; + EXPECT_CALL(dynamic_cast &>(*shutdownTask), execute()); + EXPECT_CALL(m_taskFactoryMock, createShutdown(_)).WillOnce(Return(ByMove(std::move(shutdownTask)))); + EXPECT_CALL(m_workerThreadMock, join()); + executeTaskWhenEnqueued(); +} + void GstWebAudioPlayerTestCommon::expectTermPipeline() { EXPECT_CALL(*m_gstWrapperMock, gstPipelineGetBus(GST_PIPELINE(&m_pipeline))).WillOnce(Return(&m_bus)); diff --git a/tests/unittests/media/server/gstplayer/webAudioPlayer/common/GstWebAudioPlayerTestCommon.h b/tests/unittests/media/server/gstplayer/webAudioPlayer/common/GstWebAudioPlayerTestCommon.h index 6971c09b3..787b57a86 100644 --- a/tests/unittests/media/server/gstplayer/webAudioPlayer/common/GstWebAudioPlayerTestCommon.h +++ b/tests/unittests/media/server/gstplayer/webAudioPlayer/common/GstWebAudioPlayerTestCommon.h @@ -100,6 +100,7 @@ class GstWebAudioPlayerTestCommon : public ::testing::Test void expectAddBinFailure(); void expectLinkElementFailure(); void expectTermPipeline(); + void expectResetWorkerThread(); void expectTaskStop(); GstElement m_pipeline{}; diff --git a/tests/unittests/media/server/gstplayer/webAudioPlayer/common/WebAudioTasksTestsBase.cpp b/tests/unittests/media/server/gstplayer/webAudioPlayer/common/WebAudioTasksTestsBase.cpp index 7e6374c3e..c4f3cd1f4 100644 --- a/tests/unittests/media/server/gstplayer/webAudioPlayer/common/WebAudioTasksTestsBase.cpp +++ b/tests/unittests/media/server/gstplayer/webAudioPlayer/common/WebAudioTasksTestsBase.cpp @@ -30,6 +30,7 @@ #include "tasks/webAudio/Play.h" #include "tasks/webAudio/SetCaps.h" #include "tasks/webAudio/SetVolume.h" +#include "tasks/webAudio/Shutdown.h" #include "tasks/webAudio/Stop.h" #include "tasks/webAudio/WriteBuffer.h" @@ -125,6 +126,17 @@ void WebAudioTasksTestsBase::triggerSetVolume() task.execute(); } +void WebAudioTasksTestsBase::shouldStopWorkerThread() +{ + EXPECT_CALL(testContext->m_gstPlayer, stopWorkerThread()); +} + +void WebAudioTasksTestsBase::triggerShutdown() +{ + firebolt::rialto::server::tasks::webaudio::Shutdown task{testContext->m_gstPlayer}; + task.execute(); +} + void WebAudioTasksTestsBase::shouldChangePlayerStateNull() { EXPECT_CALL(testContext->m_gstPlayer, changePipelineState(GST_STATE_NULL)); diff --git a/tests/unittests/media/server/gstplayer/webAudioPlayer/common/WebAudioTasksTestsBase.h b/tests/unittests/media/server/gstplayer/webAudioPlayer/common/WebAudioTasksTestsBase.h index 7998e65e9..ec122f4db 100644 --- a/tests/unittests/media/server/gstplayer/webAudioPlayer/common/WebAudioTasksTestsBase.h +++ b/tests/unittests/media/server/gstplayer/webAudioPlayer/common/WebAudioTasksTestsBase.h @@ -68,6 +68,10 @@ class WebAudioTasksTestsBase : public ::testing::Test void shouldGstSetVolume(); void triggerSetVolume(); + // Shutdown test methods + void shouldStopWorkerThread(); + void triggerShutdown(); + // Stop test methods void shouldChangePlayerStateNull(); void triggerStop(); diff --git a/tests/unittests/media/server/gstplayer/webAudioPlayer/taskTests/ShutdownTest.cpp b/tests/unittests/media/server/gstplayer/webAudioPlayer/taskTests/ShutdownTest.cpp new file mode 100644 index 000000000..412265ada --- /dev/null +++ b/tests/unittests/media/server/gstplayer/webAudioPlayer/taskTests/ShutdownTest.cpp @@ -0,0 +1,30 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "WebAudioTasksTestsBase.h" + +class WebAudioShutdownTest : public WebAudioTasksTestsBase +{ +}; + +TEST_F(WebAudioShutdownTest, shouldShutdown) +{ + shouldStopWorkerThread(); + triggerShutdown(); +} diff --git a/tests/unittests/media/server/gstplayer/webAudioPlayer/taskTests/WebAudioPlayerTaskFactoryTest.cpp b/tests/unittests/media/server/gstplayer/webAudioPlayer/taskTests/WebAudioPlayerTaskFactoryTest.cpp index 3d41c91d8..503a2839a 100644 --- a/tests/unittests/media/server/gstplayer/webAudioPlayer/taskTests/WebAudioPlayerTaskFactoryTest.cpp +++ b/tests/unittests/media/server/gstplayer/webAudioPlayer/taskTests/WebAudioPlayerTaskFactoryTest.cpp @@ -32,6 +32,7 @@ #include "tasks/webAudio/Play.h" #include "tasks/webAudio/SetCaps.h" #include "tasks/webAudio/SetVolume.h" +#include "tasks/webAudio/Shutdown.h" #include "tasks/webAudio/Stop.h" #include "tasks/webAudio/WriteBuffer.h" #include @@ -90,6 +91,13 @@ TEST_F(WebAudioPlayerTaskFactoryTest, ShouldStop) EXPECT_NO_THROW(dynamic_cast(*task)); } +TEST_F(WebAudioPlayerTaskFactoryTest, ShouldShutdown) +{ + auto task = m_sut.createShutdown(m_gstPlayer); + EXPECT_NE(task, nullptr); + EXPECT_NO_THROW(dynamic_cast(*task)); +} + TEST_F(WebAudioPlayerTaskFactoryTest, ShouldSetVolume) { auto task = m_sut.createSetVolume(m_context, {}); diff --git a/tests/unittests/media/server/mocks/gstplayer/GenericPlayerTaskFactoryMock.h b/tests/unittests/media/server/mocks/gstplayer/GenericPlayerTaskFactoryMock.h index 43bc6da08..656416104 100644 --- a/tests/unittests/media/server/mocks/gstplayer/GenericPlayerTaskFactoryMock.h +++ b/tests/unittests/media/server/mocks/gstplayer/GenericPlayerTaskFactoryMock.h @@ -101,6 +101,7 @@ class GenericPlayerTaskFactoryMock : public IGenericPlayerTaskFactory (GenericPlayerContext & context, IGstGenericPlayerPrivate &player, const firebolt::rialto::MediaSourceType &type, int32_t streamSyncMode), (const, override)); + MOCK_METHOD(std::unique_ptr, createShutdown, (IGstGenericPlayerPrivate & player), (const, override)); MOCK_METHOD(std::unique_ptr, createStop, (GenericPlayerContext & context, IGstGenericPlayerPrivate &player), (const, override)); MOCK_METHOD(std::unique_ptr, createUnderflow, diff --git a/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerPrivateMock.h b/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerPrivateMock.h index 45f6728b2..f54f53988 100644 --- a/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerPrivateMock.h +++ b/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerPrivateMock.h @@ -58,6 +58,7 @@ class GstGenericPlayerPrivateMock : public IGstGenericPlayerPrivate MOCK_METHOD(bool, changePipelineState, (GstState newState), (override)); MOCK_METHOD(void, startPositionReportingAndCheckAudioUnderflowTimer, (), (override)); MOCK_METHOD(void, stopPositionReportingAndCheckAudioUnderflowTimer, (), (override)); + MOCK_METHOD(void, stopWorkerThread, (), (override)); MOCK_METHOD(void, cancelUnderflow, (firebolt::rialto::MediaSourceType mediaSource), (override)); MOCK_METHOD(void, setPendingPlaybackRate, (), (override)); MOCK_METHOD(void, updatePlaybackGroup, (GstElement * typefind, const GstCaps *caps), (override)); diff --git a/tests/unittests/media/server/mocks/gstplayer/GstWebAudioPlayerPrivateMock.h b/tests/unittests/media/server/mocks/gstplayer/GstWebAudioPlayerPrivateMock.h index 0604a10fc..7b1da65fb 100644 --- a/tests/unittests/media/server/mocks/gstplayer/GstWebAudioPlayerPrivateMock.h +++ b/tests/unittests/media/server/mocks/gstplayer/GstWebAudioPlayerPrivateMock.h @@ -29,6 +29,7 @@ class GstWebAudioPlayerPrivateMock : public IGstWebAudioPlayerPrivate { public: MOCK_METHOD(bool, changePipelineState, (GstState newState), (override)); + MOCK_METHOD(void, stopWorkerThread, (), (override)); }; } // namespace firebolt::rialto::server diff --git a/tests/unittests/media/server/mocks/gstplayer/WebAudioPlayerTaskFactoryMock.h b/tests/unittests/media/server/mocks/gstplayer/WebAudioPlayerTaskFactoryMock.h index 31251367b..ba57e1f92 100644 --- a/tests/unittests/media/server/mocks/gstplayer/WebAudioPlayerTaskFactoryMock.h +++ b/tests/unittests/media/server/mocks/gstplayer/WebAudioPlayerTaskFactoryMock.h @@ -29,6 +29,7 @@ namespace firebolt::rialto::server class WebAudioPlayerTaskFactoryMock : public IWebAudioPlayerTaskFactory { public: + MOCK_METHOD(std::unique_ptr, createShutdown, (IGstWebAudioPlayerPrivate & player), (const, override)); MOCK_METHOD(std::unique_ptr, createStop, (IGstWebAudioPlayerPrivate & player), (const, override)); MOCK_METHOD(std::unique_ptr, createPlay, (IGstWebAudioPlayerPrivate & player), (const, override)); MOCK_METHOD(std::unique_ptr, createPause, (IGstWebAudioPlayerPrivate & player), (const, override)); diff --git a/tests/unittests/media/server/mocks/gstplayer/WorkerThreadMock.h b/tests/unittests/media/server/mocks/gstplayer/WorkerThreadMock.h index 095aa9a17..7b0071a78 100644 --- a/tests/unittests/media/server/mocks/gstplayer/WorkerThreadMock.h +++ b/tests/unittests/media/server/mocks/gstplayer/WorkerThreadMock.h @@ -30,6 +30,7 @@ class WorkerThreadMock : public IWorkerThread { public: MOCK_METHOD(void, stop, (), (override)); + MOCK_METHOD(void, join, (), (override)); MOCK_METHOD(void, enqueueTask, (std::unique_ptr && task), (override)); }; } // namespace firebolt::rialto::server From b693d50ebc0309262aaca40cabdfa7cbff9df707 Mon Sep 17 00:00:00 2001 From: Marcin Wojciechowski <105790697+skywojciechowskim@users.noreply.github.com> Date: Fri, 18 Jul 2025 14:24:35 +0200 Subject: [PATCH 10/15] Non-ethan logging enabled by default (#395) Summary: Non-ethan logging enabled by default Type: Fix Test Plan: UT/ CT, Fullstack Jira: NO-JIRA --- .github/workflows/build_and_deploy_gh_pages.yml | 2 +- .github/workflows/build_ut.yml | 2 +- logging/CMakeLists.txt | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_and_deploy_gh_pages.yml b/.github/workflows/build_and_deploy_gh_pages.yml index 31685bae0..907d44b64 100644 --- a/.github/workflows/build_and_deploy_gh_pages.yml +++ b/.github/workflows/build_and_deploy_gh_pages.yml @@ -62,7 +62,7 @@ jobs: doxygen - name: Download Coverage Report - uses: dawidd6/action-download-artifact@v3 + uses: dawidd6/action-download-artifact@v6 with: workflow: build_ut.yml workflow_conclusion: success diff --git a/.github/workflows/build_ut.yml b/.github/workflows/build_ut.yml index fe1cb033c..ead24de26 100644 --- a/.github/workflows/build_ut.yml +++ b/.github/workflows/build_ut.yml @@ -674,7 +674,7 @@ jobs: # Download current master coverage statistics. Should be triggered only for PRs to master - name: Download Master Coverage Statistics - uses: dawidd6/action-download-artifact@v3 + uses: dawidd6/action-download-artifact@v6 if: ${{ success() && github.event_name == 'pull_request' && github.base_ref == 'master' }} with: workflow_conclusion: success diff --git a/logging/CMakeLists.txt b/logging/CMakeLists.txt index cbc02ea2d..2c0751238 100644 --- a/logging/CMakeLists.txt +++ b/logging/CMakeLists.txt @@ -39,7 +39,8 @@ set_target_properties(RialtoLogging PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQU set_target_properties(RialtoLogging PROPERTIES POSITION_INDEPENDENT_CODE ON) find_package(EthanLog) -if (EthanLog_FOUND) +if (EthanLog_FOUND AND RIALTO_ENABLE_ETHAN_LOG) + message(STATUS "EthanLog is enabled") add_library(RialtoEthanLog STATIC ${RialtoLogging_HEADERS} ${RialtoLogging_SOURCES}) target_include_directories(RialtoEthanLog PUBLIC "$") target_compile_definitions(RialtoEthanLog PRIVATE USE_ETHANLOG) From 85828e7ab23ddbb0cee6c25b1227fe931472fb23 Mon Sep 17 00:00:00 2001 From: Marcin Wojciechowski <105790697+skywojciechowskim@users.noreply.github.com> Date: Mon, 21 Jul 2025 13:55:39 +0200 Subject: [PATCH 11/15] Add MP3 support to rialto (#396) Summary: Add MP3 support to rialto Type: Fix Test Plan: UT/ CT, Fullstack Jira: ENTDAI-748 --- media/server/gstplayer/include/CapsBuilder.h | 3 ++- .../server/gstplayer/include/GstMimeMapping.h | 25 ++++++++----------- media/server/gstplayer/source/CapsBuilder.cpp | 14 +++++++++-- .../genericPlayer/GstCapabilitiesTest.cpp | 5 ++++ .../common/GenericTasksTestsBase.cpp | 24 ++++++++++++++++++ .../common/GenericTasksTestsBase.h | 2 ++ .../tasksTests/AttachSourceTest.cpp | 7 ++++++ 7 files changed, 62 insertions(+), 18 deletions(-) diff --git a/media/server/gstplayer/include/CapsBuilder.h b/media/server/gstplayer/include/CapsBuilder.h index a8ff38a79..283f7ac04 100644 --- a/media/server/gstplayer/include/CapsBuilder.h +++ b/media/server/gstplayer/include/CapsBuilder.h @@ -61,7 +61,8 @@ class MediaSourceAudioCapsBuilder : public MediaSourceCapsBuilder GstCaps *createOpusCaps(); GstCaps *getAudioSpecificConfiguration() const; void addSampleRateAndChannelsToCaps(GstCaps *caps) const; - void addMpegVersionToCaps(GstCaps *caps) const; + void addMpegVersion4ToCaps(GstCaps *caps) const; + void addMp3Caps(GstCaps *caps) const; void addRawAudioData(GstCaps *caps) const; void addFlacSpecificData(GstCaps *caps) const; diff --git a/media/server/gstplayer/include/GstMimeMapping.h b/media/server/gstplayer/include/GstMimeMapping.h index 620136600..b8d515312 100644 --- a/media/server/gstplayer/include/GstMimeMapping.h +++ b/media/server/gstplayer/include/GstMimeMapping.h @@ -46,21 +46,15 @@ namespace firebolt::rialto::server inline GstCaps *createSimpleCapsFromMimeType(std::shared_ptr m_gstWrapper, const IMediaPipeline::MediaSource &m_attachedSource) { - static const std::unordered_map mimeToMediaType = {{"video/h264", "video/x-h264"}, - {"video/h265", "video/x-h265"}, - {"video/x-av1", "video/x-av1"}, - {"video/x-vp9", "video/x-vp9"}, - {"video/mp4", "video/mpeg"}, - {"audio/mp4", "audio/mpeg"}, - {"audio/aac", "audio/mpeg"}, - {"audio/x-eac3", "audio/x-eac3"}, - {"audio/x-opus", "audio/x-opus"}, - {"audio/b-wav", "audio/b-wav"}, - {"audio/x-raw", "audio/x-raw"}, - {"audio/x-flac", "audio/x-flac"}, - {"text/vtt", - "application/x-subtitle-vtt"}, - {"text/ttml", "application/ttml+xml"}}; + static const std::unordered_map mimeToMediaType = + {{"video/h264", "video/x-h264"}, {"video/h265", "video/x-h265"}, + {"video/x-av1", "video/x-av1"}, {"video/x-vp9", "video/x-vp9"}, + {"video/mp4", "video/mpeg"}, {"audio/mp4", "audio/mpeg"}, + {"audio/mp3", "audio/mpeg"}, {"audio/aac", "audio/mpeg"}, + {"audio/x-eac3", "audio/x-eac3"}, {"audio/x-opus", "audio/x-opus"}, + {"audio/b-wav", "audio/b-wav"}, {"audio/x-raw", "audio/x-raw"}, + {"audio/x-flac", "audio/x-flac"}, {"text/vtt", "application/x-subtitle-vtt"}, + {"text/ttml", "application/ttml+xml"}}; auto mimeToMediaTypeIt = mimeToMediaType.find(m_attachedSource.getMimeType()); if (mimeToMediaTypeIt != mimeToMediaType.end()) { @@ -85,6 +79,7 @@ convertFromCapsVectorToMimeSet(const std::vector &supportedCaps, { std::vector>> capsToMimeVec = {{m_gstWrapper->gstCapsFromString("audio/mpeg, mpegversion=(int)4"), {"audio/mp4", "audio/aac", "audio/x-eac3"}}, + {m_gstWrapper->gstCapsFromString("audio/mpeg, mpegversion=(int)1, layer=(int)3"), {"audio/mp3"}}, {m_gstWrapper->gstCapsFromString("audio/x-eac3"), {"audio/x-eac3"}}, {m_gstWrapper->gstCapsFromString("audio/b-wav"), {"audio/b-wav"}}, {m_gstWrapper->gstCapsFromString("audio/x-raw"), {"audio/x-raw"}}, diff --git a/media/server/gstplayer/source/CapsBuilder.cpp b/media/server/gstplayer/source/CapsBuilder.cpp index 4294fc8f8..4491b3656 100644 --- a/media/server/gstplayer/source/CapsBuilder.cpp +++ b/media/server/gstplayer/source/CapsBuilder.cpp @@ -109,7 +109,11 @@ GstCaps *MediaSourceAudioCapsBuilder::buildCaps() GstCaps *caps = MediaSourceCapsBuilder::buildCaps(); if (mimeType == "audio/mp4" || mimeType == "audio/aac") { - addMpegVersionToCaps(caps); + addMpegVersion4ToCaps(caps); + } + else if (mimeType == "audio/mp3") + { + addMp3Caps(caps); } else if (mimeType == "audio/b-wav" || mimeType == "audio/x-raw") { @@ -166,11 +170,17 @@ void MediaSourceAudioCapsBuilder::addSampleRateAndChannelsToCaps(GstCaps *caps) m_gstWrapper->gstCapsSetSimple(caps, "rate", G_TYPE_INT, audioConfig.sampleRate, nullptr); } -void MediaSourceAudioCapsBuilder::addMpegVersionToCaps(GstCaps *caps) const +void MediaSourceAudioCapsBuilder::addMpegVersion4ToCaps(GstCaps *caps) const { m_gstWrapper->gstCapsSetSimple(caps, "mpegversion", G_TYPE_INT, 4, nullptr); } +void MediaSourceAudioCapsBuilder::addMp3Caps(GstCaps *caps) const +{ + m_gstWrapper->gstCapsSetSimple(caps, "mpegversion", G_TYPE_INT, 1, nullptr); + m_gstWrapper->gstCapsSetSimple(caps, "layer", G_TYPE_INT, 3, nullptr); +} + void MediaSourceAudioCapsBuilder::addRawAudioData(GstCaps *caps) const { firebolt::rialto::AudioConfig audioConfig = m_attachedAudioSource.getAudioConfig(); diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/GstCapabilitiesTest.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/GstCapabilitiesTest.cpp index a9fd3a7dc..4e9c61282 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/GstCapabilitiesTest.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/GstCapabilitiesTest.cpp @@ -74,6 +74,7 @@ class GstCapabilitiesTest : public testing::Test GstCapabilitiesTest() // valid values of GstCaps are not needed, only addresses will be used : m_capsMap{{"audio/mpeg, mpegversion=(int)4", {}}, + {"audio/mpeg, mpegversion=(int)1, layer=(int)3", {}}, {"audio/x-eac3", {}}, {"audio/x-opus", {}}, {"audio/x-opus, channel-mapping-family=(int)0", {}}, @@ -584,6 +585,9 @@ TEST_F(GstCapabilitiesTest, CreateGstCapabilities_OneDecoderWithOneSinkPad_Parse .WillOnce(Return(true)); EXPECT_CALL(*m_gstWrapperMock, gstCapsCanIntersect(&m_capsMap["audio/x-raw"], &m_sinkTemplateCaps)) .WillOnce(Return(true)); + EXPECT_CALL(*m_gstWrapperMock, + gstCapsCanIntersect(&m_capsMap["audio/mpeg, mpegversion=(int)1, layer=(int)3"], &m_sinkTemplateCaps)) + .WillOnce(Return(true)); EXPECT_CALL(m_gstInitialiserMock, waitForInitialisation()); m_sut = std::make_unique(m_gstWrapperMock, m_glibWrapperMock, m_rdkGstreamerUtilsWrapperMock, @@ -593,6 +597,7 @@ TEST_F(GstCapabilitiesTest, CreateGstCapabilities_OneDecoderWithOneSinkPad_Parse EXPECT_TRUE(m_sut->isMimeTypeSupported("video/h264")); EXPECT_TRUE(m_sut->isMimeTypeSupported("audio/x-raw")); + EXPECT_TRUE(m_sut->isMimeTypeSupported("audio/mp3")); EXPECT_FALSE(m_sut->isMimeTypeSupported("video/x-av1")); EXPECT_FALSE(m_sut->isMimeTypeSupported("audio/x-opus")); } diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp index e7231dccb..3b3c9b45f 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp @@ -1540,6 +1540,30 @@ void GenericTasksTestsBase::triggerAttachFlacAudioSource() task.execute(); } +void GenericTasksTestsBase::shouldAttachMp3AudioSource() +{ + EXPECT_CALL(*testContext->m_gstWrapper, gstCapsNewEmptySimple(StrEq("audio/mpeg"))) + .WillOnce(Return(&testContext->m_gstCaps1)); + EXPECT_CALL(*testContext->m_gstWrapper, + gstCapsSetSimpleIntStub(&testContext->m_gstCaps1, StrEq("mpegversion"), G_TYPE_INT, 1)); + EXPECT_CALL(*testContext->m_gstWrapper, + gstCapsSetSimpleIntStub(&testContext->m_gstCaps1, StrEq("layer"), G_TYPE_INT, 3)); + expectSetCaps(); +} + +void GenericTasksTestsBase::triggerAttachMp3AudioSource() +{ + std::unique_ptr source = + std::make_unique("audio/mp3", false); + firebolt::rialto::server::tasks::generic::AttachSource task{testContext->m_context, + testContext->m_gstWrapper, + testContext->m_glibWrapper, + testContext->m_gstTextTrackSinkFactoryMock, + testContext->m_gstPlayer, + source}; + task.execute(); +} + void GenericTasksTestsBase::expectAddChannelAndRateAudioToCaps() { EXPECT_CALL(*testContext->m_gstWrapper, diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.h b/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.h index 45b4cfa95..0681bcfba 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.h +++ b/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.h @@ -168,6 +168,8 @@ class GenericTasksTestsBase : public ::testing::Test void triggerAttachXrawAudioSource(); void shouldAttachFlacAudioSource(); void triggerAttachFlacAudioSource(); + void shouldAttachMp3AudioSource(); + void triggerAttachMp3AudioSource(); void shouldAttachVideoSource(const std::string &mime, const std::string &alignment, const std::string &format); void triggerAttachVideoSource(const std::string &mimeType, firebolt::rialto::SegmentAlignment segmentAligment, firebolt::rialto::StreamFormat streamFormat); diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/AttachSourceTest.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/AttachSourceTest.cpp index 3842d1bdc..2b241b9fd 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/AttachSourceTest.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/tasksTests/AttachSourceTest.cpp @@ -65,6 +65,13 @@ TEST_F(AttachSourceTest, shouldAttachFlacAudioSource) checkAudioSourceAttachedWithDrm(); } +TEST_F(AttachSourceTest, shouldAttachMp3AudioSource) +{ + shouldAttachMp3AudioSource(); + triggerAttachMp3AudioSource(); + checkAudioSourceAttached(); +} + TEST_F(AttachSourceTest, shouldAttachVideoSourceAuAvc) { std::string mimeType = "video/h264"; From e9c17a075d2023cbdd61dc7f8404d93929b5f46e Mon Sep 17 00:00:00 2001 From: Marcin Wojciechowski <105790697+skywojciechowskim@users.noreply.github.com> Date: Fri, 25 Jul 2025 11:18:19 +0200 Subject: [PATCH 12/15] Add IsVideoMaster function in Rialto public interface. (#397) Summary: Add IsVideoMaster function in Rialto public interface. Type: Fix Test Plan: UT/ CT, Fullstack Jira: VPLAY-8941 --- media/client/ipc/include/MediaPipelineIpc.h | 2 + .../client/ipc/interface/IMediaPipelineIpc.h | 9 ++ media/client/ipc/source/MediaPipelineIpc.cpp | 32 ++++++ media/client/main/include/MediaPipeline.h | 2 + .../client/main/include/MediaPipelineProxy.h | 2 + media/client/main/source/MediaPipeline.cpp | 7 ++ media/public/include/IMediaPipeline.h | 9 ++ .../gstplayer/include/GstGenericPlayer.h | 1 + .../gstplayer/interface/IGstGenericPlayer.h | 9 ++ .../gstplayer/source/GstGenericPlayer.cpp | 18 +++ .../ipc/include/MediaPipelineModuleService.h | 3 + .../ipc/source/MediaPipelineModuleService.cpp | 21 ++++ .../include/MediaPipelineServerInternal.h | 11 ++ .../source/MediaPipelineServerInternal.cpp | 19 ++++ .../service/include/IMediaPipelineService.h | 1 + .../service/source/MediaPipelineService.cpp | 14 +++ .../service/source/MediaPipelineService.h | 1 + proto/mediapipelinemodule.proto | 23 ++++ .../MediaPipelineProtoRequestMatchers.h | 7 ++ .../client/mocks/MediaPipelineModuleMock.h | 3 + .../tests/base/MediaPipelineTestMethods.cpp | 24 ++++ .../tests/base/MediaPipelineTestMethods.h | 4 + .../client/tests/mse/IsVideoMasterTest.cpp | 91 +++++++++++++++ .../server/common/ActionTraits.h | 8 ++ .../server/common/MessageBuilders.cpp | 7 ++ .../server/common/MessageBuilders.h | 1 + .../mediaPipeline/PipelinePropertyTest.cpp | 36 +++++- .../unittests/media/client/ipc/CMakeLists.txt | 1 + .../mediaPipelineIpc/IsVideoMasterTest.cpp | 107 ++++++++++++++++++ .../media/client/main/CMakeLists.txt | 1 + .../main/mediaPipeline/IsVideoMasterTest.cpp | 64 +++++++++++ .../client/mocks/ipc/MediaPipelineIpcMock.h | 1 + .../main/MediaPipelineAndControlClientMock.h | 1 + .../genericPlayer/GstGenericPlayerTest.cpp | 30 +++++ .../MediaPipelineModuleServiceTests.cpp | 12 ++ ...MediaPipelineModuleServiceTestsFixture.cpp | 36 ++++++ .../MediaPipelineModuleServiceTestsFixture.h | 4 + .../MiscellaneousFunctionsTest.cpp | 37 ++++++ .../mocks/gstplayer/GstGenericPlayerMock.h | 1 + .../main/MediaPipelineServerInternalMock.h | 1 + .../mocks/service/MediaPipelineServiceMock.h | 1 + .../MediaPipelineServiceTests.cpp | 14 +++ .../MediaPipelineServiceTestsFixture.cpp | 22 ++++ .../MediaPipelineServiceTestsFixture.h | 4 + 44 files changed, 696 insertions(+), 6 deletions(-) create mode 100644 tests/componenttests/client/tests/mse/IsVideoMasterTest.cpp create mode 100644 tests/unittests/media/client/ipc/mediaPipelineIpc/IsVideoMasterTest.cpp create mode 100644 tests/unittests/media/client/main/mediaPipeline/IsVideoMasterTest.cpp diff --git a/media/client/ipc/include/MediaPipelineIpc.h b/media/client/ipc/include/MediaPipelineIpc.h index 9666027fe..9ec1a5135 100644 --- a/media/client/ipc/include/MediaPipelineIpc.h +++ b/media/client/ipc/include/MediaPipelineIpc.h @@ -142,6 +142,8 @@ class MediaPipelineIpc : public IMediaPipelineIpc, public IpcModule bool switchSource(const std::unique_ptr &source) override; + bool isVideoMaster(bool &isVideoMaster) override; + private: /** * @brief The media player client ipc. diff --git a/media/client/ipc/interface/IMediaPipelineIpc.h b/media/client/ipc/interface/IMediaPipelineIpc.h index 5ade91266..1faa37895 100644 --- a/media/client/ipc/interface/IMediaPipelineIpc.h +++ b/media/client/ipc/interface/IMediaPipelineIpc.h @@ -439,6 +439,15 @@ class IMediaPipelineIpc * @retval true on success. */ virtual bool switchSource(const std::unique_ptr &source) = 0; + + /** + * @brief Checks if the platform is video master. + * + * @param[out] isVideoMaster : The output value. True if video is master otherwise false. + * + * @retval true on success false otherwise + */ + virtual bool isVideoMaster(bool &isVideoMaster) = 0; }; }; // namespace firebolt::rialto::client diff --git a/media/client/ipc/source/MediaPipelineIpc.cpp b/media/client/ipc/source/MediaPipelineIpc.cpp index fb288c764..dcf1e5ce0 100644 --- a/media/client/ipc/source/MediaPipelineIpc.cpp +++ b/media/client/ipc/source/MediaPipelineIpc.cpp @@ -1333,6 +1333,38 @@ bool MediaPipelineIpc::switchSource(const std::unique_ptrisVideoMaster(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to check if video is master due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + isVideoMaster = response.is_video_master(); + + return true; +} + void MediaPipelineIpc::onPlaybackStateUpdated(const std::shared_ptr &event) { /* Ignore event if not for this session */ diff --git a/media/client/main/include/MediaPipeline.h b/media/client/main/include/MediaPipeline.h index 36bc4cbea..aa5f8a94a 100644 --- a/media/client/main/include/MediaPipeline.h +++ b/media/client/main/include/MediaPipeline.h @@ -203,6 +203,8 @@ class MediaPipeline : public IMediaPipelineAndIControlClient, public IMediaPipel bool switchSource(const std::unique_ptr &source) override; + bool isVideoMaster(bool &isVideoMaster) override; + void notifyApplicationState(ApplicationState state) override; protected: diff --git a/media/client/main/include/MediaPipelineProxy.h b/media/client/main/include/MediaPipelineProxy.h index d24053885..86ade929b 100644 --- a/media/client/main/include/MediaPipelineProxy.h +++ b/media/client/main/include/MediaPipelineProxy.h @@ -169,6 +169,8 @@ class MediaPipelineProxy : public IMediaPipelineAndIControlClient return m_mediaPipeline->switchSource(source); } + bool isVideoMaster(bool &isVideoMaster) { return m_mediaPipeline->isVideoMaster(isVideoMaster); } + void notifyApplicationState(ApplicationState state) override { m_mediaPipeline->notifyApplicationState(state); } private: diff --git a/media/client/main/source/MediaPipeline.cpp b/media/client/main/source/MediaPipeline.cpp index 41731d60b..ae4a17069 100644 --- a/media/client/main/source/MediaPipeline.cpp +++ b/media/client/main/source/MediaPipeline.cpp @@ -619,6 +619,13 @@ bool MediaPipeline::switchSource(const std::unique_ptr &source) return m_mediaPipelineIpc->switchSource(source); } +bool MediaPipeline::isVideoMaster(bool &isVideoMaster) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaPipelineIpc->isVideoMaster(isVideoMaster); +} + void MediaPipeline::discardNeedDataRequest(uint32_t needDataRequestId) { // Find the needDataRequest for this needDataRequestId diff --git a/media/public/include/IMediaPipeline.h b/media/public/include/IMediaPipeline.h index 61b992b86..96aaf2ec5 100644 --- a/media/public/include/IMediaPipeline.h +++ b/media/public/include/IMediaPipeline.h @@ -1523,6 +1523,15 @@ class IMediaPipeline * @retval true on success. */ virtual bool switchSource(const std::unique_ptr &source) = 0; + + /** + * @brief Checks if the platform is video master. + * + * @param[out] isVideoMaster : The output value. True if video is master otherwise false. + * + * @retval true on success false otherwise + */ + virtual bool isVideoMaster(bool &isVideoMaster) = 0; }; }; // namespace firebolt::rialto diff --git a/media/server/gstplayer/include/GstGenericPlayer.h b/media/server/gstplayer/include/GstGenericPlayer.h index 91548b7bb..cd070471a 100644 --- a/media/server/gstplayer/include/GstGenericPlayer.h +++ b/media/server/gstplayer/include/GstGenericPlayer.h @@ -142,6 +142,7 @@ class GstGenericPlayer : public IGstGenericPlayer, public IGstGenericPlayerPriva void setUseBuffering(bool useBuffering) override; bool getUseBuffering(bool &useBuffering) override; void switchSource(const std::unique_ptr &mediaSource) override; + bool isVideoMaster(bool &isVideoMaster) override; private: void scheduleNeedMediaData(GstAppSrc *src) override; diff --git a/media/server/gstplayer/interface/IGstGenericPlayer.h b/media/server/gstplayer/interface/IGstGenericPlayer.h index a6c9532bf..55810383f 100644 --- a/media/server/gstplayer/interface/IGstGenericPlayer.h +++ b/media/server/gstplayer/interface/IGstGenericPlayer.h @@ -444,6 +444,15 @@ class IGstGenericPlayer * */ virtual void switchSource(const std::unique_ptr &mediaSource) = 0; + + /** + * @brief Checks if the platform is video master. + * + * @param[out] isVideoMaster : The output value. True if video is master otherwise false. + * + * @retval true on success false otherwise + */ + virtual bool isVideoMaster(bool &isVideoMaster) = 0; }; }; // namespace firebolt::rialto::server diff --git a/media/server/gstplayer/source/GstGenericPlayer.cpp b/media/server/gstplayer/source/GstGenericPlayer.cpp index f0363de95..cf1230c8a 100644 --- a/media/server/gstplayer/source/GstGenericPlayer.cpp +++ b/media/server/gstplayer/source/GstGenericPlayer.cpp @@ -2014,6 +2014,24 @@ void GstGenericPlayer::switchSource(const std::unique_ptrgstRegistryGet(); + if (!reg) + { + RIALTO_SERVER_LOG_ERROR("Failed get the gst registry"); + return false; + } + GstPluginFeature *feature{nullptr}; + isVideoMaster = true; + if (nullptr != (feature = m_gstWrapper->gstRegistryLookupFeature(reg, "amlhalasink"))) + { + isVideoMaster = false; + m_gstWrapper->gstObjectUnref(feature); + } + return true; +} + void GstGenericPlayer::handleBusMessage(GstMessage *message) { m_workerThread->enqueueTask(m_taskFactory->createHandleBusMessage(m_context, *this, message, *m_flushWatcher)); diff --git a/media/server/ipc/include/MediaPipelineModuleService.h b/media/server/ipc/include/MediaPipelineModuleService.h index fa9c74b95..8c323e203 100644 --- a/media/server/ipc/include/MediaPipelineModuleService.h +++ b/media/server/ipc/include/MediaPipelineModuleService.h @@ -155,6 +155,9 @@ class MediaPipelineModuleService : public IMediaPipelineModuleService const ::firebolt::rialto::GetUseBufferingRequest *request, ::firebolt::rialto::GetUseBufferingResponse *response, ::google::protobuf::Closure *done) override; + void isVideoMaster(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::IsVideoMasterRequest *request, + ::firebolt::rialto::IsVideoMasterResponse *response, ::google::protobuf::Closure *done) override; private: service::IMediaPipelineService &m_mediaPipelineService; diff --git a/media/server/ipc/source/MediaPipelineModuleService.cpp b/media/server/ipc/source/MediaPipelineModuleService.cpp index ca36ee3d4..c596a526a 100644 --- a/media/server/ipc/source/MediaPipelineModuleService.cpp +++ b/media/server/ipc/source/MediaPipelineModuleService.cpp @@ -1065,4 +1065,25 @@ void MediaPipelineModuleService::getUseBuffering(::google::protobuf::RpcControll done->Run(); } + +void MediaPipelineModuleService::isVideoMaster(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::IsVideoMasterRequest *request, + ::firebolt::rialto::IsVideoMasterResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + bool isVideoMaster{}; + + if (!m_mediaPipelineService.isVideoMaster(request->session_id(), isVideoMaster)) + { + RIALTO_SERVER_LOG_ERROR("Is video master failed."); + controller->SetFailed("Operation failed"); + } + else + { + response->set_is_video_master(isVideoMaster); + } + + done->Run(); +} } // namespace firebolt::rialto::server::ipc diff --git a/media/server/main/include/MediaPipelineServerInternal.h b/media/server/main/include/MediaPipelineServerInternal.h index 015c7649b..df430e001 100644 --- a/media/server/main/include/MediaPipelineServerInternal.h +++ b/media/server/main/include/MediaPipelineServerInternal.h @@ -167,6 +167,8 @@ class MediaPipelineServerInternal : public IMediaPipelineServerInternal, public bool switchSource(const std::unique_ptr &source) override; + bool isVideoMaster(bool &isVideoMaster) override; + AddSegmentStatus addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) override; std::weak_ptr getClient() override; @@ -693,6 +695,15 @@ class MediaPipelineServerInternal : public IMediaPipelineServerInternal, public */ bool switchSourceInternal(const std::unique_ptr &source); + /** + * @brief Checks if the platform is video master. + * + * @param[out] isVideoMaster : The output value. True if video is master otherwise false. + * + * @retval true on success false otherwise + */ + bool isVideoMasterInternal(bool &isVideoMaster); + /** * @brief Returns how long should we wait to send next NeedMediaData * if rialto client returns NO_AVAILABLE_SAMPLES diff --git a/media/server/main/source/MediaPipelineServerInternal.cpp b/media/server/main/source/MediaPipelineServerInternal.cpp index e80808285..6d6465e60 100644 --- a/media/server/main/source/MediaPipelineServerInternal.cpp +++ b/media/server/main/source/MediaPipelineServerInternal.cpp @@ -1325,6 +1325,25 @@ bool MediaPipelineServerInternal::switchSourceInternal(const std::unique_ptrenqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::isVideoMasterInternal(bool &isVideoMaster) +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to check if video is master - Gstreamer player has not been loaded"); + return false; + } + return m_gstPlayer->isVideoMaster(isVideoMaster); +} + AddSegmentStatus MediaPipelineServerInternal::addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) { diff --git a/media/server/service/include/IMediaPipelineService.h b/media/server/service/include/IMediaPipelineService.h index bdabb1b17..bf7ec69af 100644 --- a/media/server/service/include/IMediaPipelineService.h +++ b/media/server/service/include/IMediaPipelineService.h @@ -89,6 +89,7 @@ class IMediaPipelineService const std::vector &propertyNames) = 0; virtual void ping(const std::shared_ptr &heartbeatProcedure) = 0; virtual bool switchSource(int sessionId, const std::unique_ptr &source) = 0; + virtual bool isVideoMaster(int sessionId, bool &isVideoMaster) = 0; }; } // namespace firebolt::rialto::server::service diff --git a/media/server/service/source/MediaPipelineService.cpp b/media/server/service/source/MediaPipelineService.cpp index 2031afdf5..35641f687 100644 --- a/media/server/service/source/MediaPipelineService.cpp +++ b/media/server/service/source/MediaPipelineService.cpp @@ -620,6 +620,20 @@ bool MediaPipelineService::switchSource(int sessionId, const std::unique_ptrsecond->switchSource(source); } +bool MediaPipelineService::isVideoMaster(int sessionId, bool &isVideoMaster) +{ + RIALTO_SERVER_LOG_INFO("MediaPipelineService requested check if video is master, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); + return false; + } + return mediaPipelineIter->second->isVideoMaster(isVideoMaster); +} + std::vector MediaPipelineService::getSupportedMimeTypes(MediaSourceType type) { return m_mediaPipelineCapabilities->getSupportedMimeTypes(type); diff --git a/media/server/service/source/MediaPipelineService.h b/media/server/service/source/MediaPipelineService.h index 86804d1d0..a426b7472 100644 --- a/media/server/service/source/MediaPipelineService.h +++ b/media/server/service/source/MediaPipelineService.h @@ -95,6 +95,7 @@ class MediaPipelineService : public IMediaPipelineService bool setUseBuffering(int sessionId, bool useBuffering) override; bool getUseBuffering(int sessionId, bool &useBuffering) override; bool switchSource(int sessionId, const std::unique_ptr &source) override; + bool isVideoMaster(int sessionId, bool &isVideoMaster) override; std::vector getSupportedMimeTypes(MediaSourceType type) override; bool isMimeTypeSupported(const std::string &mimeType) override; std::vector getSupportedProperties(MediaSourceType mediaType, diff --git a/proto/mediapipelinemodule.proto b/proto/mediapipelinemodule.proto index b326b621a..3ac808db2 100644 --- a/proto/mediapipelinemodule.proto +++ b/proto/mediapipelinemodule.proto @@ -791,6 +791,22 @@ message GetUseBufferingResponse { optional bool use_buffering = 1 [default = false]; } +/** + * @fn void isVideoMaster(bool &isVideoMaster) + * @brief Checks if the platform is video master. + * + * @param[in] session_id The id of the A/V session the request is for. + * @param[out] is_video_master True if video is master otherwise false. + * + * @retval true on success false otherwise + */ +message IsVideoMasterRequest { + optional int32 session_id = 1 [default = -1]; +} +message IsVideoMasterResponse { + optional bool is_video_master = 1; +} + /** * @brief Event sent the playback state has changed. * @@ -1221,4 +1237,11 @@ service MediaPipelineModule { */ rpc getUseBuffering(GetUseBufferingRequest) returns (GetUseBufferingResponse) { } + + /** + * @brief Checks if the platform is video master. + * @see IsVideoMasterRequest + */ + rpc isVideoMaster(IsVideoMasterRequest) returns (IsVideoMasterResponse) { + } } diff --git a/tests/common/matchers/MediaPipelineProtoRequestMatchers.h b/tests/common/matchers/MediaPipelineProtoRequestMatchers.h index ecd07f993..89e811c6f 100644 --- a/tests/common/matchers/MediaPipelineProtoRequestMatchers.h +++ b/tests/common/matchers/MediaPipelineProtoRequestMatchers.h @@ -300,6 +300,13 @@ MATCHER_P(getSyncRequestMatcher, sessionId, "") return ((kRequest->session_id() == sessionId)); } +MATCHER_P(isVideoMasterRequestMatcher, sessionId, "") +{ + const ::firebolt::rialto::IsVideoMasterRequest *kRequest = + dynamic_cast(arg); + return ((kRequest->session_id() == sessionId)); +} + MATCHER_P2(setSyncOffRequestMatcher, sessionId, syncOff, "") { const ::firebolt::rialto::SetSyncOffRequest *kRequest = diff --git a/tests/componenttests/client/mocks/MediaPipelineModuleMock.h b/tests/componenttests/client/mocks/MediaPipelineModuleMock.h index 934934205..a6fc772c0 100644 --- a/tests/componenttests/client/mocks/MediaPipelineModuleMock.h +++ b/tests/componenttests/client/mocks/MediaPipelineModuleMock.h @@ -140,6 +140,9 @@ class MediaPipelineModuleMock : public ::firebolt::rialto::MediaPipelineModule MOCK_METHOD(void, processAudioGap, (::google::protobuf::RpcController * controller, const ::firebolt::rialto::ProcessAudioGapRequest *request, ::firebolt::rialto::ProcessAudioGapResponse *response, ::google::protobuf::Closure *done)); + MOCK_METHOD(void, isVideoMaster, + (::google::protobuf::RpcController * controller, const ::firebolt::rialto::IsVideoMasterRequest *request, + ::firebolt::rialto::IsVideoMasterResponse *response, ::google::protobuf::Closure *done)); void defaultReturn(::google::protobuf::RpcController *controller, ::google::protobuf::Closure *done) { diff --git a/tests/componenttests/client/tests/base/MediaPipelineTestMethods.cpp b/tests/componenttests/client/tests/base/MediaPipelineTestMethods.cpp index 2722564c1..287b0f877 100644 --- a/tests/componenttests/client/tests/base/MediaPipelineTestMethods.cpp +++ b/tests/componenttests/client/tests/base/MediaPipelineTestMethods.cpp @@ -1587,6 +1587,30 @@ void MediaPipelineTestMethods::switchSourceMpeg() EXPECT_EQ(m_mediaPipeline->switchSource(mediaSource), true); } +void MediaPipelineTestMethods::shouldCheckIfVideoIsMaster() +{ + EXPECT_CALL(*m_mediaPipelineModuleMock, isVideoMaster(_, isVideoMasterRequestMatcher(kSessionId), _, _)) + .WillOnce(WithArgs<0, 3>(Invoke(&(*m_mediaPipelineModuleMock), &MediaPipelineModuleMock::defaultReturn))); +} + +void MediaPipelineTestMethods::shouldFailToCheckIfVideoIsMaster() +{ + EXPECT_CALL(*m_mediaPipelineModuleMock, isVideoMaster(_, isVideoMasterRequestMatcher(kSessionId), _, _)) + .WillOnce(WithArgs<0, 3>(Invoke(&(*m_mediaPipelineModuleMock), &MediaPipelineModuleMock::failureReturn))); +} + +void MediaPipelineTestMethods::isVideoMaster() +{ + bool isMaster{false}; + EXPECT_TRUE(m_mediaPipeline->isVideoMaster(isMaster)); +} + +void MediaPipelineTestMethods::isVideoMasterFailure() +{ + bool isMaster{false}; + EXPECT_FALSE(m_mediaPipeline->isVideoMaster(isMaster)); +} + /*************************** Private methods ********************************/ void MediaPipelineTestMethods::resetWriteLocation(uint32_t partitionId) diff --git a/tests/componenttests/client/tests/base/MediaPipelineTestMethods.h b/tests/componenttests/client/tests/base/MediaPipelineTestMethods.h index 5a64b9e20..8cd51364d 100644 --- a/tests/componenttests/client/tests/base/MediaPipelineTestMethods.h +++ b/tests/componenttests/client/tests/base/MediaPipelineTestMethods.h @@ -139,6 +139,8 @@ class MediaPipelineTestMethods void shouldFailToProcessAudioGap(); void shouldSwitchSourceEacs(); void shouldSwitchSourceMpeg(); + void shouldCheckIfVideoIsMaster(); + void shouldFailToCheckIfVideoIsMaster(); // MediaPipelineClient Expect methods void shouldNotifyNetworkStateBuffering(); @@ -263,6 +265,8 @@ class MediaPipelineTestMethods void processAudioGapFailure(); void switchSourceEac(); void switchSourceMpeg(); + void isVideoMaster(); + void isVideoMasterFailure(); // Event methods void sendNotifyNetworkStateBuffering(); diff --git a/tests/componenttests/client/tests/mse/IsVideoMasterTest.cpp b/tests/componenttests/client/tests/mse/IsVideoMasterTest.cpp new file mode 100644 index 000000000..fdb76420c --- /dev/null +++ b/tests/componenttests/client/tests/mse/IsVideoMasterTest.cpp @@ -0,0 +1,91 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ClientComponentTest.h" +#include + +namespace firebolt::rialto::client::ct +{ +class MuteTest : public ClientComponentTest +{ +public: + double m_isVideoMaster = false; + + MuteTest() : ClientComponentTest() + { + ClientComponentTest::startApplicationRunning(); + MediaPipelineTestMethods::startAudioVideoMediaSessionPrerollPaused(); + } + + ~MuteTest() + { + MediaPipelineTestMethods::endAudioVideoMediaSession(); + ClientComponentTest::stopApplication(); + } +}; + +/* + * Component Test: IsVideoMaster + * Test Objective: + * Test the IsVideoMaster API. + * + * Sequence Diagrams: + * IsVideoMaster - https://wiki.rdkcentral.com/display/ASP/Rialto+MSE+Misc+Sequence+Diagrams + * + * Test Setup: + * Language: C++ + * Testing Framework: Google Test + * Components: MediaPipeline + * + * Test Initialize: + * Create memory region for the shared buffer. + * Create a server that handles Control IPC requests. + * Initalise the control state to running for this test application. + * Initalise a audio video media session paused and prerolled. + * + * Test Steps: + * Step 1: Call IsVideoMaster + * Call IsVideoMaster + * Expect that IsVideoMaster propagated to the server and returns the IsVideoMaster status. + * + * Step 2: Call IsVideoMaster failure + * Call IsVideoMaster + * Expect that when IsVideoMaster fails, it returns the error status. + * + * Test Teardown: + * Terminate the media session. + * Memory region created for the shared buffer is closed. + * Server is terminated. + * + * Expected Results: + * IsVideoMaster can be set and got multiple times without issue. + * + * Code: + */ +TEST_F(MuteTest, mute) +{ + // Step 1: Call IsVideoMaster + MediaPipelineTestMethods::shouldCheckIfVideoIsMaster(); + MediaPipelineTestMethods::isVideoMaster(); + + // Step 2: Call IsVideoMaster failure + MediaPipelineTestMethods::shouldFailToCheckIfVideoIsMaster(); + MediaPipelineTestMethods::isVideoMasterFailure(); +} +} // namespace firebolt::rialto::client::ct diff --git a/tests/componenttests/server/common/ActionTraits.h b/tests/componenttests/server/common/ActionTraits.h index a88293e3f..2e3692400 100644 --- a/tests/componenttests/server/common/ActionTraits.h +++ b/tests/componenttests/server/common/ActionTraits.h @@ -344,6 +344,14 @@ struct ProcessAudioGap static constexpr auto m_kFunction{&Stub::processAudioGap}; }; +struct IsVideoMaster +{ + using RequestType = ::firebolt::rialto::IsVideoMasterRequest; + using ResponseType = ::firebolt::rialto::IsVideoMasterResponse; + using Stub = ::firebolt::rialto::MediaPipelineModule_Stub; + static constexpr auto m_kFunction{&Stub::isVideoMaster}; +}; + // mediakeys module struct CreateMediaKeys { diff --git a/tests/componenttests/server/common/MessageBuilders.cpp b/tests/componenttests/server/common/MessageBuilders.cpp index c2b4f868b..6aee8a365 100644 --- a/tests/componenttests/server/common/MessageBuilders.cpp +++ b/tests/componenttests/server/common/MessageBuilders.cpp @@ -407,6 +407,13 @@ ::firebolt::rialto::ProcessAudioGapRequest createProcessAudioGapRequest(int sess return request; } +::firebolt::rialto::IsVideoMasterRequest createIsVideoMasterRequest(int sessionId) +{ + ::firebolt::rialto::IsVideoMasterRequest request; + request.set_session_id(sessionId); + return request; +} + ::firebolt::rialto::CreateMediaKeysRequest createCreateMediaKeysRequestWidevine() { ::firebolt::rialto::CreateMediaKeysRequest request; diff --git a/tests/componenttests/server/common/MessageBuilders.h b/tests/componenttests/server/common/MessageBuilders.h index 54fe2202b..da46b666f 100644 --- a/tests/componenttests/server/common/MessageBuilders.h +++ b/tests/componenttests/server/common/MessageBuilders.h @@ -83,6 +83,7 @@ ::firebolt::rialto::SetSourcePositionRequest createSetSourcePositionRequest(int ::firebolt::rialto::ProcessAudioGapRequest createProcessAudioGapRequest(int sessionId, std::int64_t position, unsigned duration, std::int64_t discontinuityGap, bool audioAac); +::firebolt::rialto::IsVideoMasterRequest createIsVideoMasterRequest(int sessionId); // media keys module ::firebolt::rialto::CreateMediaKeysRequest createCreateMediaKeysRequestWidevine(); diff --git a/tests/componenttests/server/tests/mediaPipeline/PipelinePropertyTest.cpp b/tests/componenttests/server/tests/mediaPipeline/PipelinePropertyTest.cpp index 6ef30946e..a9e637704 100644 --- a/tests/componenttests/server/tests/mediaPipeline/PipelinePropertyTest.cpp +++ b/tests/componenttests/server/tests/mediaPipeline/PipelinePropertyTest.cpp @@ -39,6 +39,7 @@ constexpr bool kSyncOff{true}; constexpr int32_t kStreamSyncMode{1}; constexpr int32_t kBufferingLimit{4321}; constexpr bool kUseBuffering{true}; +constexpr bool kIsVideoMaster{true}; } // namespace namespace firebolt::rialto::server::ct @@ -312,6 +313,21 @@ class PipelinePropertyTest : public MediaPipelineTest .matchResponse([&](const auto &resp) { EXPECT_EQ(resp.use_buffering(), kUseBuffering); }); } + void willCheckIfVideoIsMaster() + { + EXPECT_CALL(*m_gstWrapperMock, gstRegistryGet()).WillOnce(Return(&m_registry)); + EXPECT_CALL(*m_gstWrapperMock, gstRegistryLookupFeature(&m_registry, StrEq("amlhalasink"))).WillOnce(Return(nullptr)); + } + + void checkIfVideoIsMaster() + { + auto req{createIsVideoMasterRequest(m_sessionId)}; + ConfigureAction(m_clientStub) + .send(req) + .expectSuccess() + .matchResponse([&](const auto &resp) { EXPECT_EQ(resp.is_video_master(), kIsVideoMaster); }); + } + void setImmediateOutputFailure() { auto req{createSetImmediateOutputRequest(m_sessionId, m_videoSourceId, true)}; @@ -402,6 +418,7 @@ class PipelinePropertyTest : public MediaPipelineTest GstIterator m_it{}; char m_dummy{0}; GstElementFactory *m_factory = reinterpret_cast(&m_dummy); + GstRegistry m_registry{}; }; /* @@ -487,18 +504,21 @@ class PipelinePropertyTest : public MediaPipelineTest * Step 15: Get Use Buffering * Will get the UseBuffering property of the decodebin on the Rialto Server * - * Step 16: Remove sources + * Step 16: Check if video is master + * Will check, if video is master for current device. + * + * Step 17: Remove sources * Remove the audio source. * Expect that audio source is removed. * Remove the video source. * Expect that video source is removed. * - * Step 17: Stop + * Step 18: Stop * Stop the playback. * Expect that stop propagated to the gstreamer pipeline. * Expect that server notifies the client that the Playback state has changed to STOPPED. * - * Step 18: Destroy media session + * Step 19: Destroy media session * Send DestroySessionRequest. * Expect that the session is destroyed on the server. * @@ -578,16 +598,20 @@ TEST_F(PipelinePropertyTest, pipelinePropertyGetAndSetSuccess) // Step 15: Get Use Buffering getUseBuffering(); - // Step 16: Remove sources + // Step 16: Check if video is master + willCheckIfVideoIsMaster(); + checkIfVideoIsMaster(); + + // Step 17: Remove sources willRemoveAudioSource(); removeSource(m_audioSourceId); removeSource(m_videoSourceId); - // Step 17: Stop + // Step 18: Stop willStop(); stop(); - // Step 18: Destroy media session + // Step 19: Destroy media session gstPlayerWillBeDestructed(); destroySession(); } diff --git a/tests/unittests/media/client/ipc/CMakeLists.txt b/tests/unittests/media/client/ipc/CMakeLists.txt index d00f5d6cf..c72082b1f 100644 --- a/tests/unittests/media/client/ipc/CMakeLists.txt +++ b/tests/unittests/media/client/ipc/CMakeLists.txt @@ -40,6 +40,7 @@ add_gtests ( mediaPipelineIpc/GetStatsTest.cpp mediaPipelineIpc/RenderFrameTest.cpp mediaPipelineIpc/GetVolumeTest.cpp + mediaPipelineIpc/IsVideoMasterTest.cpp mediaPipelineIpc/SetVolumeTest.cpp mediaPipelineIpc/GetMuteTest.cpp mediaPipelineIpc/SetMuteTest.cpp diff --git a/tests/unittests/media/client/ipc/mediaPipelineIpc/IsVideoMasterTest.cpp b/tests/unittests/media/client/ipc/mediaPipelineIpc/IsVideoMasterTest.cpp new file mode 100644 index 000000000..97689ecb5 --- /dev/null +++ b/tests/unittests/media/client/ipc/mediaPipelineIpc/IsVideoMasterTest.cpp @@ -0,0 +1,107 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MediaPipelineIpcTestBase.h" +#include "MediaPipelineProtoRequestMatchers.h" + +class RialtoClientMediaPipelineIpcIsVideoMasterTest : public MediaPipelineIpcTestBase +{ +protected: + virtual void SetUp() + { + MediaPipelineIpcTestBase::SetUp(); + + createMediaPipelineIpc(); + } + + virtual void TearDown() + { + destroyMediaPipelineIpc(); + + MediaPipelineIpcTestBase::TearDown(); + } +}; + +/** + * Test that isVideoMaster can be called successfully. + */ +TEST_F(RialtoClientMediaPipelineIpcIsVideoMasterTest, Success) +{ + constexpr bool kIsVideoMaster{true}; + expectIpcApiCallSuccess(); + + EXPECT_CALL(*m_channelMock, CallMethod(methodMatcher("isVideoMaster"), m_controllerMock.get(), + isVideoMasterRequestMatcher(m_sessionId), _, m_blockingClosureMock.get())) + .WillOnce(Invoke( + [&](const google::protobuf::MethodDescriptor *, google::protobuf::RpcController *, + const google::protobuf::Message *, google::protobuf::Message *response, google::protobuf::Closure *) + { + ::firebolt::rialto::IsVideoMasterResponse *resp = + dynamic_cast<::firebolt::rialto::IsVideoMasterResponse *>(response); + resp->set_is_video_master(kIsVideoMaster); + })); + + bool resultIsVideoMaster{false}; + EXPECT_TRUE(m_mediaPipelineIpc->isVideoMaster(resultIsVideoMaster)); + EXPECT_EQ(resultIsVideoMaster, kIsVideoMaster); +} + +/** + * Test that isVideoMaster fails if the ipc channel disconnected. + */ +TEST_F(RialtoClientMediaPipelineIpcIsVideoMasterTest, ChannelDisconnected) +{ + expectIpcApiCallDisconnected(); + expectUnsubscribeEvents(); + + bool isVideoMaster{false}; + EXPECT_FALSE(m_mediaPipelineIpc->isVideoMaster(isVideoMaster)); + + // Reattach channel on destroySession + EXPECT_CALL(*m_ipcClientMock, getChannel()).WillOnce(Return(m_channelMock)).RetiresOnSaturation(); + expectSubscribeEvents(); +} + +/** + * Test that isVideoMaster fails if the ipc channel disconnected and succeeds if the channel is reconnected. + */ +TEST_F(RialtoClientMediaPipelineIpcIsVideoMasterTest, ReconnectChannel) +{ + expectIpcApiCallReconnected(); + expectUnsubscribeEvents(); + expectSubscribeEvents(); + + EXPECT_CALL(*m_channelMock, CallMethod(methodMatcher("isVideoMaster"), _, _, _, _)); + + bool isVideoMaster{false}; + EXPECT_TRUE(m_mediaPipelineIpc->isVideoMaster(isVideoMaster)); +} + +/** + * Test that isVideoMaster fails when ipc fails. + */ +TEST_F(RialtoClientMediaPipelineIpcIsVideoMasterTest, IsVideoMasterFailure) +{ + expectIpcApiCallFailure(); + + EXPECT_CALL(*m_channelMock, CallMethod(methodMatcher("isVideoMaster"), _, _, _, _)); + + bool isVideoMaster{false}; + EXPECT_FALSE(m_mediaPipelineIpc->isVideoMaster(isVideoMaster)); +} diff --git a/tests/unittests/media/client/main/CMakeLists.txt b/tests/unittests/media/client/main/CMakeLists.txt index d0ae9c218..1eecfe7f6 100644 --- a/tests/unittests/media/client/main/CMakeLists.txt +++ b/tests/unittests/media/client/main/CMakeLists.txt @@ -38,6 +38,7 @@ add_gtests ( mediaPipeline/RenderFrameTest.cpp mediaPipeline/SetVolumeTest.cpp mediaPipeline/GetVolumeTest.cpp + mediaPipeline/IsVideoMasterTest.cpp mediaPipeline/SetMuteTest.cpp mediaPipeline/GetMuteTest.cpp mediaPipeline/SetLowLatencyTest.cpp diff --git a/tests/unittests/media/client/main/mediaPipeline/IsVideoMasterTest.cpp b/tests/unittests/media/client/main/mediaPipeline/IsVideoMasterTest.cpp new file mode 100644 index 000000000..a4c8ad595 --- /dev/null +++ b/tests/unittests/media/client/main/mediaPipeline/IsVideoMasterTest.cpp @@ -0,0 +1,64 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MediaPipelineTestBase.h" + +class RialtoClientMediaPipelineIsVideoMasterTest : public MediaPipelineTestBase +{ +protected: + bool m_isVideoMaster{}; + + virtual void SetUp() + { + MediaPipelineTestBase::SetUp(); + + createMediaPipeline(); + } + + virtual void TearDown() + { + destroyMediaPipeline(); + + MediaPipelineTestBase::TearDown(); + } +}; + +/** + * Test that isVideoMaster returns success if the IPC API succeeds. + */ +TEST_F(RialtoClientMediaPipelineIsVideoMasterTest, isVideoMasterSuccess) +{ + bool returnIsVideoMaster = !m_isVideoMaster; + + EXPECT_CALL(*m_mediaPipelineIpcMock, isVideoMaster(returnIsVideoMaster)) + .WillOnce(DoAll(SetArgReferee<0>(m_isVideoMaster), Return(true))); + + EXPECT_EQ(m_mediaPipeline->isVideoMaster(returnIsVideoMaster), true); + EXPECT_EQ(returnIsVideoMaster, m_isVideoMaster); +} + +/** + * Test that isVideoMaster returns failure if the IPC API fails. + */ +TEST_F(RialtoClientMediaPipelineIsVideoMasterTest, isVideoMasterFailure) +{ + EXPECT_CALL(*m_mediaPipelineIpcMock, isVideoMaster(m_isVideoMaster)).WillOnce(Return(false)); + + EXPECT_EQ(m_mediaPipeline->isVideoMaster(m_isVideoMaster), false); +} diff --git a/tests/unittests/media/client/mocks/ipc/MediaPipelineIpcMock.h b/tests/unittests/media/client/mocks/ipc/MediaPipelineIpcMock.h index b0aeaac29..76892a14a 100644 --- a/tests/unittests/media/client/mocks/ipc/MediaPipelineIpcMock.h +++ b/tests/unittests/media/client/mocks/ipc/MediaPipelineIpcMock.h @@ -73,6 +73,7 @@ class MediaPipelineIpcMock : public IMediaPipelineIpc MOCK_METHOD(bool, setUseBuffering, (bool useBuffering), (override)); MOCK_METHOD(bool, getUseBuffering, (bool &useBuffering), (override)); MOCK_METHOD(bool, switchSource, (const std::unique_ptr &source), (override)); + MOCK_METHOD(bool, isVideoMaster, (bool &isVideoMaster), (override)); }; } // namespace firebolt::rialto::client diff --git a/tests/unittests/media/client/mocks/main/MediaPipelineAndControlClientMock.h b/tests/unittests/media/client/mocks/main/MediaPipelineAndControlClientMock.h index a1e4954bc..b4c6ff1d7 100644 --- a/tests/unittests/media/client/mocks/main/MediaPipelineAndControlClientMock.h +++ b/tests/unittests/media/client/mocks/main/MediaPipelineAndControlClientMock.h @@ -88,6 +88,7 @@ class MediaPipelineAndControlClientMock : public IMediaPipelineAndIControlClient MOCK_METHOD(bool, setUseBuffering, (bool useBuffering), (override)); MOCK_METHOD(bool, getUseBuffering, (bool &useBuffering), (override)); MOCK_METHOD(bool, switchSource, (const std::unique_ptr &source), (override)); + MOCK_METHOD(bool, isVideoMaster, (bool &isVideoMaster), (override)); }; } // namespace firebolt::rialto::client diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerTest.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerTest.cpp index e3ae84101..1003fccb2 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerTest.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerTest.cpp @@ -1053,3 +1053,33 @@ TEST_F(GstGenericPlayerTest, shouldSwitchSource) m_sut->switchSource(source); } + +TEST_F(GstGenericPlayerTest, shouldFailToCheckIfVideoIsMasterWhenRegistryIsNull) +{ + EXPECT_CALL(*m_gstWrapperMock, gstRegistryGet()).WillOnce(Return(nullptr)); + bool isVideoMaster{false}; + EXPECT_FALSE(m_sut->isVideoMaster(isVideoMaster)); +} + +TEST_F(GstGenericPlayerTest, shouldCheckIfVideoIsMasterAndReturnTrue) +{ + GstRegistry registry{}; + EXPECT_CALL(*m_gstWrapperMock, gstRegistryGet()).WillOnce(Return(®istry)); + EXPECT_CALL(*m_gstWrapperMock, gstRegistryLookupFeature(®istry, StrEq("amlhalasink"))).WillOnce(Return(nullptr)); + bool isVideoMaster{false}; + EXPECT_TRUE(m_sut->isVideoMaster(isVideoMaster)); + EXPECT_TRUE(isVideoMaster); +} + +TEST_F(GstGenericPlayerTest, shouldCheckIfVideoIsMasterAndReturnFalse) +{ + GstRegistry registry{}; + GstObject feature{}; + EXPECT_CALL(*m_gstWrapperMock, gstRegistryGet()).WillOnce(Return(®istry)); + EXPECT_CALL(*m_gstWrapperMock, gstRegistryLookupFeature(®istry, StrEq("amlhalasink"))) + .WillOnce(Return(GST_PLUGIN_FEATURE(&feature))); + EXPECT_CALL(*m_gstWrapperMock, gstObjectUnref(GST_PLUGIN_FEATURE(&feature))); + bool isVideoMaster{false}; + EXPECT_TRUE(m_sut->isVideoMaster(isVideoMaster)); + EXPECT_FALSE(isVideoMaster); +} diff --git a/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTests.cpp b/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTests.cpp index 014888d24..8c40201cf 100644 --- a/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTests.cpp +++ b/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTests.cpp @@ -596,3 +596,15 @@ TEST_F(MediaPipelineModuleServiceTests, shouldFailToGetUseBuffering) mediaPipelineServiceWillFailToGetUseBuffering(); sendGetUseBufferingRequestAndReceiveResponseWithoutMatch(); } + +TEST_F(MediaPipelineModuleServiceTests, shouldCheckIfVideoIsMaster) +{ + mediaPipelineServiceWillCheckIfVideoIsMaster(); + sendIsVideoMasterRequestAndReceiveResponse(); +} + +TEST_F(MediaPipelineModuleServiceTests, shouldFailToCheckIfVideoIsMaster) +{ + mediaPipelineServiceWillFailToCheckIfVideoIsMaster(); + sendIsVideoMasterRequestAndReceiveResponseWithoutMatch(); +} diff --git a/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTestsFixture.cpp b/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTestsFixture.cpp index ee28f9233..08448c080 100644 --- a/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTestsFixture.cpp +++ b/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTestsFixture.cpp @@ -91,6 +91,7 @@ constexpr uint32_t kBufferingLimit{12341}; constexpr bool kUseBuffering{true}; constexpr uint64_t kStopPosition{2423}; constexpr bool kFramed{true}; +constexpr bool kIsVideoMaster{true}; } // namespace MATCHER_P(AttachedSourceMatcher, source, "") @@ -808,6 +809,19 @@ void MediaPipelineModuleServiceTests::mediaPipelineServiceWillFailToGetUseBuffer EXPECT_CALL(m_mediaPipelineServiceMock, getUseBuffering(kHardcodedSessionId, _)).WillOnce(Return(false)); } +void MediaPipelineModuleServiceTests::mediaPipelineServiceWillCheckIfVideoIsMaster() +{ + expectRequestSuccess(); + EXPECT_CALL(m_mediaPipelineServiceMock, isVideoMaster(kHardcodedSessionId, _)) + .WillOnce(DoAll(SetArgReferee<1>(kIsVideoMaster), Return(true))); +} + +void MediaPipelineModuleServiceTests::mediaPipelineServiceWillFailToCheckIfVideoIsMaster() +{ + expectRequestFailure(); + EXPECT_CALL(m_mediaPipelineServiceMock, isVideoMaster(kHardcodedSessionId, _)).WillOnce(Return(false)); +} + void MediaPipelineModuleServiceTests::mediaClientWillSendPlaybackStateChangedEvent() { EXPECT_CALL(*m_clientMock, sendEvent(PlaybackStateChangeEventMatcher(convertPlaybackState(kPlaybackState)))); @@ -1494,6 +1508,28 @@ void MediaPipelineModuleServiceTests::sendGetUseBufferingRequestAndReceiveRespon m_service->getUseBuffering(m_controllerMock.get(), &request, &response, m_closureMock.get()); } +void MediaPipelineModuleServiceTests::sendIsVideoMasterRequestAndReceiveResponse() +{ + firebolt::rialto::IsVideoMasterRequest request; + firebolt::rialto::IsVideoMasterResponse response; + + request.set_session_id(kHardcodedSessionId); + + m_service->isVideoMaster(m_controllerMock.get(), &request, &response, m_closureMock.get()); + + EXPECT_EQ(kIsVideoMaster, response.is_video_master()); +} + +void MediaPipelineModuleServiceTests::sendIsVideoMasterRequestAndReceiveResponseWithoutMatch() +{ + firebolt::rialto::IsVideoMasterRequest request; + firebolt::rialto::IsVideoMasterResponse response; + + request.set_session_id(kHardcodedSessionId); + + m_service->isVideoMaster(m_controllerMock.get(), &request, &response, m_closureMock.get()); +} + void MediaPipelineModuleServiceTests::sendPlaybackStateChangedEvent() { ASSERT_TRUE(m_mediaPipelineClient); diff --git a/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTestsFixture.h b/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTestsFixture.h index a3ce21e04..e77007627 100644 --- a/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTestsFixture.h +++ b/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTestsFixture.h @@ -120,6 +120,8 @@ class MediaPipelineModuleServiceTests : public testing::Test void mediaPipelineServiceWillFailToSetUseBuffering(); void mediaPipelineServiceWillGetUseBuffering(); void mediaPipelineServiceWillFailToGetUseBuffering(); + void mediaPipelineServiceWillCheckIfVideoIsMaster(); + void mediaPipelineServiceWillFailToCheckIfVideoIsMaster(); void mediaClientWillSendPlaybackStateChangedEvent(); void mediaClientWillSendNetworkStateChangedEvent(); @@ -184,6 +186,8 @@ class MediaPipelineModuleServiceTests : public testing::Test void sendSetUseBufferingRequestAndReceiveResponse(); void sendGetUseBufferingRequestAndReceiveResponse(); void sendGetUseBufferingRequestAndReceiveResponseWithoutMatch(); + void sendIsVideoMasterRequestAndReceiveResponse(); + void sendIsVideoMasterRequestAndReceiveResponseWithoutMatch(); void sendPlaybackStateChangedEvent(); void sendNetworkStateChangedEvent(); diff --git a/tests/unittests/media/server/main/mediaPipeline/MiscellaneousFunctionsTest.cpp b/tests/unittests/media/server/main/mediaPipeline/MiscellaneousFunctionsTest.cpp index b932f0887..7100bbffe 100644 --- a/tests/unittests/media/server/main/mediaPipeline/MiscellaneousFunctionsTest.cpp +++ b/tests/unittests/media/server/main/mediaPipeline/MiscellaneousFunctionsTest.cpp @@ -940,6 +940,43 @@ TEST_F(RialtoServerMediaPipelineMiscellaneousFunctionsTest, GetUseBufferingSucce EXPECT_EQ(resultUseBuffering, kUseBuffering); } +/** + * Test that IsVideoMaster returns failure if the gstreamer player is not initialized + */ +TEST_F(RialtoServerMediaPipelineMiscellaneousFunctionsTest, IsVideoMasterFailureDueToUninitializedPlayer) +{ + mainThreadWillEnqueueTaskAndWait(); + bool resultIsVideoMaster{}; + EXPECT_FALSE(m_mediaPipeline->isVideoMaster(resultIsVideoMaster)); +} + +/** + * Test that IsVideoMaster returns failure if the gstreamer API fails + */ +TEST_F(RialtoServerMediaPipelineMiscellaneousFunctionsTest, IsVideoMasterFailure) +{ + loadGstPlayer(); + mainThreadWillEnqueueTaskAndWait(); + bool resultIsVideoMaster{}; + EXPECT_CALL(*m_gstPlayerMock, isVideoMaster(_)).WillOnce(Return(false)); + EXPECT_FALSE(m_mediaPipeline->isVideoMaster(resultIsVideoMaster)); +} + +/** + * Test that IsVideoMaster returns success if the gstreamer API succeeds + */ +TEST_F(RialtoServerMediaPipelineMiscellaneousFunctionsTest, IsVideoMasterSuccess) +{ + constexpr bool kIsVideoMaster{true}; + bool resultIsVideoMaster{}; + loadGstPlayer(); + mainThreadWillEnqueueTaskAndWait(); + EXPECT_CALL(*m_gstPlayerMock, isVideoMaster(_)).WillOnce(DoAll(SetArgReferee<0>(kIsVideoMaster), Return(true))); + + EXPECT_TRUE(m_mediaPipeline->isVideoMaster(resultIsVideoMaster)); + EXPECT_EQ(resultIsVideoMaster, kIsVideoMaster); +} + /** * Test that active requests are invalidated successfully */ diff --git a/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerMock.h b/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerMock.h index 224147f1d..e998224ab 100644 --- a/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerMock.h +++ b/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerMock.h @@ -77,6 +77,7 @@ class GstGenericPlayerMock : public IGstGenericPlayer MOCK_METHOD(void, setUseBuffering, (bool useBuffering), (override)); MOCK_METHOD(bool, getUseBuffering, (bool &useBuffering), (override)); MOCK_METHOD(void, switchSource, (const std::unique_ptr &mediaSource), (override)); + MOCK_METHOD(bool, isVideoMaster, (bool &isVideoMaster), (override)); }; } // namespace firebolt::rialto::server diff --git a/tests/unittests/media/server/mocks/main/MediaPipelineServerInternalMock.h b/tests/unittests/media/server/mocks/main/MediaPipelineServerInternalMock.h index a25c29d8f..fbce6065d 100644 --- a/tests/unittests/media/server/mocks/main/MediaPipelineServerInternalMock.h +++ b/tests/unittests/media/server/mocks/main/MediaPipelineServerInternalMock.h @@ -75,6 +75,7 @@ class MediaPipelineServerInternalMock : public IMediaPipelineServerInternal MOCK_METHOD(bool, setUseBuffering, (bool useBuffering), (override)); MOCK_METHOD(bool, getUseBuffering, (bool &useBuffering), (override)); MOCK_METHOD(bool, switchSource, (const std::unique_ptr &source), (override)); + MOCK_METHOD(bool, isVideoMaster, (bool &isVideoMaster), (override)); }; } // namespace firebolt::rialto::server diff --git a/tests/unittests/media/server/mocks/service/MediaPipelineServiceMock.h b/tests/unittests/media/server/mocks/service/MediaPipelineServiceMock.h index 136d89f66..0aa3796a2 100644 --- a/tests/unittests/media/server/mocks/service/MediaPipelineServiceMock.h +++ b/tests/unittests/media/server/mocks/service/MediaPipelineServiceMock.h @@ -78,6 +78,7 @@ class MediaPipelineServiceMock : public IMediaPipelineService MOCK_METHOD(bool, setUseBuffering, (int sessionId, bool useBuffering), (override)); MOCK_METHOD(bool, getUseBuffering, (int sessionId, bool &useBuffering), (override)); MOCK_METHOD(bool, switchSource, (int, const std::unique_ptr &), (override)); + MOCK_METHOD(bool, isVideoMaster, (int sessionId, bool &isVideoMaster), (override)); MOCK_METHOD(std::vector, getSupportedMimeTypes, (MediaSourceType type), (override)); MOCK_METHOD(bool, isMimeTypeSupported, (const std::string &mimeType), (override)); MOCK_METHOD(std::vector, getSupportedProperties, diff --git a/tests/unittests/media/server/service/mediaPipelineService/MediaPipelineServiceTests.cpp b/tests/unittests/media/server/service/mediaPipelineService/MediaPipelineServiceTests.cpp index 32f0c0b2e..4cd1f95d1 100644 --- a/tests/unittests/media/server/service/mediaPipelineService/MediaPipelineServiceTests.cpp +++ b/tests/unittests/media/server/service/mediaPipelineService/MediaPipelineServiceTests.cpp @@ -819,6 +819,20 @@ TEST_F(MediaPipelineServiceTests, shouldSwitchSource) switchSourceShouldSucceed(); } +TEST_F(MediaPipelineServiceTests, shouldFailToCheckIfVideoIsMaster) +{ + initSession(); + mediaPipelineWillFailToCheckIfVideoIsMaster(); + isVideoMasterShouldFail(); +} + +TEST_F(MediaPipelineServiceTests, shouldCheckIfVideoIsMaster) +{ + initSession(); + mediaPipelineWillCheckIfVideoIsMaster(); + isVideoMasterShouldSucceed(); +} + TEST_F(MediaPipelineServiceTests, shouldPing) { initSession(); diff --git a/tests/unittests/media/server/service/mediaPipelineService/MediaPipelineServiceTestsFixture.cpp b/tests/unittests/media/server/service/mediaPipelineService/MediaPipelineServiceTestsFixture.cpp index dedf20042..b64a961d0 100644 --- a/tests/unittests/media/server/service/mediaPipelineService/MediaPipelineServiceTestsFixture.cpp +++ b/tests/unittests/media/server/service/mediaPipelineService/MediaPipelineServiceTestsFixture.cpp @@ -486,6 +486,16 @@ void MediaPipelineServiceTests::mediaPipelineWillFailToSwitchSource() EXPECT_CALL(m_mediaPipelineMock, switchSource(_)).WillOnce(Return(false)); } +void MediaPipelineServiceTests::mediaPipelineWillCheckIfVideoIsMaster() +{ + EXPECT_CALL(m_mediaPipelineMock, isVideoMaster(_)).WillOnce(Return(true)); +} + +void MediaPipelineServiceTests::mediaPipelineWillFailToCheckIfVideoIsMaster() +{ + EXPECT_CALL(m_mediaPipelineMock, isVideoMaster(_)).WillOnce(Return(false)); +} + void MediaPipelineServiceTests::mediaPipelineWillPing() { EXPECT_CALL(*m_heartbeatProcedureMock, createHandler()) @@ -995,6 +1005,18 @@ void MediaPipelineServiceTests::switchSourceShouldFail() EXPECT_FALSE(m_sut->switchSource(kSessionId, mediaSource)); } +void MediaPipelineServiceTests::isVideoMasterShouldSucceed() +{ + bool isMaster{false}; + EXPECT_TRUE(m_sut->isVideoMaster(kSessionId, isMaster)); +} + +void MediaPipelineServiceTests::isVideoMasterShouldFail() +{ + bool isMaster{false}; + EXPECT_FALSE(m_sut->isVideoMaster(kSessionId, isMaster)); +} + void MediaPipelineServiceTests::clearMediaPipelines() { m_sut->clearMediaPipelines(); diff --git a/tests/unittests/media/server/service/mediaPipelineService/MediaPipelineServiceTestsFixture.h b/tests/unittests/media/server/service/mediaPipelineService/MediaPipelineServiceTestsFixture.h index e766bbd69..ead87a642 100644 --- a/tests/unittests/media/server/service/mediaPipelineService/MediaPipelineServiceTestsFixture.h +++ b/tests/unittests/media/server/service/mediaPipelineService/MediaPipelineServiceTestsFixture.h @@ -112,6 +112,8 @@ class MediaPipelineServiceTests : public testing::Test void mediaPipelineWillFailToGetUseBuffering(); void mediaPipelineWillSwitchSource(); void mediaPipelineWillFailToSwitchSource(); + void mediaPipelineWillCheckIfVideoIsMaster(); + void mediaPipelineWillFailToCheckIfVideoIsMaster(); void mediaPipelineWillPing(); @@ -205,6 +207,8 @@ class MediaPipelineServiceTests : public testing::Test void getUseBufferingShouldFail(); void switchSourceShouldSucceed(); void switchSourceShouldFail(); + void isVideoMasterShouldSucceed(); + void isVideoMasterShouldFail(); void clearMediaPipelines(); void initSession(); From d25f686f1e0ad3dec36d8d0770fb0e83b786fc3a Mon Sep 17 00:00:00 2001 From: Marcin Wojciechowski <105790697+skywojciechowskim@users.noreply.github.com> Date: Thu, 31 Jul 2025 12:23:10 +0200 Subject: [PATCH 13/15] Downcasting of the offset for TextTrack removed (#398) Summary: Downcasting of the offset for TextTrack removed Type: Fix Test Plan: UT/ CT, Fullstack Jira: VPLAY-10419 --- .github/workflows/client_component_test.yml | 2 +- media/server/gstplayer/source/GstTextTrackSink.cpp | 4 ++-- media/server/main/include/ITextTrackAccessor.h | 2 +- media/server/main/include/TextTrackAccessor.h | 2 +- media/server/main/include/TextTrackSession.h | 2 +- media/server/main/interface/ITextTrackSession.h | 2 +- media/server/main/source/TextTrackAccessor.cpp | 5 ++--- media/server/main/source/TextTrackSession.cpp | 2 +- tests/common/externalLibraryMocks/TextTrackWrapperMock.h | 2 +- .../media/server/mocks/main/TextTrackAccessorMock.h | 2 +- wrappers/include/TextTrackWrapper.h | 2 +- wrappers/interface/ITextTrackWrapper.h | 2 +- wrappers/source/TextTrackWrapper.cpp | 2 +- 13 files changed, 15 insertions(+), 16 deletions(-) diff --git a/.github/workflows/client_component_test.yml b/.github/workflows/client_component_test.yml index bc46552e8..9879d7d7c 100644 --- a/.github/workflows/client_component_test.yml +++ b/.github/workflows/client_component_test.yml @@ -137,4 +137,4 @@ jobs: # Run the check_coverage_stats script - name: Process Coverage Statistics if: ${{ success() && github.event_name == 'pull_request' && github.base_ref == 'master' }} - run: python scripts/coverage/check_coverage_stats.py build/coverage_statistics_public_apis.txt 98 + run: python scripts/coverage/check_coverage_stats.py build/coverage_statistics_public_apis.txt 97 diff --git a/media/server/gstplayer/source/GstTextTrackSink.cpp b/media/server/gstplayer/source/GstTextTrackSink.cpp index d85d6d61a..7e4d8db7e 100644 --- a/media/server/gstplayer/source/GstTextTrackSink.cpp +++ b/media/server/gstplayer/source/GstTextTrackSink.cpp @@ -188,10 +188,10 @@ static GstFlowReturn gst_rialto_text_track_sink_render(GstBaseSink *sink, GstBuf if (gst_buffer_map(buffer, &info, GST_MAP_READ)) { std::string data(reinterpret_cast(info.data), info.size); - int32_t displayOffset{0}; + int64_t displayOffset{0}; if (GST_BUFFER_OFFSET_NONE != GST_BUFFER_OFFSET(buffer)) { - displayOffset = static_cast(GST_BUFFER_OFFSET(buffer)); + displayOffset = static_cast(GST_BUFFER_OFFSET(buffer)); } textTrackSink->priv->m_textTrackSession->sendData(data, 0 - displayOffset); diff --git a/media/server/main/include/ITextTrackAccessor.h b/media/server/main/include/ITextTrackAccessor.h index 57d55557a..d167b13cb 100644 --- a/media/server/main/include/ITextTrackAccessor.h +++ b/media/server/main/include/ITextTrackAccessor.h @@ -58,7 +58,7 @@ class ITextTrackAccessor virtual bool play(uint32_t sessionId) = 0; virtual bool mute(uint32_t sessionId, bool mute) = 0; virtual bool setPosition(uint32_t sessionId, uint64_t mediaTimestampMs) = 0; - virtual bool sendData(uint32_t sessionId, const std::string &data, DataType datatype, int32_t displayOffsetMs = 0) = 0; + virtual bool sendData(uint32_t sessionId, const std::string &data, DataType datatype, int64_t displayOffsetMs = 0) = 0; virtual bool setSessionWebVTTSelection(uint32_t sessionId) = 0; virtual bool setSessionTTMLSelection(uint32_t sessionId) = 0; virtual bool setSessionCCSelection(uint32_t sessionId, const std::string &service) = 0; diff --git a/media/server/main/include/TextTrackAccessor.h b/media/server/main/include/TextTrackAccessor.h index 14c788121..af2c4d533 100644 --- a/media/server/main/include/TextTrackAccessor.h +++ b/media/server/main/include/TextTrackAccessor.h @@ -51,7 +51,7 @@ class TextTrackAccessor : public ITextTrackAccessor bool play(uint32_t sessionId) override; bool mute(uint32_t sessionId, bool mute) override; bool setPosition(uint32_t sessionId, uint64_t mediaTimestampMs) override; - bool sendData(uint32_t sessionId, const std::string &data, DataType datatype, int32_t displayOffsetMs) override; + bool sendData(uint32_t sessionId, const std::string &data, DataType datatype, int64_t displayOffsetMs) override; bool setSessionWebVTTSelection(uint32_t sessionId) override; bool setSessionTTMLSelection(uint32_t sessionId) override; bool setSessionCCSelection(uint32_t sessionId, const std::string &service) override; diff --git a/media/server/main/include/TextTrackSession.h b/media/server/main/include/TextTrackSession.h index ce566d11b..6a344e289 100644 --- a/media/server/main/include/TextTrackSession.h +++ b/media/server/main/include/TextTrackSession.h @@ -44,7 +44,7 @@ class TextTrackSession : public ITextTrackSession bool play() override; bool mute(bool mute) override; bool setPosition(uint64_t mediaTimestampMs) override; - bool sendData(const std::string &data, int32_t displayOffsetMs = 0) override; + bool sendData(const std::string &data, int64_t displayOffsetMs = 0) override; bool setSessionWebVTTSelection() override; bool setSessionTTMLSelection() override; bool setSessionCCSelection(const std::string &service) override; diff --git a/media/server/main/interface/ITextTrackSession.h b/media/server/main/interface/ITextTrackSession.h index d198f156f..d5e86b2dc 100644 --- a/media/server/main/interface/ITextTrackSession.h +++ b/media/server/main/interface/ITextTrackSession.h @@ -46,7 +46,7 @@ class ITextTrackSession virtual bool play() = 0; virtual bool mute(bool mute) = 0; virtual bool setPosition(uint64_t mediaTimestampMs) = 0; - virtual bool sendData(const std::string &data, int32_t displayOffsetMs = 0) = 0; + virtual bool sendData(const std::string &data, int64_t displayOffsetMs = 0) = 0; virtual bool setSessionWebVTTSelection() = 0; virtual bool setSessionTTMLSelection() = 0; virtual bool setSessionCCSelection(const std::string &service) = 0; diff --git a/media/server/main/source/TextTrackAccessor.cpp b/media/server/main/source/TextTrackAccessor.cpp index 177173dd0..824735286 100644 --- a/media/server/main/source/TextTrackAccessor.cpp +++ b/media/server/main/source/TextTrackAccessor.cpp @@ -162,7 +162,7 @@ bool TextTrackAccessor::setPosition(uint32_t sessionId, uint64_t mediaTimestampM return false; } -bool TextTrackAccessor::sendData(uint32_t sessionId, const std::string &data, DataType datatype, int32_t displayOffsetMs) +bool TextTrackAccessor::sendData(uint32_t sessionId, const std::string &data, DataType datatype, int64_t displayOffsetMs) { firebolt::rialto::wrappers::ITextTrackWrapper::DataType wrapperDataType{}; if (datatype == DataType::WebVTT) @@ -182,8 +182,7 @@ bool TextTrackAccessor::sendData(uint32_t sessionId, const std::string &data, Da const uint32_t result = m_textTrackWrapper->sendSessionData(sessionId, wrapperDataType, displayOffsetMs, data); if (m_thunderWrapper->isSuccessful(result)) { - RIALTO_SERVER_LOG_DEBUG("Sending data to TextTrack session %u was successful; offset %d, size %zu", sessionId, - displayOffsetMs, data.size()); + RIALTO_SERVER_LOG_DEBUG("Sending data to TextTrack session %u was successful; size %zu", sessionId, data.size()); return true; } diff --git a/media/server/main/source/TextTrackSession.cpp b/media/server/main/source/TextTrackSession.cpp index c5c969ead..3a68491b7 100644 --- a/media/server/main/source/TextTrackSession.cpp +++ b/media/server/main/source/TextTrackSession.cpp @@ -121,7 +121,7 @@ bool TextTrackSession::setPosition(uint64_t mediaTimestampMs) return m_textTrackAccessor->setPosition(m_sessionId, mediaTimestampMs); } -bool TextTrackSession::sendData(const std::string &data, int32_t displayOffsetMs) +bool TextTrackSession::sendData(const std::string &data, int64_t displayOffsetMs) { return m_textTrackAccessor->sendData(m_sessionId, data, m_dataType, displayOffsetMs); } diff --git a/tests/common/externalLibraryMocks/TextTrackWrapperMock.h b/tests/common/externalLibraryMocks/TextTrackWrapperMock.h index f43d16592..101caeb84 100644 --- a/tests/common/externalLibraryMocks/TextTrackWrapperMock.h +++ b/tests/common/externalLibraryMocks/TextTrackWrapperMock.h @@ -41,7 +41,7 @@ class TextTrackWrapperMock : public ITextTrackWrapper MOCK_METHOD(std::uint32_t, sendSessionTimestamp, (std::uint32_t sessionId, std::uint64_t mediaTimestampMs), (const, override)); MOCK_METHOD(std::uint32_t, sendSessionData, - (std::uint32_t sessionId, ITextTrackWrapper::DataType type, std::int32_t displayOffsetMs, + (std::uint32_t sessionId, ITextTrackWrapper::DataType type, std::int64_t displayOffsetMs, const std::string &data), (const, override)); MOCK_METHOD(std::uint32_t, setSessionWebVTTSelection, (std::uint32_t sessionId), (const, override)); diff --git a/tests/unittests/media/server/mocks/main/TextTrackAccessorMock.h b/tests/unittests/media/server/mocks/main/TextTrackAccessorMock.h index 9f80bd05f..8b1688f31 100644 --- a/tests/unittests/media/server/mocks/main/TextTrackAccessorMock.h +++ b/tests/unittests/media/server/mocks/main/TextTrackAccessorMock.h @@ -37,7 +37,7 @@ class TextTrackAccessorMock : public ITextTrackAccessor MOCK_METHOD(bool, mute, (uint32_t sessionId, bool mute), (override)); MOCK_METHOD(bool, setPosition, (uint32_t sessionId, uint64_t mediaTimestampMs), (override)); MOCK_METHOD(bool, sendData, - (uint32_t sessionId, const std::string &data, DataType datatype, int32_t displayOffsetMs), (override)); + (uint32_t sessionId, const std::string &data, DataType datatype, int64_t displayOffsetMs), (override)); MOCK_METHOD(bool, setSessionWebVTTSelection, (uint32_t sessionId), (override)); MOCK_METHOD(bool, setSessionTTMLSelection, (uint32_t sessionId), (override)); MOCK_METHOD(bool, setSessionCCSelection, (uint32_t sessionId, const std::string &service), (override)); diff --git a/wrappers/include/TextTrackWrapper.h b/wrappers/include/TextTrackWrapper.h index 392a48120..bc2d5e297 100644 --- a/wrappers/include/TextTrackWrapper.h +++ b/wrappers/include/TextTrackWrapper.h @@ -43,7 +43,7 @@ class TextTrackWrapper : public ITextTrackWrapper std::uint32_t resetSession(std::uint32_t sessionId) const override; std::uint32_t sendSessionTimestamp(std::uint32_t sessionId, std::uint64_t mediaTimestampMs) const override; std::uint32_t sendSessionData(std::uint32_t sessionId, ITextTrackWrapper::DataType type, - std::int32_t displayOffsetMs, const std::string &data) const override; + std::int64_t displayOffsetMs, const std::string &data) const override; std::uint32_t setSessionWebVTTSelection(std::uint32_t sessionId) const override; std::uint32_t setSessionTTMLSelection(std::uint32_t sessionId) const override; std::uint32_t setSessionClosedCaptionsService(std::uint32_t sessionId, const std::string &service) const override; diff --git a/wrappers/interface/ITextTrackWrapper.h b/wrappers/interface/ITextTrackWrapper.h index 699fca875..3699e7d67 100644 --- a/wrappers/interface/ITextTrackWrapper.h +++ b/wrappers/interface/ITextTrackWrapper.h @@ -129,7 +129,7 @@ class ITextTrackWrapper * * @retval the error code */ - virtual std::uint32_t sendSessionData(std::uint32_t sessionId, DataType type, std::int32_t displayOffsetMs, + virtual std::uint32_t sendSessionData(std::uint32_t sessionId, DataType type, std::int64_t displayOffsetMs, const std::string &data) const = 0; /** diff --git a/wrappers/source/TextTrackWrapper.cpp b/wrappers/source/TextTrackWrapper.cpp index 295cc3f57..174f66922 100644 --- a/wrappers/source/TextTrackWrapper.cpp +++ b/wrappers/source/TextTrackWrapper.cpp @@ -91,7 +91,7 @@ std::uint32_t TextTrackWrapper::sendSessionTimestamp(std::uint32_t sessionId, st } std::uint32_t TextTrackWrapper::sendSessionData(std::uint32_t sessionId, ITextTrackWrapper::DataType type, - std::int32_t displayOffsetMs, const std::string &data) const + std::int64_t displayOffsetMs, const std::string &data) const { return m_textTrackControlInterface->SendSessionData(sessionId, convertDataType(type), displayOffsetMs, data); } From 1e498d3b17e9455ee180b7287fa43b2f6e980611 Mon Sep 17 00:00:00 2001 From: Marcin Wojciechowski <105790697+skywojciechowskim@users.noreply.github.com> Date: Mon, 4 Aug 2025 14:15:51 +0200 Subject: [PATCH 14/15] IsVideoMaster function moved to IMediaPipelineCapabilities interface (#399) Summary: IsVideoMaster function moved to IMediaPipelineCapabilities interface Type: Fix Test Plan: UT/ CT, Fullstack Jira: VPLAY-8941 --- .../include/MediaPipelineCapabilitiesIpc.h | 9 ++ media/client/ipc/include/MediaPipelineIpc.h | 2 - .../client/ipc/interface/IMediaPipelineIpc.h | 9 -- .../source/MediaPipelineCapabilitiesIpc.cpp | 28 +++++ media/client/ipc/source/MediaPipelineIpc.cpp | 32 ------ media/client/main/include/MediaPipeline.h | 2 - .../main/include/MediaPipelineCapabilities.h | 9 ++ .../client/main/include/MediaPipelineProxy.h | 2 - media/client/main/source/MediaPipeline.cpp | 7 -- .../main/source/MediaPipelineCapabilities.cpp | 6 + media/public/include/IMediaPipeline.h | 9 -- .../include/IMediaPipelineCapabilities.h | 9 ++ .../gstplayer/include/GstCapabilities.h | 9 ++ .../gstplayer/include/GstGenericPlayer.h | 1 - .../gstplayer/interface/IGstCapabilities.h | 9 ++ .../gstplayer/interface/IGstGenericPlayer.h | 9 -- .../gstplayer/source/GstCapabilities.cpp | 20 ++++ .../gstplayer/source/GstGenericPlayer.cpp | 18 --- .../MediaPipelineCapabilitiesModuleService.h | 3 + .../ipc/include/MediaPipelineModuleService.h | 3 - ...MediaPipelineCapabilitiesModuleService.cpp | 28 +++++ .../ipc/source/MediaPipelineModuleService.cpp | 21 ---- .../main/include/MediaPipelineCapabilities.h | 1 + .../include/MediaPipelineServerInternal.h | 11 -- .../main/source/MediaPipelineCapabilities.cpp | 5 + .../source/MediaPipelineServerInternal.cpp | 19 ---- .../service/include/IMediaPipelineService.h | 2 +- .../service/source/MediaPipelineService.cpp | 13 +-- .../service/source/MediaPipelineService.h | 2 +- proto/mediapipelinecapabilitiesmodule.proto | 22 ++++ proto/mediapipelinemodule.proto | 23 ---- .../MediaPipelineProtoRequestMatchers.h | 7 -- .../MediaPipelineCapabilitiesModuleMock.h | 5 + .../tests/base/MediaPipelineTestMethods.cpp | 12 +- .../tests/base/MediaPipelineTestMethods.h | 4 +- .../client/tests/mse/IsVideoMasterTest.cpp | 12 +- .../server/common/ActionTraits.h | 16 +-- .../server/common/MessageBuilders.cpp | 13 +-- .../server/common/MessageBuilders.h | 2 +- .../mediaPipeline/PipelinePropertyTest.cpp | 33 +----- .../MediaPipelineCapabilitiesTest.cpp | 48 ++++++++ .../unittests/media/client/ipc/CMakeLists.txt | 1 - .../MediaPipelineCapabilitiesIpcTest.cpp | 57 ++++++++++ .../mediaPipelineIpc/IsVideoMasterTest.cpp | 107 ------------------ .../media/client/main/CMakeLists.txt | 1 - .../main/mediaPipeline/IsVideoMasterTest.cpp | 64 ----------- .../MediaPipelineCapabilitiesTest.cpp | 9 ++ .../ipc/MediaPipelineCapabilitiesIpcMock.h | 1 + .../client/mocks/ipc/MediaPipelineIpcMock.h | 1 - .../main/MediaPipelineAndControlClientMock.h | 1 - .../genericPlayer/GstCapabilitiesTest.cpp | 36 ++++++ .../genericPlayer/GstGenericPlayerTest.cpp | 30 ----- ...PipelineCapabilitiesModuleServiceTests.cpp | 12 ++ ...eCapabilitiesModuleServiceTestsFixture.cpp | 25 ++++ ...ineCapabilitiesModuleServiceTestsFixture.h | 3 + .../MediaPipelineModuleServiceTests.cpp | 12 -- ...MediaPipelineModuleServiceTestsFixture.cpp | 35 ------ .../MediaPipelineModuleServiceTestsFixture.h | 4 - .../MiscellaneousFunctionsTest.cpp | 37 ------ .../MediaPipelineCapabilitiesTest.cpp | 10 ++ .../mocks/gstplayer/GstCapabilitiesMock.h | 1 + .../mocks/gstplayer/GstGenericPlayerMock.h | 1 - .../main/MediaPipelineCapabilitiesMock.h | 1 + .../main/MediaPipelineServerInternalMock.h | 1 - .../mocks/service/MediaPipelineServiceMock.h | 2 +- .../MediaPipelineServiceTestsFixture.cpp | 8 +- 66 files changed, 414 insertions(+), 541 deletions(-) delete mode 100644 tests/unittests/media/client/ipc/mediaPipelineIpc/IsVideoMasterTest.cpp delete mode 100644 tests/unittests/media/client/main/mediaPipeline/IsVideoMasterTest.cpp diff --git a/media/client/ipc/include/MediaPipelineCapabilitiesIpc.h b/media/client/ipc/include/MediaPipelineCapabilitiesIpc.h index 09fedad9f..19b63ee2d 100644 --- a/media/client/ipc/include/MediaPipelineCapabilitiesIpc.h +++ b/media/client/ipc/include/MediaPipelineCapabilitiesIpc.h @@ -92,6 +92,15 @@ class MediaPipelineCapabilitiesIpc : public IMediaPipelineCapabilities, public I std::vector getSupportedProperties(MediaSourceType mediaType, const std::vector &propertyNames) override; + /** + * @brief Checks if the platform is video master. + * + * @param[out] isVideoMaster : The output value. True if video is master otherwise false. + * + * @retval true on success false otherwise + */ + bool isVideoMaster(bool &isVideoMaster) override; + private: /** * @brief The ipc protobuf media Pipeline capabilities stub. diff --git a/media/client/ipc/include/MediaPipelineIpc.h b/media/client/ipc/include/MediaPipelineIpc.h index 9ec1a5135..9666027fe 100644 --- a/media/client/ipc/include/MediaPipelineIpc.h +++ b/media/client/ipc/include/MediaPipelineIpc.h @@ -142,8 +142,6 @@ class MediaPipelineIpc : public IMediaPipelineIpc, public IpcModule bool switchSource(const std::unique_ptr &source) override; - bool isVideoMaster(bool &isVideoMaster) override; - private: /** * @brief The media player client ipc. diff --git a/media/client/ipc/interface/IMediaPipelineIpc.h b/media/client/ipc/interface/IMediaPipelineIpc.h index 1faa37895..5ade91266 100644 --- a/media/client/ipc/interface/IMediaPipelineIpc.h +++ b/media/client/ipc/interface/IMediaPipelineIpc.h @@ -439,15 +439,6 @@ class IMediaPipelineIpc * @retval true on success. */ virtual bool switchSource(const std::unique_ptr &source) = 0; - - /** - * @brief Checks if the platform is video master. - * - * @param[out] isVideoMaster : The output value. True if video is master otherwise false. - * - * @retval true on success false otherwise - */ - virtual bool isVideoMaster(bool &isVideoMaster) = 0; }; }; // namespace firebolt::rialto::client diff --git a/media/client/ipc/source/MediaPipelineCapabilitiesIpc.cpp b/media/client/ipc/source/MediaPipelineCapabilitiesIpc.cpp index a866ce98a..68843ee9a 100644 --- a/media/client/ipc/source/MediaPipelineCapabilitiesIpc.cpp +++ b/media/client/ipc/source/MediaPipelineCapabilitiesIpc.cpp @@ -177,4 +177,32 @@ std::vector MediaPipelineCapabilitiesIpc::getSupportedProperties(Me return std::vector{response.supported_properties().begin(), response.supported_properties().end()}; } +bool MediaPipelineCapabilitiesIpc::isVideoMaster(bool &isVideoMaster) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return {}; + } + + firebolt::rialto::IsVideoMasterRequest request; + firebolt::rialto::IsVideoMasterResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineCapabilitiesStub->isVideoMaster(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + isVideoMaster = response.is_video_master(); + + return true; +} }; // namespace firebolt::rialto::client diff --git a/media/client/ipc/source/MediaPipelineIpc.cpp b/media/client/ipc/source/MediaPipelineIpc.cpp index dcf1e5ce0..fb288c764 100644 --- a/media/client/ipc/source/MediaPipelineIpc.cpp +++ b/media/client/ipc/source/MediaPipelineIpc.cpp @@ -1333,38 +1333,6 @@ bool MediaPipelineIpc::switchSource(const std::unique_ptrisVideoMaster(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to check if video is master due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - isVideoMaster = response.is_video_master(); - - return true; -} - void MediaPipelineIpc::onPlaybackStateUpdated(const std::shared_ptr &event) { /* Ignore event if not for this session */ diff --git a/media/client/main/include/MediaPipeline.h b/media/client/main/include/MediaPipeline.h index aa5f8a94a..36bc4cbea 100644 --- a/media/client/main/include/MediaPipeline.h +++ b/media/client/main/include/MediaPipeline.h @@ -203,8 +203,6 @@ class MediaPipeline : public IMediaPipelineAndIControlClient, public IMediaPipel bool switchSource(const std::unique_ptr &source) override; - bool isVideoMaster(bool &isVideoMaster) override; - void notifyApplicationState(ApplicationState state) override; protected: diff --git a/media/client/main/include/MediaPipelineCapabilities.h b/media/client/main/include/MediaPipelineCapabilities.h index f4853aff2..ccd36203b 100644 --- a/media/client/main/include/MediaPipelineCapabilities.h +++ b/media/client/main/include/MediaPipelineCapabilities.h @@ -95,6 +95,15 @@ class MediaPipelineCapabilities : public IMediaPipelineCapabilities std::vector getSupportedProperties(MediaSourceType mediaType, const std::vector &propertyNames) override; + /** + * @brief Checks if the platform is video master. + * + * @param[out] isVideoMaster : The output value. True if video is master otherwise false. + * + * @retval true on success false otherwise + */ + bool isVideoMaster(bool &isVideoMaster) override; + private: /** * @brief The media pipeline capabilities ipc object. diff --git a/media/client/main/include/MediaPipelineProxy.h b/media/client/main/include/MediaPipelineProxy.h index 86ade929b..d24053885 100644 --- a/media/client/main/include/MediaPipelineProxy.h +++ b/media/client/main/include/MediaPipelineProxy.h @@ -169,8 +169,6 @@ class MediaPipelineProxy : public IMediaPipelineAndIControlClient return m_mediaPipeline->switchSource(source); } - bool isVideoMaster(bool &isVideoMaster) { return m_mediaPipeline->isVideoMaster(isVideoMaster); } - void notifyApplicationState(ApplicationState state) override { m_mediaPipeline->notifyApplicationState(state); } private: diff --git a/media/client/main/source/MediaPipeline.cpp b/media/client/main/source/MediaPipeline.cpp index ae4a17069..41731d60b 100644 --- a/media/client/main/source/MediaPipeline.cpp +++ b/media/client/main/source/MediaPipeline.cpp @@ -619,13 +619,6 @@ bool MediaPipeline::switchSource(const std::unique_ptr &source) return m_mediaPipelineIpc->switchSource(source); } -bool MediaPipeline::isVideoMaster(bool &isVideoMaster) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaPipelineIpc->isVideoMaster(isVideoMaster); -} - void MediaPipeline::discardNeedDataRequest(uint32_t needDataRequestId) { // Find the needDataRequest for this needDataRequestId diff --git a/media/client/main/source/MediaPipelineCapabilities.cpp b/media/client/main/source/MediaPipelineCapabilities.cpp index e2f4f0431..fdafd2c67 100644 --- a/media/client/main/source/MediaPipelineCapabilities.cpp +++ b/media/client/main/source/MediaPipelineCapabilities.cpp @@ -102,4 +102,10 @@ std::vector MediaPipelineCapabilities::getSupportedProperties(Media return m_mediaPipelineCapabilitiesIpc->getSupportedProperties(mediaType, propertyNames); } +bool MediaPipelineCapabilities::isVideoMaster(bool &isVideoMaster) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaPipelineCapabilitiesIpc->isVideoMaster(isVideoMaster); +} }; // namespace firebolt::rialto::client diff --git a/media/public/include/IMediaPipeline.h b/media/public/include/IMediaPipeline.h index 96aaf2ec5..61b992b86 100644 --- a/media/public/include/IMediaPipeline.h +++ b/media/public/include/IMediaPipeline.h @@ -1523,15 +1523,6 @@ class IMediaPipeline * @retval true on success. */ virtual bool switchSource(const std::unique_ptr &source) = 0; - - /** - * @brief Checks if the platform is video master. - * - * @param[out] isVideoMaster : The output value. True if video is master otherwise false. - * - * @retval true on success false otherwise - */ - virtual bool isVideoMaster(bool &isVideoMaster) = 0; }; }; // namespace firebolt::rialto diff --git a/media/public/include/IMediaPipelineCapabilities.h b/media/public/include/IMediaPipelineCapabilities.h index 3239a61b5..fa0c85628 100644 --- a/media/public/include/IMediaPipelineCapabilities.h +++ b/media/public/include/IMediaPipelineCapabilities.h @@ -107,6 +107,15 @@ class IMediaPipelineCapabilities */ virtual std::vector getSupportedProperties(MediaSourceType mediaType, const std::vector &propertyNames) = 0; + + /** + * @brief Checks if the platform is video master. + * + * @param[out] isVideoMaster : The output value. True if video is master otherwise false. + * + * @retval true on success false otherwise + */ + virtual bool isVideoMaster(bool &isVideoMaster) = 0; }; }; // namespace firebolt::rialto diff --git a/media/server/gstplayer/include/GstCapabilities.h b/media/server/gstplayer/include/GstCapabilities.h index 57668fedd..742fc565f 100644 --- a/media/server/gstplayer/include/GstCapabilities.h +++ b/media/server/gstplayer/include/GstCapabilities.h @@ -95,6 +95,15 @@ class GstCapabilities : public IGstCapabilities std::vector getSupportedProperties(MediaSourceType mediaType, const std::vector &propertyNames) override; + /** + * @brief Checks if the platform is video master. + * + * @param[out] isVideoMaster : The output value. True if video is master otherwise false. + * + * @retval true on success false otherwise + */ + bool isVideoMaster(bool &isVideoMaster) override; + private: /** * @brief Sets list of supported mime types diff --git a/media/server/gstplayer/include/GstGenericPlayer.h b/media/server/gstplayer/include/GstGenericPlayer.h index cd070471a..91548b7bb 100644 --- a/media/server/gstplayer/include/GstGenericPlayer.h +++ b/media/server/gstplayer/include/GstGenericPlayer.h @@ -142,7 +142,6 @@ class GstGenericPlayer : public IGstGenericPlayer, public IGstGenericPlayerPriva void setUseBuffering(bool useBuffering) override; bool getUseBuffering(bool &useBuffering) override; void switchSource(const std::unique_ptr &mediaSource) override; - bool isVideoMaster(bool &isVideoMaster) override; private: void scheduleNeedMediaData(GstAppSrc *src) override; diff --git a/media/server/gstplayer/interface/IGstCapabilities.h b/media/server/gstplayer/interface/IGstCapabilities.h index 2b9dbc5f8..68e09865b 100644 --- a/media/server/gstplayer/interface/IGstCapabilities.h +++ b/media/server/gstplayer/interface/IGstCapabilities.h @@ -89,6 +89,15 @@ class IGstCapabilities */ virtual std::vector getSupportedProperties(MediaSourceType mediaType, const std::vector &propertyNames) = 0; + + /** + * @brief Checks if the platform is video master. + * + * @param[out] isVideoMaster : The output value. True if video is master otherwise false. + * + * @retval true on success false otherwise + */ + virtual bool isVideoMaster(bool &isVideoMaster) = 0; }; }; // namespace firebolt::rialto::server diff --git a/media/server/gstplayer/interface/IGstGenericPlayer.h b/media/server/gstplayer/interface/IGstGenericPlayer.h index 55810383f..a6c9532bf 100644 --- a/media/server/gstplayer/interface/IGstGenericPlayer.h +++ b/media/server/gstplayer/interface/IGstGenericPlayer.h @@ -444,15 +444,6 @@ class IGstGenericPlayer * */ virtual void switchSource(const std::unique_ptr &mediaSource) = 0; - - /** - * @brief Checks if the platform is video master. - * - * @param[out] isVideoMaster : The output value. True if video is master otherwise false. - * - * @retval true on success false otherwise - */ - virtual bool isVideoMaster(bool &isVideoMaster) = 0; }; }; // namespace firebolt::rialto::server diff --git a/media/server/gstplayer/source/GstCapabilities.cpp b/media/server/gstplayer/source/GstCapabilities.cpp index d0080d3b4..b4d96e32f 100644 --- a/media/server/gstplayer/source/GstCapabilities.cpp +++ b/media/server/gstplayer/source/GstCapabilities.cpp @@ -439,6 +439,26 @@ void GstCapabilities::waitForInitialisation() m_initialisationCv.wait(lock, [this]() { return m_isInitialised; }); } +bool GstCapabilities::isVideoMaster(bool &isVideoMaster) +{ + waitForInitialisation(); + + GstRegistry *reg = m_gstWrapper->gstRegistryGet(); + if (!reg) + { + RIALTO_SERVER_LOG_ERROR("Failed get the gst registry"); + return false; + } + GstPluginFeature *feature{nullptr}; + isVideoMaster = true; + if (nullptr != (feature = m_gstWrapper->gstRegistryLookupFeature(reg, "amlhalasink"))) + { + isVideoMaster = false; + m_gstWrapper->gstObjectUnref(feature); + } + return true; +} + } // namespace firebolt::rialto::server // namespace firebolt::rialto::server diff --git a/media/server/gstplayer/source/GstGenericPlayer.cpp b/media/server/gstplayer/source/GstGenericPlayer.cpp index cf1230c8a..f0363de95 100644 --- a/media/server/gstplayer/source/GstGenericPlayer.cpp +++ b/media/server/gstplayer/source/GstGenericPlayer.cpp @@ -2014,24 +2014,6 @@ void GstGenericPlayer::switchSource(const std::unique_ptrgstRegistryGet(); - if (!reg) - { - RIALTO_SERVER_LOG_ERROR("Failed get the gst registry"); - return false; - } - GstPluginFeature *feature{nullptr}; - isVideoMaster = true; - if (nullptr != (feature = m_gstWrapper->gstRegistryLookupFeature(reg, "amlhalasink"))) - { - isVideoMaster = false; - m_gstWrapper->gstObjectUnref(feature); - } - return true; -} - void GstGenericPlayer::handleBusMessage(GstMessage *message) { m_workerThread->enqueueTask(m_taskFactory->createHandleBusMessage(m_context, *this, message, *m_flushWatcher)); diff --git a/media/server/ipc/include/MediaPipelineCapabilitiesModuleService.h b/media/server/ipc/include/MediaPipelineCapabilitiesModuleService.h index 8660f8373..51a19410c 100644 --- a/media/server/ipc/include/MediaPipelineCapabilitiesModuleService.h +++ b/media/server/ipc/include/MediaPipelineCapabilitiesModuleService.h @@ -59,6 +59,9 @@ class MediaPipelineCapabilitiesModuleService : public IMediaPipelineCapabilities const ::firebolt::rialto::GetSupportedPropertiesRequest *request, ::firebolt::rialto::GetSupportedPropertiesResponse *response, ::google::protobuf::Closure *done) override; + void isVideoMaster(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::IsVideoMasterRequest *request, + ::firebolt::rialto::IsVideoMasterResponse *response, ::google::protobuf::Closure *done) override; private: service::IMediaPipelineService &m_mediaPipelineService; diff --git a/media/server/ipc/include/MediaPipelineModuleService.h b/media/server/ipc/include/MediaPipelineModuleService.h index 8c323e203..fa9c74b95 100644 --- a/media/server/ipc/include/MediaPipelineModuleService.h +++ b/media/server/ipc/include/MediaPipelineModuleService.h @@ -155,9 +155,6 @@ class MediaPipelineModuleService : public IMediaPipelineModuleService const ::firebolt::rialto::GetUseBufferingRequest *request, ::firebolt::rialto::GetUseBufferingResponse *response, ::google::protobuf::Closure *done) override; - void isVideoMaster(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::IsVideoMasterRequest *request, - ::firebolt::rialto::IsVideoMasterResponse *response, ::google::protobuf::Closure *done) override; private: service::IMediaPipelineService &m_mediaPipelineService; diff --git a/media/server/ipc/source/MediaPipelineCapabilitiesModuleService.cpp b/media/server/ipc/source/MediaPipelineCapabilitiesModuleService.cpp index 2feca2411..efed009cc 100644 --- a/media/server/ipc/source/MediaPipelineCapabilitiesModuleService.cpp +++ b/media/server/ipc/source/MediaPipelineCapabilitiesModuleService.cpp @@ -152,4 +152,32 @@ void MediaPipelineCapabilitiesModuleService::getSupportedProperties( done->Run(); } +void MediaPipelineCapabilitiesModuleService::isVideoMaster(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::IsVideoMasterRequest *request, + ::firebolt::rialto::IsVideoMasterResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + auto ipcController = dynamic_cast(controller); + if (!ipcController) + { + RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); + controller->SetFailed("ipc library provided incompatible controller object"); + done->Run(); + return; + } + + bool isMaster{false}; + if (!m_mediaPipelineService.isVideoMaster(isMaster)) + { + RIALTO_SERVER_LOG_ERROR("isVideoMaster check failed"); + controller->SetFailed("isVideoMaster check failed"); + done->Run(); + return; + } + + response->set_is_video_master(isMaster); + + done->Run(); +} } // namespace firebolt::rialto::server::ipc diff --git a/media/server/ipc/source/MediaPipelineModuleService.cpp b/media/server/ipc/source/MediaPipelineModuleService.cpp index c596a526a..ca36ee3d4 100644 --- a/media/server/ipc/source/MediaPipelineModuleService.cpp +++ b/media/server/ipc/source/MediaPipelineModuleService.cpp @@ -1065,25 +1065,4 @@ void MediaPipelineModuleService::getUseBuffering(::google::protobuf::RpcControll done->Run(); } - -void MediaPipelineModuleService::isVideoMaster(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::IsVideoMasterRequest *request, - ::firebolt::rialto::IsVideoMasterResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - bool isVideoMaster{}; - - if (!m_mediaPipelineService.isVideoMaster(request->session_id(), isVideoMaster)) - { - RIALTO_SERVER_LOG_ERROR("Is video master failed."); - controller->SetFailed("Operation failed"); - } - else - { - response->set_is_video_master(isVideoMaster); - } - - done->Run(); -} } // namespace firebolt::rialto::server::ipc diff --git a/media/server/main/include/MediaPipelineCapabilities.h b/media/server/main/include/MediaPipelineCapabilities.h index 008da32b0..be5a34451 100644 --- a/media/server/main/include/MediaPipelineCapabilities.h +++ b/media/server/main/include/MediaPipelineCapabilities.h @@ -66,6 +66,7 @@ class MediaPipelineCapabilities : public IMediaPipelineCapabilities bool isMimeTypeSupported(const std::string &mimeType) override; std::vector getSupportedProperties(MediaSourceType mediaType, const std::vector &propertyNames) override; + bool isVideoMaster(bool &isVideoMaster) override; private: /** diff --git a/media/server/main/include/MediaPipelineServerInternal.h b/media/server/main/include/MediaPipelineServerInternal.h index df430e001..015c7649b 100644 --- a/media/server/main/include/MediaPipelineServerInternal.h +++ b/media/server/main/include/MediaPipelineServerInternal.h @@ -167,8 +167,6 @@ class MediaPipelineServerInternal : public IMediaPipelineServerInternal, public bool switchSource(const std::unique_ptr &source) override; - bool isVideoMaster(bool &isVideoMaster) override; - AddSegmentStatus addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) override; std::weak_ptr getClient() override; @@ -695,15 +693,6 @@ class MediaPipelineServerInternal : public IMediaPipelineServerInternal, public */ bool switchSourceInternal(const std::unique_ptr &source); - /** - * @brief Checks if the platform is video master. - * - * @param[out] isVideoMaster : The output value. True if video is master otherwise false. - * - * @retval true on success false otherwise - */ - bool isVideoMasterInternal(bool &isVideoMaster); - /** * @brief Returns how long should we wait to send next NeedMediaData * if rialto client returns NO_AVAILABLE_SAMPLES diff --git a/media/server/main/source/MediaPipelineCapabilities.cpp b/media/server/main/source/MediaPipelineCapabilities.cpp index 184c3b0f2..67cd7c19a 100644 --- a/media/server/main/source/MediaPipelineCapabilities.cpp +++ b/media/server/main/source/MediaPipelineCapabilities.cpp @@ -94,4 +94,9 @@ std::vector MediaPipelineCapabilities::getSupportedProperties(Media return m_gstCapabilities->getSupportedProperties(mediaType, propertyNames); } +bool MediaPipelineCapabilities::isVideoMaster(bool &isVideoMaster) +{ + return m_gstCapabilities->isVideoMaster(isVideoMaster); +} + }; // namespace firebolt::rialto::server diff --git a/media/server/main/source/MediaPipelineServerInternal.cpp b/media/server/main/source/MediaPipelineServerInternal.cpp index 6d6465e60..e80808285 100644 --- a/media/server/main/source/MediaPipelineServerInternal.cpp +++ b/media/server/main/source/MediaPipelineServerInternal.cpp @@ -1325,25 +1325,6 @@ bool MediaPipelineServerInternal::switchSourceInternal(const std::unique_ptrenqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::isVideoMasterInternal(bool &isVideoMaster) -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to check if video is master - Gstreamer player has not been loaded"); - return false; - } - return m_gstPlayer->isVideoMaster(isVideoMaster); -} - AddSegmentStatus MediaPipelineServerInternal::addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) { diff --git a/media/server/service/include/IMediaPipelineService.h b/media/server/service/include/IMediaPipelineService.h index bf7ec69af..0a4336f36 100644 --- a/media/server/service/include/IMediaPipelineService.h +++ b/media/server/service/include/IMediaPipelineService.h @@ -89,7 +89,7 @@ class IMediaPipelineService const std::vector &propertyNames) = 0; virtual void ping(const std::shared_ptr &heartbeatProcedure) = 0; virtual bool switchSource(int sessionId, const std::unique_ptr &source) = 0; - virtual bool isVideoMaster(int sessionId, bool &isVideoMaster) = 0; + virtual bool isVideoMaster(bool &isVideoMaster) = 0; }; } // namespace firebolt::rialto::server::service diff --git a/media/server/service/source/MediaPipelineService.cpp b/media/server/service/source/MediaPipelineService.cpp index 35641f687..608e0171e 100644 --- a/media/server/service/source/MediaPipelineService.cpp +++ b/media/server/service/source/MediaPipelineService.cpp @@ -620,18 +620,11 @@ bool MediaPipelineService::switchSource(int sessionId, const std::unique_ptrsecond->switchSource(source); } -bool MediaPipelineService::isVideoMaster(int sessionId, bool &isVideoMaster) +bool MediaPipelineService::isVideoMaster(bool &isVideoMaster) { - RIALTO_SERVER_LOG_INFO("MediaPipelineService requested check if video is master, session id: %d", sessionId); + RIALTO_SERVER_LOG_INFO("MediaPipelineService requested check if video is master"); - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); - return false; - } - return mediaPipelineIter->second->isVideoMaster(isVideoMaster); + return m_mediaPipelineCapabilities->isVideoMaster(isVideoMaster); } std::vector MediaPipelineService::getSupportedMimeTypes(MediaSourceType type) diff --git a/media/server/service/source/MediaPipelineService.h b/media/server/service/source/MediaPipelineService.h index a426b7472..7ec49309b 100644 --- a/media/server/service/source/MediaPipelineService.h +++ b/media/server/service/source/MediaPipelineService.h @@ -95,7 +95,7 @@ class MediaPipelineService : public IMediaPipelineService bool setUseBuffering(int sessionId, bool useBuffering) override; bool getUseBuffering(int sessionId, bool &useBuffering) override; bool switchSource(int sessionId, const std::unique_ptr &source) override; - bool isVideoMaster(int sessionId, bool &isVideoMaster) override; + bool isVideoMaster(bool &isVideoMaster) override; std::vector getSupportedMimeTypes(MediaSourceType type) override; bool isMimeTypeSupported(const std::string &mimeType) override; std::vector getSupportedProperties(MediaSourceType mediaType, diff --git a/proto/mediapipelinecapabilitiesmodule.proto b/proto/mediapipelinecapabilitiesmodule.proto index df3c47d73..1e18f9227 100644 --- a/proto/mediapipelinecapabilitiesmodule.proto +++ b/proto/mediapipelinecapabilitiesmodule.proto @@ -55,6 +55,21 @@ message IsMimeTypeSupportedResponse { optional bool is_supported = 1; } +/** + * @fn void isVideoMaster(bool &isVideoMaster) + * @brief Checks if the platform is video master. + * + * @param[out] is_video_master True if video is master otherwise false. + * + * @retval true on success false otherwise +*/ + +message IsVideoMasterRequest { +} +message IsVideoMasterResponse { + optional bool is_video_master = 1; +} + /** * @fn vector getSupportedProperties(MediaSourceType media_type, const vector &property_names) * @brief Has any gstreamer sink or decoder got a named property @@ -93,4 +108,11 @@ service MediaPipelineCapabilitiesModule { */ rpc getSupportedProperties(GetSupportedPropertiesRequest) returns (GetSupportedPropertiesResponse) { } + + /** + * @brief Checks if the platform is video master. + * @see IsVideoMasterRequest + */ + rpc isVideoMaster(IsVideoMasterRequest) returns (IsVideoMasterResponse) { + } } \ No newline at end of file diff --git a/proto/mediapipelinemodule.proto b/proto/mediapipelinemodule.proto index 3ac808db2..b326b621a 100644 --- a/proto/mediapipelinemodule.proto +++ b/proto/mediapipelinemodule.proto @@ -791,22 +791,6 @@ message GetUseBufferingResponse { optional bool use_buffering = 1 [default = false]; } -/** - * @fn void isVideoMaster(bool &isVideoMaster) - * @brief Checks if the platform is video master. - * - * @param[in] session_id The id of the A/V session the request is for. - * @param[out] is_video_master True if video is master otherwise false. - * - * @retval true on success false otherwise - */ -message IsVideoMasterRequest { - optional int32 session_id = 1 [default = -1]; -} -message IsVideoMasterResponse { - optional bool is_video_master = 1; -} - /** * @brief Event sent the playback state has changed. * @@ -1237,11 +1221,4 @@ service MediaPipelineModule { */ rpc getUseBuffering(GetUseBufferingRequest) returns (GetUseBufferingResponse) { } - - /** - * @brief Checks if the platform is video master. - * @see IsVideoMasterRequest - */ - rpc isVideoMaster(IsVideoMasterRequest) returns (IsVideoMasterResponse) { - } } diff --git a/tests/common/matchers/MediaPipelineProtoRequestMatchers.h b/tests/common/matchers/MediaPipelineProtoRequestMatchers.h index 89e811c6f..ecd07f993 100644 --- a/tests/common/matchers/MediaPipelineProtoRequestMatchers.h +++ b/tests/common/matchers/MediaPipelineProtoRequestMatchers.h @@ -300,13 +300,6 @@ MATCHER_P(getSyncRequestMatcher, sessionId, "") return ((kRequest->session_id() == sessionId)); } -MATCHER_P(isVideoMasterRequestMatcher, sessionId, "") -{ - const ::firebolt::rialto::IsVideoMasterRequest *kRequest = - dynamic_cast(arg); - return ((kRequest->session_id() == sessionId)); -} - MATCHER_P2(setSyncOffRequestMatcher, sessionId, syncOff, "") { const ::firebolt::rialto::SetSyncOffRequest *kRequest = diff --git a/tests/componenttests/client/mocks/MediaPipelineCapabilitiesModuleMock.h b/tests/componenttests/client/mocks/MediaPipelineCapabilitiesModuleMock.h index 81cc315a1..958dc8be7 100644 --- a/tests/componenttests/client/mocks/MediaPipelineCapabilitiesModuleMock.h +++ b/tests/componenttests/client/mocks/MediaPipelineCapabilitiesModuleMock.h @@ -46,6 +46,11 @@ class MediaPipelineCapabilitiesModuleMock : public ::firebolt::rialto::MediaPipe ::firebolt::rialto::GetSupportedPropertiesResponse *response, ::google::protobuf::Closure *done), (override)); + MOCK_METHOD(void, isVideoMaster, + (::google::protobuf::RpcController * controller, const ::firebolt::rialto::IsVideoMasterRequest *request, + ::firebolt::rialto::IsVideoMasterResponse *response, ::google::protobuf::Closure *done), + (override)); + void defaultReturn(::google::protobuf::RpcController *controller, ::google::protobuf::Closure *done) { done->Run(); diff --git a/tests/componenttests/client/tests/base/MediaPipelineTestMethods.cpp b/tests/componenttests/client/tests/base/MediaPipelineTestMethods.cpp index 287b0f877..0379384c8 100644 --- a/tests/componenttests/client/tests/base/MediaPipelineTestMethods.cpp +++ b/tests/componenttests/client/tests/base/MediaPipelineTestMethods.cpp @@ -1587,28 +1587,28 @@ void MediaPipelineTestMethods::switchSourceMpeg() EXPECT_EQ(m_mediaPipeline->switchSource(mediaSource), true); } -void MediaPipelineTestMethods::shouldCheckIfVideoIsMaster() +void MediaPipelineTestMethods::shouldCheckIsVideoMaster() { - EXPECT_CALL(*m_mediaPipelineModuleMock, isVideoMaster(_, isVideoMasterRequestMatcher(kSessionId), _, _)) + EXPECT_CALL(*m_mediaPipelineCapabilitiesModuleMock, isVideoMaster(_, _, _, _)) .WillOnce(WithArgs<0, 3>(Invoke(&(*m_mediaPipelineModuleMock), &MediaPipelineModuleMock::defaultReturn))); } -void MediaPipelineTestMethods::shouldFailToCheckIfVideoIsMaster() +void MediaPipelineTestMethods::shouldFailToCheckIsVideoMaster() { - EXPECT_CALL(*m_mediaPipelineModuleMock, isVideoMaster(_, isVideoMasterRequestMatcher(kSessionId), _, _)) + EXPECT_CALL(*m_mediaPipelineCapabilitiesModuleMock, isVideoMaster(_, _, _, _)) .WillOnce(WithArgs<0, 3>(Invoke(&(*m_mediaPipelineModuleMock), &MediaPipelineModuleMock::failureReturn))); } void MediaPipelineTestMethods::isVideoMaster() { bool isMaster{false}; - EXPECT_TRUE(m_mediaPipeline->isVideoMaster(isMaster)); + EXPECT_TRUE(m_mediaPipelineCapabilities->isVideoMaster(isMaster)); } void MediaPipelineTestMethods::isVideoMasterFailure() { bool isMaster{false}; - EXPECT_FALSE(m_mediaPipeline->isVideoMaster(isMaster)); + EXPECT_FALSE(m_mediaPipelineCapabilities->isVideoMaster(isMaster)); } /*************************** Private methods ********************************/ diff --git a/tests/componenttests/client/tests/base/MediaPipelineTestMethods.h b/tests/componenttests/client/tests/base/MediaPipelineTestMethods.h index 8cd51364d..b2f007e84 100644 --- a/tests/componenttests/client/tests/base/MediaPipelineTestMethods.h +++ b/tests/componenttests/client/tests/base/MediaPipelineTestMethods.h @@ -139,8 +139,8 @@ class MediaPipelineTestMethods void shouldFailToProcessAudioGap(); void shouldSwitchSourceEacs(); void shouldSwitchSourceMpeg(); - void shouldCheckIfVideoIsMaster(); - void shouldFailToCheckIfVideoIsMaster(); + void shouldCheckIsVideoMaster(); + void shouldFailToCheckIsVideoMaster(); // MediaPipelineClient Expect methods void shouldNotifyNetworkStateBuffering(); diff --git a/tests/componenttests/client/tests/mse/IsVideoMasterTest.cpp b/tests/componenttests/client/tests/mse/IsVideoMasterTest.cpp index fdb76420c..f7a3da184 100644 --- a/tests/componenttests/client/tests/mse/IsVideoMasterTest.cpp +++ b/tests/componenttests/client/tests/mse/IsVideoMasterTest.cpp @@ -68,6 +68,14 @@ class MuteTest : public ClientComponentTest * Call IsVideoMaster * Expect that when IsVideoMaster fails, it returns the error status. * + * Step 3: Call IsVideoMaster capability + * Call IsVideoMaster capability + * Expect that IsVideoMaster propagated to the server and returns the IsVideoMaster status. + * + * Step 4: Call IsVideoMaster capability failure + * Call IsVideoMaster capability + * Expect that when IsVideoMaster fails, it returns the error status. + * * Test Teardown: * Terminate the media session. * Memory region created for the shared buffer is closed. @@ -81,11 +89,11 @@ class MuteTest : public ClientComponentTest TEST_F(MuteTest, mute) { // Step 1: Call IsVideoMaster - MediaPipelineTestMethods::shouldCheckIfVideoIsMaster(); + MediaPipelineTestMethods::shouldCheckIsVideoMaster(); MediaPipelineTestMethods::isVideoMaster(); // Step 2: Call IsVideoMaster failure - MediaPipelineTestMethods::shouldFailToCheckIfVideoIsMaster(); + MediaPipelineTestMethods::shouldFailToCheckIsVideoMaster(); MediaPipelineTestMethods::isVideoMasterFailure(); } } // namespace firebolt::rialto::client::ct diff --git a/tests/componenttests/server/common/ActionTraits.h b/tests/componenttests/server/common/ActionTraits.h index 2e3692400..d601e8d9f 100644 --- a/tests/componenttests/server/common/ActionTraits.h +++ b/tests/componenttests/server/common/ActionTraits.h @@ -344,14 +344,6 @@ struct ProcessAudioGap static constexpr auto m_kFunction{&Stub::processAudioGap}; }; -struct IsVideoMaster -{ - using RequestType = ::firebolt::rialto::IsVideoMasterRequest; - using ResponseType = ::firebolt::rialto::IsVideoMasterResponse; - using Stub = ::firebolt::rialto::MediaPipelineModule_Stub; - static constexpr auto m_kFunction{&Stub::isVideoMaster}; -}; - // mediakeys module struct CreateMediaKeys { @@ -588,6 +580,14 @@ struct GetSupportedProperties static constexpr auto m_kFunction{&Stub::getSupportedProperties}; }; +struct IsVideoMaster +{ + using RequestType = ::firebolt::rialto::IsVideoMasterRequest; + using ResponseType = ::firebolt::rialto::IsVideoMasterResponse; + using Stub = ::firebolt::rialto::MediaPipelineCapabilitiesModule_Stub; + static constexpr auto m_kFunction{&Stub::isVideoMaster}; +}; + // web audio player module struct CreateWebAudioPlayer { diff --git a/tests/componenttests/server/common/MessageBuilders.cpp b/tests/componenttests/server/common/MessageBuilders.cpp index 6aee8a365..848b925f8 100644 --- a/tests/componenttests/server/common/MessageBuilders.cpp +++ b/tests/componenttests/server/common/MessageBuilders.cpp @@ -407,13 +407,6 @@ ::firebolt::rialto::ProcessAudioGapRequest createProcessAudioGapRequest(int sess return request; } -::firebolt::rialto::IsVideoMasterRequest createIsVideoMasterRequest(int sessionId) -{ - ::firebolt::rialto::IsVideoMasterRequest request; - request.set_session_id(sessionId); - return request; -} - ::firebolt::rialto::CreateMediaKeysRequest createCreateMediaKeysRequestWidevine() { ::firebolt::rialto::CreateMediaKeysRequest request; @@ -662,6 +655,12 @@ createGetSupportedPropertiesRequest(const ProtoMediaSourceType &mediaType, const return request; } +::firebolt::rialto::IsVideoMasterRequest createIsVideoMasterRequest() +{ + ::firebolt::rialto::IsVideoMasterRequest request; + return request; +} + ::firebolt::rialto::CreateWebAudioPlayerRequest createCreateWebAudioPlayerRequest(uint32 pcmRate, uint32 pcmChannels, uint32 pcmSampleSize, bool pcmIsBigEndian, bool pcmIsSigned, bool pcmIsFloat, const std::string &audioMimeType, uint32 priority) diff --git a/tests/componenttests/server/common/MessageBuilders.h b/tests/componenttests/server/common/MessageBuilders.h index da46b666f..dae4679ae 100644 --- a/tests/componenttests/server/common/MessageBuilders.h +++ b/tests/componenttests/server/common/MessageBuilders.h @@ -83,7 +83,6 @@ ::firebolt::rialto::SetSourcePositionRequest createSetSourcePositionRequest(int ::firebolt::rialto::ProcessAudioGapRequest createProcessAudioGapRequest(int sessionId, std::int64_t position, unsigned duration, std::int64_t discontinuityGap, bool audioAac); -::firebolt::rialto::IsVideoMasterRequest createIsVideoMasterRequest(int sessionId); // media keys module ::firebolt::rialto::CreateMediaKeysRequest createCreateMediaKeysRequestWidevine(); @@ -131,6 +130,7 @@ createGetSupportedMimeTypesRequest(const ProtoMediaSourceType &mediaSourceType); ::firebolt::rialto::IsMimeTypeSupportedRequest createIsMimeTypeSupportedRequest(const std::string &mimeType); ::firebolt::rialto::GetSupportedPropertiesRequest createGetSupportedPropertiesRequest(const ProtoMediaSourceType &mediaType, const std::vector &propertyNames); +::firebolt::rialto::IsVideoMasterRequest createIsVideoMasterRequest(); // web audio player module ::firebolt::rialto::CreateWebAudioPlayerRequest diff --git a/tests/componenttests/server/tests/mediaPipeline/PipelinePropertyTest.cpp b/tests/componenttests/server/tests/mediaPipeline/PipelinePropertyTest.cpp index a9e637704..2284fd8cd 100644 --- a/tests/componenttests/server/tests/mediaPipeline/PipelinePropertyTest.cpp +++ b/tests/componenttests/server/tests/mediaPipeline/PipelinePropertyTest.cpp @@ -39,7 +39,6 @@ constexpr bool kSyncOff{true}; constexpr int32_t kStreamSyncMode{1}; constexpr int32_t kBufferingLimit{4321}; constexpr bool kUseBuffering{true}; -constexpr bool kIsVideoMaster{true}; } // namespace namespace firebolt::rialto::server::ct @@ -313,21 +312,6 @@ class PipelinePropertyTest : public MediaPipelineTest .matchResponse([&](const auto &resp) { EXPECT_EQ(resp.use_buffering(), kUseBuffering); }); } - void willCheckIfVideoIsMaster() - { - EXPECT_CALL(*m_gstWrapperMock, gstRegistryGet()).WillOnce(Return(&m_registry)); - EXPECT_CALL(*m_gstWrapperMock, gstRegistryLookupFeature(&m_registry, StrEq("amlhalasink"))).WillOnce(Return(nullptr)); - } - - void checkIfVideoIsMaster() - { - auto req{createIsVideoMasterRequest(m_sessionId)}; - ConfigureAction(m_clientStub) - .send(req) - .expectSuccess() - .matchResponse([&](const auto &resp) { EXPECT_EQ(resp.is_video_master(), kIsVideoMaster); }); - } - void setImmediateOutputFailure() { auto req{createSetImmediateOutputRequest(m_sessionId, m_videoSourceId, true)}; @@ -504,21 +488,18 @@ class PipelinePropertyTest : public MediaPipelineTest * Step 15: Get Use Buffering * Will get the UseBuffering property of the decodebin on the Rialto Server * - * Step 16: Check if video is master - * Will check, if video is master for current device. - * - * Step 17: Remove sources + * Step 16: Remove sources * Remove the audio source. * Expect that audio source is removed. * Remove the video source. * Expect that video source is removed. * - * Step 18: Stop + * Step 17: Stop * Stop the playback. * Expect that stop propagated to the gstreamer pipeline. * Expect that server notifies the client that the Playback state has changed to STOPPED. * - * Step 19: Destroy media session + * Step 18: Destroy media session * Send DestroySessionRequest. * Expect that the session is destroyed on the server. * @@ -598,16 +579,12 @@ TEST_F(PipelinePropertyTest, pipelinePropertyGetAndSetSuccess) // Step 15: Get Use Buffering getUseBuffering(); - // Step 16: Check if video is master - willCheckIfVideoIsMaster(); - checkIfVideoIsMaster(); - - // Step 17: Remove sources + // Step 16: Remove sources willRemoveAudioSource(); removeSource(m_audioSourceId); removeSource(m_videoSourceId); - // Step 18: Stop + // Step 17: Stop willStop(); stop(); diff --git a/tests/componenttests/server/tests/mediaPipelineCapabilities/MediaPipelineCapabilitiesTest.cpp b/tests/componenttests/server/tests/mediaPipelineCapabilities/MediaPipelineCapabilitiesTest.cpp index 2ebc6ec14..acfcef40b 100644 --- a/tests/componenttests/server/tests/mediaPipelineCapabilities/MediaPipelineCapabilitiesTest.cpp +++ b/tests/componenttests/server/tests/mediaPipelineCapabilities/MediaPipelineCapabilitiesTest.cpp @@ -91,6 +91,12 @@ class MediaPipelineCapabilitiesTest : public RialtoServerComponentTest m_listOfFactories = nullptr; } + void willCheckIfVideoIsMaster() + { + EXPECT_CALL(*m_gstWrapperMock, gstRegistryGet()).WillOnce(Return(&m_registry)); + EXPECT_CALL(*m_gstWrapperMock, gstRegistryLookupFeature(&m_registry, StrEq("amlhalasink"))).WillOnce(Return(nullptr)); + } + private: GList *m_listOfFactories{nullptr}; GParamSpec m_dummyParams[kNumPropertiesOnSink]; @@ -98,6 +104,7 @@ class MediaPipelineCapabilitiesTest : public RialtoServerComponentTest std::vector m_kParamNames{kPropertyName1, kPropertyName3, kPropertyName2, kAudioFade}; GstElement m_object; GstElementFactory *m_elementFactory; + GstRegistry m_registry{}; }; /* @@ -372,4 +379,45 @@ TEST_F(MediaPipelineCapabilitiesTest, checkGetSupportedProperties) willCallGetSupportedProperties(); callGetSupportedProperties(); } + +/* + * Component Test: Check, if video is master + * Test Objective: + * Test if video is master in Rialto Server + * + * Sequence Diagrams: + * Capabilities + * https://wiki.rdkcentral.com/display/ASP/Rialto+MSE+Misc+Sequence+Diagrams#RialtoMSEMiscSequenceDiagrams + * + * Test Setup: + * Language: C++ + * Testing Framework: Google Test + * Components: MediaPipelineCapabilities + * + * Test Initialize: + * Set Rialto Server to Active + * Connect Rialto Client Stub + * + * Test Steps: + * Step 1: Check is video master + * Client stub requests the server to check, if video is master + * Expect that server returns, that video is master + * + * Test Teardown: + * Server is terminated. + * + * Expected Results: + * Rialto server checks, if mime types are supported. + * + * Code: + */ +TEST_F(MediaPipelineCapabilitiesTest, checkIsVideoMaster) +{ + // Step 1: Check is video master + willCheckIfVideoIsMaster(); + ConfigureAction{m_clientStub} + .send(createIsVideoMasterRequest()) + .expectSuccess() + .matchResponse([](const auto &resp) { EXPECT_TRUE(resp.is_video_master()); }); +}; } // namespace firebolt::rialto::server::ct diff --git a/tests/unittests/media/client/ipc/CMakeLists.txt b/tests/unittests/media/client/ipc/CMakeLists.txt index c72082b1f..d00f5d6cf 100644 --- a/tests/unittests/media/client/ipc/CMakeLists.txt +++ b/tests/unittests/media/client/ipc/CMakeLists.txt @@ -40,7 +40,6 @@ add_gtests ( mediaPipelineIpc/GetStatsTest.cpp mediaPipelineIpc/RenderFrameTest.cpp mediaPipelineIpc/GetVolumeTest.cpp - mediaPipelineIpc/IsVideoMasterTest.cpp mediaPipelineIpc/SetVolumeTest.cpp mediaPipelineIpc/GetMuteTest.cpp mediaPipelineIpc/SetMuteTest.cpp diff --git a/tests/unittests/media/client/ipc/mediaPipelineCapabilitiesIpc/MediaPipelineCapabilitiesIpcTest.cpp b/tests/unittests/media/client/ipc/mediaPipelineCapabilitiesIpc/MediaPipelineCapabilitiesIpcTest.cpp index 1fba66ab9..13cbffe06 100644 --- a/tests/unittests/media/client/ipc/mediaPipelineCapabilitiesIpc/MediaPipelineCapabilitiesIpcTest.cpp +++ b/tests/unittests/media/client/ipc/mediaPipelineCapabilitiesIpc/MediaPipelineCapabilitiesIpcTest.cpp @@ -66,6 +66,13 @@ class MediaPipelineCapabilitiesIpcTest : public IpcModuleBase, public ::testing: dynamic_cast(response); getSupportedPropertiesResponse->add_supported_properties(kPropertyName); } + + void setIsVideoMasterResponse(google::protobuf::Message *response) + { + firebolt::rialto::IsVideoMasterResponse *isVideoMasterResponse = + dynamic_cast(response); + isVideoMasterResponse->set_is_video_master(true); + } }; TEST_F(MediaPipelineCapabilitiesIpcTest, createMediaPipelineCapabilitiesIpc) @@ -217,3 +224,53 @@ TEST_F(MediaPipelineCapabilitiesIpcTest, GetSupportedSubtitlesMimeTypesSuccess) EXPECT_EQ(m_sut->getSupportedMimeTypes(MediaSourceType::SUBTITLE), m_mimeTypes); } + +TEST_F(MediaPipelineCapabilitiesIpcTest, IsVideoMasterSuccess) +{ + bool isMaster{false}; + + createMediaPipelineCapabilitiesIpc(); + expectIpcApiCallSuccess(); + + EXPECT_CALL(*m_channelMock, + CallMethod(methodMatcher("isVideoMaster"), m_controllerMock.get(), _, _, m_blockingClosureMock.get())) + .WillOnce(WithArgs<3>(Invoke(this, &MediaPipelineCapabilitiesIpcTest::setIsVideoMasterResponse))); + + EXPECT_TRUE(m_sut->isVideoMaster(isMaster)); +} + +TEST_F(MediaPipelineCapabilitiesIpcTest, IsVideoMastersDisconnected) +{ + bool isMaster{false}; + + createMediaPipelineCapabilitiesIpc(); + expectIpcApiCallDisconnected(); + + EXPECT_FALSE(m_sut->isVideoMaster(isMaster)); +} + +TEST_F(MediaPipelineCapabilitiesIpcTest, IsVideoMasterDisconnectedReconnectChannel) +{ + bool isMaster{false}; + + createMediaPipelineCapabilitiesIpc(); + expectIpcApiCallReconnected(); + + EXPECT_CALL(*m_channelMock, + CallMethod(methodMatcher("isVideoMaster"), m_controllerMock.get(), _, _, m_blockingClosureMock.get())) + .WillOnce(WithArgs<3>(Invoke(this, &MediaPipelineCapabilitiesIpcTest::setIsVideoMasterResponse))); + + EXPECT_TRUE(m_sut->isVideoMaster(isMaster)); +} + +TEST_F(MediaPipelineCapabilitiesIpcTest, IsVideoMasterFailure) +{ + bool isMaster{false}; + + createMediaPipelineCapabilitiesIpc(); + expectIpcApiCallFailure(); + + EXPECT_CALL(*m_channelMock, CallMethod(methodMatcher("isVideoMaster"), _, _, _, _)); + + EXPECT_FALSE(m_sut->isVideoMaster(isMaster)); +} diff --git a/tests/unittests/media/client/ipc/mediaPipelineIpc/IsVideoMasterTest.cpp b/tests/unittests/media/client/ipc/mediaPipelineIpc/IsVideoMasterTest.cpp deleted file mode 100644 index 97689ecb5..000000000 --- a/tests/unittests/media/client/ipc/mediaPipelineIpc/IsVideoMasterTest.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2025 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "MediaPipelineIpcTestBase.h" -#include "MediaPipelineProtoRequestMatchers.h" - -class RialtoClientMediaPipelineIpcIsVideoMasterTest : public MediaPipelineIpcTestBase -{ -protected: - virtual void SetUp() - { - MediaPipelineIpcTestBase::SetUp(); - - createMediaPipelineIpc(); - } - - virtual void TearDown() - { - destroyMediaPipelineIpc(); - - MediaPipelineIpcTestBase::TearDown(); - } -}; - -/** - * Test that isVideoMaster can be called successfully. - */ -TEST_F(RialtoClientMediaPipelineIpcIsVideoMasterTest, Success) -{ - constexpr bool kIsVideoMaster{true}; - expectIpcApiCallSuccess(); - - EXPECT_CALL(*m_channelMock, CallMethod(methodMatcher("isVideoMaster"), m_controllerMock.get(), - isVideoMasterRequestMatcher(m_sessionId), _, m_blockingClosureMock.get())) - .WillOnce(Invoke( - [&](const google::protobuf::MethodDescriptor *, google::protobuf::RpcController *, - const google::protobuf::Message *, google::protobuf::Message *response, google::protobuf::Closure *) - { - ::firebolt::rialto::IsVideoMasterResponse *resp = - dynamic_cast<::firebolt::rialto::IsVideoMasterResponse *>(response); - resp->set_is_video_master(kIsVideoMaster); - })); - - bool resultIsVideoMaster{false}; - EXPECT_TRUE(m_mediaPipelineIpc->isVideoMaster(resultIsVideoMaster)); - EXPECT_EQ(resultIsVideoMaster, kIsVideoMaster); -} - -/** - * Test that isVideoMaster fails if the ipc channel disconnected. - */ -TEST_F(RialtoClientMediaPipelineIpcIsVideoMasterTest, ChannelDisconnected) -{ - expectIpcApiCallDisconnected(); - expectUnsubscribeEvents(); - - bool isVideoMaster{false}; - EXPECT_FALSE(m_mediaPipelineIpc->isVideoMaster(isVideoMaster)); - - // Reattach channel on destroySession - EXPECT_CALL(*m_ipcClientMock, getChannel()).WillOnce(Return(m_channelMock)).RetiresOnSaturation(); - expectSubscribeEvents(); -} - -/** - * Test that isVideoMaster fails if the ipc channel disconnected and succeeds if the channel is reconnected. - */ -TEST_F(RialtoClientMediaPipelineIpcIsVideoMasterTest, ReconnectChannel) -{ - expectIpcApiCallReconnected(); - expectUnsubscribeEvents(); - expectSubscribeEvents(); - - EXPECT_CALL(*m_channelMock, CallMethod(methodMatcher("isVideoMaster"), _, _, _, _)); - - bool isVideoMaster{false}; - EXPECT_TRUE(m_mediaPipelineIpc->isVideoMaster(isVideoMaster)); -} - -/** - * Test that isVideoMaster fails when ipc fails. - */ -TEST_F(RialtoClientMediaPipelineIpcIsVideoMasterTest, IsVideoMasterFailure) -{ - expectIpcApiCallFailure(); - - EXPECT_CALL(*m_channelMock, CallMethod(methodMatcher("isVideoMaster"), _, _, _, _)); - - bool isVideoMaster{false}; - EXPECT_FALSE(m_mediaPipelineIpc->isVideoMaster(isVideoMaster)); -} diff --git a/tests/unittests/media/client/main/CMakeLists.txt b/tests/unittests/media/client/main/CMakeLists.txt index 1eecfe7f6..d0ae9c218 100644 --- a/tests/unittests/media/client/main/CMakeLists.txt +++ b/tests/unittests/media/client/main/CMakeLists.txt @@ -38,7 +38,6 @@ add_gtests ( mediaPipeline/RenderFrameTest.cpp mediaPipeline/SetVolumeTest.cpp mediaPipeline/GetVolumeTest.cpp - mediaPipeline/IsVideoMasterTest.cpp mediaPipeline/SetMuteTest.cpp mediaPipeline/GetMuteTest.cpp mediaPipeline/SetLowLatencyTest.cpp diff --git a/tests/unittests/media/client/main/mediaPipeline/IsVideoMasterTest.cpp b/tests/unittests/media/client/main/mediaPipeline/IsVideoMasterTest.cpp deleted file mode 100644 index a4c8ad595..000000000 --- a/tests/unittests/media/client/main/mediaPipeline/IsVideoMasterTest.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2025 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "MediaPipelineTestBase.h" - -class RialtoClientMediaPipelineIsVideoMasterTest : public MediaPipelineTestBase -{ -protected: - bool m_isVideoMaster{}; - - virtual void SetUp() - { - MediaPipelineTestBase::SetUp(); - - createMediaPipeline(); - } - - virtual void TearDown() - { - destroyMediaPipeline(); - - MediaPipelineTestBase::TearDown(); - } -}; - -/** - * Test that isVideoMaster returns success if the IPC API succeeds. - */ -TEST_F(RialtoClientMediaPipelineIsVideoMasterTest, isVideoMasterSuccess) -{ - bool returnIsVideoMaster = !m_isVideoMaster; - - EXPECT_CALL(*m_mediaPipelineIpcMock, isVideoMaster(returnIsVideoMaster)) - .WillOnce(DoAll(SetArgReferee<0>(m_isVideoMaster), Return(true))); - - EXPECT_EQ(m_mediaPipeline->isVideoMaster(returnIsVideoMaster), true); - EXPECT_EQ(returnIsVideoMaster, m_isVideoMaster); -} - -/** - * Test that isVideoMaster returns failure if the IPC API fails. - */ -TEST_F(RialtoClientMediaPipelineIsVideoMasterTest, isVideoMasterFailure) -{ - EXPECT_CALL(*m_mediaPipelineIpcMock, isVideoMaster(m_isVideoMaster)).WillOnce(Return(false)); - - EXPECT_EQ(m_mediaPipeline->isVideoMaster(m_isVideoMaster), false); -} diff --git a/tests/unittests/media/client/main/mediaPipelineCapabilities/MediaPipelineCapabilitiesTest.cpp b/tests/unittests/media/client/main/mediaPipelineCapabilities/MediaPipelineCapabilitiesTest.cpp index b48532202..6b77b620c 100644 --- a/tests/unittests/media/client/main/mediaPipelineCapabilities/MediaPipelineCapabilitiesTest.cpp +++ b/tests/unittests/media/client/main/mediaPipelineCapabilities/MediaPipelineCapabilitiesTest.cpp @@ -102,6 +102,15 @@ TEST_F(MediaPipelineCapabilitiesTest, getSupportedProperties) EXPECT_EQ(supportedProperties, kProperties); } +TEST_F(MediaPipelineCapabilitiesTest, isVideoMaster) +{ + bool isMaster{false}; + createMediaPipelineCapabilitiesIpcSucceeds(); + + EXPECT_CALL(*m_mediaPipelineCapabilitiesIpcMock, isVideoMaster(isMaster)).WillOnce(Return(true)); + EXPECT_TRUE(m_sut->isVideoMaster(isMaster)); +} + /** * Test the factory failure */ diff --git a/tests/unittests/media/client/mocks/ipc/MediaPipelineCapabilitiesIpcMock.h b/tests/unittests/media/client/mocks/ipc/MediaPipelineCapabilitiesIpcMock.h index 7e6ac845a..4b90da019 100644 --- a/tests/unittests/media/client/mocks/ipc/MediaPipelineCapabilitiesIpcMock.h +++ b/tests/unittests/media/client/mocks/ipc/MediaPipelineCapabilitiesIpcMock.h @@ -38,6 +38,7 @@ class MediaPipelineCapabilitiesIpcMock : public IMediaPipelineCapabilities MOCK_METHOD(bool, isMimeTypeSupported, (const std::string &mimeType), (override)); MOCK_METHOD(std::vector, getSupportedProperties, (MediaSourceType mediaType, const std::vector &propertyNames), (override)); + MOCK_METHOD(bool, isVideoMaster, (bool &isVideoMaster), (override)); }; } // namespace firebolt::rialto::client diff --git a/tests/unittests/media/client/mocks/ipc/MediaPipelineIpcMock.h b/tests/unittests/media/client/mocks/ipc/MediaPipelineIpcMock.h index 76892a14a..b0aeaac29 100644 --- a/tests/unittests/media/client/mocks/ipc/MediaPipelineIpcMock.h +++ b/tests/unittests/media/client/mocks/ipc/MediaPipelineIpcMock.h @@ -73,7 +73,6 @@ class MediaPipelineIpcMock : public IMediaPipelineIpc MOCK_METHOD(bool, setUseBuffering, (bool useBuffering), (override)); MOCK_METHOD(bool, getUseBuffering, (bool &useBuffering), (override)); MOCK_METHOD(bool, switchSource, (const std::unique_ptr &source), (override)); - MOCK_METHOD(bool, isVideoMaster, (bool &isVideoMaster), (override)); }; } // namespace firebolt::rialto::client diff --git a/tests/unittests/media/client/mocks/main/MediaPipelineAndControlClientMock.h b/tests/unittests/media/client/mocks/main/MediaPipelineAndControlClientMock.h index b4c6ff1d7..a1e4954bc 100644 --- a/tests/unittests/media/client/mocks/main/MediaPipelineAndControlClientMock.h +++ b/tests/unittests/media/client/mocks/main/MediaPipelineAndControlClientMock.h @@ -88,7 +88,6 @@ class MediaPipelineAndControlClientMock : public IMediaPipelineAndIControlClient MOCK_METHOD(bool, setUseBuffering, (bool useBuffering), (override)); MOCK_METHOD(bool, getUseBuffering, (bool &useBuffering), (override)); MOCK_METHOD(bool, switchSource, (const std::unique_ptr &source), (override)); - MOCK_METHOD(bool, isVideoMaster, (bool &isVideoMaster), (override)); }; } // namespace firebolt::rialto::client diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/GstCapabilitiesTest.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/GstCapabilitiesTest.cpp index 4e9c61282..9d9940488 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/GstCapabilitiesTest.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/GstCapabilitiesTest.cpp @@ -883,3 +883,39 @@ TEST_F(GstCapabilitiesTest, CreateGstCapabilities_GetSubtitlesMimeTypes) EXPECT_EQ(m_sut->getSupportedMimeTypes(MediaSourceType::SUBTITLE), kSubtitleMimeTypes); } + +TEST_F(GstCapabilitiesTest, shouldFailToCheckIfVideoIsMasterWhenRegistryIsNull) +{ + createSutWithNoDecoderAndNoSink(); + + EXPECT_CALL(*m_gstWrapperMock, gstRegistryGet()).WillOnce(Return(nullptr)); + bool isVideoMaster{false}; + EXPECT_FALSE(m_sut->isVideoMaster(isVideoMaster)); +} + +TEST_F(GstCapabilitiesTest, shouldCheckIfVideoIsMasterAndReturnTrue) +{ + createSutWithNoDecoderAndNoSink(); + + GstRegistry registry{}; + EXPECT_CALL(*m_gstWrapperMock, gstRegistryGet()).WillOnce(Return(®istry)); + EXPECT_CALL(*m_gstWrapperMock, gstRegistryLookupFeature(®istry, StrEq("amlhalasink"))).WillOnce(Return(nullptr)); + bool isVideoMaster{false}; + EXPECT_TRUE(m_sut->isVideoMaster(isVideoMaster)); + EXPECT_TRUE(isVideoMaster); +} + +TEST_F(GstCapabilitiesTest, shouldCheckIfVideoIsMasterAndReturnFalse) +{ + createSutWithNoDecoderAndNoSink(); + + GstRegistry registry{}; + GstObject feature{}; + EXPECT_CALL(*m_gstWrapperMock, gstRegistryGet()).WillOnce(Return(®istry)); + EXPECT_CALL(*m_gstWrapperMock, gstRegistryLookupFeature(®istry, StrEq("amlhalasink"))) + .WillOnce(Return(GST_PLUGIN_FEATURE(&feature))); + EXPECT_CALL(*m_gstWrapperMock, gstObjectUnref(GST_PLUGIN_FEATURE(&feature))); + bool isVideoMaster{false}; + EXPECT_TRUE(m_sut->isVideoMaster(isVideoMaster)); + EXPECT_FALSE(isVideoMaster); +} diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerTest.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerTest.cpp index 1003fccb2..e3ae84101 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerTest.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerTest.cpp @@ -1053,33 +1053,3 @@ TEST_F(GstGenericPlayerTest, shouldSwitchSource) m_sut->switchSource(source); } - -TEST_F(GstGenericPlayerTest, shouldFailToCheckIfVideoIsMasterWhenRegistryIsNull) -{ - EXPECT_CALL(*m_gstWrapperMock, gstRegistryGet()).WillOnce(Return(nullptr)); - bool isVideoMaster{false}; - EXPECT_FALSE(m_sut->isVideoMaster(isVideoMaster)); -} - -TEST_F(GstGenericPlayerTest, shouldCheckIfVideoIsMasterAndReturnTrue) -{ - GstRegistry registry{}; - EXPECT_CALL(*m_gstWrapperMock, gstRegistryGet()).WillOnce(Return(®istry)); - EXPECT_CALL(*m_gstWrapperMock, gstRegistryLookupFeature(®istry, StrEq("amlhalasink"))).WillOnce(Return(nullptr)); - bool isVideoMaster{false}; - EXPECT_TRUE(m_sut->isVideoMaster(isVideoMaster)); - EXPECT_TRUE(isVideoMaster); -} - -TEST_F(GstGenericPlayerTest, shouldCheckIfVideoIsMasterAndReturnFalse) -{ - GstRegistry registry{}; - GstObject feature{}; - EXPECT_CALL(*m_gstWrapperMock, gstRegistryGet()).WillOnce(Return(®istry)); - EXPECT_CALL(*m_gstWrapperMock, gstRegistryLookupFeature(®istry, StrEq("amlhalasink"))) - .WillOnce(Return(GST_PLUGIN_FEATURE(&feature))); - EXPECT_CALL(*m_gstWrapperMock, gstObjectUnref(GST_PLUGIN_FEATURE(&feature))); - bool isVideoMaster{false}; - EXPECT_TRUE(m_sut->isVideoMaster(isVideoMaster)); - EXPECT_FALSE(isVideoMaster); -} diff --git a/tests/unittests/media/server/ipc/mediaPipelineCapabilitiesModule/MediaPipelineCapabilitiesModuleServiceTests.cpp b/tests/unittests/media/server/ipc/mediaPipelineCapabilitiesModule/MediaPipelineCapabilitiesModuleServiceTests.cpp index 17c38161f..75d8697dc 100644 --- a/tests/unittests/media/server/ipc/mediaPipelineCapabilitiesModule/MediaPipelineCapabilitiesModuleServiceTests.cpp +++ b/tests/unittests/media/server/ipc/mediaPipelineCapabilitiesModule/MediaPipelineCapabilitiesModuleServiceTests.cpp @@ -65,3 +65,15 @@ TEST_F(MediaPipelineCapabilitiesModuleServiceTests, shouldConvertMediaType) { expectCorrectMediaTypeConversion(); } + +TEST_F(MediaPipelineCapabilitiesModuleServiceTests, shouldCheckIfVideoIsMaster) +{ + mediaPipelineWillCheckIfVideoIsMaster(); + sendIsVideoMasterRequestWithSuccess(); +} + +TEST_F(MediaPipelineCapabilitiesModuleServiceTests, shouldFailToCheckIfVideoIsMaster) +{ + expectInvalidControlFailure(); + sendIsVideoMasterRequestAndExpectFailure(); +} diff --git a/tests/unittests/media/server/ipc/mediaPipelineCapabilitiesModule/MediaPipelineCapabilitiesModuleServiceTestsFixture.cpp b/tests/unittests/media/server/ipc/mediaPipelineCapabilitiesModule/MediaPipelineCapabilitiesModuleServiceTestsFixture.cpp index ff47788a6..cd5f796b2 100644 --- a/tests/unittests/media/server/ipc/mediaPipelineCapabilitiesModule/MediaPipelineCapabilitiesModuleServiceTestsFixture.cpp +++ b/tests/unittests/media/server/ipc/mediaPipelineCapabilitiesModule/MediaPipelineCapabilitiesModuleServiceTestsFixture.cpp @@ -40,6 +40,7 @@ const std::vector kMimeTypes{"video/h264", "video/h265"}; const firebolt::rialto::MediaSourceType kSourceType{firebolt::rialto::MediaSourceType::VIDEO}; const firebolt::rialto::ProtoMediaSourceType kMediaSourceType{firebolt::rialto::ProtoMediaSourceType::VIDEO}; const std::vector kPropertyNames{"test-property", "another-property"}; +constexpr bool kIsVideoMaster{true}; } // namespace MediaPipelineCapabilitiesModuleServiceTests::MediaPipelineCapabilitiesModuleServiceTests() @@ -80,6 +81,13 @@ void MediaPipelineCapabilitiesModuleServiceTests::mediaPipelineWillGetSupportedP .WillOnce(Return(kPropertyNames)); } +void MediaPipelineCapabilitiesModuleServiceTests::mediaPipelineWillCheckIfVideoIsMaster() +{ + expectRequestSuccess(); + EXPECT_CALL(m_mediaPipelineServiceMock, isVideoMaster(_)) + .WillOnce(DoAll(SetArgReferee<0>(kIsVideoMaster), Return(true))); +} + void MediaPipelineCapabilitiesModuleServiceTests::expectRequestSuccess() { EXPECT_CALL(*m_closureMock, Run()); @@ -170,6 +178,23 @@ void MediaPipelineCapabilitiesModuleServiceTests::sendGetSupportedPropertiesRequ EXPECT_TRUE(supportedProperties.empty()); } +void MediaPipelineCapabilitiesModuleServiceTests::sendIsVideoMasterRequestWithSuccess() +{ + firebolt::rialto::IsVideoMasterRequest request; + firebolt::rialto::IsVideoMasterResponse response; + + m_service->isVideoMaster(m_controllerMock.get(), &request, &response, m_closureMock.get()); + + EXPECT_EQ(response.is_video_master(), kIsVideoMaster); +} + +void MediaPipelineCapabilitiesModuleServiceTests::sendIsVideoMasterRequestAndExpectFailure() +{ + firebolt::rialto::IsVideoMasterRequest request; + firebolt::rialto::IsVideoMasterResponse response; + m_service->isVideoMaster(m_invalidControllerMock.get(), &request, &response, m_closureMock.get()); +} + void MediaPipelineCapabilitiesModuleServiceTests::expectCorrectMediaTypeConversion() { EXPECT_EQ(firebolt::rialto::server::ipc::convertMediaSourceType(firebolt::rialto::ProtoMediaSourceType::UNKNOWN), diff --git a/tests/unittests/media/server/ipc/mediaPipelineCapabilitiesModule/MediaPipelineCapabilitiesModuleServiceTestsFixture.h b/tests/unittests/media/server/ipc/mediaPipelineCapabilitiesModule/MediaPipelineCapabilitiesModuleServiceTestsFixture.h index beb677c97..cd4583972 100644 --- a/tests/unittests/media/server/ipc/mediaPipelineCapabilitiesModule/MediaPipelineCapabilitiesModuleServiceTestsFixture.h +++ b/tests/unittests/media/server/ipc/mediaPipelineCapabilitiesModule/MediaPipelineCapabilitiesModuleServiceTestsFixture.h @@ -42,6 +42,7 @@ class MediaPipelineCapabilitiesModuleServiceTests : public testing::Test void mediaPipelineServiceWillGetSupportedMimeTypes(); void mediaPipelineWillCheckIfMimeTypeIsSupported(); void mediaPipelineWillGetSupportedProperties(); + void mediaPipelineWillCheckIfVideoIsMaster(); void sendClientConnected(); void sendClientDisconnected(); @@ -51,6 +52,8 @@ class MediaPipelineCapabilitiesModuleServiceTests : public testing::Test void sendIsMimeTypeSupportedRequestAndExpectFailure(); void sendGetSupportedPropertiesRequestWithSuccess(); void sendGetSupportedPropertiesRequestAndExpectFailure(); + void sendIsVideoMasterRequestWithSuccess(); + void sendIsVideoMasterRequestAndExpectFailure(); void expectInvalidControlFailure(); void expectCorrectMediaTypeConversion(); diff --git a/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTests.cpp b/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTests.cpp index 8c40201cf..014888d24 100644 --- a/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTests.cpp +++ b/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTests.cpp @@ -596,15 +596,3 @@ TEST_F(MediaPipelineModuleServiceTests, shouldFailToGetUseBuffering) mediaPipelineServiceWillFailToGetUseBuffering(); sendGetUseBufferingRequestAndReceiveResponseWithoutMatch(); } - -TEST_F(MediaPipelineModuleServiceTests, shouldCheckIfVideoIsMaster) -{ - mediaPipelineServiceWillCheckIfVideoIsMaster(); - sendIsVideoMasterRequestAndReceiveResponse(); -} - -TEST_F(MediaPipelineModuleServiceTests, shouldFailToCheckIfVideoIsMaster) -{ - mediaPipelineServiceWillFailToCheckIfVideoIsMaster(); - sendIsVideoMasterRequestAndReceiveResponseWithoutMatch(); -} diff --git a/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTestsFixture.cpp b/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTestsFixture.cpp index 08448c080..80ed6c280 100644 --- a/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTestsFixture.cpp +++ b/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTestsFixture.cpp @@ -809,19 +809,6 @@ void MediaPipelineModuleServiceTests::mediaPipelineServiceWillFailToGetUseBuffer EXPECT_CALL(m_mediaPipelineServiceMock, getUseBuffering(kHardcodedSessionId, _)).WillOnce(Return(false)); } -void MediaPipelineModuleServiceTests::mediaPipelineServiceWillCheckIfVideoIsMaster() -{ - expectRequestSuccess(); - EXPECT_CALL(m_mediaPipelineServiceMock, isVideoMaster(kHardcodedSessionId, _)) - .WillOnce(DoAll(SetArgReferee<1>(kIsVideoMaster), Return(true))); -} - -void MediaPipelineModuleServiceTests::mediaPipelineServiceWillFailToCheckIfVideoIsMaster() -{ - expectRequestFailure(); - EXPECT_CALL(m_mediaPipelineServiceMock, isVideoMaster(kHardcodedSessionId, _)).WillOnce(Return(false)); -} - void MediaPipelineModuleServiceTests::mediaClientWillSendPlaybackStateChangedEvent() { EXPECT_CALL(*m_clientMock, sendEvent(PlaybackStateChangeEventMatcher(convertPlaybackState(kPlaybackState)))); @@ -1508,28 +1495,6 @@ void MediaPipelineModuleServiceTests::sendGetUseBufferingRequestAndReceiveRespon m_service->getUseBuffering(m_controllerMock.get(), &request, &response, m_closureMock.get()); } -void MediaPipelineModuleServiceTests::sendIsVideoMasterRequestAndReceiveResponse() -{ - firebolt::rialto::IsVideoMasterRequest request; - firebolt::rialto::IsVideoMasterResponse response; - - request.set_session_id(kHardcodedSessionId); - - m_service->isVideoMaster(m_controllerMock.get(), &request, &response, m_closureMock.get()); - - EXPECT_EQ(kIsVideoMaster, response.is_video_master()); -} - -void MediaPipelineModuleServiceTests::sendIsVideoMasterRequestAndReceiveResponseWithoutMatch() -{ - firebolt::rialto::IsVideoMasterRequest request; - firebolt::rialto::IsVideoMasterResponse response; - - request.set_session_id(kHardcodedSessionId); - - m_service->isVideoMaster(m_controllerMock.get(), &request, &response, m_closureMock.get()); -} - void MediaPipelineModuleServiceTests::sendPlaybackStateChangedEvent() { ASSERT_TRUE(m_mediaPipelineClient); diff --git a/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTestsFixture.h b/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTestsFixture.h index e77007627..a3ce21e04 100644 --- a/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTestsFixture.h +++ b/tests/unittests/media/server/ipc/mediaPipelineModuleService/MediaPipelineModuleServiceTestsFixture.h @@ -120,8 +120,6 @@ class MediaPipelineModuleServiceTests : public testing::Test void mediaPipelineServiceWillFailToSetUseBuffering(); void mediaPipelineServiceWillGetUseBuffering(); void mediaPipelineServiceWillFailToGetUseBuffering(); - void mediaPipelineServiceWillCheckIfVideoIsMaster(); - void mediaPipelineServiceWillFailToCheckIfVideoIsMaster(); void mediaClientWillSendPlaybackStateChangedEvent(); void mediaClientWillSendNetworkStateChangedEvent(); @@ -186,8 +184,6 @@ class MediaPipelineModuleServiceTests : public testing::Test void sendSetUseBufferingRequestAndReceiveResponse(); void sendGetUseBufferingRequestAndReceiveResponse(); void sendGetUseBufferingRequestAndReceiveResponseWithoutMatch(); - void sendIsVideoMasterRequestAndReceiveResponse(); - void sendIsVideoMasterRequestAndReceiveResponseWithoutMatch(); void sendPlaybackStateChangedEvent(); void sendNetworkStateChangedEvent(); diff --git a/tests/unittests/media/server/main/mediaPipeline/MiscellaneousFunctionsTest.cpp b/tests/unittests/media/server/main/mediaPipeline/MiscellaneousFunctionsTest.cpp index 7100bbffe..b932f0887 100644 --- a/tests/unittests/media/server/main/mediaPipeline/MiscellaneousFunctionsTest.cpp +++ b/tests/unittests/media/server/main/mediaPipeline/MiscellaneousFunctionsTest.cpp @@ -940,43 +940,6 @@ TEST_F(RialtoServerMediaPipelineMiscellaneousFunctionsTest, GetUseBufferingSucce EXPECT_EQ(resultUseBuffering, kUseBuffering); } -/** - * Test that IsVideoMaster returns failure if the gstreamer player is not initialized - */ -TEST_F(RialtoServerMediaPipelineMiscellaneousFunctionsTest, IsVideoMasterFailureDueToUninitializedPlayer) -{ - mainThreadWillEnqueueTaskAndWait(); - bool resultIsVideoMaster{}; - EXPECT_FALSE(m_mediaPipeline->isVideoMaster(resultIsVideoMaster)); -} - -/** - * Test that IsVideoMaster returns failure if the gstreamer API fails - */ -TEST_F(RialtoServerMediaPipelineMiscellaneousFunctionsTest, IsVideoMasterFailure) -{ - loadGstPlayer(); - mainThreadWillEnqueueTaskAndWait(); - bool resultIsVideoMaster{}; - EXPECT_CALL(*m_gstPlayerMock, isVideoMaster(_)).WillOnce(Return(false)); - EXPECT_FALSE(m_mediaPipeline->isVideoMaster(resultIsVideoMaster)); -} - -/** - * Test that IsVideoMaster returns success if the gstreamer API succeeds - */ -TEST_F(RialtoServerMediaPipelineMiscellaneousFunctionsTest, IsVideoMasterSuccess) -{ - constexpr bool kIsVideoMaster{true}; - bool resultIsVideoMaster{}; - loadGstPlayer(); - mainThreadWillEnqueueTaskAndWait(); - EXPECT_CALL(*m_gstPlayerMock, isVideoMaster(_)).WillOnce(DoAll(SetArgReferee<0>(kIsVideoMaster), Return(true))); - - EXPECT_TRUE(m_mediaPipeline->isVideoMaster(resultIsVideoMaster)); - EXPECT_EQ(resultIsVideoMaster, kIsVideoMaster); -} - /** * Test that active requests are invalidated successfully */ diff --git a/tests/unittests/media/server/main/mediaPipelineCapabilities/MediaPipelineCapabilitiesTest.cpp b/tests/unittests/media/server/main/mediaPipelineCapabilities/MediaPipelineCapabilitiesTest.cpp index 784004fd3..a7e0396d7 100644 --- a/tests/unittests/media/server/main/mediaPipelineCapabilities/MediaPipelineCapabilitiesTest.cpp +++ b/tests/unittests/media/server/main/mediaPipelineCapabilities/MediaPipelineCapabilitiesTest.cpp @@ -149,3 +149,13 @@ TEST_F(MediaPipelineCapabilitiesTest, getSupportedProperties) std::vector supportedProperties{m_sut->getSupportedProperties(kMediaType, kProperties)}; EXPECT_EQ(kProperties, supportedProperties); } + +TEST_F(MediaPipelineCapabilitiesTest, isVideoMaster) +{ + bool isMaster{false}; + + EXPECT_CALL(*m_gstCapabilities, isVideoMaster(isMaster)).WillOnce(Return(true)); + + createMediaPipelineCapabilities(); + EXPECT_TRUE(m_sut->isVideoMaster(isMaster)); +} diff --git a/tests/unittests/media/server/mocks/gstplayer/GstCapabilitiesMock.h b/tests/unittests/media/server/mocks/gstplayer/GstCapabilitiesMock.h index 345705d48..dcc8bacaa 100644 --- a/tests/unittests/media/server/mocks/gstplayer/GstCapabilitiesMock.h +++ b/tests/unittests/media/server/mocks/gstplayer/GstCapabilitiesMock.h @@ -34,6 +34,7 @@ class GstCapabilitiesMock : public IGstCapabilities MOCK_METHOD(bool, isMimeTypeSupported, (const std::string &mimeType), (override)); MOCK_METHOD(std::vector, getSupportedProperties, (MediaSourceType mediaType, const std::vector &propertyNames), (override)); + MOCK_METHOD(bool, isVideoMaster, (bool &isVideoMaster), (override)); }; } // namespace firebolt::rialto::server diff --git a/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerMock.h b/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerMock.h index e998224ab..224147f1d 100644 --- a/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerMock.h +++ b/tests/unittests/media/server/mocks/gstplayer/GstGenericPlayerMock.h @@ -77,7 +77,6 @@ class GstGenericPlayerMock : public IGstGenericPlayer MOCK_METHOD(void, setUseBuffering, (bool useBuffering), (override)); MOCK_METHOD(bool, getUseBuffering, (bool &useBuffering), (override)); MOCK_METHOD(void, switchSource, (const std::unique_ptr &mediaSource), (override)); - MOCK_METHOD(bool, isVideoMaster, (bool &isVideoMaster), (override)); }; } // namespace firebolt::rialto::server diff --git a/tests/unittests/media/server/mocks/main/MediaPipelineCapabilitiesMock.h b/tests/unittests/media/server/mocks/main/MediaPipelineCapabilitiesMock.h index 87a295f42..d317b39ca 100644 --- a/tests/unittests/media/server/mocks/main/MediaPipelineCapabilitiesMock.h +++ b/tests/unittests/media/server/mocks/main/MediaPipelineCapabilitiesMock.h @@ -35,6 +35,7 @@ class MediaPipelineCapabilitiesMock : public IMediaPipelineCapabilities MOCK_METHOD(bool, isMimeTypeSupported, (const std::string &mimeType), (override)); MOCK_METHOD(std::vector, getSupportedProperties, (MediaSourceType mediaType, const std::vector &propertyNames), (override)); + MOCK_METHOD(bool, isVideoMaster, (bool &isVideoMaster), (override)); }; } // namespace firebolt::rialto::server diff --git a/tests/unittests/media/server/mocks/main/MediaPipelineServerInternalMock.h b/tests/unittests/media/server/mocks/main/MediaPipelineServerInternalMock.h index fbce6065d..a25c29d8f 100644 --- a/tests/unittests/media/server/mocks/main/MediaPipelineServerInternalMock.h +++ b/tests/unittests/media/server/mocks/main/MediaPipelineServerInternalMock.h @@ -75,7 +75,6 @@ class MediaPipelineServerInternalMock : public IMediaPipelineServerInternal MOCK_METHOD(bool, setUseBuffering, (bool useBuffering), (override)); MOCK_METHOD(bool, getUseBuffering, (bool &useBuffering), (override)); MOCK_METHOD(bool, switchSource, (const std::unique_ptr &source), (override)); - MOCK_METHOD(bool, isVideoMaster, (bool &isVideoMaster), (override)); }; } // namespace firebolt::rialto::server diff --git a/tests/unittests/media/server/mocks/service/MediaPipelineServiceMock.h b/tests/unittests/media/server/mocks/service/MediaPipelineServiceMock.h index 0aa3796a2..47022425f 100644 --- a/tests/unittests/media/server/mocks/service/MediaPipelineServiceMock.h +++ b/tests/unittests/media/server/mocks/service/MediaPipelineServiceMock.h @@ -78,7 +78,7 @@ class MediaPipelineServiceMock : public IMediaPipelineService MOCK_METHOD(bool, setUseBuffering, (int sessionId, bool useBuffering), (override)); MOCK_METHOD(bool, getUseBuffering, (int sessionId, bool &useBuffering), (override)); MOCK_METHOD(bool, switchSource, (int, const std::unique_ptr &), (override)); - MOCK_METHOD(bool, isVideoMaster, (int sessionId, bool &isVideoMaster), (override)); + MOCK_METHOD(bool, isVideoMaster, (bool &isVideoMaster), (override)); MOCK_METHOD(std::vector, getSupportedMimeTypes, (MediaSourceType type), (override)); MOCK_METHOD(bool, isMimeTypeSupported, (const std::string &mimeType), (override)); MOCK_METHOD(std::vector, getSupportedProperties, diff --git a/tests/unittests/media/server/service/mediaPipelineService/MediaPipelineServiceTestsFixture.cpp b/tests/unittests/media/server/service/mediaPipelineService/MediaPipelineServiceTestsFixture.cpp index b64a961d0..9b9e441dd 100644 --- a/tests/unittests/media/server/service/mediaPipelineService/MediaPipelineServiceTestsFixture.cpp +++ b/tests/unittests/media/server/service/mediaPipelineService/MediaPipelineServiceTestsFixture.cpp @@ -488,12 +488,12 @@ void MediaPipelineServiceTests::mediaPipelineWillFailToSwitchSource() void MediaPipelineServiceTests::mediaPipelineWillCheckIfVideoIsMaster() { - EXPECT_CALL(m_mediaPipelineMock, isVideoMaster(_)).WillOnce(Return(true)); + EXPECT_CALL(m_mediaPipelineCapabilitiesMock, isVideoMaster(_)).WillOnce(Return(true)); } void MediaPipelineServiceTests::mediaPipelineWillFailToCheckIfVideoIsMaster() { - EXPECT_CALL(m_mediaPipelineMock, isVideoMaster(_)).WillOnce(Return(false)); + EXPECT_CALL(m_mediaPipelineCapabilitiesMock, isVideoMaster(_)).WillOnce(Return(false)); } void MediaPipelineServiceTests::mediaPipelineWillPing() @@ -1008,13 +1008,13 @@ void MediaPipelineServiceTests::switchSourceShouldFail() void MediaPipelineServiceTests::isVideoMasterShouldSucceed() { bool isMaster{false}; - EXPECT_TRUE(m_sut->isVideoMaster(kSessionId, isMaster)); + EXPECT_TRUE(m_sut->isVideoMaster(isMaster)); } void MediaPipelineServiceTests::isVideoMasterShouldFail() { bool isMaster{false}; - EXPECT_FALSE(m_sut->isVideoMaster(kSessionId, isMaster)); + EXPECT_FALSE(m_sut->isVideoMaster(isMaster)); } void MediaPipelineServiceTests::clearMediaPipelines() From 4d09c70b53942506416029d09a8afb1b24866f5c Mon Sep 17 00:00:00 2001 From: Marcin Wojciechowski <105790697+skywojciechowskim@users.noreply.github.com> Date: Tue, 12 Aug 2025 10:45:12 +0200 Subject: [PATCH 15/15] Logging improvement (#401) Summary: Logging improvement Type: Feature Test Plan: UT/ CT, Fullstack Jira: VPLAY-1495 --- media/client/main/source/ClientController.cpp | 4 ++-- media/server/gstplayer/source/GstGenericPlayer.cpp | 7 +++++++ media/server/gstplayer/source/GstWebAudioPlayer.cpp | 3 +++ .../gstplayer/source/tasks/generic/AttachSource.cpp | 11 +++++++---- .../source/tasks/generic/FinishSetupSource.cpp | 2 ++ .../server/gstplayer/source/tasks/generic/Flush.cpp | 2 ++ .../source/tasks/generic/HandleBusMessage.cpp | 8 ++++---- .../server/gstplayer/source/tasks/generic/Pause.cpp | 1 + media/server/gstplayer/source/tasks/generic/Play.cpp | 1 + .../tasks/generic/ReadShmDataAndAttachSamples.cpp | 8 +++++++- .../gstplayer/source/tasks/generic/RemoveSource.cpp | 2 ++ .../gstplayer/source/tasks/generic/SetMute.cpp | 3 +++ .../source/tasks/generic/SetPlaybackRate.cpp | 2 +- .../gstplayer/source/tasks/generic/SetPosition.cpp | 4 +++- media/server/gstplayer/source/tasks/generic/Stop.cpp | 1 + .../gstplayer/source/tasks/generic/SwitchSource.cpp | 3 +++ media/server/gstplayer/source/tasks/webAudio/Eos.cpp | 1 + .../source/tasks/webAudio/HandleBusMessage.cpp | 8 ++++---- .../server/gstplayer/source/tasks/webAudio/Pause.cpp | 1 + .../server/gstplayer/source/tasks/webAudio/Play.cpp | 1 + .../gstplayer/source/tasks/webAudio/SetCaps.cpp | 1 + .../server/gstplayer/source/tasks/webAudio/Stop.cpp | 1 + .../ipc/source/ApplicationManagementServer.cpp | 3 ++- media/server/ipc/source/SessionManagementServer.cpp | 7 +++++++ media/server/main/source/ControlServerInternal.cpp | 2 +- media/server/main/source/MediaKeySession.cpp | 2 ++ media/server/service/source/SessionServerManager.cpp | 3 +++ .../server/fixtures/MediaPipelineTest.cpp | 4 ++++ .../tests/mediaPipeline/DualVideoPlaybackTest.cpp | 2 ++ .../genericPlayer/common/GenericTasksTestsBase.cpp | 12 ++++++++++++ 30 files changed, 91 insertions(+), 19 deletions(-) diff --git a/media/client/main/source/ClientController.cpp b/media/client/main/source/ClientController.cpp index 8c27413e7..eac82154c 100644 --- a/media/client/main/source/ClientController.cpp +++ b/media/client/main/source/ClientController.cpp @@ -257,8 +257,8 @@ void ClientController::changeStateAndNotifyClients(ApplicationState state) std::vector> currentClients; { std::lock_guard lock{m_mutex}; - RIALTO_CLIENT_LOG_INFO("Rialto application state changed from %s to %s", stateToString(m_currentState).c_str(), - stateToString(state).c_str()); + RIALTO_CLIENT_LOG_MIL("Rialto application state changed from %s to %s", stateToString(m_currentState).c_str(), + stateToString(state).c_str()); m_currentState = state; for (const std::weak_ptr &client : m_clients) { diff --git a/media/server/gstplayer/source/GstGenericPlayer.cpp b/media/server/gstplayer/source/GstGenericPlayer.cpp index f0363de95..1e6f9f0f7 100644 --- a/media/server/gstplayer/source/GstGenericPlayer.cpp +++ b/media/server/gstplayer/source/GstGenericPlayer.cpp @@ -243,6 +243,7 @@ void GstGenericPlayer::initMsePipeline() { GST_WARNING("No playsink ?!?!?"); } + RIALTO_SERVER_LOG_MIL("New RialtoServer's pipeline created"); } void GstGenericPlayer::resetWorkerThread() @@ -289,6 +290,8 @@ void GstGenericPlayer::termPipeline() // Delete the pipeline m_gstWrapper->gstObjectUnref(m_context.pipeline); + + RIALTO_SERVER_LOG_MIL("RialtoServer's pipeline terminated"); } unsigned GstGenericPlayer::getGstPlayFlag(const char *nick) @@ -395,6 +398,7 @@ bool GstGenericPlayer::getPosition(std::int64_t &position) } if (!m_gstWrapper->gstElementQueryPosition(m_context.pipeline, GST_FORMAT_TIME, &position)) { + RIALTO_SERVER_LOG_WARN("Query position failed"); return false; } return true; @@ -811,6 +815,7 @@ void GstGenericPlayer::attachData(const firebolt::rialto::MediaSourceType mediaT { m_context.bufferedNotificationSent = true; m_gstPlayerClient->notifyNetworkState(NetworkState::BUFFERED); + RIALTO_SERVER_LOG_MIL("Buffered NetworkState reached"); } cancelUnderflow(mediaType); @@ -1010,6 +1015,8 @@ void GstGenericPlayer::setTextTrackPositionIfRequired(GstElement *source) return; } + RIALTO_SERVER_LOG_MIL("New subtitle position set %" GST_TIME_FORMAT, + GST_TIME_ARGS(initialPosition->second.back().position)); m_glibWrapper->gObjectSet(m_context.subtitleSink, "position", static_cast(initialPosition->second.back().position), nullptr); diff --git a/media/server/gstplayer/source/GstWebAudioPlayer.cpp b/media/server/gstplayer/source/GstWebAudioPlayer.cpp index d71b51ddc..ef6aa666a 100644 --- a/media/server/gstplayer/source/GstWebAudioPlayer.cpp +++ b/media/server/gstplayer/source/GstWebAudioPlayer.cpp @@ -154,6 +154,8 @@ bool GstWebAudioPlayer::initWebAudioPipeline(const uint32_t priority) return false; } + RIALTO_SERVER_LOG_MIL("RialtoServer's webaudio pipeline constructed"); + // Create and initalise appsrc m_context.source = m_gstWrapper->gstElementFactoryMake("appsrc", "audsrc"); if (!m_context.source) @@ -367,6 +369,7 @@ void GstWebAudioPlayer::termWebAudioPipeline() m_gstWrapper->gstObjectUnref(m_context.pipeline); } + RIALTO_SERVER_LOG_MIL("RialtoServer's webaudio pipeline terminated."); } void GstWebAudioPlayer::resetWorkerThread() diff --git a/media/server/gstplayer/source/tasks/generic/AttachSource.cpp b/media/server/gstplayer/source/tasks/generic/AttachSource.cpp index 567d26e70..f65daa212 100644 --- a/media/server/gstplayer/source/tasks/generic/AttachSource.cpp +++ b/media/server/gstplayer/source/tasks/generic/AttachSource.cpp @@ -77,21 +77,21 @@ void AttachSource::addSource() const RIALTO_SERVER_LOG_ERROR("Failed to create caps from media source"); return; } - + gchar *capsStr = m_gstWrapper->gstCapsToString(caps); GstElement *appSrc = nullptr; if (m_attachedSource->getType() == MediaSourceType::AUDIO) { - RIALTO_SERVER_LOG_MIL("Adding Audio appsrc"); + RIALTO_SERVER_LOG_MIL("Adding Audio appsrc with caps %s", capsStr); appSrc = m_gstWrapper->gstElementFactoryMake("appsrc", "audsrc"); } else if (m_attachedSource->getType() == MediaSourceType::VIDEO) { - RIALTO_SERVER_LOG_MIL("Adding Video appsrc"); + RIALTO_SERVER_LOG_MIL("Adding Video appsrc with caps %s", capsStr); appSrc = m_gstWrapper->gstElementFactoryMake("appsrc", "vidsrc"); } else if (m_attachedSource->getType() == MediaSourceType::SUBTITLE) { - RIALTO_SERVER_LOG_MIL("Adding Subtitle appsrc"); + RIALTO_SERVER_LOG_MIL("Adding Subtitle appsrc with caps %s", capsStr); appSrc = m_gstWrapper->gstElementFactoryMake("appsrc", "subsrc"); if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(m_context.pipeline), "text-sink")) @@ -102,6 +102,7 @@ void AttachSource::addSource() const m_glibWrapper->gObjectSet(m_context.pipeline, "text-sink", elem, nullptr); } } + m_glibWrapper->gFree(capsStr); m_gstWrapper->gstAppSrcSetCaps(GST_APP_SRC(appSrc), caps); m_context.streamInfo.emplace(m_attachedSource->getType(), StreamInfo{appSrc, m_attachedSource->getHasDrm()}); @@ -124,5 +125,7 @@ void AttachSource::reattachAudioSource() const m_context.streamInfo[m_attachedSource->getType()].isDataNeeded = true; m_context.audioSourceRemoved = false; m_player.notifyNeedMediaData(MediaSourceType::AUDIO); + + RIALTO_SERVER_LOG_MIL("Audio source reattached"); } } // namespace firebolt::rialto::server::tasks::generic diff --git a/media/server/gstplayer/source/tasks/generic/FinishSetupSource.cpp b/media/server/gstplayer/source/tasks/generic/FinishSetupSource.cpp index 7ae44a486..32d539a56 100644 --- a/media/server/gstplayer/source/tasks/generic/FinishSetupSource.cpp +++ b/media/server/gstplayer/source/tasks/generic/FinishSetupSource.cpp @@ -121,5 +121,7 @@ void FinishSetupSource::execute() const m_gstPlayerClient->notifyPlaybackState(PlaybackState::IDLE); m_context.setupSourceFinished = true; + + RIALTO_SERVER_LOG_MIL("All sources attached."); } } // namespace firebolt::rialto::server::tasks::generic diff --git a/media/server/gstplayer/source/tasks/generic/Flush.cpp b/media/server/gstplayer/source/tasks/generic/Flush.cpp index 1343153e0..fca5731f1 100644 --- a/media/server/gstplayer/source/tasks/generic/Flush.cpp +++ b/media/server/gstplayer/source/tasks/generic/Flush.cpp @@ -103,5 +103,7 @@ void Flush::execute() const // Notify GstGenericPlayer, that flush has been finished m_player.setSourceFlushed(m_type); + + RIALTO_SERVER_LOG_MIL("%s source flushed.", common::convertMediaSourceType(m_type)); } } // namespace firebolt::rialto::server::tasks::generic diff --git a/media/server/gstplayer/source/tasks/generic/HandleBusMessage.cpp b/media/server/gstplayer/source/tasks/generic/HandleBusMessage.cpp index 132ecc333..bf88ca1d6 100644 --- a/media/server/gstplayer/source/tasks/generic/HandleBusMessage.cpp +++ b/media/server/gstplayer/source/tasks/generic/HandleBusMessage.cpp @@ -54,10 +54,10 @@ void HandleBusMessage::execute() const { GstState oldState, newState, pending; m_gstWrapper->gstMessageParseStateChanged(m_message, &oldState, &newState, &pending); - RIALTO_SERVER_LOG_INFO("State changed (old: %s, new: %s, pending: %s)", - m_gstWrapper->gstElementStateGetName(oldState), - m_gstWrapper->gstElementStateGetName(newState), - m_gstWrapper->gstElementStateGetName(pending)); + RIALTO_SERVER_LOG_MIL("State changed (old: %s, new: %s, pending: %s)", + m_gstWrapper->gstElementStateGetName(oldState), + m_gstWrapper->gstElementStateGetName(newState), + m_gstWrapper->gstElementStateGetName(pending)); std::string filename = std::string(m_gstWrapper->gstElementStateGetName(oldState)) + "-" + std::string(m_gstWrapper->gstElementStateGetName(newState)); diff --git a/media/server/gstplayer/source/tasks/generic/Pause.cpp b/media/server/gstplayer/source/tasks/generic/Pause.cpp index 4a3bdd1fe..bb97ac3d9 100644 --- a/media/server/gstplayer/source/tasks/generic/Pause.cpp +++ b/media/server/gstplayer/source/tasks/generic/Pause.cpp @@ -39,5 +39,6 @@ void Pause::execute() const m_player.stopPositionReportingAndCheckAudioUnderflowTimer(); m_player.changePipelineState(GST_STATE_PAUSED); m_context.isPlaying = false; + RIALTO_SERVER_LOG_MIL("State change to PAUSED requested"); } } // namespace firebolt::rialto::server::tasks::generic diff --git a/media/server/gstplayer/source/tasks/generic/Play.cpp b/media/server/gstplayer/source/tasks/generic/Play.cpp index 6e0f588de..404a9cba6 100644 --- a/media/server/gstplayer/source/tasks/generic/Play.cpp +++ b/media/server/gstplayer/source/tasks/generic/Play.cpp @@ -37,5 +37,6 @@ void Play::execute() const { RIALTO_SERVER_LOG_DEBUG("Executing Play"); m_player.changePipelineState(GST_STATE_PLAYING); + RIALTO_SERVER_LOG_MIL("State change to PLAYING requested"); } } // namespace firebolt::rialto::server::tasks::generic diff --git a/media/server/gstplayer/source/tasks/generic/ReadShmDataAndAttachSamples.cpp b/media/server/gstplayer/source/tasks/generic/ReadShmDataAndAttachSamples.cpp index 6e220449a..1df7213a7 100644 --- a/media/server/gstplayer/source/tasks/generic/ReadShmDataAndAttachSamples.cpp +++ b/media/server/gstplayer/source/tasks/generic/ReadShmDataAndAttachSamples.cpp @@ -98,7 +98,13 @@ void ReadShmDataAndAttachSamples::execute() const // All segments in vector have the same type if (!mediaSegments.empty()) { - m_player.notifyNeedMediaData(mediaSegments.front()->getType()); + const auto kMediaType{mediaSegments.front()->getType()}; + const auto kFirstTimestamp{mediaSegments.front()->getTimeStamp()}; + const auto kLastTimestamp{mediaSegments.back()->getTimeStamp()}; + RIALTO_SERVER_LOG_DEBUG("%s data received. First ts: %" GST_TIME_FORMAT " last ts: %" GST_TIME_FORMAT, + common::convertMediaSourceType(kMediaType), GST_TIME_ARGS(kFirstTimestamp), + GST_TIME_ARGS(kLastTimestamp)); + m_player.notifyNeedMediaData(kMediaType); } } diff --git a/media/server/gstplayer/source/tasks/generic/RemoveSource.cpp b/media/server/gstplayer/source/tasks/generic/RemoveSource.cpp index 16f03e6eb..29127c08c 100644 --- a/media/server/gstplayer/source/tasks/generic/RemoveSource.cpp +++ b/media/server/gstplayer/source/tasks/generic/RemoveSource.cpp @@ -75,5 +75,7 @@ void RemoveSource::execute() const // Turn audio off, removing audio sink from playsink m_player.setPlaybinFlags(false); + + RIALTO_SERVER_LOG_MIL("%s source removed", common::convertMediaSourceType(m_type)); } } // namespace firebolt::rialto::server::tasks::generic diff --git a/media/server/gstplayer/source/tasks/generic/SetMute.cpp b/media/server/gstplayer/source/tasks/generic/SetMute.cpp index b8ed1b04c..da66764a8 100644 --- a/media/server/gstplayer/source/tasks/generic/SetMute.cpp +++ b/media/server/gstplayer/source/tasks/generic/SetMute.cpp @@ -69,6 +69,9 @@ void SetMute::execute() const { RIALTO_SERVER_LOG_ERROR("Setting mute for type %s unsupported", common::convertMediaSourceType(m_mediaSourceType)); + return; } + RIALTO_SERVER_LOG_MIL("%s source %s", common::convertMediaSourceType(m_mediaSourceType), + (m_mute ? "muted" : "unmuted")); } } // namespace firebolt::rialto::server::tasks::generic diff --git a/media/server/gstplayer/source/tasks/generic/SetPlaybackRate.cpp b/media/server/gstplayer/source/tasks/generic/SetPlaybackRate.cpp index 803860985..f5f8f609c 100644 --- a/media/server/gstplayer/source/tasks/generic/SetPlaybackRate.cpp +++ b/media/server/gstplayer/source/tasks/generic/SetPlaybackRate.cpp @@ -93,7 +93,7 @@ void SetPlaybackRate::execute() const if (success) { - RIALTO_SERVER_LOG_INFO("Playback rate set to: %lf", m_rate); + RIALTO_SERVER_LOG_MIL("Playback rate set to: %lf", m_rate); m_context.playbackRate = m_rate; } diff --git a/media/server/gstplayer/source/tasks/generic/SetPosition.cpp b/media/server/gstplayer/source/tasks/generic/SetPosition.cpp index e37b206e0..df9d1b72b 100644 --- a/media/server/gstplayer/source/tasks/generic/SetPosition.cpp +++ b/media/server/gstplayer/source/tasks/generic/SetPosition.cpp @@ -84,13 +84,15 @@ void SetPosition::execute() const return; } + RIALTO_SERVER_LOG_MIL("Pipeline seek to: %" GST_TIME_FORMAT, GST_TIME_ARGS(m_position)); + // Reset Eos info m_context.endOfStreamInfo.clear(); m_context.eosNotified = false; m_gstPlayerClient->notifyPlaybackState(PlaybackState::SEEK_DONE); - // // Trigger NeedMediaData for all attached sources + // Trigger NeedMediaData for all attached sources for (const auto &streamInfo : m_context.streamInfo) { if (streamInfo.second.appSrc) diff --git a/media/server/gstplayer/source/tasks/generic/Stop.cpp b/media/server/gstplayer/source/tasks/generic/Stop.cpp index 050c4a8a1..3f82478b5 100644 --- a/media/server/gstplayer/source/tasks/generic/Stop.cpp +++ b/media/server/gstplayer/source/tasks/generic/Stop.cpp @@ -43,5 +43,6 @@ void Stop::execute() const { streamInfo.second.isDataNeeded = false; } + RIALTO_SERVER_LOG_MIL("State change to NULL requested"); } } // namespace firebolt::rialto::server::tasks::generic diff --git a/media/server/gstplayer/source/tasks/generic/SwitchSource.cpp b/media/server/gstplayer/source/tasks/generic/SwitchSource.cpp index 5eb201471..22de55f5c 100644 --- a/media/server/gstplayer/source/tasks/generic/SwitchSource.cpp +++ b/media/server/gstplayer/source/tasks/generic/SwitchSource.cpp @@ -19,6 +19,7 @@ #include "SwitchSource.h" #include "RialtoServerLogging.h" +#include "TypeConverters.h" #include "Utils.h" namespace firebolt::rialto::server::tasks::generic @@ -40,6 +41,8 @@ void SwitchSource::execute() const if (!m_player.reattachSource(m_source)) { RIALTO_SERVER_LOG_WARN("Switch audio source failed"); + return; } + RIALTO_SERVER_LOG_MIL("%s source switched", common::convertMediaSourceType(m_source->getType())); } } // namespace firebolt::rialto::server::tasks::generic diff --git a/media/server/gstplayer/source/tasks/webAudio/Eos.cpp b/media/server/gstplayer/source/tasks/webAudio/Eos.cpp index 365f9b34d..be11e5405 100644 --- a/media/server/gstplayer/source/tasks/webAudio/Eos.cpp +++ b/media/server/gstplayer/source/tasks/webAudio/Eos.cpp @@ -42,5 +42,6 @@ void Eos::execute() const { RIALTO_SERVER_LOG_WARN("Set eos failed - Gstreamer error"); } + RIALTO_SERVER_LOG_MIL("EOS set for webaudio source"); } } // namespace firebolt::rialto::server::tasks::webaudio diff --git a/media/server/gstplayer/source/tasks/webAudio/HandleBusMessage.cpp b/media/server/gstplayer/source/tasks/webAudio/HandleBusMessage.cpp index f26146c8a..e8ffad051 100644 --- a/media/server/gstplayer/source/tasks/webAudio/HandleBusMessage.cpp +++ b/media/server/gstplayer/source/tasks/webAudio/HandleBusMessage.cpp @@ -52,10 +52,10 @@ void HandleBusMessage::execute() const { GstState oldState, newState, pending; m_gstWrapper->gstMessageParseStateChanged(m_message, &oldState, &newState, &pending); - RIALTO_SERVER_LOG_INFO("State changed (old: %s, new: %s, pending: %s)", - m_gstWrapper->gstElementStateGetName(oldState), - m_gstWrapper->gstElementStateGetName(newState), - m_gstWrapper->gstElementStateGetName(pending)); + RIALTO_SERVER_LOG_MIL("State changed (old: %s, new: %s, pending: %s)", + m_gstWrapper->gstElementStateGetName(oldState), + m_gstWrapper->gstElementStateGetName(newState), + m_gstWrapper->gstElementStateGetName(pending)); std::string filename = std::string(m_gstWrapper->gstElementStateGetName(oldState)) + "-" + std::string(m_gstWrapper->gstElementStateGetName(newState)); diff --git a/media/server/gstplayer/source/tasks/webAudio/Pause.cpp b/media/server/gstplayer/source/tasks/webAudio/Pause.cpp index 298cab286..a7acec661 100644 --- a/media/server/gstplayer/source/tasks/webAudio/Pause.cpp +++ b/media/server/gstplayer/source/tasks/webAudio/Pause.cpp @@ -41,5 +41,6 @@ void Pause::execute() const { RIALTO_SERVER_LOG_ERROR("Failed to pause the web audio player"); } + RIALTO_SERVER_LOG_MIL("State change to PAUSED requested for webaudio pipeline"); } } // namespace firebolt::rialto::server::tasks::webaudio diff --git a/media/server/gstplayer/source/tasks/webAudio/Play.cpp b/media/server/gstplayer/source/tasks/webAudio/Play.cpp index b1b8c529a..19605b457 100644 --- a/media/server/gstplayer/source/tasks/webAudio/Play.cpp +++ b/media/server/gstplayer/source/tasks/webAudio/Play.cpp @@ -41,5 +41,6 @@ void Play::execute() const { RIALTO_SERVER_LOG_ERROR("Failed to play the web audio player"); } + RIALTO_SERVER_LOG_MIL("State change to PLAYING requested for webaudio pipeline"); } } // namespace firebolt::rialto::server::tasks::webaudio diff --git a/media/server/gstplayer/source/tasks/webAudio/SetCaps.cpp b/media/server/gstplayer/source/tasks/webAudio/SetCaps.cpp index 03f92b1d2..5d42d4c31 100644 --- a/media/server/gstplayer/source/tasks/webAudio/SetCaps.cpp +++ b/media/server/gstplayer/source/tasks/webAudio/SetCaps.cpp @@ -154,6 +154,7 @@ void SetCaps::execute() const m_gstWrapper->gstCapsUnref(caps); setBytesPerSample(); + RIALTO_SERVER_LOG_MIL("New caps set for webaudio source: %s", strCaps.c_str()); } } diff --git a/media/server/gstplayer/source/tasks/webAudio/Stop.cpp b/media/server/gstplayer/source/tasks/webAudio/Stop.cpp index 906764d40..56d01b7ae 100644 --- a/media/server/gstplayer/source/tasks/webAudio/Stop.cpp +++ b/media/server/gstplayer/source/tasks/webAudio/Stop.cpp @@ -38,5 +38,6 @@ void Stop::execute() const { RIALTO_SERVER_LOG_DEBUG("Executing Stop"); m_player.changePipelineState(GST_STATE_NULL); + RIALTO_SERVER_LOG_MIL("State change to NULL requested for webaudio pipeline"); } } // namespace firebolt::rialto::server::tasks::webaudio diff --git a/media/server/ipc/source/ApplicationManagementServer.cpp b/media/server/ipc/source/ApplicationManagementServer.cpp index 69ee05d91..dd7db2272 100644 --- a/media/server/ipc/source/ApplicationManagementServer.cpp +++ b/media/server/ipc/source/ApplicationManagementServer.cpp @@ -79,6 +79,7 @@ bool ApplicationManagementServer::initialize(int socket) return false; } m_ipcClient->exportService(m_service); + RIALTO_SERVER_LOG_MIL("ApplicationManagementServer initialized"); return true; } @@ -116,6 +117,6 @@ void ApplicationManagementServer::stop() void ApplicationManagementServer::onClientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &client) { - RIALTO_SERVER_LOG_INFO("Rialto Server Manager disconnected"); + RIALTO_SERVER_LOG_WARN("Rialto Server Manager disconnected"); } } // namespace firebolt::rialto::server::ipc diff --git a/media/server/ipc/source/SessionManagementServer.cpp b/media/server/ipc/source/SessionManagementServer.cpp index 80ae051b7..ab9954a92 100644 --- a/media/server/ipc/source/SessionManagementServer.cpp +++ b/media/server/ipc/source/SessionManagementServer.cpp @@ -99,6 +99,8 @@ bool SessionManagementServer::initialize(const std::string &socketName, unsigned common::setFilePermissions(socketName, socketPermissions); common::setFileOwnership(socketName, socketOwner, socketGroup); + RIALTO_SERVER_LOG_MIL("Session Management Server initialized"); + return true; } @@ -121,6 +123,9 @@ bool SessionManagementServer::initialize(int32_t socketFd) socketFd); return false; } + + RIALTO_SERVER_LOG_MIL("Session Management Server initialized"); + return true; } @@ -158,6 +163,7 @@ void SessionManagementServer::setLogLevels(RIALTO_DEBUG_LEVEL defaultLogLevels, void SessionManagementServer::onClientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &client) { + RIALTO_SERVER_LOG_MIL("Client app connected"); m_controlModule->clientConnected(client); m_mediaPipelineModule->clientConnected(client); m_mediaPipelineCapabilitiesModule->clientConnected(client); @@ -169,6 +175,7 @@ void SessionManagementServer::onClientConnected(const std::shared_ptr<::firebolt void SessionManagementServer::onClientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &client) { + RIALTO_SERVER_LOG_MIL("Client app disconnected"); m_setLogLevelsService.clientDisconnected(client); m_mediaKeysCapabilitiesModule->clientDisconnected(client); m_mediaKeysModule->clientDisconnected(client); diff --git a/media/server/main/source/ControlServerInternal.cpp b/media/server/main/source/ControlServerInternal.cpp index 996124844..49ae2e78a 100644 --- a/media/server/main/source/ControlServerInternal.cpp +++ b/media/server/main/source/ControlServerInternal.cpp @@ -118,7 +118,7 @@ void ControlServerInternal::ack(int32_t ackId) void ControlServerInternal::setApplicationState(const ApplicationState &state) { - RIALTO_SERVER_LOG_INFO("Notify rialto client about state changed to: %s", convertApplicationState(state)); + RIALTO_SERVER_LOG_MIL("Notify rialto client about state changed to: %s", convertApplicationState(state)); auto task = [&]() { m_currentState = state; diff --git a/media/server/main/source/MediaKeySession.cpp b/media/server/main/source/MediaKeySession.cpp index a45a977a1..414856cd8 100644 --- a/media/server/main/source/MediaKeySession.cpp +++ b/media/server/main/source/MediaKeySession.cpp @@ -81,6 +81,7 @@ MediaKeySession::MediaKeySession(const std::string &keySystem, int32_t keySessio { throw std::runtime_error("Ocdm session could not be created"); } + RIALTO_SERVER_LOG_MIL("New OCDM session created"); } MediaKeySession::~MediaKeySession() @@ -254,6 +255,7 @@ MediaKeyErrorStatus MediaKeySession::closeKeySession() RIALTO_SERVER_LOG_WARN("Failed to clean the decrypt context for the key session"); } status = MediaKeyErrorStatus::OK; + RIALTO_SERVER_LOG_MIL("OCDM session closed"); } else { diff --git a/media/server/service/source/SessionServerManager.cpp b/media/server/service/source/SessionServerManager.cpp index 5e2ec150d..b63a7752f 100644 --- a/media/server/service/source/SessionServerManager.cpp +++ b/media/server/service/source/SessionServerManager.cpp @@ -212,6 +212,7 @@ bool SessionServerManager::switchToActive() { m_controlService.setApplicationState(ApplicationState::RUNNING); m_currentState.store(common::SessionServerState::ACTIVE); + RIALTO_SERVER_LOG_MIL("RialtoServer state is ACTIVE now"); return true; } m_playbackService.switchToInactive(); @@ -232,6 +233,7 @@ bool SessionServerManager::switchToInactive() { m_controlService.setApplicationState(ApplicationState::INACTIVE); m_currentState.store(common::SessionServerState::INACTIVE); + RIALTO_SERVER_LOG_MIL("RialtoServer state is INACTIVE now"); return true; } if (m_currentState.load() == common::SessionServerState::ACTIVE) @@ -250,6 +252,7 @@ bool SessionServerManager::switchToInactive() bool SessionServerManager::switchToNotRunning() { + RIALTO_SERVER_LOG_MIL("RialtoServer state switch to NOT_RUNNING requested"); if (m_currentState.load() == common::SessionServerState::NOT_RUNNING) { RIALTO_SERVER_LOG_DEBUG("Session server already in NotRunning state."); diff --git a/tests/componenttests/server/fixtures/MediaPipelineTest.cpp b/tests/componenttests/server/fixtures/MediaPipelineTest.cpp index ee022fee4..ea021e5d2 100644 --- a/tests/componenttests/server/fixtures/MediaPipelineTest.cpp +++ b/tests/componenttests/server/fixtures/MediaPipelineTest.cpp @@ -118,6 +118,8 @@ void MediaPipelineTest::audioSourceWillBeAttached() EXPECT_CALL(*m_gstWrapperMock, gstCapsSetSimpleIntStub(&m_audioCaps, StrEq("mpegversion"), G_TYPE_INT, 4)); EXPECT_CALL(*m_gstWrapperMock, gstCapsSetSimpleIntStub(&m_audioCaps, StrEq("channels"), G_TYPE_INT, kNumOfChannels)); EXPECT_CALL(*m_gstWrapperMock, gstCapsSetSimpleIntStub(&m_audioCaps, StrEq("rate"), G_TYPE_INT, kSampleRate)); + EXPECT_CALL(*m_gstWrapperMock, gstCapsToString(&m_audioCaps)).WillOnce(Return(&m_audioCapsStr)); + EXPECT_CALL(*m_glibWrapperMock, gFree(&m_audioCapsStr)); EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("appsrc"), StrEq("audsrc"))) .WillOnce(Return(GST_ELEMENT(&m_audioAppSrc))); EXPECT_CALL(*m_gstWrapperMock, gstAppSrcSetCaps(&m_audioAppSrc, &m_audioCaps)); @@ -133,6 +135,8 @@ void MediaPipelineTest::videoSourceWillBeAttached() gstCapsSetSimpleStringStub(&m_videoCaps, StrEq("stream-format"), G_TYPE_STRING, StrEq("raw"))); EXPECT_CALL(*m_gstWrapperMock, gstCapsSetSimpleIntStub(&m_videoCaps, StrEq("width"), G_TYPE_INT, kWidth)); EXPECT_CALL(*m_gstWrapperMock, gstCapsSetSimpleIntStub(&m_videoCaps, StrEq("height"), G_TYPE_INT, kHeight)); + EXPECT_CALL(*m_gstWrapperMock, gstCapsToString(&m_videoCaps)).WillOnce(Return(&m_videoCapsStr)); + EXPECT_CALL(*m_glibWrapperMock, gFree(&m_videoCapsStr)); EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("appsrc"), StrEq("vidsrc"))) .WillOnce(Return(GST_ELEMENT(&m_videoAppSrc))); EXPECT_CALL(*m_gstWrapperMock, gstAppSrcSetCaps(&m_videoAppSrc, &m_videoCaps)); diff --git a/tests/componenttests/server/tests/mediaPipeline/DualVideoPlaybackTest.cpp b/tests/componenttests/server/tests/mediaPipeline/DualVideoPlaybackTest.cpp index 7e3b90170..5b3efd9d9 100644 --- a/tests/componenttests/server/tests/mediaPipeline/DualVideoPlaybackTest.cpp +++ b/tests/componenttests/server/tests/mediaPipeline/DualVideoPlaybackTest.cpp @@ -141,6 +141,8 @@ class DualVideoPlaybackTest : public MediaPipelineTest .RetiresOnSaturation(); EXPECT_CALL(*m_gstWrapperMock, gstCapsSetSimpleIntStub(&m_videoCaps, StrEq("height"), G_TYPE_INT, kHeight)) .RetiresOnSaturation(); + EXPECT_CALL(*m_gstWrapperMock, gstCapsToString(&m_videoCaps)).WillOnce(Return(&m_videoCapsStr)); + EXPECT_CALL(*m_glibWrapperMock, gFree(&m_videoCapsStr)); EXPECT_CALL(*m_gstWrapperMock, gstElementFactoryMake(StrEq("appsrc"), StrEq("vidsrc"))) .WillOnce(Return(GST_ELEMENT(&m_secondaryVideoAppSrc))); EXPECT_CALL(*m_gstWrapperMock, gstAppSrcSetCaps(&m_secondaryVideoAppSrc, &m_videoCaps)); diff --git a/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp b/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp index 3b3c9b45f..852abf977 100644 --- a/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp +++ b/tests/unittests/media/server/gstplayer/genericPlayer/common/GenericTasksTestsBase.cpp @@ -1608,6 +1608,9 @@ void GenericTasksTestsBase::expectAddFramedToCaps() void GenericTasksTestsBase::expectSetCaps() { + EXPECT_CALL(*testContext->m_gstWrapper, gstCapsToString(&testContext->m_gstCaps1)) + .WillOnce(Return(&testContext->m_capsStr)); + EXPECT_CALL(*testContext->m_glibWrapper, gFree(&testContext->m_capsStr)); EXPECT_CALL(*testContext->m_gstWrapper, gstElementFactoryMake(_, StrEq(kAudName.c_str()))) .WillOnce(Return(&testContext->m_appSrcAudio)); EXPECT_CALL(*testContext->m_gstWrapper, @@ -1666,6 +1669,9 @@ void GenericTasksTestsBase::triggerAttachUnknownSource() void GenericTasksTestsBase::shouldAttachSubtitleSource() { EXPECT_CALL(*testContext->m_gstWrapper, gstCapsNewEmpty()).WillOnce(Return(&testContext->m_gstCaps2)); + EXPECT_CALL(*testContext->m_gstWrapper, gstCapsToString(&testContext->m_gstCaps2)) + .WillOnce(Return(&testContext->m_capsStr)); + EXPECT_CALL(*testContext->m_glibWrapper, gFree(&testContext->m_capsStr)); EXPECT_CALL(*testContext->m_gstWrapper, gstElementFactoryMake(_, StrEq(kSubtitleName.c_str()))) .WillOnce(Return(&testContext->m_appSrcSubtitle)); EXPECT_CALL(*testContext->m_gstTextTrackSinkFactoryMock, createGstTextTrackSink()) @@ -1768,6 +1774,9 @@ void GenericTasksTestsBase::shouldAttachVideoSourceWithEmptyCodecData() EXPECT_CALL(*testContext->m_gstWrapper, gstBufferUnref(&(testContext->m_videoBuffer))); EXPECT_CALL(*testContext->m_gstWrapper, gstCapsSetSimpleStringStub(&testContext->m_gstCaps1, StrEq("stream-format"), _, StrEq("avc"))); + EXPECT_CALL(*testContext->m_gstWrapper, gstCapsToString(&testContext->m_gstCaps1)) + .WillOnce(Return(&testContext->m_capsStr)); + EXPECT_CALL(*testContext->m_glibWrapper, gFree(&testContext->m_capsStr)); EXPECT_CALL(*testContext->m_gstWrapper, gstElementFactoryMake(_, StrEq(kVidName.c_str()))) .WillOnce(Return(&testContext->m_appSrcVideo)); EXPECT_CALL(*testContext->m_gstWrapper, @@ -1837,6 +1846,9 @@ void GenericTasksTestsBase::expectSetGenericVideoCaps() gstCapsSetSimpleIntStub(&testContext->m_gstCaps1, StrEq("width"), G_TYPE_INT, kWidth)); EXPECT_CALL(*testContext->m_gstWrapper, gstCapsSetSimpleIntStub(&testContext->m_gstCaps1, StrEq("height"), G_TYPE_INT, kHeight)); + EXPECT_CALL(*testContext->m_gstWrapper, gstCapsToString(&testContext->m_gstCaps1)) + .WillOnce(Return(&testContext->m_capsStr)); + EXPECT_CALL(*testContext->m_glibWrapper, gFree(&testContext->m_capsStr)); EXPECT_CALL(*testContext->m_gstWrapper, gstElementFactoryMake(_, StrEq(kVidName.c_str()))) .WillOnce(Return(&testContext->m_appSrcVideo)); EXPECT_CALL(*testContext->m_gstWrapper,