Skip to content

Commit

Permalink
Rename decrypter elements (#263)
Browse files Browse the repository at this point in the history
Summary: Set the name on the decryptor elements, and use it to determine
the src type.
Type: Feature
Test Plan: Unittests, Component Tests, Fullstack builds.
Jira: RIALTO-463
  • Loading branch information
skyfroxl authored Feb 6, 2024
1 parent 76afbc9 commit 359b52d
Show file tree
Hide file tree
Showing 10 changed files with 127 additions and 96 deletions.
18 changes: 15 additions & 3 deletions media/server/gstplayer/source/GstDecryptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,20 +199,32 @@ GstElement *GstDecryptorElementFactory::createDecryptorElement(
const gchar *name, firebolt::rialto::server::IDecryptionService *decryptionService,
const std::shared_ptr<firebolt::rialto::wrappers::IGstWrapper> &gstWrapper) const
{
GstRialtoDecryptor *decrypter = GST_RIALTO_DECRYPTOR(g_object_new(GST_RIALTO_DECRYPTOR_TYPE, name));
// Bypass the glib wrapper here, this is the only place we can create a proper Decryptor element
GstRialtoDecryptor *decryptor = GST_RIALTO_DECRYPTOR(g_object_new(GST_RIALTO_DECRYPTOR_TYPE, nullptr));
if (name)
{
if (!gstWrapper->gstObjectSetName(GST_OBJECT(decryptor), name))
{
RIALTO_SERVER_LOG_ERROR("Failed to set the decryptor name to %s", name);
g_object_unref(GST_OBJECT(decryptor));
return nullptr;
}
}

GstRialtoDecryptorPrivate *priv =
reinterpret_cast<GstRialtoDecryptorPrivate *>(gst_rialto_decryptor_get_instance_private(decrypter));
reinterpret_cast<GstRialtoDecryptorPrivate *>(gst_rialto_decryptor_get_instance_private(decryptor));
std::shared_ptr<firebolt::rialto::server::IGstProtectionMetadataHelperFactory> metadataFactory =
firebolt::rialto::server::IGstProtectionMetadataHelperFactory::createFactory();
if (priv)
{
priv->setDecryptionService(decryptionService);
priv->setProtectionMetadataWrapper(metadataFactory->createProtectionMetadataWrapper(gstWrapper));
return GST_ELEMENT(decrypter);
return GST_ELEMENT(decryptor);
}
else
{
RIALTO_SERVER_LOG_ERROR("Failed to create the decryptor element");
g_object_unref(GST_OBJECT(decryptor));
return nullptr;
}
}
Expand Down
10 changes: 8 additions & 2 deletions media/server/gstplayer/source/GstSrc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,16 +377,22 @@ void GstSrc::setupAndAddAppArc(IDecryptionService *decryptionService, GstElement
m_gstWrapper->gstAppSrcSetStreamType(GST_APP_SRC(streamInfo.appSrc), GST_APP_STREAM_TYPE_SEEKABLE);

GstRialtoSrc *src = GST_RIALTO_SRC(source);
gchar *name = m_glibWrapper->gStrdupPrintf("src_%u", src->priv->appsrc_count);
guint id = src->priv->appsrc_count;
src->priv->appsrc_count++;
gchar *name = m_glibWrapper->gStrdupPrintf("src_%u", id);
m_gstWrapper->gstBinAdd(GST_BIN(source), streamInfo.appSrc);

GstElement *src_elem = streamInfo.appSrc;

// Configure and add decryptor
if (streamInfo.hasDrm)
{
GstElement *decryptor = m_decryptorFactory->createDecryptorElement(nullptr, decryptionService, m_gstWrapper);
gchar *decryptorName =
m_glibWrapper->gStrdupPrintf("rialtodecryptor%s_%u",
(type == firebolt::rialto::MediaSourceType::VIDEO) ? "video" : "audio", id);
GstElement *decryptor =
m_decryptorFactory->createDecryptorElement(decryptorName, decryptionService, m_gstWrapper);
m_glibWrapper->gFree(decryptorName);
if (decryptor)
{
GST_DEBUG_OBJECT(src, "Injecting decryptor element %" GST_PTR_FORMAT, decryptor);
Expand Down
40 changes: 8 additions & 32 deletions media/server/gstplayer/source/tasks/generic/HandleBusMessage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,44 +217,20 @@ void HandleBusMessage::execute() const

if ((PlaybackError::UNKNOWN != rialtoError) && (m_gstPlayerClient))
{
const gchar *mimetype = nullptr;
GstPad *srcpad = m_gstWrapper->gstElementGetStaticPad(GST_ELEMENT(GST_MESSAGE_SRC(m_message)), "src");
if (srcpad)
const gchar *name = GST_ELEMENT_NAME(GST_ELEMENT(GST_MESSAGE_SRC(m_message)));
if (g_strrstr(name, "video"))
{
GstCaps *caps = m_gstWrapper->gstPadGetCurrentCaps(srcpad);
if (caps)
{
GstStructure *structure = m_gstWrapper->gstCapsGetStructure(caps, 0);
if (structure)
{
mimetype = m_gstWrapper->gstStructureGetName(structure);
m_glibWrapper->gObjectUnref(structure);
}
m_glibWrapper->gObjectUnref(caps);
}
m_glibWrapper->gObjectUnref(srcpad);
m_gstPlayerClient->notifyPlaybackError(firebolt::rialto::MediaSourceType::VIDEO,
PlaybackError::DECRYPTION);
}

if (mimetype)
else if (g_strrstr(name, "audio"))
{
if (g_strrstr(mimetype, "video"))
{
m_gstPlayerClient->notifyPlaybackError(firebolt::rialto::MediaSourceType::VIDEO,
PlaybackError::DECRYPTION);
}
else if (g_strrstr(mimetype, "audio"))
{
m_gstPlayerClient->notifyPlaybackError(firebolt::rialto::MediaSourceType::AUDIO,
PlaybackError::DECRYPTION);
}
else
{
RIALTO_SERVER_LOG_WARN("Unknown source type for class '%s', not propagating error", mimetype);
}
m_gstPlayerClient->notifyPlaybackError(firebolt::rialto::MediaSourceType::AUDIO,
PlaybackError::DECRYPTION);
}
else
{
RIALTO_SERVER_LOG_WARN("Could not get source type from elment, not propagating error");
RIALTO_SERVER_LOG_WARN("Unknown source type for element '%s', not propagating error", name);
}
}

Expand Down
17 changes: 16 additions & 1 deletion tests/common/externalLibraryMocks/GlibWrapperMock.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,22 @@ class GlibWrapperMock : public IGlibWrapper
}
MOCK_METHOD(void, gObjectGetStub, (gpointer object, const gchar *first_property_name, void *element));

gchar *gStrdupPrintf(const gchar *format, ...) override { return gStrdupPrintfStub(format); };
gchar *gStrdupPrintf(const gchar *format, ...) override
{
gchar *buffer;
va_list args;

va_start(args, format);
buffer = g_strdup_vprintf(format, args);
va_end(args);

gchar *str = gStrdupPrintfStub(buffer);

// free the string
g_free(buffer);

return str;
};
MOCK_METHOD(gchar *, gStrdupPrintfStub, (const gchar *format));

MOCK_METHOD(GParamSpec *, gObjectClassFindProperty, (GObjectClass *, const gchar *), (override));
Expand Down
1 change: 1 addition & 0 deletions tests/common/externalLibraryMocks/GstWrapperMock.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ class GstWrapperMock : public IGstWrapper
MOCK_METHOD(GstCaps *, gstPadGetCurrentCaps, (GstPad * pad), (const, override));
MOCK_METHOD(GstStructure *, gstCapsGetStructure, (const GstCaps *caps, guint index), (const, override));
MOCK_METHOD(const gchar *, gstStructureGetName, (const GstStructure *structure), (const, override));
MOCK_METHOD(gboolean, gstObjectSetName, (GstObject * object, const gchar *name), (const, override));

GstCaps *gstCapsNewSimple(const char *media_type, const char *fieldname, ...) const override
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ namespace
{
constexpr unsigned kFramesToPush{1};
constexpr int kFrameCountInPausedState{3};
const std::string kAudioMimeType{"audio/mpeg"};
const std::string kVideoMimeType{"video/x-h264"};
const std::string kAudioDecryptorName{"rialtodecryptoraudio_0"};
const std::string kVideoDecryptorName{"rialtodecryptorvideo_0"};
} // namespace

MATCHER_P2(gstWarningMatcher, error, debug, "")
Expand Down Expand Up @@ -62,30 +62,23 @@ class NonFatalPlayerErrorUpdatesTest : public MediaPipelineTest
EXPECT_CALL(*m_glibWrapperMock, gErrorFree(&m_err)).WillOnce(Invoke(this, &MediaPipelineTest::workerFinished));
}

void gstWarning()
void gstWarning(const char *srcName)
{
m_gstreamerStub.sendWarning(&m_src, &m_err, m_debug);
m_src = GST_OBJECT_CAST(g_object_new(GST_TYPE_BIN, nullptr));
gst_object_set_name(m_src, srcName);
m_gstreamerStub.sendWarning(GST_ELEMENT(m_src), &m_err, m_debug);

// Warning executed on the bus thread, wait for it to complete
waitWorker();
}

void willGetMimeType(const char *mimeType)
{
EXPECT_CALL(*m_gstWrapperMock, gstElementGetStaticPad(GST_ELEMENT(&m_src), StrEq("src"))).WillOnce(Return(&m_srcpad));
EXPECT_CALL(*m_gstWrapperMock, gstPadGetCurrentCaps(&m_srcpad)).WillOnce(Return(&m_caps));
EXPECT_CALL(*m_gstWrapperMock, gstCapsGetStructure(&m_caps, 0)).WillOnce(Return(&m_structure));
EXPECT_CALL(*m_gstWrapperMock, gstStructureGetName(&m_structure)).WillOnce(Return(mimeType));
EXPECT_CALL(*m_glibWrapperMock, gObjectUnref(&m_structure));
EXPECT_CALL(*m_glibWrapperMock, gObjectUnref(&m_caps));
EXPECT_CALL(*m_glibWrapperMock, gObjectUnref(&m_srcpad));
g_object_unref(m_src);
}

void notifyPlaybackError(int sourceId, PlaybackError error)
void notifyPlaybackError(int sourceId, PlaybackError error, const char *srcName)
{
ExpectMessage<PlaybackErrorEvent> expectedPlaybackError{m_clientStub};

gstWarning();
gstWarning(srcName);

auto receivedPlaybackError = expectedPlaybackError.getMessage();
ASSERT_TRUE(receivedPlaybackError);
Expand All @@ -95,12 +88,9 @@ class NonFatalPlayerErrorUpdatesTest : public MediaPipelineTest
}

private:
GstElement m_src{};
GstObject *m_src;
GError m_err{};
gchar m_debug[14]{"Error message"};
GstPad m_srcpad{};
GstCaps m_caps{};
GstStructure m_structure{};
};

/*
Expand Down Expand Up @@ -273,21 +263,19 @@ TEST_F(NonFatalPlayerErrorUpdatesTest, warningMessage)

// Step 9: Audio generic warning
willHandleWarningMessage(GST_CORE_ERROR, GST_CORE_ERROR_FAILED);
gstWarning();
gstWarning(kAudioDecryptorName.c_str());

// Step 10: Video generic warning
willHandleWarningMessage(GST_CORE_ERROR, GST_CORE_ERROR_FAILED);
gstWarning();
gstWarning(kVideoDecryptorName.c_str());

// Step 11: Audio decrypt warning
willHandleWarningMessage(GST_STREAM_ERROR, GST_STREAM_ERROR_DECRYPT);
willGetMimeType(kAudioMimeType.c_str());
notifyPlaybackError(m_audioSourceId, PlaybackError::DECRYPTION);
notifyPlaybackError(m_audioSourceId, PlaybackError::DECRYPTION, kAudioDecryptorName.c_str());

// Step 12: Video decrypt warning
willHandleWarningMessage(GST_STREAM_ERROR, GST_STREAM_ERROR_DECRYPT);
willGetMimeType(kVideoMimeType.c_str());
notifyPlaybackError(m_videoSourceId, PlaybackError::DECRYPTION);
notifyPlaybackError(m_videoSourceId, PlaybackError::DECRYPTION, kVideoDecryptorName.c_str());

// Step 13: End of audio stream
// Step 14: End of video stream
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class HandleBusMessageTest : public testing::Test
GstPad m_srcpad{};
GstCaps m_caps{};
GstStructure m_structure{};
GstBaseTransform m_decryptorBase = {};
GstElement m_decryptorBase{};

HandleBusMessageTest()
{
Expand All @@ -67,20 +67,6 @@ class HandleBusMessageTest : public testing::Test
m_context.streamInfo.emplace(firebolt::rialto::MediaSourceType::VIDEO, GST_ELEMENT(&m_videoSrc));
}

void expectGetMimeType(const gchar *mimeType)
{
EXPECT_CALL(*m_gstWrapper, gstMessageParseWarning(&m_message, _, _))
.WillOnce(DoAll(SetArgPointee<1>(&m_err), SetArgPointee<2>(m_debug)));
EXPECT_CALL(*m_gstWrapper, gstElementGetStaticPad(GST_ELEMENT(&m_decryptorBase), StrEq("src")))
.WillOnce(Return(&m_srcpad));
EXPECT_CALL(*m_gstWrapper, gstPadGetCurrentCaps(&m_srcpad)).WillOnce(Return(&m_caps));
EXPECT_CALL(*m_gstWrapper, gstCapsGetStructure(&m_caps, 0)).WillOnce(Return(&m_structure));
EXPECT_CALL(*m_gstWrapper, gstStructureGetName(&m_structure)).WillOnce(Return(mimeType));
EXPECT_CALL(*m_glibWrapper, gObjectUnref(&m_structure));
EXPECT_CALL(*m_glibWrapper, gObjectUnref(&m_caps));
EXPECT_CALL(*m_glibWrapper, gObjectUnref(&m_srcpad));
}

void expectFreeErrorMessage()
{
EXPECT_CALL(*m_glibWrapper, gFree(m_debug));
Expand Down Expand Up @@ -516,50 +502,66 @@ TEST_F(HandleBusMessageTest, shouldHandleStreamErrorMessageWhenEosAllSourcesAndE
*/
TEST_F(HandleBusMessageTest, shouldHandleWarningMessageForAudioDecryption)
{
// Set decryptor audio
GstObject *decryptor = GST_OBJECT_CAST(g_object_new(GST_TYPE_BIN, nullptr));
gst_object_set_name(decryptor, "rialtodecryptoraudio_0");

GST_MESSAGE_TYPE(&m_message) = GST_MESSAGE_WARNING;
GST_MESSAGE_SRC(&m_message) = GST_OBJECT_CAST(&m_decryptorBase);
GST_MESSAGE_SRC(&m_message) = decryptor;
m_err.domain = GST_STREAM_ERROR;
m_err.code = GST_STREAM_ERROR_DECRYPT;

gchar *audioMimeType = "audio/mpeg";
expectGetMimeType(audioMimeType);
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};
task.execute();

g_object_unref(decryptor);
}

/**
* Test HandleBusMessage notifies WARNING for decrypt errors while decrypting video frames.
*/
TEST_F(HandleBusMessageTest, shouldHandleWarningMessageForVideoDecryption)
{
// Set decryptor video
GstObject *decryptor = GST_OBJECT_CAST(g_object_new(GST_TYPE_BIN, nullptr));
gst_object_set_name(decryptor, "rialtodecryptorvideo_0");

GST_MESSAGE_TYPE(&m_message) = GST_MESSAGE_WARNING;
GST_MESSAGE_SRC(&m_message) = GST_OBJECT_CAST(&m_decryptorBase);
GST_MESSAGE_SRC(&m_message) = decryptor;
m_err.domain = GST_STREAM_ERROR;
m_err.code = GST_STREAM_ERROR_DECRYPT;

gchar *videoMimeType = "video/mp4";
expectGetMimeType(videoMimeType);
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};
task.execute();

g_object_unref(decryptor);
}

/**
* Test HandleBusMessage ignores generic warnings.
*/
TEST_F(HandleBusMessageTest, shouldHandleWarningMessageGeneric)
{
// Set decryptor generic
GstObject *element = GST_OBJECT_CAST(g_object_new(GST_TYPE_BIN, nullptr));
gst_object_set_name(element, "element_0");

GST_MESSAGE_TYPE(&m_message) = GST_MESSAGE_WARNING;
GST_MESSAGE_SRC(&m_message) = GST_OBJECT_CAST(&m_decryptorBase);
GST_MESSAGE_SRC(&m_message) = element;
m_err.domain = GST_CORE_ERROR;

EXPECT_CALL(*m_gstWrapper, gstMessageParseWarning(&m_message, _, _))
Expand All @@ -569,4 +571,6 @@ TEST_F(HandleBusMessageTest, shouldHandleWarningMessageGeneric)
firebolt::rialto::server::tasks::generic::HandleBusMessage task{m_context, m_gstPlayer, &m_gstPlayerClient,
m_gstWrapper, m_glibWrapper, &m_message};
task.execute();

g_object_unref(element);
}
Loading

0 comments on commit 359b52d

Please sign in to comment.