Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions media/server/gstplayer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ add_library(
source/tasks/generic/Play.cpp
source/tasks/generic/ProcessAudioGap.cpp
source/tasks/generic/ReadShmDataAndAttachSamples.cpp
source/tasks/generic/RemoveSource.cpp
source/tasks/generic/RenderFrame.cpp
source/tasks/generic/ReportPosition.cpp
source/tasks/generic/SetBufferingLimit.cpp
Expand Down
7 changes: 7 additions & 0 deletions media/server/gstplayer/include/GenericPlayerContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,13 @@ struct GenericPlayerContext
*/
IDecryptionService *decryptionService{nullptr};

/**
* @brief Flag used to check, if audio source has been recently removed
*
* Flag can be used only in worker thread
*/
bool audioSourceRemoved{false};

/**
* @brief Audio elements of gst pipeline.
*
Expand Down
1 change: 1 addition & 0 deletions media/server/gstplayer/include/GstGenericPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ class GstGenericPlayer : public IGstGenericPlayer, public IGstGenericPlayerPriva
virtual ~GstGenericPlayer();

void attachSource(const std::unique_ptr<IMediaPipeline::MediaSource> &mediaSource) override;
void removeSource(const MediaSourceType &mediaSourceType) override;
void allSourcesAttached() override;
void play(bool &async) override;
void pause() override;
Expand Down
13 changes: 13 additions & 0 deletions media/server/gstplayer/include/tasks/IGenericPlayerTaskFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,19 @@ class IGenericPlayerTaskFactory
createReadShmDataAndAttachSamples(GenericPlayerContext &context, IGstGenericPlayerPrivate &player,
const std::shared_ptr<IDataReader> &dataReader) const = 0;

/**
* @brief Creates a Remove Source task.
*
* @param[in] context : The GstPlayer context
* @param[in] player : The GstGenericPlayer instance
* @param[in] type : The media source type to remove
*
* @retval the new Remove Source task instance.
*/
virtual std::unique_ptr<IPlayerTask> createRemoveSource(GenericPlayerContext &context,
IGstGenericPlayerPrivate &player,
const firebolt::rialto::MediaSourceType &type) const = 0;

/**
* @brief Creates a ReportPosition task.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ class GenericPlayerTaskFactory : public IGenericPlayerTaskFactory
std::unique_ptr<IPlayerTask>
createReadShmDataAndAttachSamples(GenericPlayerContext &context, IGstGenericPlayerPrivate &player,
const std::shared_ptr<IDataReader> &dataReader) const override;
std::unique_ptr<IPlayerTask> createRemoveSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player,
const firebolt::rialto::MediaSourceType &type) const override;
std::unique_ptr<IPlayerTask> createReportPosition(GenericPlayerContext &context,
IGstGenericPlayerPrivate &player) const override;
std::unique_ptr<IPlayerTask> createCheckAudioUnderflow(GenericPlayerContext &context,
Expand Down
49 changes: 49 additions & 0 deletions media/server/gstplayer/include/tasks/generic/RemoveSource.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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_GENERIC_REMOVE_SOURCE_H_
#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_REMOVE_SOURCE_H_

#include "GenericPlayerContext.h"
#include "IGstGenericPlayerClient.h"
#include "IGstGenericPlayerPrivate.h"
#include "IGstWrapper.h"
#include "IPlayerTask.h"
#include <memory>

namespace firebolt::rialto::server::tasks::generic
{
class RemoveSource : public IPlayerTask
{
public:
RemoveSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client,
const std::shared_ptr<firebolt::rialto::wrappers::IGstWrapper> &gstWrapper, const MediaSourceType &type);
~RemoveSource() override;
void execute() const override;

private:
GenericPlayerContext &m_context;
IGstGenericPlayerPrivate &m_player;
IGstGenericPlayerClient *m_gstPlayerClient;
std::shared_ptr<firebolt::rialto::wrappers::IGstWrapper> m_gstWrapper;
MediaSourceType m_type;
};
} // namespace firebolt::rialto::server::tasks::generic

#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_REMOVE_SOURCE_H_
8 changes: 8 additions & 0 deletions media/server/gstplayer/interface/IGstGenericPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,14 @@ class IGstGenericPlayer
*/
virtual void attachSource(const std::unique_ptr<IMediaPipeline::MediaSource> &mediaSource) = 0;

/**
* @brief Removes a source from gstreamer.
*
* @param[in] mediaSourceType : The media source type.
*
*/
virtual void removeSource(const MediaSourceType &mediaSourceType) = 0;

/**
* @brief Handles notification that all sources were attached
*
Expand Down
10 changes: 9 additions & 1 deletion media/server/gstplayer/source/GstGenericPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,14 @@ void GstGenericPlayer::attachSource(const std::unique_ptr<IMediaPipeline::MediaS
}
}

void GstGenericPlayer::removeSource(const MediaSourceType &mediaSourceType)
{
if (m_workerThread)
{
m_workerThread->enqueueTask(m_taskFactory->createRemoveSource(m_context, *this, mediaSourceType));
}
}

void GstGenericPlayer::allSourcesAttached()
{
if (m_workerThread)
Expand Down Expand Up @@ -1687,7 +1695,7 @@ void GstGenericPlayer::scheduleAudioUnderflow()
{
if (m_workerThread)
{
bool underflowEnabled = m_context.isPlaying;
bool underflowEnabled = m_context.isPlaying && !m_context.audioSourceRemoved;
m_workerThread->enqueueTask(
m_taskFactory->createUnderflow(m_context, *this, underflowEnabled, MediaSourceType::AUDIO));
}
Expand Down
5 changes: 5 additions & 0 deletions media/server/gstplayer/source/tasks/generic/AttachSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ void AttachSource::reattachAudioSource() const
RIALTO_SERVER_LOG_ERROR("Reattaching source failed!");
return;
}

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
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ void CheckAudioUnderflow::execute() const
{
RIALTO_SERVER_LOG_WARN("Audio stream underflow! Position %" PRIu64 ", lastAudioSampleTimestamps: %" PRIu64,
position, m_context.lastAudioSampleTimestamps);
bool underflowEnabled = m_context.isPlaying;
bool underflowEnabled = m_context.isPlaying && !m_context.audioSourceRemoved;
Underflow task(m_context, m_player, m_gstPlayerClient, underflowEnabled, MediaSourceType::AUDIO);
task.execute();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "tasks/generic/Play.h"
#include "tasks/generic/ProcessAudioGap.h"
#include "tasks/generic/ReadShmDataAndAttachSamples.h"
#include "tasks/generic/RemoveSource.h"
#include "tasks/generic/RenderFrame.h"
#include "tasks/generic/ReportPosition.h"
#include "tasks/generic/SetBufferingLimit.h"
Expand Down Expand Up @@ -147,6 +148,13 @@ std::unique_ptr<IPlayerTask> GenericPlayerTaskFactory::createReadShmDataAndAttac
return std::make_unique<tasks::generic::ReadShmDataAndAttachSamples>(context, m_gstWrapper, player, dataReader);
}

std::unique_ptr<IPlayerTask>
GenericPlayerTaskFactory::createRemoveSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player,
const firebolt::rialto::MediaSourceType &type) const
{
return std::make_unique<tasks::generic::RemoveSource>(context, player, m_client, m_gstWrapper, type);
}

std::unique_ptr<IPlayerTask> GenericPlayerTaskFactory::createReportPosition(GenericPlayerContext &context,
IGstGenericPlayerPrivate &player) const
{
Expand Down
5 changes: 5 additions & 0 deletions media/server/gstplayer/source/tasks/generic/NeedData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ void NeedData::execute() const

if (m_gstPlayerClient && !elem.second.isNeedDataPending)
{
if (sourceType == MediaSourceType::AUDIO && m_context.audioSourceRemoved)
{
RIALTO_SERVER_LOG_DEBUG("Audio source is removed, no need to request data");
break;
}
elem.second.isNeedDataPending = m_gstPlayerClient->notifyNeedMediaData(sourceType);
}
break;
Expand Down
75 changes: 75 additions & 0 deletions media/server/gstplayer/source/tasks/generic/RemoveSource.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* 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/generic/RemoveSource.h"
#include "RialtoServerLogging.h"
#include "TypeConverters.h"

namespace firebolt::rialto::server::tasks::generic
{
RemoveSource::RemoveSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player,
IGstGenericPlayerClient *client,
const std::shared_ptr<firebolt::rialto::wrappers::IGstWrapper> &gstWrapper,
const MediaSourceType &type)
: m_context{context}, m_player{player}, m_gstPlayerClient{client}, m_gstWrapper{gstWrapper}, m_type{type}
{
RIALTO_SERVER_LOG_DEBUG("Constructing RemoveSource");
}

RemoveSource::~RemoveSource()
{
RIALTO_SERVER_LOG_DEBUG("RemoveSource finished");
}

void RemoveSource::execute() const
{
RIALTO_SERVER_LOG_DEBUG("Executing RemoveSource for %s source", common::convertMediaSourceType(m_type));
if (MediaSourceType::AUDIO != m_type)
{
RIALTO_SERVER_LOG_DEBUG("RemoveSource not supported for type != AUDIO");
return;
}
m_context.audioSourceRemoved = true;
if (m_gstPlayerClient)
{
m_gstPlayerClient->invalidateActiveRequests(m_type);
}
auto sourceElem = m_context.streamInfo.find(m_type);
if (sourceElem == m_context.streamInfo.end())
{
RIALTO_SERVER_LOG_WARN("Failed to remove source - streamInfo not found");
return;
}
StreamInfo &streamInfo = sourceElem->second;
for (auto &buffer : streamInfo.buffers)
{
m_gstWrapper->gstBufferUnref(buffer);
}
streamInfo.buffers.clear();
streamInfo.isDataNeeded = false;
streamInfo.isNeedDataPending = false;
m_context.initialPositions.erase(streamInfo.appSrc);

// Reset Eos info
m_context.endOfStreamInfo.erase(m_type);
m_context.eosNotified = false;

RIALTO_SERVER_LOG_MIL("%s source removed", common::convertMediaSourceType(m_type));
}
} // namespace firebolt::rialto::server::tasks::generic
28 changes: 28 additions & 0 deletions media/server/main/source/MediaKeySession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,34 @@ MediaKeyErrorStatus MediaKeySession::decrypt(GstBuffer *encrypted, GstCaps *caps
status = MediaKeyErrorStatus::FAIL;
}

switch (status)
{
case firebolt::rialto::MediaKeyErrorStatus::OK:
RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : OK");
break;
Comment on lines +279 to +283
case firebolt::rialto::MediaKeyErrorStatus::FAIL:
RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : FAIL");
break;
case firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID:
RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : BAD_SESSION_ID");
break;
case firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED:
RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : INTERFACE_NOT_IMPLEMENTED");
break;
case firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL:
RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : BUFFER_TOO_SMALL");
break;
case firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED:
RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : NOT_SUPPORTED");
break;
case firebolt::rialto::MediaKeyErrorStatus::INVALID_STATE:
RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : INVALID_STATE");
break;
case firebolt::rialto::MediaKeyErrorStatus::OUTPUT_RESTRICTED:
RIALTO_SERVER_LOG_ERROR("DEBUG PURPOSE : Key session status : OUTPUT_RESTRICTED");
break;
}

return status;
}

Expand Down
1 change: 1 addition & 0 deletions media/server/main/source/MediaPipelineServerInternal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ bool MediaPipelineServerInternal::removeSourceInternal(int32_t id)

MediaSourceType type = sourceIter->first;

m_gstPlayer->removeSource(type);
m_needMediaDataTimers.erase(type);
m_noAvailableSamplesCounter.erase(type);
m_isMediaTypeEosMap.erase(type);
Expand Down
1 change: 1 addition & 0 deletions tests/unittests/media/server/gstplayer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ add_gtests(RialtoServerGstPlayerUnitTests
genericPlayer/tasksTests/PlayTest.cpp
genericPlayer/tasksTests/ProcessAudioGapTest.cpp
genericPlayer/tasksTests/ReadShmDataAndAttachSamplesTest.cpp
genericPlayer/tasksTests/RemoveSourceTest.cpp
genericPlayer/tasksTests/RenderFrameTest.cpp
genericPlayer/tasksTests/ReportPositionTest.cpp
genericPlayer/tasksTests/SetBufferingLimitTest.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,12 @@ TEST_F(GstGenericPlayerPrivateTest, shouldScheduleEnoughDataData)

TEST_F(GstGenericPlayerPrivateTest, shouldScheduleAudioUnderflowWithUnderflowEnabled)
{
modifyContext([&](GenericPlayerContext &context) { context.isPlaying = true; });
modifyContext(
[&](GenericPlayerContext &context)
{
context.isPlaying = true;
context.audioSourceRemoved = false;
});

std::unique_ptr<IPlayerTask> task{std::make_unique<StrictMock<PlayerTaskMock>>()};
EXPECT_CALL(dynamic_cast<StrictMock<PlayerTaskMock> &>(*task), execute());
Expand All @@ -267,7 +272,29 @@ TEST_F(GstGenericPlayerPrivateTest, shouldScheduleAudioUnderflowWithUnderflowEna

TEST_F(GstGenericPlayerPrivateTest, shouldScheduleAudioUnderflowWithUnderflowDisabledNotPlaying)
{
modifyContext([&](GenericPlayerContext &context) { context.isPlaying = false; });
modifyContext(
[&](GenericPlayerContext &context)
{
context.isPlaying = false;
context.audioSourceRemoved = false;
});

std::unique_ptr<IPlayerTask> task{std::make_unique<StrictMock<PlayerTaskMock>>()};
EXPECT_CALL(dynamic_cast<StrictMock<PlayerTaskMock> &>(*task), execute());
EXPECT_CALL(m_taskFactoryMock, createUnderflow(_, _, false, MediaSourceType::AUDIO))
.WillOnce(Return(ByMove(std::move(task))));

m_sut->scheduleAudioUnderflow();
}

TEST_F(GstGenericPlayerPrivateTest, shouldScheduleAudioUnderflowWithUnderflowDisabledRemoveSource)
{
modifyContext(
[&](GenericPlayerContext &context)
{
context.isPlaying = true;
context.audioSourceRemoved = true;
});

std::unique_ptr<IPlayerTask> task{std::make_unique<StrictMock<PlayerTaskMock>>()};
EXPECT_CALL(dynamic_cast<StrictMock<PlayerTaskMock> &>(*task), execute());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,16 @@ TEST_F(GstGenericPlayerTest, shouldAttachSource)
m_sut->attachSource(source);
}

TEST_F(GstGenericPlayerTest, shouldRemoveSource)
{
std::unique_ptr<IPlayerTask> task{std::make_unique<StrictMock<PlayerTaskMock>>()};
EXPECT_CALL(dynamic_cast<StrictMock<PlayerTaskMock> &>(*task), execute());
EXPECT_CALL(m_taskFactoryMock, createRemoveSource(_, _, MediaSourceType::AUDIO))
.WillOnce(Return(ByMove(std::move(task))));

m_sut->removeSource(MediaSourceType::AUDIO);
}

TEST_F(GstGenericPlayerTest, shouldAllSourcesAttached)
{
std::unique_ptr<IPlayerTask> task{std::make_unique<StrictMock<PlayerTaskMock>>()};
Expand Down
Loading
Loading