gst_plugins_base/gst-libs/gst/tag/tags.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
     1 /* GStreamer non-core tag registration and tag utility functions
     1 /* GStreamer non-core tag registration and tag utility functions
     2  * Copyright (C) 2005 Ross Burton <ross@burtonini.com>
     2  * Copyright (C) 2005 Ross Burton <ross@burtonini.com>
     3  * Copyright (C) 2006-2008 Tim-Philipp Müller <tim centricular net>
     3  * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
     4  *
     4  *
     5  * This library is free software; you can redistribute it and/or
     5  * This library is free software; you can redistribute it and/or
     6  * modify it under the terms of the GNU Library General Public
     6  * modify it under the terms of the GNU Library General Public
     7  * License as published by the Free Software Foundation; either
     7  * License as published by the Free Software Foundation; either
     8  * version 2 of the License, or (at your option) any later version.
     8  * version 2 of the License, or (at your option) any later version.
    20 
    20 
    21 #ifdef HAVE_CONFIG_H
    21 #ifdef HAVE_CONFIG_H
    22 #include "config.h"
    22 #include "config.h"
    23 #endif
    23 #endif
    24 
    24 
       
    25 #ifndef __SYMBIAN32__
    25 #include <gst/gst-i18n-plugin.h>
    26 #include <gst/gst-i18n-plugin.h>
    26 #include <gst/base/gsttypefindhelper.h>
    27 #else
       
    28 #include "gst/gst-i18n-plugin.h"
       
    29 #endif
    27 #include <gst/gst.h>
    30 #include <gst/gst.h>
    28 #include "tag.h"
    31 #include "tag.h"
    29 
    32 
    30 #include <string.h>
    33 #include <string.h>
    31 
    34 
    49 {
    52 {
    50 #ifdef ENABLE_NLS
    53 #ifdef ENABLE_NLS
    51   GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
    54   GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
    52       LOCALEDIR);
    55       LOCALEDIR);
    53   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
    56   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
    54   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
       
    55 #endif
    57 #endif
    56 
    58 
    57   /* musicbrainz tags */
    59   /* musicbrainz tags */
    58   gst_tag_register (GST_TAG_MUSICBRAINZ_TRACKID, GST_TAG_FLAG_META,
    60   gst_tag_register (GST_TAG_MUSICBRAINZ_TRACKID, GST_TAG_FLAG_META,
    59       G_TYPE_STRING, _("track ID"), _("MusicBrainz track ID"), NULL);
    61       G_TYPE_STRING, _("track ID"), _("MusicBrainz track ID"), NULL);
   110 
   112 
   111 static void
   113 static void
   112 register_tag_image_type_enum (GType * id)
   114 register_tag_image_type_enum (GType * id)
   113 {
   115 {
   114   static const GEnumValue image_types[] = {
   116   static const GEnumValue image_types[] = {
   115     {GST_TAG_IMAGE_TYPE_NONE, "GST_TAG_IMAGE_TYPE_NONE", "none"},
       
   116     {GST_TAG_IMAGE_TYPE_UNDEFINED, "GST_TAG_IMAGE_TYPE_UNDEFINED", "undefined"},
   117     {GST_TAG_IMAGE_TYPE_UNDEFINED, "GST_TAG_IMAGE_TYPE_UNDEFINED", "undefined"},
   117     {GST_TAG_IMAGE_TYPE_FRONT_COVER, "GST_TAG_IMAGE_TYPE_FRONT_COVER",
   118     {GST_TAG_IMAGE_TYPE_FRONT_COVER, "GST_TAG_IMAGE_TYPE_FRONT_COVER",
   118         "front-cover"},
   119         "front-cover"},
   119     {GST_TAG_IMAGE_TYPE_BACK_COVER, "GST_TAG_IMAGE_TYPE_BACK_COVER",
   120     {GST_TAG_IMAGE_TYPE_BACK_COVER, "GST_TAG_IMAGE_TYPE_BACK_COVER",
   120         "back-cover"},
   121         "back-cover"},
   149         "publisher-studio-logo"},
   150         "publisher-studio-logo"},
   150     {0, NULL, NULL}
   151     {0, NULL, NULL}
   151   };
   152   };
   152 
   153 
   153   *id = g_enum_register_static ("GstTagImageType", image_types);
   154   *id = g_enum_register_static ("GstTagImageType", image_types);
   154 
       
   155   /* work around thread-safety issue with class creation in GLib */
       
   156   g_type_class_ref (*id);
       
   157 }
   155 }
   158 #ifdef __SYMBIAN32__
   156 #ifdef __SYMBIAN32__
   159 EXPORT_C
   157 EXPORT_C
   160 #endif
   158 #endif
   161 
   159 
   162 
   160 
   163 GType
   161 GType
   164 gst_tag_image_type_get_type (void)
   162 gst_tag_image_type_get_type (void)
   165 {
   163 {
   166   static GType id;
   164   static GType id;
   167 
       
   168   static GOnce once = G_ONCE_INIT;
   165   static GOnce once = G_ONCE_INIT;
   169 
   166 
   170   g_once (&once, (GThreadFunc) register_tag_image_type_enum, &id);
   167   g_once (&once, (GThreadFunc) register_tag_image_type_enum, &id);
   171   return id;
   168   return id;
   172 }
       
   173 
       
   174 static inline gboolean
       
   175 gst_tag_image_type_is_valid (GstTagImageType type)
       
   176 {
       
   177   GEnumClass *klass;
       
   178 
       
   179   gboolean res;
       
   180 
       
   181   klass = g_type_class_ref (gst_tag_image_type_get_type ());
       
   182   res = (g_enum_get_value (klass, type) != NULL);
       
   183   g_type_class_unref (klass);
       
   184 
       
   185   return res;
       
   186 }
   169 }
   187 
   170 
   188 /**
   171 /**
   189  * gst_tag_parse_extended_comment:
   172  * gst_tag_parse_extended_comment:
   190  * @ext_comment: an extended comment string, see #GST_TAG_EXTENDED_COMMENT
   173  * @ext_comment: an extended comment string, see #GST_TAG_EXTENDED_COMMENT
   279 gchar *
   262 gchar *
   280 gst_tag_freeform_string_to_utf8 (const gchar * data, gint size,
   263 gst_tag_freeform_string_to_utf8 (const gchar * data, gint size,
   281     const gchar ** env_vars)
   264     const gchar ** env_vars)
   282 {
   265 {
   283   const gchar *cur_loc = NULL;
   266   const gchar *cur_loc = NULL;
   284 
       
   285   gsize bytes_read;
   267   gsize bytes_read;
   286 
       
   287   gchar *utf8 = NULL;
   268   gchar *utf8 = NULL;
   288 
   269 
   289   g_return_val_if_fail (data != NULL, NULL);
   270   g_return_val_if_fail (data != NULL, NULL);
   290 
   271 
   291   if (size < 0)
   272   if (size < 0)
   363   }
   344   }
   364 
   345 
   365   g_free (utf8);
   346   g_free (utf8);
   366   return NULL;
   347   return NULL;
   367 }
   348 }
   368 
       
   369 /**
       
   370  * gst_tag_image_data_to_image_buffer:
       
   371  * @image_data: the (encoded) image
       
   372  * @image_data_len: the length of the encoded image data at @image_data
       
   373  * @image_type: type of the image, or #GST_TAG_IMAGE_TYPE_UNDEFINED. Pass
       
   374  *     #GST_TAG_IMAGE_TYPE_NONE if no image type should be set at all (e.g.
       
   375  *     for preview images)
       
   376  *
       
   377  * Helper function for tag-reading plugins to create a #GstBuffer suitable to
       
   378  * add to a #GstTagList as an image tag (such as #GST_TAG_IMAGE or
       
   379  * #GST_TAG_PREVIEW_IMAGE) from the encoded image data and an (optional) image
       
   380  * type.
       
   381  *
       
   382  * Background: cover art and other images in tags are usually stored as a
       
   383  * blob of binary image data, often accompanied by a MIME type or some other
       
   384  * content type string (e.g. 'png', 'jpeg', 'jpg'). Sometimes there is also an
       
   385  * 'image type' to indicate what kind of image this is (e.g. front cover,
       
   386  * back cover, artist, etc.). The image data may also be an URI to the image
       
   387  * rather than the image itself.
       
   388  *
       
   389  * In GStreamer, image tags are #GstBuffer<!-- -->s containing the raw image
       
   390  * data, with the buffer caps describing the content type of the image
       
   391  * (e.g. image/jpeg, image/png, text/uri-list). The buffer caps may contain
       
   392  * an additional 'image-type' field of #GST_TYPE_TAG_IMAGE_TYPE to describe
       
   393  * the type of image (front cover, back cover etc.). #GST_TAG_PREVIEW_IMAGE
       
   394  * tags should not carry an image type, their type is already indicated via
       
   395  * the special tag name.
       
   396  *
       
   397  * This function will do various checks and typefind the encoded image
       
   398  * data (we can't trust the declared mime type).
       
   399  *
       
   400  * Returns: a newly-allocated image buffer for use in tag lists, or NULL
       
   401  *
       
   402  * Since: 0.10.20
       
   403  */
       
   404 #ifdef __SYMBIAN32__
       
   405 EXPORT_C
       
   406 #endif
       
   407 
       
   408 GstBuffer *
       
   409 gst_tag_image_data_to_image_buffer (const guint8 * image_data,
       
   410     guint image_data_len, GstTagImageType image_type)
       
   411 {
       
   412   const gchar *name;
       
   413 
       
   414   GstBuffer *image;
       
   415 
       
   416   GstCaps *caps;
       
   417 
       
   418   g_return_val_if_fail (image_data != NULL, NULL);
       
   419   g_return_val_if_fail (image_data_len > 0, NULL);
       
   420   g_return_val_if_fail (gst_tag_image_type_is_valid (image_type), NULL);
       
   421 
       
   422   GST_DEBUG ("image data len: %u bytes", image_data_len);
       
   423 
       
   424   /* allocate space for a NUL terminator for an uri too */
       
   425   image = gst_buffer_try_new_and_alloc (image_data_len + 1);
       
   426   if (image == NULL) {
       
   427     GST_WARNING ("failed to allocate buffer of %d for image", image_data_len);
       
   428     return NULL;
       
   429   }
       
   430 
       
   431   memcpy (GST_BUFFER_DATA (image), image_data, image_data_len);
       
   432   GST_BUFFER_DATA (image)[image_data_len] = '\0';
       
   433 
       
   434   /* Find GStreamer media type, can't trust declared type */
       
   435   caps = gst_type_find_helper_for_buffer (NULL, image, NULL);
       
   436 
       
   437   if (caps == NULL)
       
   438     goto no_type;
       
   439 
       
   440   GST_DEBUG ("Found GStreamer media type: %" GST_PTR_FORMAT, caps);
       
   441 
       
   442   /* sanity check: make sure typefound/declared caps are either URI or image */
       
   443   name = gst_structure_get_name (gst_caps_get_structure (caps, 0));
       
   444 
       
   445   if (!g_str_has_prefix (name, "image/") &&
       
   446       !g_str_has_prefix (name, "video/") &&
       
   447       !g_str_equal (name, "text/uri-list")) {
       
   448     GST_DEBUG ("Unexpected image type '%s', ignoring image frame", name);
       
   449     goto error;
       
   450   }
       
   451 
       
   452   /* Decrease size by 1 if we don't have an URI list
       
   453    * to keep the original size of the image
       
   454    */
       
   455   if (!g_str_equal (name, "text/uri-list"))
       
   456     GST_BUFFER_SIZE (image) = image_data_len;
       
   457 
       
   458   if (image_type != GST_TAG_IMAGE_TYPE_NONE) {
       
   459     GST_LOG ("Setting image type: %d", image_type);
       
   460     caps = gst_caps_make_writable (caps);
       
   461     gst_caps_set_simple (caps, "image-type", GST_TYPE_TAG_IMAGE_TYPE,
       
   462         image_type, NULL);
       
   463   }
       
   464 
       
   465   gst_buffer_set_caps (image, caps);
       
   466   gst_caps_unref (caps);
       
   467   return image;
       
   468 
       
   469 /* ERRORS */
       
   470 no_type:
       
   471   {
       
   472     GST_DEBUG ("Could not determine GStreamer media type, ignoring image");
       
   473     /* fall through */
       
   474   }
       
   475 error:
       
   476   {
       
   477     if (image)
       
   478       gst_buffer_unref (image);
       
   479     if (caps)
       
   480       gst_caps_unref (caps);
       
   481     return NULL;
       
   482   }
       
   483 }