From f1f0625e97a72e78316c54c6d11846e5eccd5ffc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 29 Mar 2011 15:41:33 +0200 Subject: [PATCH 1/9] encodebin: Requesting a pad again now gives a g_return_val_if_fail() Before the behaviour was undefined and implemented differently by elements, now core checks for this (and other problems) and returns NULL and an assertion. --- tests/check/elements/encodebin.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/check/elements/encodebin.c b/tests/check/elements/encodebin.c index 03ff262806..0d0d009486 100644 --- a/tests/check/elements/encodebin.c +++ b/tests/check/elements/encodebin.c @@ -504,7 +504,8 @@ GST_START_TEST (test_encodebin_render_audio_only_static) fail_unless (gst_element_link_many (audiotestsrc, ebin, fakesink, NULL)); /* Requesting a new pad should fail */ - fail_if (gst_element_get_request_pad (ebin, "audio_0") != NULL); + ASSERT_CRITICAL (gst_element_get_request_pad (ebin, "audio_0")); + sinkcaps = gst_caps_new_simple ("audio/x-raw-int", NULL); g_signal_emit_by_name (ebin, "request-pad", sinkcaps, &sinkpad); gst_caps_unref (sinkcaps); From 6cc96a67ec8c9e49b761ac0d4e79e226bdd88c21 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 18 Mar 2011 09:28:23 -0300 Subject: [PATCH 2/9] tag: xmp: Add function to list the available schemas Adds a function to list the available schemas in our xmp lib https://bugzilla.gnome.org/show_bug.cgi?id=645167 --- gst-libs/gst/tag/gstxmptag.c | 109 ++++++++++++++++++++++++++++++----- gst-libs/gst/tag/tag.h | 3 + win32/common/libgsttag.def | 2 + 3 files changed, 101 insertions(+), 13 deletions(-) diff --git a/gst-libs/gst/tag/gstxmptag.c b/gst-libs/gst/tag/gstxmptag.c index 0b1b7bd29d..aa3b9a7f6a 100644 --- a/gst-libs/gst/tag/gstxmptag.c +++ b/gst-libs/gst/tag/gstxmptag.c @@ -35,6 +35,7 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif +#include "tag.h" #include #include "gsttageditingprivate.h" #include @@ -43,6 +44,32 @@ #include #include +static const gchar *schema_list[] = { + "dc", + "xap", + "tiff", + "exif", + "photoshop", + "Iptc4xmpCore", + NULL +}; + +/** + * gst_tag_xmp_list_schemas: + * + * Gets the list of supported schemas in the xmp lib + * + * Returns: a %NULL terminated array of strings with the schema names + * + * Since: 0.10.33 + */ +const gchar ** +gst_tag_xmp_list_schemas (void) +{ + return schema_list; +} + +typedef struct _XmpSerializationData XmpSerializationData; typedef struct _XmpTag XmpTag; /* @@ -63,6 +90,29 @@ typedef void (*XmpDeserializationFunc) (XmpTag * xmptag, GstTagList * taglist, const gchar * gst_tag, const gchar * xmp_tag_value, const gchar * str, GSList ** pending_tags); +struct _XmpSerializationData +{ + GString *data; + GList *schemas; +}; + +static gboolean +xmp_serialization_data_use_schema (XmpSerializationData * serdata, + const gchar * schemaname) +{ + GList *iter; + if (serdata->schemas == NULL) + return TRUE; + + for (iter = serdata->schemas; iter; iter = g_list_next (iter)) { + const gchar *name = (const gchar *) iter->data; + + if (strcmp (name, schemaname) == 0) + return TRUE; + } + return FALSE; +} + #define GST_XMP_TAG_TYPE_SIMPLE 0 #define GST_XMP_TAG_TYPE_BAG 1 @@ -192,18 +242,22 @@ _gst_xmp_schema_add_simple_mapping (GstXmpSchema * schema, * have our lists modified during usage */ static GPtrArray * -_xmp_tag_get_mapping (const gchar * gst_tag) +_xmp_tag_get_mapping (const gchar * gst_tag, XmpSerializationData * serdata) { GPtrArray *ret = NULL; GHashTableIter iter; GQuark key = g_quark_from_string (gst_tag); gpointer iterkey, value; + const gchar *schemaname; g_hash_table_iter_init (&iter, __xmp_schemas); while (!ret && g_hash_table_iter_next (&iter, &iterkey, &value)) { GstXmpSchema *schema = (GstXmpSchema *) value; - ret = (GPtrArray *) gst_xmp_schema_lookup (schema, GUINT_TO_POINTER (key)); + schemaname = g_quark_to_string (GPOINTER_TO_UINT (iterkey)); + if (xmp_serialization_data_use_schema (serdata, schemaname)) + ret = + (GPtrArray *) gst_xmp_schema_lookup (schema, GUINT_TO_POINTER (key)); } return ret; } @@ -818,7 +872,7 @@ _init_xmp_tag_map () schema = gst_xmp_schema_new (); _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_USER_RATING, "xmp:Rating", GST_XMP_TAG_TYPE_SIMPLE, NULL, deserialize_xmp_rating); - _gst_xmp_add_schema ("xmp", schema); + _gst_xmp_add_schema ("xap", schema); /* tiff */ schema = gst_xmp_schema_new (); @@ -1453,12 +1507,13 @@ static void write_one_tag (const GstTagList * list, const gchar * tag, gpointer user_data) { guint i = 0, ct = gst_tag_list_get_tag_size (list, tag), tag_index; - GString *data = user_data; + XmpSerializationData *serialization_data = user_data; + GString *data = serialization_data->data; GPtrArray *xmp_tag_array = NULL; char *s; /* map gst-tag to xmp tag */ - xmp_tag_array = _xmp_tag_get_mapping (tag); + xmp_tag_array = _xmp_tag_get_mapping (tag, serialization_data); if (!xmp_tag_array) { GST_WARNING ("no mapping for %s to xmp", tag); @@ -1516,23 +1571,32 @@ write_one_tag (const GstTagList * list, const gchar * tag, gpointer user_data) } /** - * gst_tag_list_to_xmp_buffer: + * gst_tag_list_to_xmp_buffer_full: * @list: tags * @read_only: does the container forbid inplace editing + * @schemas: list of schemas to be used on serialization * - * Formats a taglist as a xmp packet. + * Formats a taglist as a xmp packet using only the selected + * schemas. An empty list (%NULL) means that all schemas should + * be used * * Returns: new buffer or %NULL, unref the buffer when done * - * Since: 0.10.29 + * Since: 0.10.33 */ GstBuffer * -gst_tag_list_to_xmp_buffer (const GstTagList * list, gboolean read_only) +gst_tag_list_to_xmp_buffer_full (const GstTagList * list, gboolean read_only, + GList * schemas) { GstBuffer *buffer = NULL; - GString *data = g_string_sized_new (4096); + XmpSerializationData serialization_data; + GString *data; guint i; + serialization_data.data = g_string_sized_new (4096); + serialization_data.schemas = schemas; + data = serialization_data.data; + xmp_tags_initialize (); g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL); @@ -1546,15 +1610,17 @@ gst_tag_list_to_xmp_buffer (const GstTagList * list, gboolean read_only) "\n"); g_string_append (data, "\n"); /* iterate the taglist */ - gst_tag_list_foreach (list, write_one_tag, data); + gst_tag_list_foreach (list, write_one_tag, &serialization_data); /* xmp footer */ g_string_append (data, "\n"); @@ -1581,5 +1647,22 @@ gst_tag_list_to_xmp_buffer (const GstTagList * list, gboolean read_only) return buffer; } +/** + * gst_tag_list_to_xmp_buffer: + * @list: tags + * @read_only: does the container forbid inplace editing + * + * Formats a taglist as a xmp packet. + * + * Returns: new buffer or %NULL, unref the buffer when done + * + * Since: 0.10.29 + */ +GstBuffer * +gst_tag_list_to_xmp_buffer (const GstTagList * list, gboolean read_only) +{ + return gst_tag_list_to_xmp_buffer_full (list, read_only, NULL); +} + #undef gst_xmp_schema_lookup #undef gst_xmp_schema_insert diff --git a/gst-libs/gst/tag/tag.h b/gst-libs/gst/tag/tag.h index 15906df171..ed91e133f2 100644 --- a/gst-libs/gst/tag/tag.h +++ b/gst-libs/gst/tag/tag.h @@ -474,6 +474,9 @@ gboolean gst_tag_list_add_id3_image (GstTagList * tag_list, GstTagList * gst_tag_list_from_xmp_buffer (const GstBuffer * buffer); GstBuffer * gst_tag_list_to_xmp_buffer (const GstTagList * list, gboolean read_only); +GstBuffer * gst_tag_list_to_xmp_buffer_full (const GstTagList * list, + gboolean read_only, GList * schemas); +const gchar** gst_tag_xmp_list_schemas (void); /* functions related to exif */ GstBuffer * gst_tag_list_to_exif_buffer (const GstTagList * taglist, diff --git a/win32/common/libgsttag.def b/win32/common/libgsttag.def index 846bba6604..349cfc05ab 100644 --- a/win32/common/libgsttag.def +++ b/win32/common/libgsttag.def @@ -24,9 +24,11 @@ EXPORTS gst_tag_list_to_exif_buffer_with_tiff_header gst_tag_list_to_vorbiscomment_buffer gst_tag_list_to_xmp_buffer + gst_tag_list_to_xmp_buffer_full gst_tag_parse_extended_comment gst_tag_register_musicbrainz_tags gst_tag_to_id3_tag gst_tag_to_vorbis_comments gst_tag_to_vorbis_tag + gst_tag_xmp_list_schemas gst_vorbis_tag_add From 34ba387d0bab06eded02cba411e7ea8c30abfd46 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 17 Mar 2011 15:42:28 -0300 Subject: [PATCH 3/9] tagxmpwriter: Adds a new GstTagXmpWriter interface The GstTagXmpWriter interface is to be implemented on elements that provide xmp serialization. It allows users to select which xmp schemas should be used on serialization. API: GstTagXmpWriter https://bugzilla.gnome.org/show_bug.cgi?id=645167 --- gst-libs/gst/tag/Makefile.am | 4 +- gst-libs/gst/tag/gstxmptag.c | 15 +- gst-libs/gst/tag/tag.h | 2 +- gst-libs/gst/tag/xmpwriter.c | 322 +++++++++++++++++++++++++++++++++++ gst-libs/gst/tag/xmpwriter.h | 68 ++++++++ win32/common/libgsttag.def | 7 + 6 files changed, 407 insertions(+), 11 deletions(-) create mode 100644 gst-libs/gst/tag/xmpwriter.c create mode 100644 gst-libs/gst/tag/xmpwriter.h diff --git a/gst-libs/gst/tag/Makefile.am b/gst-libs/gst/tag/Makefile.am index 15263dd49e..f953e60a7d 100644 --- a/gst-libs/gst/tag/Makefile.am +++ b/gst-libs/gst/tag/Makefile.am @@ -2,13 +2,13 @@ libgsttagincludedir = \ $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/tag libgsttaginclude_HEADERS = \ - tag.h gsttagdemux.h + tag.h gsttagdemux.h xmpwriter.h lib_LTLIBRARIES = libgsttag-@GST_MAJORMINOR@.la libgsttag_@GST_MAJORMINOR@_la_SOURCES = \ gstvorbistag.c gstid3tag.c gstxmptag.c gstexiftag.c \ - lang.c tags.c gsttagdemux.c gsttageditingprivate.c + lang.c tags.c gsttagdemux.c gsttageditingprivate.c xmpwriter.c libgsttag_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) libgsttag_@GST_MAJORMINOR@_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(LIBM) libgsttag_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) diff --git a/gst-libs/gst/tag/gstxmptag.c b/gst-libs/gst/tag/gstxmptag.c index aa3b9a7f6a..dce3e416d3 100644 --- a/gst-libs/gst/tag/gstxmptag.c +++ b/gst-libs/gst/tag/gstxmptag.c @@ -93,22 +93,21 @@ typedef void (*XmpDeserializationFunc) (XmpTag * xmptag, GstTagList * taglist, struct _XmpSerializationData { GString *data; - GList *schemas; + const gchar **schemas; }; static gboolean xmp_serialization_data_use_schema (XmpSerializationData * serdata, const gchar * schemaname) { - GList *iter; + gint i = 0; if (serdata->schemas == NULL) return TRUE; - for (iter = serdata->schemas; iter; iter = g_list_next (iter)) { - const gchar *name = (const gchar *) iter->data; - - if (strcmp (name, schemaname) == 0) + while (serdata->schemas[i] != NULL) { + if (strcmp (serdata->schemas[i], schemaname) == 0) return TRUE; + i++; } return FALSE; } @@ -1574,7 +1573,7 @@ write_one_tag (const GstTagList * list, const gchar * tag, gpointer user_data) * gst_tag_list_to_xmp_buffer_full: * @list: tags * @read_only: does the container forbid inplace editing - * @schemas: list of schemas to be used on serialization + * @schemas: %NULL terminated array of schemas to be used on serialization * * Formats a taglist as a xmp packet using only the selected * schemas. An empty list (%NULL) means that all schemas should @@ -1586,7 +1585,7 @@ write_one_tag (const GstTagList * list, const gchar * tag, gpointer user_data) */ GstBuffer * gst_tag_list_to_xmp_buffer_full (const GstTagList * list, gboolean read_only, - GList * schemas) + const gchar ** schemas) { GstBuffer *buffer = NULL; XmpSerializationData serialization_data; diff --git a/gst-libs/gst/tag/tag.h b/gst-libs/gst/tag/tag.h index ed91e133f2..472110b2ab 100644 --- a/gst-libs/gst/tag/tag.h +++ b/gst-libs/gst/tag/tag.h @@ -475,7 +475,7 @@ GstTagList * gst_tag_list_from_xmp_buffer (const GstBuffer * buffer GstBuffer * gst_tag_list_to_xmp_buffer (const GstTagList * list, gboolean read_only); GstBuffer * gst_tag_list_to_xmp_buffer_full (const GstTagList * list, - gboolean read_only, GList * schemas); + gboolean read_only, const gchar ** schemas); const gchar** gst_tag_xmp_list_schemas (void); /* functions related to exif */ diff --git a/gst-libs/gst/tag/xmpwriter.c b/gst-libs/gst/tag/xmpwriter.c new file mode 100644 index 0000000000..573224cb1d --- /dev/null +++ b/gst-libs/gst/tag/xmpwriter.c @@ -0,0 +1,322 @@ +/* GStreamer XmpConfig + * Copyright (C) 2010 Thiago Santos + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:gstxmpconfig + * @short_description: Interface for elements that provide XMP serialization + * + * + * + * This interface is implemented by elements that are able to do XMP serialization. Examples for + * such elements are #jifmux and #qtmux. + * + * + * Applications can use this interface to configure which XMP schemas should be used when serializing + * tags into XMP. Schemas are represented by their names, a full list of the supported schemas can be + * obtained from gst_tag_xmp_list_schemas(). By default, all schemas are used. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xmpwriter.h" +#include +#include + +static GQuark tag_xmp_writer_key; + +typedef struct +{ + GSList *schemas; + GStaticMutex lock; +} GstTagXmpWriterData; + +GType +gst_tag_xmp_writer_get_type (void) +{ + static volatile gsize xmp_config_type = 0; + + if (g_once_init_enter (&xmp_config_type)) { + GType _type; + static const GTypeInfo xmp_config_info = { + sizeof (GstTagXmpWriterInterface), /* class_size */ + NULL, /* base_init */ + NULL, /* base_finalize */ + NULL, + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, + NULL + }; + + _type = g_type_register_static (G_TYPE_INTERFACE, "GstTagXmpWriter", + &xmp_config_info, 0); + tag_xmp_writer_key = g_quark_from_static_string ("GST_TAG_XMP_WRITER"); + g_type_interface_add_prerequisite (_type, GST_TYPE_ELEMENT); + + g_once_init_leave (&xmp_config_type, _type); + } + + return xmp_config_type; +} + +static void +gst_tag_xmp_writer_data_add_schema_unlocked (GstTagXmpWriterData * data, + const gchar * schema) +{ + if (!g_slist_find_custom (data->schemas, schema, (GCompareFunc) strcmp)) { + data->schemas = g_slist_prepend (data->schemas, g_strdup (schema)); + } +} + +static void +gst_tag_xmp_writer_data_add_all_schemas_unlocked (GstTagXmpWriterData * data) +{ + const gchar **schemas; + gint i = 0; + + /* initialize it with all schemas */ + schemas = gst_tag_xmp_list_schemas (); + while (schemas[i] != NULL) { + gst_tag_xmp_writer_data_add_schema_unlocked (data, schemas[i]); + i++; + } +} + + +static void +gst_tag_xmp_writer_data_free (gpointer p) +{ + GstTagXmpWriterData *data = (GstTagXmpWriterData *) p; + GSList *iter; + + if (data->schemas) { + for (iter = data->schemas; iter; iter = g_slist_next (iter)) { + g_free (iter->data); + } + g_slist_free (data->schemas); + } + + g_static_mutex_free (&data->lock); + + g_slice_free (GstTagXmpWriterData, data); +} + +static GstTagXmpWriterData * +gst_tag_xmp_writer_get_data (GstTagXmpWriter * xmpconfig) +{ + GstTagXmpWriterData *data; + + data = g_object_get_qdata (G_OBJECT (xmpconfig), tag_xmp_writer_key); + if (!data) { + static GStaticMutex create_mutex = G_STATIC_MUTEX_INIT; + + /* make sure no other thread is creating a GstTagXmpWriterData at the same time */ + g_static_mutex_lock (&create_mutex); + data = g_object_get_qdata (G_OBJECT (xmpconfig), tag_xmp_writer_key); + if (!data) { + data = g_slice_new (GstTagXmpWriterData); + g_static_mutex_init (&data->lock); + + data->schemas = NULL; + gst_tag_xmp_writer_data_add_all_schemas_unlocked (data); + + g_object_set_qdata_full (G_OBJECT (xmpconfig), tag_xmp_writer_key, data, + gst_tag_xmp_writer_data_free); + } + g_static_mutex_unlock (&create_mutex); + } + + return data; +} + +/** + * gst_tag_xmp_writer_add_all_schemas: + * @config: a #GstTagXmpWriter + * + * Adds all available XMP schemas to the configuration. Meaning that + * all will be used. + * + * Since: 0.10.33 + */ +void +gst_tag_xmp_writer_add_all_schemas (GstTagXmpWriter * config) +{ + GstTagXmpWriterData *data; + + g_return_if_fail (GST_IS_TAG_XMP_WRITER (config)); + + data = gst_tag_xmp_writer_get_data (config); + + g_static_mutex_lock (&data->lock); + gst_tag_xmp_writer_data_add_all_schemas_unlocked (data); + g_static_mutex_unlock (&data->lock); +} + +/** + * gst_tag_xmp_writer_add_schema: + * @config: a #GstTagXmpWriter + * @schema: the schema to be added + * + * Adds @schema to the list schemas + * + * Since: 0.10.33 + */ +void +gst_tag_xmp_writer_add_schema (GstTagXmpWriter * config, const gchar * schema) +{ + GstTagXmpWriterData *data; + + g_return_if_fail (GST_IS_TAG_XMP_WRITER (config)); + + data = gst_tag_xmp_writer_get_data (config); + + g_static_mutex_lock (&data->lock); + gst_tag_xmp_writer_data_add_schema_unlocked (data, schema); + g_static_mutex_unlock (&data->lock); +} + +/** + * gst_tag_xmp_writer_has_schema: + * @config: a #GstTagXmpWriter + * @schema: the schema to test + * + * Checks if @schema is going to be used + * + * Returns: %TRUE if it is going to be used + * Since: 0.10.33 + */ +gboolean +gst_tag_xmp_writer_has_schema (GstTagXmpWriter * config, const gchar * schema) +{ + GstTagXmpWriterData *data; + gboolean ret = FALSE; + GSList *iter; + + g_return_val_if_fail (GST_IS_TAG_XMP_WRITER (config), FALSE); + + data = gst_tag_xmp_writer_get_data (config); + + g_static_mutex_lock (&data->lock); + for (iter = data->schemas; iter; iter = g_slist_next (iter)) { + if (strcmp ((const gchar *) iter->data, schema) == 0) { + ret = TRUE; + break; + } + } + g_static_mutex_unlock (&data->lock); + + return ret; +} + +/** + * gst_tag_xmp_writer_remove_schema: + * @config: a #GstTagXmpWriter + * @schema: the schema to remove + * + * Removes a schema from the list of schemas to use. Nothing is done if + * the schema wasn't in the list + * + * Since: 0.10.33 + */ +void +gst_tag_xmp_writer_remove_schema (GstTagXmpWriter * config, + const gchar * schema) +{ + GstTagXmpWriterData *data; + GSList *iter = NULL; + + g_return_if_fail (GST_IS_TAG_XMP_WRITER (config)); + + data = gst_tag_xmp_writer_get_data (config); + + g_static_mutex_lock (&data->lock); + for (iter = data->schemas; iter; iter = g_slist_next (iter)) { + if (strcmp ((const gchar *) iter->data, schema) == 0) { + g_free (iter->data); + data->schemas = g_slist_delete_link (data->schemas, iter); + break; + } + } + g_static_mutex_unlock (&data->lock); +} + +/** + * gst_tag_xmp_writer_remove_all_schemas: + * @config: a #GstTagXmpWriter + * + * Removes all schemas from the list of schemas to use. Meaning that no + * XMP will be generated. + * + * Since: 0.10.33 + */ +void +gst_tag_xmp_writer_remove_all_schemas (GstTagXmpWriter * config) +{ + GstTagXmpWriterData *data; + GSList *iter; + + g_return_if_fail (GST_IS_TAG_XMP_WRITER (config)); + + data = gst_tag_xmp_writer_get_data (config); + + g_static_mutex_lock (&data->lock); + if (data->schemas) { + for (iter = data->schemas; iter; iter = g_slist_next (iter)) { + g_free (iter->data); + } + g_slist_free (data->schemas); + } + data->schemas = NULL; + g_static_mutex_unlock (&data->lock); +} + +GstBuffer * +gst_tag_xmp_writer_tag_list_to_xmp_buffer (GstTagXmpWriter * config, + const GstTagList * taglist, gboolean read_only) +{ + GstTagXmpWriterData *data; + GstBuffer *buf = NULL; + const gchar **array; + gint i = 0; + GSList *iter; + + g_return_val_if_fail (GST_IS_TAG_XMP_WRITER (config), NULL); + + data = gst_tag_xmp_writer_get_data (config); + + g_static_mutex_lock (&data->lock); + if (data->schemas) { + array = g_new0 (const gchar *, g_slist_length (data->schemas) + 1); + if (array) { + for (iter = data->schemas; iter; iter = g_slist_next (iter)) { + array[i++] = (const gchar *) iter->data; + } + buf = gst_tag_list_to_xmp_buffer_full (taglist, read_only, array); + g_free (array); + } + } + g_static_mutex_unlock (&data->lock); + + return buf; +} diff --git a/gst-libs/gst/tag/xmpwriter.h b/gst-libs/gst/tag/xmpwriter.h new file mode 100644 index 0000000000..6c89072c23 --- /dev/null +++ b/gst-libs/gst/tag/xmpwriter.h @@ -0,0 +1,68 @@ +/* GStreamer XmpConfig + * Copyright (C) 2011 Thiago Santos + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __TAG_XMP_WRITER_H__ +#define __TAG_XMP_WRITER_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_TAG_XMP_WRITER \ + (gst_tag_xmp_writer_get_type ()) +#define GST_TAG_XMP_WRITER(obj) \ + (GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TAG_XMP_WRITER, GstTagXmpWriter)) +#define GST_TAG_XMP_WRITER_INTERFACE(iface) \ + (G_TYPE_CHECK_INTERFACE_CAST ((iface), GST_TYPE_TAG_XMP_WRITER, GstTagXmpWriterInterface)) +#define GST_IS_TAG_XMP_WRITER(obj) \ + (GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TAG_XMP_WRITER)) +#define GST_IS_TAG_XMP_WRITER_INTERFACE(iface) \ + (G_TYPE_CHECK_INTERFACE_TYPE ((iface), GST_TYPE_TAG_XMP_WRITER)) +#define GST_TAG_XMP_WRITER_GET_INTERFACE(inst) \ + (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_TAG_XMP_WRITER, GstTagXmpWriterInterface)) + +typedef struct _GstTagXmpWriter GstTagXmpWriter; +typedef struct _GstTagXmpWriterInterface GstTagXmpWriterInterface; + +struct _GstTagXmpWriterInterface { + GTypeInterface parent; +}; + +GType gst_tag_xmp_writer_get_type (void); + +void gst_tag_xmp_writer_add_all_schemas (GstTagXmpWriter * config); + +void gst_tag_xmp_writer_add_schema (GstTagXmpWriter * config, + const gchar * schema); + +gboolean gst_tag_xmp_writer_has_schema (GstTagXmpWriter * config, + const gchar * schema); + +void gst_tag_xmp_writer_remove_schema (GstTagXmpWriter * config, + const gchar * schema); + +void gst_tag_xmp_writer_remove_all_schemas (GstTagXmpWriter * config); + +GstBuffer* gst_tag_xmp_writer_tag_list_to_xmp_buffer (GstTagXmpWriter * config, + const GstTagList * taglist, + gboolean read_only); + +G_END_DECLS + +#endif /* __TAG_XMP_WRITER_H__ */ diff --git a/win32/common/libgsttag.def b/win32/common/libgsttag.def index 349cfc05ab..bab6bbda21 100644 --- a/win32/common/libgsttag.def +++ b/win32/common/libgsttag.def @@ -31,4 +31,11 @@ EXPORTS gst_tag_to_vorbis_comments gst_tag_to_vorbis_tag gst_tag_xmp_list_schemas + gst_tag_xmp_writer_add_all_schemas + gst_tag_xmp_writer_add_schema + gst_tag_xmp_writer_get_type + gst_tag_xmp_writer_has_schema + gst_tag_xmp_writer_remove_all_schemas + gst_tag_xmp_writer_remove_schema + gst_tag_xmp_writer_tag_list_to_xmp_buffer gst_vorbis_tag_add From b5246da456bdd079ccc65800359604c13abb8c98 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 21 Mar 2011 15:34:09 -0300 Subject: [PATCH 4/9] tagxmpwriter: Add check tests https://bugzilla.gnome.org/show_bug.cgi?id=645167 --- tests/check/Makefile.am | 12 ++ tests/check/libs/xmpwriter.c | 275 +++++++++++++++++++++++++++++++++++ 2 files changed, 287 insertions(+) create mode 100644 tests/check/libs/xmpwriter.c diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index c5bd554623..8a7c7cdc0d 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -150,6 +150,7 @@ check_PROGRAMS = \ libs/rtsp \ libs/tag \ libs/video \ + libs/xmpwriter \ $(cxx_checks) \ $(check_orc) \ pipelines/simple-launch-lines \ @@ -307,6 +308,17 @@ libs_profile_CFLAGS = \ libs_profile_LDADD = \ $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la $(LDADD) +libs_xmpwriter_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(AM_CFLAGS) + +libs_xmpwriter_LDADD = \ + $(top_builddir)/gst-libs/gst/tag/libgsttag-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) \ + $(LDADD) + + libs_gstlibscpp_SOURCES = libs/gstlibscpp.cc elements_appsink_CFLAGS = \ diff --git a/tests/check/libs/xmpwriter.c b/tests/check/libs/xmpwriter.c new file mode 100644 index 0000000000..99b84ae855 --- /dev/null +++ b/tests/check/libs/xmpwriter.c @@ -0,0 +1,275 @@ +/* GStreamer + * + * unit tests for xmp config library + * + * Copyright (C) 2011 Thiago Santos + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include + +#include + +#define TEST_ELEMENT_TYPE (test_element_get_type()) + +typedef struct TestElement TestElement; +typedef struct TestElementClass TestElementClass; + +struct TestElement +{ + GstElement parent; +}; + +struct TestElementClass +{ + GstElementClass parent_class; +}; + +GType test_element_get_type (void); + +static void init_interface (GType type); + +GST_BOILERPLATE_FULL (TestElement, test_element, GstElement, GST_TYPE_ELEMENT, + init_interface); + +static void +init_interface (GType type) +{ + static const GInterfaceInfo tagxmpwriter_info = { + NULL, + NULL, + NULL, + }; + + g_type_add_interface_static (type, GST_TYPE_TAG_XMP_WRITER, + &tagxmpwriter_info); +} + +static void +test_element_base_init (gpointer klass) +{ +} + +static void +test_element_class_init (TestElementClass * klass) +{ +} + +static void +test_element_init (TestElement * this, TestElementClass * klass) +{ +} + +static void +tag_list_equals (GstTagList * taglist, GstTagList * taglist2) +{ + const gchar *name_sent, *name_recv; + const GValue *value_sent, *value_recv; + gboolean found; + gint comparison; + gint n_recv; + gint n_sent; + gint i, j; + + /* verify tags */ + fail_unless (taglist2 != NULL); + n_recv = gst_structure_n_fields (taglist2); + n_sent = gst_structure_n_fields (taglist); + fail_unless (n_recv == n_sent); + fail_unless (n_sent > 0); + + /* FIXME: compare taglist values */ + for (i = 0; i < n_sent; i++) { + name_sent = gst_structure_nth_field_name (taglist, i); + value_sent = gst_structure_get_value (taglist, name_sent); + found = FALSE; + for (j = 0; j < n_recv; j++) { + name_recv = gst_structure_nth_field_name (taglist2, j); + if (!strcmp (name_sent, name_recv)) { + value_recv = gst_structure_get_value (taglist2, name_recv); + comparison = gst_value_compare (value_sent, value_recv); + if (comparison != GST_VALUE_EQUAL) { + gchar *vs = g_strdup_value_contents (value_sent); + gchar *vr = g_strdup_value_contents (value_recv); + GST_DEBUG ("sent = %s:'%s', recv = %s:'%s'", + G_VALUE_TYPE_NAME (value_sent), vs, + G_VALUE_TYPE_NAME (value_recv), vr); + g_free (vs); + g_free (vr); + } + if (comparison != GST_VALUE_EQUAL && + G_VALUE_HOLDS (value_sent, G_TYPE_DOUBLE)) { + gdouble vs; + gdouble vr; + + /* add some tolerance for doubles */ + vs = g_value_get_double (value_sent); + vr = g_value_get_double (value_recv); + if (vr >= vs - 0.001 && vr <= vs + 0.001) + comparison = GST_VALUE_EQUAL; + } + fail_unless (comparison == GST_VALUE_EQUAL, + "tag item %s has been received with different type or value", + name_sent); + found = TRUE; + break; + } + } + fail_unless (found, "tag item %s is lost", name_sent); + } +} + +static gboolean +gst_buffer_equals (GstBuffer * buf_a, GstBuffer * buf_b) +{ + if (GST_BUFFER_SIZE (buf_a) != GST_BUFFER_SIZE (buf_b)) + return FALSE; + + return memcmp (GST_BUFFER_DATA (buf_a), GST_BUFFER_DATA (buf_b), + GST_BUFFER_SIZE (buf_a)) == 0; +} + +static GstTagList * +create_taglist (void) +{ + return gst_tag_list_new_full (GST_TAG_ARTIST, "artist", + GST_TAG_TITLE, "title", GST_TAG_COPYRIGHT, "copyright", NULL); +} + +GST_START_TEST (test_no_xmp) +{ + GstTagList *taglist = create_taglist (); + GstElement *test_element = + (GstElement *) g_object_new (TEST_ELEMENT_TYPE, NULL); + + gst_tag_xmp_writer_remove_all_schemas (GST_TAG_XMP_WRITER (test_element)); + + fail_unless (gst_tag_xmp_writer_tag_list_to_xmp_buffer (GST_TAG_XMP_WRITER + (test_element), taglist, TRUE) == NULL); + + gst_object_unref (test_element); + gst_tag_list_free (taglist); +} + +GST_END_TEST; + + +GST_START_TEST (test_default) +{ + GstTagList *taglist = create_taglist (); + GstElement *test_element = + (GstElement *) g_object_new (TEST_ELEMENT_TYPE, NULL); + GstBuffer *buf; + GstBuffer *buf2; + + buf = + gst_tag_xmp_writer_tag_list_to_xmp_buffer (GST_TAG_XMP_WRITER + (test_element), taglist, TRUE); + buf2 = gst_tag_list_to_xmp_buffer (taglist, TRUE); + fail_unless (gst_buffer_equals (buf, buf2)); + + gst_object_unref (test_element); + gst_buffer_unref (buf); + gst_buffer_unref (buf2); + gst_tag_list_free (taglist); +} + +GST_END_TEST; + + +GST_START_TEST (test_disable) +{ + GstTagList *taglist; + GstTagList *taglist2; + GstElement *test_element = + (GstElement *) g_object_new (TEST_ELEMENT_TYPE, NULL); + GstBuffer *buf; + const gchar *str; + + taglist = gst_tag_list_new_full (GST_TAG_ARTIST, "artist", NULL); + + /* add a tag that is mapped on xmp schema (as of Mar, 21th 2011) */ + gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_USER_RATING, 5, + NULL); + + buf = + gst_tag_xmp_writer_tag_list_to_xmp_buffer (GST_TAG_XMP_WRITER + (test_element), taglist, TRUE); + taglist2 = gst_tag_list_from_xmp_buffer (buf); + tag_list_equals (taglist, taglist2); + gst_tag_list_free (taglist2); + gst_buffer_unref (buf); + + gst_tag_xmp_writer_remove_schema (GST_TAG_XMP_WRITER (test_element), "xap"); + buf = + gst_tag_xmp_writer_tag_list_to_xmp_buffer (GST_TAG_XMP_WRITER + (test_element), taglist, TRUE); + taglist2 = gst_tag_list_from_xmp_buffer (buf); + + /* artist should be there, but rating shouldn't */ + fail_unless (gst_tag_list_peek_string_index (taglist2, GST_TAG_ARTIST, 0, + &str)); + fail_unless (gst_tag_list_get_value_index (taglist2, GST_TAG_USER_RATING, + 0) == NULL); + + gst_tag_list_free (taglist2); + gst_buffer_unref (buf); + + gst_object_unref (test_element); + gst_tag_list_free (taglist); +} + +GST_END_TEST; + + +static Suite * +xmp_config_suite (void) +{ + Suite *s = suite_create ("xmpconfig interface"); + TCase *tc_chain = tcase_create ("configuration"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_no_xmp); + tcase_add_test (tc_chain, test_default); + tcase_add_test (tc_chain, test_disable); + + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = xmp_config_suite (); + SRunner *sr = srunner_create (s); + + gst_check_init (&argc, &argv); + + srunner_run_all (sr, CK_NORMAL); + nf = srunner_ntests_failed (sr); + srunner_free (sr); + + return nf; +} From 7eb1ded8c1372edce56f50d688c3d3581f2c2100 Mon Sep 17 00:00:00 2001 From: Andoni Morales Alastruey Date: Mon, 14 Feb 2011 19:05:09 +0100 Subject: [PATCH 5/9] typefind: add m3u8 playlists --- gst/typefind/gsttypefindfunctions.c | 47 +++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/gst/typefind/gsttypefindfunctions.c b/gst/typefind/gsttypefindfunctions.c index 861549032f..c58e3f2ee6 100644 --- a/gst/typefind/gsttypefindfunctions.c +++ b/gst/typefind/gsttypefindfunctions.c @@ -266,6 +266,50 @@ uri_type_find (GstTypeFind * tf, gpointer unused) } } +/*** plaulist/m3u8 ***/ + +static GstStaticCaps m3u8_caps = GST_STATIC_CAPS ("playlist/m3u8"); + +#define M3U8_CAPS (gst_static_caps_get(&m3u8_caps)) +#define M3U8_BUFFER_SIZE 24 +#define M3U8_INC_BUFFER { \ + pos++; \ + if (pos == M3U8_BUFFER_SIZE) { \ + pos = 0; \ + offset += M3U8_BUFFER_SIZE; \ + data = gst_type_find_peek (tf, offset, M3U8_BUFFER_SIZE); \ + if (data == NULL) return; \ + } else { \ + data++; \ + } \ +} + +static void +m3u8_type_find (GstTypeFind * tf, gpointer unused) +{ + guint pos = 0; + guint offset = 0; + guint8 *data = gst_type_find_peek (tf, 0, 7); + + if (memcmp (data, "#EXTM3U", 7)) + return; + M3U8_INC_BUFFER; + + while (data) { + /* Search for # comment lines */ + while (*data != '#') { + M3U8_INC_BUFFER; + } + + if (memcmp (data, "#EXT-X-TARGETDURATION", 21) == 0 || + memcmp (data, "#EXT-X-STREAM-INF", 17) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, M3U8_CAPS); + return; + } + M3U8_INC_BUFFER; + } +} + /*** application/xml **********************************************************/ @@ -4162,6 +4206,7 @@ plugin_init (GstPlugin * plugin) static const gchar *shn_exts[] = { "shn", NULL }; static const gchar *ape_exts[] = { "ape", NULL }; static const gchar *uri_exts[] = { "ram", NULL }; + static const gchar *m3u8_exts[] = { "m3u8", NULL }; static const gchar *sdp_exts[] = { "sdp", NULL }; static const gchar *smil_exts[] = { "smil", NULL }; static const gchar *html_exts[] = { "htm", "html", NULL }; @@ -4325,6 +4370,8 @@ plugin_init (GstPlugin * plugin) utf8_exts, UTF8_CAPS, NULL, NULL); TYPE_FIND_REGISTER (plugin, "text/uri-list", GST_RANK_MARGINAL, uri_type_find, uri_exts, URI_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "playlist/m3u8", GST_RANK_MARGINAL, + m3u8_type_find, m3u8_exts, M3U8_CAPS, NULL, NULL); TYPE_FIND_REGISTER (plugin, "application/sdp", GST_RANK_SECONDARY, sdp_type_find, sdp_exts, SDP_CAPS, NULL, NULL); TYPE_FIND_REGISTER (plugin, "application/smil", GST_RANK_SECONDARY, From 70148cdf9746f013f7c1fc0cde60da365747e410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 30 Mar 2011 09:12:25 +0200 Subject: [PATCH 6/9] typefind: Use the DataScanCtx for the m3u8 typefinder --- gst/typefind/gsttypefindfunctions.c | 42 +++++++++++------------------ 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/gst/typefind/gsttypefindfunctions.c b/gst/typefind/gsttypefindfunctions.c index c58e3f2ee6..1c4e559d08 100644 --- a/gst/typefind/gsttypefindfunctions.c +++ b/gst/typefind/gsttypefindfunctions.c @@ -269,44 +269,34 @@ uri_type_find (GstTypeFind * tf, gpointer unused) /*** plaulist/m3u8 ***/ static GstStaticCaps m3u8_caps = GST_STATIC_CAPS ("playlist/m3u8"); - #define M3U8_CAPS (gst_static_caps_get(&m3u8_caps)) -#define M3U8_BUFFER_SIZE 24 -#define M3U8_INC_BUFFER { \ - pos++; \ - if (pos == M3U8_BUFFER_SIZE) { \ - pos = 0; \ - offset += M3U8_BUFFER_SIZE; \ - data = gst_type_find_peek (tf, offset, M3U8_BUFFER_SIZE); \ - if (data == NULL) return; \ - } else { \ - data++; \ - } \ -} static void m3u8_type_find (GstTypeFind * tf, gpointer unused) { - guint pos = 0; - guint offset = 0; - guint8 *data = gst_type_find_peek (tf, 0, 7); + DataScanCtx c = { 0, NULL, 0 }; - if (memcmp (data, "#EXTM3U", 7)) + if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 7))) return; - M3U8_INC_BUFFER; - while (data) { + if (memcmp (c.data, "#EXTM3U", 7)) + return; + + data_scan_ctx_advance (tf, &c, 7); + + /* Check only the first 256 bytes */ + while (c.offset < 256) { + if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 21))) + return; + /* Search for # comment lines */ - while (*data != '#') { - M3U8_INC_BUFFER; - } - - if (memcmp (data, "#EXT-X-TARGETDURATION", 21) == 0 || - memcmp (data, "#EXT-X-STREAM-INF", 17) == 0) { + if (c.data[0] == '#' && (memcmp (c.data, "#EXT-X-TARGETDURATION", 21) == 0 + || memcmp (c.data, "#EXT-X-STREAM-INF", 17) == 0)) { gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, M3U8_CAPS); return; } - M3U8_INC_BUFFER; + + data_scan_ctx_advance (tf, &c, 1); } } From 34548c16d807623f418cc7dc9222fbd9e187b91c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 30 Mar 2011 09:18:00 +0200 Subject: [PATCH 7/9] typefind: Fix comment typo and add a link the the HTTP live streaming spec --- gst/typefind/gsttypefindfunctions.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gst/typefind/gsttypefindfunctions.c b/gst/typefind/gsttypefindfunctions.c index 1c4e559d08..c05f7ff84b 100644 --- a/gst/typefind/gsttypefindfunctions.c +++ b/gst/typefind/gsttypefindfunctions.c @@ -266,11 +266,12 @@ uri_type_find (GstTypeFind * tf, gpointer unused) } } -/*** plaulist/m3u8 ***/ +/*** playlist/m3u8 ***/ static GstStaticCaps m3u8_caps = GST_STATIC_CAPS ("playlist/m3u8"); #define M3U8_CAPS (gst_static_caps_get(&m3u8_caps)) +/* See http://tools.ietf.org/html/draft-pantos-http-live-streaming-05 */ static void m3u8_type_find (GstTypeFind * tf, gpointer unused) { From 143dc4810d40068696adc436a182bfe137d5198f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Wed, 30 Mar 2011 15:44:45 +0100 Subject: [PATCH 8/9] typefindfunctions: rename type playlist/m3u8 to application/x-hls We should keep playlist/m3u8 available for normal m3u8 playlists, which we we'll likely support some day. Also, we probably don't want this handled like other playlists, so application/* seems more appropriate in this case, even if it's really just a playlist. --- gst/typefind/gsttypefindfunctions.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/gst/typefind/gsttypefindfunctions.c b/gst/typefind/gsttypefindfunctions.c index c05f7ff84b..4a24910cf7 100644 --- a/gst/typefind/gsttypefindfunctions.c +++ b/gst/typefind/gsttypefindfunctions.c @@ -266,14 +266,14 @@ uri_type_find (GstTypeFind * tf, gpointer unused) } } -/*** playlist/m3u8 ***/ +/*** application/x-hls ***/ -static GstStaticCaps m3u8_caps = GST_STATIC_CAPS ("playlist/m3u8"); -#define M3U8_CAPS (gst_static_caps_get(&m3u8_caps)) +static GstStaticCaps hls_caps = GST_STATIC_CAPS ("application/x-hls"); +#define HLS_CAPS (gst_static_caps_get(&hls_caps)) /* See http://tools.ietf.org/html/draft-pantos-http-live-streaming-05 */ static void -m3u8_type_find (GstTypeFind * tf, gpointer unused) +hls_type_find (GstTypeFind * tf, gpointer unused) { DataScanCtx c = { 0, NULL, 0 }; @@ -293,7 +293,7 @@ m3u8_type_find (GstTypeFind * tf, gpointer unused) /* Search for # comment lines */ if (c.data[0] == '#' && (memcmp (c.data, "#EXT-X-TARGETDURATION", 21) == 0 || memcmp (c.data, "#EXT-X-STREAM-INF", 17) == 0)) { - gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, M3U8_CAPS); + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, HLS_CAPS); return; } @@ -4197,7 +4197,7 @@ plugin_init (GstPlugin * plugin) static const gchar *shn_exts[] = { "shn", NULL }; static const gchar *ape_exts[] = { "ape", NULL }; static const gchar *uri_exts[] = { "ram", NULL }; - static const gchar *m3u8_exts[] = { "m3u8", NULL }; + static const gchar *hls_exts[] = { "m3u8", NULL }; static const gchar *sdp_exts[] = { "sdp", NULL }; static const gchar *smil_exts[] = { "smil", NULL }; static const gchar *html_exts[] = { "htm", "html", NULL }; @@ -4361,8 +4361,8 @@ plugin_init (GstPlugin * plugin) utf8_exts, UTF8_CAPS, NULL, NULL); TYPE_FIND_REGISTER (plugin, "text/uri-list", GST_RANK_MARGINAL, uri_type_find, uri_exts, URI_CAPS, NULL, NULL); - TYPE_FIND_REGISTER (plugin, "playlist/m3u8", GST_RANK_MARGINAL, - m3u8_type_find, m3u8_exts, M3U8_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "application/x-hls", GST_RANK_MARGINAL, + hls_type_find, hls_exts, HLS_CAPS, NULL, NULL); TYPE_FIND_REGISTER (plugin, "application/sdp", GST_RANK_SECONDARY, sdp_type_find, sdp_exts, SDP_CAPS, NULL, NULL); TYPE_FIND_REGISTER (plugin, "application/smil", GST_RANK_SECONDARY, From 2e220e352fe467234bb0937b6078f007ef9b6c07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Wed, 30 Mar 2011 15:47:38 +0100 Subject: [PATCH 9/9] tests: add typefind test for application/x-hls To make sure we don't break detection when we add typefinding for normal m3u8 playlists. --- tests/check/gst/typefindfunctions.c | 15 +++++++++++++++ tests/files/Makefile.am | 1 + tests/files/hls.m3u8 | 15 +++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 tests/files/hls.m3u8 diff --git a/tests/check/gst/typefindfunctions.c b/tests/check/gst/typefindfunctions.c index cbe188a19e..c53c671772 100644 --- a/tests/check/gst/typefindfunctions.c +++ b/tests/check/gst/typefindfunctions.c @@ -354,6 +354,20 @@ GST_START_TEST (test_random_data) GST_END_TEST; +GST_START_TEST (test_hls_m3u8) +{ + const gchar *type; + GstCaps *caps = NULL; + + caps = typefind_test_file ("hls.m3u8"); + type = gst_structure_get_name (gst_caps_get_structure (caps, 0)); + fail_unless_equals_string (type, "application/x-hls"); + + gst_caps_unref (caps); +} + +GST_END_TEST; + static Suite * typefindfunctions_suite (void) { @@ -369,6 +383,7 @@ typefindfunctions_suite (void) tcase_add_test (tc_chain, test_ac3); tcase_add_test (tc_chain, test_eac3); tcase_add_test (tc_chain, test_random_data); + tcase_add_test (tc_chain, test_hls_m3u8); return s; } diff --git a/tests/files/Makefile.am b/tests/files/Makefile.am index fb3bba53f6..ca997a2a07 100644 --- a/tests/files/Makefile.am +++ b/tests/files/Makefile.am @@ -1,3 +1,4 @@ EXTRA_DIST = \ 623663.mts \ + hls.m3u8 \ partialframe.mjpeg diff --git a/tests/files/hls.m3u8 b/tests/files/hls.m3u8 new file mode 100644 index 0000000000..3acce06afc --- /dev/null +++ b/tests/files/hls.m3u8 @@ -0,0 +1,15 @@ +#EXTM3U +#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=246221 +0240/prog_index.m3u8 +#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=38872 +0064/prog_index.m3u8 +#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=153059 +0150/prog_index.m3u8 +#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=455394 +0440/prog_index.m3u8 +#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=650356 +0640/prog_index.m3u8 +#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=861738 +0840/prog_index.m3u8 +#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1258987 +1240/prog_index.m3u8