Example #1
0
EXPORT_C
#endif

GstTagList *
gst_tag_list_merge (const GstTagList * list1, const GstTagList * list2,
    GstTagMergeMode mode)
{
  g_return_val_if_fail (list1 == NULL || GST_IS_TAG_LIST (list1), NULL);
  g_return_val_if_fail (list2 == NULL || GST_IS_TAG_LIST (list2), NULL);
  g_return_val_if_fail (GST_TAG_MODE_IS_VALID (mode), NULL);

  if (!list1 && !list2) {
    return NULL;
  } else if (!list1) {
    return gst_tag_list_copy (list2);
  } else if (!list2) {
    return gst_tag_list_copy (list1);
  } else {
    GstTagList *ret;

    ret = gst_tag_list_copy (list1);
    gst_tag_list_insert (ret, list2, mode);
    return ret;
  }
}
Example #2
0
/**
 * gst_toc_entry_copy:
 * @entry: #GstTocEntry to copy.
 *
 * Copy #GstTocEntry with all subentries (deep copy).
 *
 * Returns: newly allocated #GstTocEntry in case of success, NULL otherwise;
 * free it when done with gst_toc_entry_unref().
 */
static GstTocEntry *
gst_toc_entry_copy (const GstTocEntry * entry)
{
  GstTocEntry *ret, *sub;
  GstTagList *list;
  GList *cur;

  g_return_val_if_fail (entry != NULL, NULL);

  ret = gst_toc_entry_new (entry->type, entry->uid);

  ret->start = entry->start;
  ret->stop = entry->stop;

  if (GST_IS_TAG_LIST (entry->tags)) {
    list = gst_tag_list_copy (entry->tags);
    if (ret->tags)
      gst_tag_list_unref (ret->tags);
    ret->tags = list;
  }

  cur = entry->subentries;
  while (cur != NULL) {
    sub = gst_toc_entry_copy (cur->data);

    if (sub != NULL)
      ret->subentries = g_list_prepend (ret->subentries, sub);

    cur = cur->next;
  }
  ret->subentries = g_list_reverse (ret->subentries);

  return ret;
}
Example #3
0
/**
 * gst_toc_copy:
 * @toc: #GstToc to copy.
 *
 * Copy #GstToc with all subentries (deep copy).
 *
 * Returns: newly allocated #GstToc in case of success, NULL otherwise;
 * free it when done with gst_toc_unref().
 */
static GstToc *
gst_toc_copy (const GstToc * toc)
{
  GstToc *ret;
  GstTocEntry *entry;
  GList *cur;
  GstTagList *list;

  g_return_val_if_fail (toc != NULL, NULL);

  ret = gst_toc_new (toc->scope);

  if (GST_IS_TAG_LIST (toc->tags)) {
    list = gst_tag_list_copy (toc->tags);
    gst_tag_list_unref (ret->tags);
    ret->tags = list;
  }

  cur = toc->entries;
  while (cur != NULL) {
    entry = gst_toc_entry_copy (cur->data);

    if (entry != NULL)
      ret->entries = g_list_prepend (ret->entries, entry);

    cur = cur->next;
  }
  ret->entries = g_list_reverse (ret->entries);
  return ret;
}
Example #4
0
EXPORT_C
#endif

gboolean
gst_tag_list_copy_value (GValue * dest, const GstTagList * list,
    const gchar * tag)
{
  const GValue *src;

  g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
  g_return_val_if_fail (tag != NULL, FALSE);
  g_return_val_if_fail (dest != NULL, FALSE);
  g_return_val_if_fail (G_VALUE_TYPE (dest) == 0, FALSE);

  src = gst_structure_get_value ((GstStructure *) list, tag);
  if (!src)
    return FALSE;

  if (G_VALUE_TYPE (src) == GST_TYPE_LIST) {
    GstTagInfo *info = gst_tag_lookup (g_quark_from_string (tag));

    /* must be there or lists aren't allowed */
    g_assert (info->merge_func);
    info->merge_func (dest, src);
  } else {
    g_value_init (dest, G_VALUE_TYPE (src));
    g_value_copy (src, dest);
  }
  return TRUE;
}
Example #5
0
EXPORT_C
#endif

G_CONST_RETURN GValue *
gst_tag_list_get_value_index (const GstTagList * list, const gchar * tag,
    guint index)
{
  const GValue *value;

  g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL);
  g_return_val_if_fail (tag != NULL, NULL);

  value = gst_structure_get_value ((GstStructure *) list, tag);
  if (value == NULL)
    return NULL;

  if (GST_VALUE_HOLDS_LIST (value)) {
    if (index >= gst_value_list_get_size (value))
      return NULL;
    return gst_value_list_get_value (value, index);
  } else {
    if (index > 0)
      return NULL;
    return value;
  }
}
/**
 * gst_pb_utils_add_codec_description_to_tag_list:
 * @taglist: a #GstTagList
 * @codec_tag: a GStreamer codec tag such as #GST_TAG_AUDIO_CODEC,
 *             #GST_TAG_VIDEO_CODEC or #GST_TAG_CODEC
 * @caps: the (fixed) #GstCaps for which a codec tag should be added.
 *
 * Adds a codec tag describing the format specified by @caps to @taglist.
 *
 * Returns: TRUE if a codec tag was added, FALSE otherwise.
 */
gboolean
gst_pb_utils_add_codec_description_to_tag_list (GstTagList * taglist,
    const gchar * codec_tag, const GstCaps * caps)
{
  const FormatInfo *info;
  gchar *desc;

  g_return_val_if_fail (taglist != NULL, FALSE);
  g_return_val_if_fail (GST_IS_TAG_LIST (taglist), FALSE);
  g_return_val_if_fail (codec_tag != NULL, FALSE);
  g_return_val_if_fail (gst_tag_exists (codec_tag), FALSE);
  g_return_val_if_fail (gst_tag_get_type (codec_tag) == G_TYPE_STRING, FALSE);
  g_return_val_if_fail (caps != NULL, FALSE);
  g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);

  info = find_format_info (caps);
  if (info == NULL)
    return FALSE;

  desc = format_info_get_desc (info, caps);
  gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, codec_tag, desc, NULL);
  g_free (desc);

  return TRUE;
}
Example #7
0
EXPORT_C
#endif

void
gst_tag_list_free (GstTagList * list)
{
  g_return_if_fail (GST_IS_TAG_LIST (list));
  gst_structure_free ((GstStructure *) list);
}
Example #8
0
EXPORT_C
#endif

GstTagList *
gst_tag_list_copy (const GstTagList * list)
{
  g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL);

  return GST_TAG_LIST (gst_structure_copy ((GstStructure *) list));
}
Example #9
0
EXPORT_C
#endif

gboolean
gst_tag_list_is_empty (const GstTagList * list)
{
  g_return_val_if_fail (list != NULL, FALSE);
  g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);

  return (gst_structure_n_fields ((GstStructure *) list) == 0);
}
Example #10
0
/**
 * 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)
{
  GstBuffer *buffer = NULL;
  GString *data = g_string_sized_new (4096);
  guint i;

  xmp_tags_initialize ();

  g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL);

  /* xmp header */
  g_string_append (data,
      "<?xpacket begin=\"\xEF\xBB\xBF\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n");
  g_string_append (data,
      "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"GStreamer\">\n");
  g_string_append (data,
      "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"");
  i = 0;
  while (ns_match[i].ns_prefix) {
    g_string_append_printf (data, " xmlns:%s=\"%s\"", ns_match[i].ns_prefix,
        ns_match[i].ns_uri);
    i++;
  }
  g_string_append (data, ">\n");
  g_string_append (data, "<rdf:Description rdf:about=\"\">\n");

  /* iterate the taglist */
  gst_tag_list_foreach (list, write_one_tag, data);

  /* xmp footer */
  g_string_append (data, "</rdf:Description>\n");
  g_string_append (data, "</rdf:RDF>\n");
  g_string_append (data, "</x:xmpmeta>\n");

  if (!read_only) {
    /* the xmp spec recommand to add 2-4KB padding for in-place editable xmp */
    guint i;

    for (i = 0; i < 32; i++) {
      g_string_append (data, "                " "                "
          "                " "                " "\n");
    }
  }
  g_string_append_printf (data, "<?xpacket end=\"%c\"?>\n",
      (read_only ? 'r' : 'w'));

  buffer = gst_buffer_new ();
  GST_BUFFER_SIZE (buffer) = data->len + 1;
  GST_BUFFER_DATA (buffer) = (guint8 *) g_string_free (data, FALSE);
  GST_BUFFER_MALLOCDATA (buffer) = GST_BUFFER_DATA (buffer);

  return buffer;
}
Example #11
0
EXPORT_C
#endif

void
gst_tag_list_remove_tag (GstTagList * list, const gchar * tag)
{
  g_return_if_fail (GST_IS_TAG_LIST (list));
  g_return_if_fail (tag != NULL);

  gst_structure_remove_field ((GstStructure *) list, tag);
}
Example #12
0
EXPORT_C
#endif

void
gst_tag_list_insert (GstTagList * into, const GstTagList * from,
    GstTagMergeMode mode)
{
  GstTagCopyData data;

  g_return_if_fail (GST_IS_TAG_LIST (into));
  g_return_if_fail (GST_IS_TAG_LIST (from));
  g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));

  data.list = (GstStructure *) into;
  data.mode = mode;
  if (mode == GST_TAG_MERGE_REPLACE_ALL) {
    gst_structure_remove_all_fields (data.list);
  }
  gst_structure_foreach ((GstStructure *) from, gst_tag_list_copy_foreach,
      &data);
}
Example #13
0
EXPORT_C
#endif

void
gst_tag_list_add_values (GstTagList * list, GstTagMergeMode mode,
    const gchar * tag, ...)
{
  va_list args;

  g_return_if_fail (GST_IS_TAG_LIST (list));
  g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
  g_return_if_fail (tag != NULL);

  va_start (args, tag);
  gst_tag_list_add_valist_values (list, mode, tag, args);
  va_end (args);
}
static gboolean
bbd_pipeline_bus_callback (GstBus *bus, GstMessage *message, gpointer data)
{
    BansheeBpmDetector *detector = (BansheeBpmDetector *)data;

    g_return_val_if_fail (detector != NULL, FALSE);

    switch (GST_MESSAGE_TYPE (message)) {
        case GST_MESSAGE_TAG: {
            GstTagList *tags;
            gst_message_parse_tag (message, &tags);
            if (GST_IS_TAG_LIST (tags)) {
                gst_tag_list_foreach (tags, (GstTagForeachFunc)bbd_pipeline_process_tag, detector);
                gst_tag_list_free (tags);
            }
            break;
        }

        case GST_MESSAGE_ERROR: {
            GError *error;
            gchar *debug;
            
            gst_message_parse_error (message, &error, &debug);
            bbd_raise_error (detector, error->message, debug);
            g_error_free (error);
            g_free (debug);
            
            detector->is_detecting = FALSE;
            break;
        }

        case GST_MESSAGE_EOS: {
            detector->is_detecting = FALSE;
            gst_element_set_state (GST_ELEMENT (detector->pipeline), GST_STATE_NULL);

            if (detector->finished_cb != NULL) {
                detector->finished_cb ();
            }
            break;
        }
        
        default: break;
    }
    
    return TRUE;
}
Example #15
0
/**
 * gst_tag_setter_merge_tags:
 * @setter: a #GstTagSetter
 * @list: a tag list to merge from
 * @mode: the mode to merge with
 *
 * Merges the given list into the setter's list using the given mode.
 */
void
gst_tag_setter_merge_tags (GstTagSetter * setter, const GstTagList * list,
                           GstTagMergeMode mode)
{
    GstTagData *data;

    g_return_if_fail (GST_IS_TAG_SETTER (setter));
    g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
    g_return_if_fail (GST_IS_TAG_LIST (list));

    data = gst_tag_setter_get_data (setter);
    if (data->list == NULL) {
        if (mode != GST_TAG_MERGE_KEEP_ALL)
            data->list = gst_tag_list_copy (list);
    } else {
        gst_tag_list_insert (data->list, list, mode);
    }
}
Example #16
0
EXPORT_C
#endif

void
gst_tag_list_foreach (const GstTagList * list, GstTagForeachFunc func,
    gpointer user_data)
{
  TagForeachData data;

  g_return_if_fail (GST_IS_TAG_LIST (list));
  g_return_if_fail (func != NULL);

  data.func = func;
  data.tag_list = list;
  data.data = user_data;
  gst_structure_foreach ((GstStructure *) list, structure_foreach_wrapper,
      &data);
}
Example #17
0
EXPORT_C
#endif

guint
gst_tag_list_get_tag_size (const GstTagList * list, const gchar * tag)
{
  const GValue *value;

  g_return_val_if_fail (GST_IS_TAG_LIST (list), 0);

  value = gst_structure_get_value ((GstStructure *) list, tag);
  if (value == NULL)
    return 0;
  if (G_VALUE_TYPE (value) != GST_TYPE_LIST)
    return 1;

  return gst_value_list_get_size (value);
}
Example #18
0
EXPORT_C
#endif

gboolean
gst_tag_list_get_date_index (const GstTagList * list,
    const gchar * tag, guint index, GDate ** value)
{
  const GValue *v;

  g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
  g_return_val_if_fail (tag != NULL, FALSE);
  g_return_val_if_fail (value != NULL, FALSE);

  if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL)
    return FALSE;
  *value = (GDate *) g_value_dup_boxed (v);
  return (*value != NULL);
}
Example #19
0
EXPORT_C
#endif

gboolean
gst_tag_list_get_date (const GstTagList * list, const gchar * tag,
    GDate ** value)
{
  GValue v = { 0, };

  g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
  g_return_val_if_fail (tag != NULL, FALSE);
  g_return_val_if_fail (value != NULL, FALSE);

  if (!gst_tag_list_copy_value (&v, list, tag))
    return FALSE;
  *value = (GDate *) g_value_dup_boxed (&v);
  g_value_unset (&v);
  return (*value != NULL);
}
Example #20
0
/**
 * gst_aggregator_merge_tags:
 * @self: a #GstAggregator
 * @tags: a #GstTagList to merge
 * @mode: the #GstTagMergeMode to use
 *
 * Adds tags to so-called pending tags, which will be processed
 * before pushing out data downstream.
 *
 * Note that this is provided for convenience, and the subclass is
 * not required to use this and can still do tag handling on its own.
 *
 * MT safe.
 */
void
gst_aggregator_merge_tags (GstAggregator * self,
    const GstTagList * tags, GstTagMergeMode mode)
{
  GstTagList *otags;

  g_return_if_fail (GST_IS_AGGREGATOR (self));
  g_return_if_fail (tags == NULL || GST_IS_TAG_LIST (tags));

  /* FIXME Check if we can use OBJECT lock here! */
  GST_OBJECT_LOCK (self);
  if (tags)
    GST_DEBUG_OBJECT (self, "merging tags %" GST_PTR_FORMAT, tags);
  otags = self->priv->tags;
  self->priv->tags = gst_tag_list_merge (self->priv->tags, tags, mode);
  if (otags)
    gst_tag_list_unref (otags);
  self->priv->tags_changed = TRUE;
  GST_OBJECT_UNLOCK (self);
}
Example #21
0
EXPORT_C
#endif

gboolean
gst_tag_list_add_id3_image (GstTagList * tag_list, const guint8 * image_data,
    guint image_data_len, guint id3_picture_type)
{
  GstTagImageType tag_image_type;
  const gchar *tag_name;
  GstBuffer *image;

  g_return_val_if_fail (GST_IS_TAG_LIST (tag_list), FALSE);
  g_return_val_if_fail (image_data != NULL, FALSE);
  g_return_val_if_fail (image_data_len > 0, FALSE);

  if (id3_picture_type == 0x01 || id3_picture_type == 0x02) {
    /* file icon for preview. Don't add image-type to caps, since there
     * is only supposed to be one of these, and the type is already indicated
     * via the special tag */
    tag_name = GST_TAG_PREVIEW_IMAGE;
    tag_image_type = GST_TAG_IMAGE_TYPE_NONE;
  } else {
    tag_name = GST_TAG_IMAGE;

    /* Remap the ID3v2 APIC type our ImageType enum */
    if (id3_picture_type >= 0x3 && id3_picture_type <= 0x14)
      tag_image_type = (GstTagImageType) (id3_picture_type - 2);
    else
      tag_image_type = GST_TAG_IMAGE_TYPE_UNDEFINED;
  }

  image = gst_tag_image_data_to_image_buffer (image_data, image_data_len,
      tag_image_type);

  if (image == NULL)
    return FALSE;

  gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND, tag_name, image, NULL);
  gst_buffer_unref (image);
  return TRUE;
}
/**
 * gst_pb_utils_add_codec_description_to_tag_list:
 * @taglist: a #GstTagList
 * @codec_tag: (allow-none): a GStreamer codec tag such as #GST_TAG_AUDIO_CODEC,
 *             #GST_TAG_VIDEO_CODEC or #GST_TAG_CODEC. If none is specified,
 *             the function will attempt to detect the appropriate category.
 * @caps: the (fixed) #GstCaps for which a codec tag should be added.
 *
 * Adds a codec tag describing the format specified by @caps to @taglist.
 *
 * Returns: TRUE if a codec tag was added, FALSE otherwise.
 */
gboolean
gst_pb_utils_add_codec_description_to_tag_list (GstTagList * taglist,
    const gchar * codec_tag, const GstCaps * caps)
{
  const FormatInfo *info;
  gchar *desc;

  g_return_val_if_fail (taglist != NULL, FALSE);
  g_return_val_if_fail (GST_IS_TAG_LIST (taglist), FALSE);
  g_return_val_if_fail (codec_tag == NULL || (gst_tag_exists (codec_tag)
          && gst_tag_get_type (codec_tag) == G_TYPE_STRING), FALSE);
  g_return_val_if_fail (caps != NULL, FALSE);
  g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);

  info = find_format_info (caps);
  if (info == NULL)
    return FALSE;

  /* Attempt to find tag classification */
  if (codec_tag == NULL) {
    if (info->flags & FLAG_CONTAINER)
      codec_tag = GST_TAG_CONTAINER_FORMAT;
    else if (info->flags & FLAG_AUDIO)
      codec_tag = GST_TAG_AUDIO_CODEC;
    else if (info->flags & FLAG_VIDEO)
      codec_tag = GST_TAG_VIDEO_CODEC;
    else if (info->flags & FLAG_SUB)
      codec_tag = GST_TAG_SUBTITLE_CODEC;
    else
      codec_tag = GST_TAG_CODEC;
  }

  desc = format_info_get_desc (info, caps);
  gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, codec_tag, desc, NULL);
  g_free (desc);

  return TRUE;
}
Example #23
0
EXPORT_C
#endif

void
gst_tag_list_add_valist (GstTagList * list, GstTagMergeMode mode,
    const gchar * tag, va_list var_args)
{
  GstTagInfo *info;
  GQuark quark;
  gchar *error = NULL;

  g_return_if_fail (GST_IS_TAG_LIST (list));
  g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
  g_return_if_fail (tag != NULL);

  while (tag != NULL) {
    GValue value = { 0, };

    quark = g_quark_from_string (tag);
    info = gst_tag_lookup (quark);
    if (info == NULL)
      g_warning ("no GstTag for %s", tag);
    g_return_if_fail (info != NULL);
    g_value_init (&value, info->type);
    G_VALUE_COLLECT (&value, var_args, 0, &error);
    if (error) {
      g_warning ("%s: %s", G_STRLOC, error);
      g_free (error);
      /* we purposely leak the value here, it might not be
       * in a sane state if an error condition occoured
       */
      return;
    }
    gst_tag_list_add_value_internal (list, mode, quark, &value);
    g_value_unset (&value);
    tag = va_arg (var_args, gchar *);
  }
}
Example #24
0
EXPORT_C
#endif

void
gst_tag_list_add_valist_values (GstTagList * list, GstTagMergeMode mode,
    const gchar * tag, va_list var_args)
{
  GstTagInfo *info;
  GQuark quark;

  g_return_if_fail (GST_IS_TAG_LIST (list));
  g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
  g_return_if_fail (tag != NULL);

  while (tag != NULL) {
    quark = g_quark_from_string (tag);
    info = gst_tag_lookup (quark);
    g_return_if_fail (info != NULL);
    gst_tag_list_add_value_internal (list, mode, quark, va_arg (var_args,
            GValue *));
    tag = va_arg (var_args, gchar *);
  }
}