Exemplo n.º 1
0
gboolean
rb_gst_encoder_set_encoding_style (GstElement *encoder, const char *style)
{
	GstElementFactory *factory;
	char *group_name;
	char **keys;
	int i;

	factory = gst_element_get_factory (encoder);
	group_name = g_strdup_printf (ENCODER_STYLE_SETTINGS_PREFIX "%s-%s",
				      gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)),
				      style);
	rb_debug ("applying settings from %s", group_name);

	keys = g_key_file_get_keys (get_target_keyfile (), group_name, NULL, NULL);
	if (keys == NULL) {
		rb_debug ("nothing to apply");
		g_free (group_name);
		return FALSE;
	}

	for (i = 0; keys[i] != NULL; i++) {
		GParamSpec *pspec;
		GValue v = {0,};
		char *value;

		pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (encoder), keys[i]);
		if (pspec == NULL) {
			rb_debug ("couldn't find property %s", keys[i]);
			continue;
		}

		value = g_key_file_get_string (get_target_keyfile (), group_name, keys[i], NULL);
		if (value == NULL) {
			rb_debug ("couldn't get value for property %s", keys[i]);
			continue;
		}

		g_value_init (&v, pspec->value_type);
		if (gst_value_deserialize (&v, value)) {
			rb_debug ("applying value \"%s\" to property %s", value, keys[i]);
			g_object_set_property (G_OBJECT (encoder), keys[i], &v);
		} else {
			rb_debug ("couldn't deserialize value \"%s\" for property %s", value, keys[i]);
		}

		g_value_unset (&v);
	}

	g_strfreev (keys);
	g_free (group_name);
	return TRUE;
}
Exemplo n.º 2
0
void Property::set(const std::string &value) {
  if(nullptr == object_) {
    g_warning("trying to set a property of a NULL gobject");
    return;
  }
  GValue transformed_val = G_VALUE_INIT;
  g_value_init(&transformed_val, property_->value_type);

  if (!gst_value_deserialize(&transformed_val, value.c_str())) {
    const gchar *type_name = g_type_name(property_->value_type);
    if (nullptr == type_name)
      g_warning("property does not have a valid type");
    else
      g_warning("string %s not transformable into gvalue of type %s",
                value.c_str(),
                type_name);
    return;
  }

  g_object_set_property(object_, property_->name, &transformed_val);
}
static gboolean
gst_rtp_mp4v_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps)
{
  GstStructure *structure;
  GstCaps *srccaps;
  const gchar *str;
  gint clock_rate;
  gboolean res;

  structure = gst_caps_get_structure (caps, 0);

  if (!gst_structure_get_int (structure, "clock-rate", &clock_rate))
    clock_rate = 90000;         /* default */
  depayload->clock_rate = clock_rate;

  srccaps = gst_caps_new_simple ("video/mpeg",
      "mpegversion", G_TYPE_INT, 4,
      "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);

  if ((str = gst_structure_get_string (structure, "config"))) {
    GValue v = { 0 };

    g_value_init (&v, GST_TYPE_BUFFER);
    if (gst_value_deserialize (&v, str)) {
      GstBuffer *buffer;

      buffer = gst_value_get_buffer (&v);
      gst_caps_set_simple (srccaps,
          "codec_data", GST_TYPE_BUFFER, buffer, NULL);
      /* caps takes ref */
      g_value_unset (&v);
    } else {
      g_warning ("cannot convert config to buffer");
    }
  }
  res = gst_pad_set_caps (depayload->srcpad, srccaps);
  gst_caps_unref (srccaps);

  return res;
}
static GstPlay *
play_new (gchar ** uris, const gchar * audio_sink, const gchar * video_sink,
    gboolean gapless, gdouble initial_volume, gboolean verbose,
    const gchar * flags_string)
{
  GstElement *sink, *playbin;
  GstPlay *play;

  playbin = gst_element_factory_make ("playbin", "playbin");
  if (playbin == NULL)
    return NULL;

  play = g_new0 (GstPlay, 1);

  play->uris = uris;
  play->num_uris = g_strv_length (uris);
  play->cur_idx = -1;

  play->playbin = playbin;

  if (audio_sink != NULL) {
    if (strchr (audio_sink, ' ') != NULL)
      sink = gst_parse_bin_from_description (audio_sink, TRUE, NULL);
    else
      sink = gst_element_factory_make (audio_sink, NULL);

    if (sink != NULL)
      g_object_set (play->playbin, "audio-sink", sink, NULL);
    else
      g_warning ("Couldn't create specified audio sink '%s'", audio_sink);
  }
  if (video_sink != NULL) {
    if (strchr (video_sink, ' ') != NULL)
      sink = gst_parse_bin_from_description (video_sink, TRUE, NULL);
    else
      sink = gst_element_factory_make (video_sink, NULL);

    if (sink != NULL)
      g_object_set (play->playbin, "video-sink", sink, NULL);
    else
      g_warning ("Couldn't create specified video sink '%s'", video_sink);
  }

  if (flags_string != NULL) {
    GParamSpec *pspec;
    GValue val = { 0, };

    pspec =
        g_object_class_find_property (G_OBJECT_GET_CLASS (playbin), "flags");
    g_value_init (&val, pspec->value_type);
    if (gst_value_deserialize (&val, flags_string))
      g_object_set_property (G_OBJECT (play->playbin), "flags", &val);
    else
      g_printerr ("Couldn't convert '%s' to playbin flags!\n", flags_string);
    g_value_unset (&val);
  }

  if (verbose) {
    play->deep_notify_id = g_signal_connect (play->playbin, "deep-notify",
        G_CALLBACK (gst_object_default_deep_notify), NULL);
  }

  play->loop = g_main_loop_new (NULL, FALSE);

  play->bus_watch = gst_bus_add_watch (GST_ELEMENT_BUS (play->playbin),
      play_bus_msg, play);

  /* FIXME: make configurable incl. 0 for disable */
  play->timeout = g_timeout_add (100, play_timeout, play);

  play->missing = NULL;
  play->buffering = FALSE;
  play->is_live = FALSE;

  play->desired_state = GST_STATE_PLAYING;

  play->gapless = gapless;
  if (gapless) {
    g_signal_connect (play->playbin, "about-to-finish",
        G_CALLBACK (play_about_to_finish), play);
  }

  if (initial_volume != -1)
    play_set_relative_volume (play, initial_volume - 1.0);

  play->rate = 1.0;
  play->trick_mode = GST_PLAY_TRICK_MODE_NONE;

  return play;
}
Exemplo n.º 5
0
static GstBuffer *
gst_rtp_sv3v_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
{

  GstRtpSV3VDepay *rtpsv3vdepay;
  GstBuffer *outbuf;
  guint16 seq;

  rtpsv3vdepay = GST_RTP_SV3V_DEPAY (depayload);

  if (!gst_rtp_buffer_validate (buf))
    goto bad_packet;

  /* flush on sequence number gaps */
  seq = gst_rtp_buffer_get_seq (buf);
  if (seq != rtpsv3vdepay->nextseq) {
    gst_adapter_clear (rtpsv3vdepay->adapter);
  }
  rtpsv3vdepay->nextseq = seq + 1;

  {
    gint payload_len;
    guint8 *payload;
    gboolean M;
    gboolean C, S, E;

    payload_len = gst_rtp_buffer_get_payload_len (buf);
    if (payload_len < 3)
      goto bad_packet;

    payload = gst_rtp_buffer_get_payload (buf);

    M = gst_rtp_buffer_get_marker (buf);

    /* This is all a guess:
     *                      1 1 1 1 1 1
     *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     * |0|C|S|E|0|0|0|0|0|0|0|0|0|0|0|0|
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     *
     * C: config, packet contains config info
     * S: start, packet contains start of frame
     * E: end, packet contains end of frame
     */
    /* this seems to indicate a packet with a config string sent before each
     * keyframe */
    C = (payload[0] & 0x40) == 0x40;

    /* redundant with the RTP marker bit */
    S = (payload[0] & 0x20) == 0x20;
    E = (payload[0] & 0x10) == 0x10;

    if (C) {
      GstCaps *caps;
      GstBuffer *codec_data;
      GValue value = { 0 };

      /* if we already have caps, we don't need to do anything. FIXME, check if
       * something changed. */
      if (GST_PAD_CAPS (GST_BASE_RTP_DEPAYLOAD_SRCPAD (depayload)))
        return NULL;

      /* No idea... These are the two examples I found.. */
      if (payload[2] == 0x1d) {
        rtpsv3vdepay->width = 160;
        rtpsv3vdepay->height = 128;
      } else if (payload[2] == 0xdd) {
        rtpsv3vdepay->width = 320;
        rtpsv3vdepay->height = 240;
      }

      /* we need a dummy empty codec data */
      g_value_init (&value, GST_TYPE_BUFFER);
      gst_value_deserialize (&value, "");
      codec_data = gst_value_get_buffer (&value);

      caps = gst_caps_new_simple ("video/x-svq",
          "svqversion", G_TYPE_INT, 3,
          "width", G_TYPE_INT, rtpsv3vdepay->width,
          "height", G_TYPE_INT, rtpsv3vdepay->height,
          "codec_data", GST_TYPE_BUFFER, codec_data, NULL);
      gst_pad_set_caps (GST_BASE_RTP_DEPAYLOAD_SRCPAD (depayload), caps);
      gst_caps_unref (caps);
      g_value_unset (&value);

      return NULL;
    }

    /* store data in adapter, stip off 2 bytes header */
    outbuf = gst_rtp_buffer_get_payload_subbuffer (buf, 2, -1);
    gst_adapter_push (rtpsv3vdepay->adapter, outbuf);

    if (M) {
      /* frame is completed: push contents of adapter */
      guint avail;

      avail = gst_adapter_available (rtpsv3vdepay->adapter);
      outbuf = gst_adapter_take_buffer (rtpsv3vdepay->adapter, avail);

      /* timestamp for complete buffer is that of last buffer as well */
      gst_buffer_set_caps (outbuf, GST_PAD_CAPS (depayload->srcpad));

      return outbuf;
    }
  }
  return NULL;

  /* ERRORS */
bad_packet:
  {
    GST_ELEMENT_WARNING (rtpsv3vdepay, STREAM, DECODE,
        ("Packet did not validate"), (NULL));
    return NULL;
  }
}
Exemplo n.º 6
0
/* load the presets of @name for the instance @preset. Returns %FALSE if something
 * failed. */
static gboolean
gst_preset_default_load_preset (GstPreset * preset, const gchar * name)
{
  GKeyFile *presets;
  gchar **props;
  guint i;
  GObjectClass *gclass;
  gboolean is_child_proxy;

  /* get the presets from the type */
  if (!(presets = preset_get_keyfile (preset)))
    goto no_presets;

  /* get the preset name */
  if (!g_key_file_has_group (presets, name))
    goto no_group;

  GST_DEBUG_OBJECT (preset, "loading preset : '%s'", name);

  /* get the properties that we can configure in this element */
  if (!(props = gst_preset_get_property_names (preset)))
    goto no_properties;

  gclass = G_OBJECT_CLASS (GST_ELEMENT_GET_CLASS (preset));
  is_child_proxy = GST_IS_CHILD_PROXY (preset);

  /* for each of the property names, find the preset parameter and try to
   * configure the property with its value */
  for (i = 0; props[i]; i++) {
    gchar *str;
    GValue gvalue = { 0, };
    GParamSpec *property = NULL;

    /* check if we have a settings for this element property */
    if (!(str = g_key_file_get_value (presets, name, props[i], NULL))) {
      /* the element has a property but the parameter is not in the keyfile */
      GST_WARNING_OBJECT (preset, "parameter '%s' not in preset", props[i]);
      continue;
    }

    GST_DEBUG_OBJECT (preset, "setting value '%s' for property '%s'", str,
        props[i]);

    if (is_child_proxy) {
      gst_child_proxy_lookup ((GstChildProxy *) preset, props[i], NULL,
          &property);
    } else {
      property = g_object_class_find_property (gclass, props[i]);
    }
    if (!property) {
      /* the parameter was in the keyfile, the element said it supported it but
       * then the property was not found in the element. This should not happen. */
      GST_WARNING_OBJECT (preset, "property '%s' not in object", props[i]);
      g_free (str);
      continue;
    }

    /* try to deserialize the property value from the keyfile and set it as
     * the object property */
    g_value_init (&gvalue, property->value_type);
    if (gst_value_deserialize (&gvalue, str)) {
      if (is_child_proxy) {
        gst_child_proxy_set_property ((GstChildProxy *) preset, props[i],
            &gvalue);
      } else {
        g_object_set_property ((GObject *) preset, props[i], &gvalue);
      }
    } else {
      GST_WARNING_OBJECT (preset,
          "deserialization of value '%s' for property '%s' failed", str,
          props[i]);
    }
    g_value_unset (&gvalue);
    g_free (str);
  }
  g_strfreev (props);

  return TRUE;

  /* ERRORS */
no_presets:
  {
    GST_WARNING_OBJECT (preset, "no presets");
    return FALSE;
  }
no_group:
  {
    GST_WARNING_OBJECT (preset, "no preset named '%s'", name);
    return FALSE;
  }
no_properties:
  {
    GST_INFO_OBJECT (preset, "no properties");
    return FALSE;
  }
}
Exemplo n.º 7
0
gboolean command_set (const char* line) {
    gboolean result = FALSE;
    char* args;
    char* element_name;
    char* property_name;
    char* value_string;
    GstElement* element;
    GParamSpec* property;
    GType property_type;
    GValue property_value = {0};
    g_return_val_if_fail (line != NULL, FALSE);
    args = g_strdup (line);
    if (args == NULL) {
        g_printerr ("No element given\n");
        result = FALSE;
        _g_free0 (args);
        return result;
    }
    element_name = pop_string (&args);
    if (args == NULL) {
        g_printerr ("No property given\n");
        result = FALSE;
        _g_free0 (element_name);
        _g_free0 (args);
        return result;
    }
    property_name = pop_string (&args);
    if (args == NULL) {
        g_printerr ("No value given\n");
        result = FALSE;
        _g_free0 (property_name);
        _g_free0 (element_name);
        _g_free0 (args);
        return result;
    }
    value_string = pop_string (&args);
    element = gst_bin_get_by_name (pipeline, element_name);
    if (element == NULL) {
        g_printerr ("No element named '%s'\n", element_name);
        result = FALSE;
        _gst_object_unref0 (element);
        _g_free0 (value_string);
        _g_free0 (property_name);
        _g_free0 (element_name);
        _g_free0 (args);
        return result;
    }
    property = g_object_class_find_property (G_OBJECT_GET_CLASS ((GObject*) element), property_name);
    if (property == NULL) {
        g_printerr ("No property named '%s'\n", property_name);
        result = FALSE;
        _gst_object_unref0 (element);
        _g_free0 (value_string);
        _g_free0 (property_name);
        _g_free0 (element_name);
        _g_free0 (args);
        return result;
    }
    property_type = property->value_type;
    g_value_init (&property_value, property_type);
    if (gst_value_deserialize (&property_value, value_string)) {
        g_object_set_property ((GObject*) element, property_name, &property_value);
        result = TRUE;
        _gst_object_unref0 (element);
        _g_free0 (value_string);
        _g_free0 (property_name);
        _g_free0 (element_name);
        _g_free0 (args);
        return result;
    } else {
        g_printerr ("Could not transform value %s to type %s\n", value_string, g_type_name (property_type));
        result = FALSE;
        _gst_object_unref0 (element);
        _g_free0 (value_string);
        _g_free0 (property_name);
        _g_free0 (element_name);
        _g_free0 (args);
        return result;
    }
    _gst_object_unref0 (element);
    _g_free0 (value_string);
    _g_free0 (property_name);
    _g_free0 (element_name);
    _g_free0 (args);
}
Exemplo n.º 8
0
gboolean
gss_config_handle_post_hash (GObject * object, GssTransaction * t,
    GHashTable * hash)
{
  char *key, *value;
  GHashTableIter iter;

  g_return_val_if_fail (hash != NULL, FALSE);

  g_hash_table_iter_init (&iter, hash);
  while (g_hash_table_iter_next (&iter, (gpointer) & key, (gpointer) & value)) {
    GParamSpec *ps;

    if (strcmp (key, "session_id") == 0)
      continue;

    ps = g_object_class_find_property (G_OBJECT_GET_CLASS (object), key);
    if (ps == NULL) {
      GST_WARNING ("request with bad property '%s'", key);
      return FALSE;
    }
  }

  g_hash_table_iter_init (&iter, hash);
  while (g_hash_table_iter_next (&iter, (gpointer) & key, (gpointer) & value)) {
    GParamSpec *ps;
    GValue val = G_VALUE_INIT;
    gboolean ret;

    if (strcmp (key, "session_id") == 0)
      continue;

    ps = g_object_class_find_property (G_OBJECT_GET_CLASS (object), key);

    g_value_init (&val, ps->value_type);
    if (ps->value_type == G_TYPE_STRING) {
      if (ps->flags & GSS_PARAM_MULTILINE) {
        char *to_lf;
        to_lf = gss_utils_crlf_to_lf (value);
        g_value_set_string (&val, to_lf);
        g_free (to_lf);
      } else {
        g_value_set_string (&val, value);
      }
      ret = TRUE;
    } else {
      ret = gst_value_deserialize (&val, value);
    }

    if (ret) {
      GST_DEBUG ("setting property %s to '%s'", key, value);
      g_object_set_property (object, key, &val);
    } else {
      GST_ERROR ("could not deserialize property %s, value %s", key, value);
    }

    g_value_unset (&val);
  }

  gss_config_save_config_file ();

  return TRUE;
}
static void
_bin_added_from_keyfile (FsElementAddedNotifier *notifier, GstBin *bin,
    GstElement *element, gpointer user_data)
{
  GKeyFile *keyfile = user_data;
  GstElementFactory *factory = NULL;
  const gchar *name;
  gchar **keys;
  gint i;

  factory = gst_element_get_factory (element);

  if (!factory)
    return;

  name = gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory));

  if (!name)
    return;


  if (!g_key_file_has_group (keyfile, name))
    return;


  DEBUG ("Found config for %s", name);
  keys = g_key_file_get_keys (keyfile, name, NULL, NULL);

  for (i = 0; keys[i]; i++)
  {
    GParamSpec *param_spec;
    GValue prop_value = { 0 };
    gchar *str_value;

    DEBUG ("getting %s", keys[i]);
    param_spec = g_object_class_find_property (G_OBJECT_GET_CLASS(element),
        keys[i]);

    if (!param_spec)
    {
      DEBUG ("Property %s does not exist in element %s, ignoring",
          keys[i], name);
      continue;
    }

    g_value_init (&prop_value, param_spec->value_type);

    str_value = g_key_file_get_value (keyfile, name, keys[i], NULL);
    if (str_value && gst_value_deserialize (&prop_value, str_value))
    {
      DEBUG ("Setting %s to on %s", keys[i], name);
      g_object_set_property (G_OBJECT (element), keys[i], &prop_value);
    }
    else
    {
      DEBUG ("Could not read value for property %s", keys[i]);
    }
    g_free (str_value);
    g_value_unset (&prop_value);
  }

  g_strfreev (keys);
}
Exemplo n.º 10
0
/**
 * gst_riff_parse_info:
 * @element: caller element (used for debugging/error).
 * @buf: input data to be used for parsing, stripped from header.
 * @taglist: a pointer to a taglist (returned by this function)
 *           containing information about this stream. May be
 *           NULL if no supported tags were found.
 *
 * Parses stream metadata from input data.
 */
void
gst_riff_parse_info (GstElement * element,
    GstBuffer * buf, GstTagList ** _taglist)
{
  guint8 *data;
  guint size, tsize;
  guint32 tag;
  const gchar *type;
  GstTagList *taglist;

  g_return_if_fail (_taglist != NULL);

  if (!buf) {
    *_taglist = NULL;
    return;
  }
  data = GST_BUFFER_DATA (buf);
  size = GST_BUFFER_SIZE (buf);
  taglist = gst_tag_list_new ();

  while (size > 8) {
    tag = GST_READ_UINT32_LE (data);
    tsize = GST_READ_UINT32_LE (data + 4);

    GST_MEMDUMP_OBJECT (element, "tag chunk", data, MIN (tsize + 8, size));

    size -= 8;
    data += 8;

    GST_DEBUG ("tag %" GST_FOURCC_FORMAT ", size %u",
        GST_FOURCC_ARGS (tag), tsize);

    if (tsize > size) {
      GST_WARNING_OBJECT (element,
          "Tagsize %d is larger than available data %d", tsize, size);
      tsize = size;
    }

    /* make uppercase */
    tag = tag & 0xDFDFDFDF;

    /* find out the type of metadata */
    switch (tag) {
      case GST_RIFF_INFO_IARL:
        type = GST_TAG_LOCATION;
        break;
      case GST_RIFF_INFO_IAAR:
        type = GST_TAG_ALBUM_ARTIST;
        break;
      case GST_RIFF_INFO_IART:
        type = GST_TAG_ARTIST;
        break;
      case GST_RIFF_INFO_ICMS:
        type = NULL;            /*"Commissioner"; */
        break;
      case GST_RIFF_INFO_ICMT:
        type = GST_TAG_COMMENT;
        break;
      case GST_RIFF_INFO_ICOP:
        type = GST_TAG_COPYRIGHT;
        break;
      case GST_RIFF_INFO_ICRD:
        type = GST_TAG_DATE;
        break;
      case GST_RIFF_INFO_ICRP:
        type = NULL;            /*"Cropped"; */
        break;
      case GST_RIFF_INFO_IDIM:
        type = NULL;            /*"Dimensions"; */
        break;
      case GST_RIFF_INFO_IDPI:
        type = NULL;            /*"Dots per Inch"; */
        break;
      case GST_RIFF_INFO_IENG:
        type = NULL;            /*"Engineer"; */
        break;
      case GST_RIFF_INFO_IGNR:
        type = GST_TAG_GENRE;
        break;
      case GST_RIFF_INFO_IKEY:
        type = GST_TAG_KEYWORDS;
        break;
      case GST_RIFF_INFO_ILGT:
        type = NULL;            /*"Lightness"; */
        break;
      case GST_RIFF_INFO_IMED:
        type = NULL;            /*"Medium"; */
        break;
      case GST_RIFF_INFO_INAM:
        type = GST_TAG_TITLE;
        break;
      case GST_RIFF_INFO_IPLT:
        type = NULL;            /*"Palette"; */
        break;
      case GST_RIFF_INFO_IPRD:
        type = GST_TAG_ALBUM;
        break;
      case GST_RIFF_INFO_ISBJ:
        type = GST_TAG_ALBUM_ARTIST;
        break;
      case GST_RIFF_INFO_ISFT:
        type = GST_TAG_ENCODER;
        break;
      case GST_RIFF_INFO_ISHP:
        type = NULL;            /*"Sharpness"; */
        break;
      case GST_RIFF_INFO_ISRC:
        type = GST_TAG_ISRC;
        break;
      case GST_RIFF_INFO_ISRF:
        type = NULL;            /*"Source Form"; */
        break;
      case GST_RIFF_INFO_ITCH:
        type = NULL;            /*"Technician"; */
        break;
      case GST_RIFF_INFO_ITRK:
        type = GST_TAG_TRACK_NUMBER;
        break;
      default:
        type = NULL;
        GST_WARNING_OBJECT (element,
            "Unknown INFO (metadata) tag entry %" GST_FOURCC_FORMAT,
            GST_FOURCC_ARGS (tag));
        break;
    }

    if (type != NULL && data[0] != '\0') {
      static const gchar *env_vars[] = { "GST_AVI_TAG_ENCODING",
        "GST_RIFF_TAG_ENCODING", "GST_TAG_ENCODING", NULL
      };
      GType tag_type;
      gchar *val;

      GST_DEBUG_OBJECT (element, "mapped tag %" GST_FOURCC_FORMAT " to tag %s",
          GST_FOURCC_ARGS (tag), type);

      tag_type = gst_tag_get_type (type);
      val = gst_tag_freeform_string_to_utf8 ((gchar *) data, tsize, env_vars);

      if (val != NULL) {
        if (tag_type == G_TYPE_STRING) {
          gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, type, val, NULL);
        } else {
          GValue tag_val = { 0, };

          g_value_init (&tag_val, tag_type);
          if (gst_value_deserialize (&tag_val, val)) {
            gst_tag_list_add_value (taglist, GST_TAG_MERGE_APPEND, type,
                &tag_val);
          } else {
            GST_WARNING_OBJECT (element, "could not deserialize '%s' into a "
                "tag %s of type %s", val, type, g_type_name (tag_type));
          }
          g_value_unset (&tag_val);
        }
        g_free (val);
      } else {
        GST_WARNING_OBJECT (element, "could not extract %s tag", type);
      }
    }

    if (tsize & 1) {
      tsize++;
      if (tsize > size)
        tsize = size;
    }

    data += tsize;
    size -= tsize;
  }

  if (!gst_tag_list_is_empty (taglist)) {
    GST_INFO_OBJECT (element, "extracted tags: %" GST_PTR_FORMAT, taglist);
    *_taglist = taglist;
  } else {
    *_taglist = NULL;
    gst_tag_list_free (taglist);
  }

  return;
}