gstreamer/tests/check/gst/gstprotection.c
Matthew Waters 3d887c7f07 gst: don't use volatile to mean atomic
volatile is not sufficient to provide atomic guarantees and real atomics
should be used instead.  GCC 11 has started warning about using volatile
with atomic operations.

https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1719

Discovered in https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/issues/868

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/775>
2021-03-19 04:15:19 +00:00

294 lines
8.9 KiB
C

/* GStreamer
*
* Unit tests for protection library.
*
* Copyright (C) <2015> YouView TV Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gst/check/gstcheck.h>
#include <gst/gstprotection.h>
#ifndef GST_PACKAGE_NAME
#define GST_PACKAGE_NAME "gstreamer"
#endif
#ifndef GST_PACKAGE_ORIGIN
#define GST_PACKAGE_ORIGIN "https://developer.gnome.org/gstreamer/"
#endif
static GType gst_protection_test_get_type (void);
#define GST_TYPE_PROTECTION_TEST (gst_protection_test_get_type ())
#define GST_PROTECTION_TEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PROTECTION_TEST, GstProtectionTest))
#define GST_PROTECTION_TEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PROTECTION_TEST, GstProtectionTestClass))
#define GST_IS_PROTECTION_TEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PROTECTION_TEST))
#define GST_IS_PROTECTION_TEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PROTECTION_TEST))
#define GST_PROTECTION_TEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_PROTECTION_TEST, GstProtectionTestClass))
#define GST_PROTECTION_TEST_NAME "protection-test"
#define CLEARKEY_SYSTEM_ID "78f32170-d883-11e0-9572-0800200c9a66"
typedef struct _GstProtectionTest
{
GstElement parent;
gint test;
} GstProtectionTest;
typedef struct _GstProtectionTestClass
{
GstElementClass parent_class;
} GstProtectionTestClass;
typedef struct _PluginInitContext
{
const gchar *name;
guint rank;
GType type;
} PluginInitContext;
static GstStaticPadTemplate gst_decrypt_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS
("application/x-cenc, original-media-type=(string)video/x-h264, "
GST_PROTECTION_SYSTEM_ID_CAPS_FIELD "=(string)" CLEARKEY_SYSTEM_ID)
);
static void
gst_protection_test_class_init (GObjectClass * klass)
{
}
static void
gst_protection_test_base_init (GstProtectionTestClass * klass)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
gst_element_class_add_static_pad_template (element_class,
&gst_decrypt_sink_template);
gst_element_class_set_metadata (element_class,
"Decryptor element for unit tests",
GST_ELEMENT_FACTORY_KLASS_DECRYPTOR,
"Use in unit tests", "Alex Ashley <alex.ashley@youview.com>");
}
static GType
gst_protection_test_get_type (void)
{
static gsize protection_test_type = 0;
if (g_once_init_enter (&protection_test_type)) {
GType type;
const GTypeInfo info = {
sizeof (GstProtectionTestClass),
(GBaseInitFunc) gst_protection_test_base_init, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gst_protection_test_class_init, /* class_init */
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GstProtectionTest),
0, /* n_preallocs */
NULL, /* instance_init */
NULL /* value_table */
};
type =
g_type_register_static (GST_TYPE_ELEMENT, "GstProtectionTest", &info,
0);
g_once_init_leave (&protection_test_type, type);
}
return protection_test_type;
}
static gboolean
protection_plugin_init_func (GstPlugin * plugin, gpointer user_data)
{
PluginInitContext *context = (PluginInitContext *) user_data;
gboolean ret;
ret =
gst_element_register (plugin, context->name, context->rank,
context->type);
return ret;
}
static gboolean
protection_create_plugin (GstRegistry * registry, const gchar * name,
GType type)
{
gboolean ret;
PluginInitContext context;
context.name = name;
context.rank = GST_RANK_MARGINAL;
context.type = type;
ret = gst_plugin_register_static_full (GST_VERSION_MAJOR, /* version */
GST_VERSION_MINOR, /* version */
name, /* name */
"Protection unit test", /* description */
protection_plugin_init_func, /* init function */
"0.0.0", /* version string */
GST_LICENSE_UNKNOWN, /* license */
__FILE__, /* source */
GST_PACKAGE_NAME, /* package */
GST_PACKAGE_ORIGIN, /* origin */
&context /* user_data */
);
return ret;
}
static void
test_setup (void)
{
GstRegistry *registry;
registry = gst_registry_get ();
protection_create_plugin (registry, GST_PROTECTION_TEST_NAME,
GST_TYPE_PROTECTION_TEST);
}
static void
test_teardown (void)
{
}
GST_START_TEST (test_decryptor_element_class)
{
GstElement *elem;
const gchar *selected_id;
const gchar *sys_ids[] = {
CLEARKEY_SYSTEM_ID,
"69f908af-4816-46ea-910c-cd5dcccb0a3a",
"5e629af5-38da-4063-8977-97ffbd9902d4",
NULL
};
#ifdef DEBUG_PLUGINS
GList *list, *walk;
list = gst_registry_get_plugin_list (gst_registry_get ());
for (walk = list; walk; walk = g_list_next (walk)) {
GstPlugin *plugin = (GstPlugin *) walk->data;
g_print ("Element %s\n", gst_plugin_get_name (plugin));
}
#endif
elem = gst_element_factory_make (GST_PROTECTION_TEST_NAME, NULL);
fail_unless (GST_IS_ELEMENT (elem));
selected_id = gst_protection_select_system (sys_ids);
fail_if (selected_id == NULL);
selected_id = gst_protection_select_system (&sys_ids[1]);
fail_unless (selected_id == NULL);
selected_id = gst_protection_select_system (&sys_ids[3]);
fail_unless (selected_id == NULL);
gst_object_unref (elem);
}
GST_END_TEST;
GST_START_TEST (test_protection_metadata)
{
GstBuffer *buf = NULL;
GstBuffer *iv, *kid;
GstBuffer *fetched_iv = NULL, *fetched_key_id = NULL;
GstStructure *meta_info;
GstProtectionMeta *meta = NULL;
const GstMetaInfo *info = NULL;
const GValue *value;
/* Check correct type info is returned */
info = gst_protection_meta_get_info ();
fail_unless (info != NULL);
fail_unless (info->api == GST_PROTECTION_META_API_TYPE);
iv = gst_buffer_new_allocate (NULL, 16, NULL);
gst_buffer_memset (iv, 0, 'i', 16);
ASSERT_MINI_OBJECT_REFCOUNT (iv, "iv", 1);
kid = gst_buffer_new_allocate (NULL, 16, NULL);
gst_buffer_memset (kid, 0, 'k', 16);
ASSERT_MINI_OBJECT_REFCOUNT (kid, "kid", 1);
meta_info = gst_structure_new ("application/x-cenc",
"encrypted", G_TYPE_BOOLEAN, TRUE,
"iv", GST_TYPE_BUFFER, iv,
"iv_size", G_TYPE_UINT, 16, "kid", GST_TYPE_BUFFER, kid, NULL);
ASSERT_MINI_OBJECT_REFCOUNT (kid, "kid", 2);
ASSERT_MINI_OBJECT_REFCOUNT (iv, "iv", 2);
buf = gst_buffer_new_allocate (NULL, 1024, NULL);
/* Test attaching protection metadata to buffer */
meta = gst_buffer_add_protection_meta (buf, meta_info);
fail_unless (meta != NULL);
/* gst_buffer_new_allocate takes ownership of info GstStructure */
ASSERT_MINI_OBJECT_REFCOUNT (buf, "Buffer", 1);
/* Test detaching protection metadata from buffer, and check that
* contained data is correct */
meta = NULL;
meta = gst_buffer_get_protection_meta (buf);
fail_unless (meta != NULL);
ASSERT_MINI_OBJECT_REFCOUNT (buf, "Buffer", 1);
value = gst_structure_get_value (meta->info, "iv");
fail_unless (value != NULL);
fetched_iv = gst_value_get_buffer (value);
fail_unless (fetched_iv != NULL);
fail_unless (gst_buffer_get_size (fetched_iv) == 16);
value = gst_structure_get_value (meta->info, "kid");
fail_unless (value != NULL);
fetched_key_id = gst_value_get_buffer (value);
fail_unless (fetched_key_id != NULL);
fail_unless (gst_buffer_get_size (fetched_key_id) == 16);
gst_buffer_remove_meta (buf, (GstMeta *) meta);
/* Check that refcounts are decremented after metadata is freed */
ASSERT_MINI_OBJECT_REFCOUNT (buf, "Buffer", 1);
ASSERT_MINI_OBJECT_REFCOUNT (iv, "IV", 1);
ASSERT_MINI_OBJECT_REFCOUNT (kid, "KID", 1);
gst_buffer_unref (buf);
gst_buffer_unref (iv);
gst_buffer_unref (kid);
}
GST_END_TEST;
static Suite *
protection_suite (void)
{
Suite *s = suite_create ("protection library");
TCase *tc_chain = tcase_create ("general");
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_decryptor_element_class);
tcase_add_test (tc_chain, test_protection_metadata);
tcase_add_unchecked_fixture (tc_chain, test_setup, test_teardown);
return s;
}
GST_CHECK_MAIN (protection);