static void gst_wavpack_dec_post_tags (GstWavpackDec * dec) { GstTagList *list; GstFormat format_time = GST_FORMAT_TIME, format_bytes = GST_FORMAT_BYTES; gint64 duration, size; list = gst_tag_list_new (); gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_AUDIO_CODEC, "Wavpack", NULL); /* try to estimate the average bitrate */ if (gst_pad_query_peer_duration (dec->sinkpad, &format_bytes, &size) && gst_pad_query_peer_duration (dec->sinkpad, &format_time, &duration) && size > 0 && duration > 0) { guint64 bitrate; bitrate = gst_util_uint64_scale (size, 8 * GST_SECOND, duration); gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, (guint) bitrate, NULL); } gst_element_post_message (GST_ELEMENT (dec), gst_message_new_tag (GST_OBJECT (dec), list)); }
static VALUE tag_initialize(VALUE self, VALUE src, VALUE tag_list) { G_INITIALIZE(self, gst_message_new_tag(RVAL2GST_OBJ(src), RVAL2GST_TAG_LIST(tag_list))); /* FIXME */ return Qnil; }
/* takes ownership of tag list */ static gboolean gst_icydemux_send_tag_event (GstICYDemux * icydemux, GstTagList * tags) { GstEvent *event; gst_element_post_message (GST_ELEMENT (icydemux), gst_message_new_tag (GST_OBJECT (icydemux), gst_tag_list_copy (tags))); event = gst_event_new_tag (tags); GST_EVENT_TIMESTAMP (event) = 0; GST_DEBUG_OBJECT (icydemux, "Sending tag event on src pad"); return gst_pad_push_event (icydemux->srcpad, event); }
static void avrcp_metadata_cb (GstAvrcpConnection * avrcp, GstTagList * taglist, gpointer user_data) { GstAvdtpSrc *src = GST_AVDTP_SRC (user_data); guint64 duration; if (gst_tag_list_get_uint64 (taglist, GST_TAG_DURATION, &duration)) { src->duration = duration; gst_element_post_message (GST_ELEMENT (src), gst_message_new_duration_changed (GST_OBJECT (src))); } gst_pad_push_event (GST_BASE_SRC_PAD (src), gst_event_new_tag (gst_tag_list_copy (taglist))); gst_element_post_message (GST_ELEMENT (src), gst_message_new_tag (GST_OBJECT (src), taglist)); }
GstFlowReturn gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder, GstElement * element, GstPad * pad, GstBuffer * buf, GstPad * srcpad, GstPad * tagpad, GstCaps ** src_caps, const kate_event ** ev) { kate_packet kp; int ret; GstFlowReturn rflow = GST_FLOW_OK; gboolean is_header; guint8 *data; gsize size; guint8 header[1]; size = gst_buffer_extract (buf, 0, header, 1); GST_DEBUG_OBJECT (element, "got kate packet, %u bytes, type %02x", gst_buffer_get_size (buf), size == 0 ? -1 : header[0]); is_header = size > 0 && (header[0] & 0x80); if (!is_header && decoder->tags) { /* after we've processed headers, send any tags before processing the data packet */ GST_DEBUG_OBJECT (element, "Not a header, sending tags for pad %s:%s", GST_DEBUG_PAD_NAME (tagpad)); gst_element_found_tags_for_pad (element, tagpad, decoder->tags); decoder->tags = NULL; } data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ); kate_packet_wrap (&kp, size, data); ret = kate_high_decode_packetin (&decoder->k, &kp, ev); gst_buffer_unmap (buf, data, size); if (G_UNLIKELY (ret < 0)) { GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL), ("Failed to decode Kate packet: %s", gst_kate_util_get_error_message (ret))); return GST_FLOW_ERROR; } if (G_UNLIKELY (ret > 0)) { GST_DEBUG_OBJECT (element, "kate_high_decode_packetin has received EOS packet"); } /* headers may be interesting to retrieve information from */ if (G_UNLIKELY (is_header)) { switch (header[0]) { case 0x80: /* ID header */ GST_INFO_OBJECT (element, "Parsed ID header: language %s, category %s", decoder->k.ki->language, decoder->k.ki->category); if (src_caps) { if (*src_caps) { gst_caps_unref (*src_caps); *src_caps = NULL; } if (strcmp (decoder->k.ki->category, "K-SPU") == 0 || strcmp (decoder->k.ki->category, "spu-subtitles") == 0) { *src_caps = gst_caps_new_empty_simple ("video/x-dvd-subpicture"); } else if (decoder->k.ki->text_markup_type == kate_markup_none) { *src_caps = gst_caps_new_empty_simple ("text/plain"); } else { *src_caps = gst_caps_new_empty_simple ("text/x-pango-markup"); } GST_INFO_OBJECT (srcpad, "Setting caps: %" GST_PTR_FORMAT, *src_caps); if (!gst_pad_set_caps (srcpad, *src_caps)) { GST_ERROR_OBJECT (srcpad, "Failed to set caps %" GST_PTR_FORMAT, *src_caps); } } if (decoder->k.ki->language && *decoder->k.ki->language) { GstTagList *old = decoder->tags, *tags = gst_tag_list_new_empty (); if (tags) { gchar *lang_code; /* en_GB -> en */ lang_code = g_ascii_strdown (decoder->k.ki->language, -1); g_strdelimit (lang_code, NULL, '\0'); gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_LANGUAGE_CODE, lang_code, NULL); g_free (lang_code); /* TODO: category - where should it go ? */ decoder->tags = gst_tag_list_merge (decoder->tags, tags, GST_TAG_MERGE_REPLACE); gst_tag_list_free (tags); if (old) gst_tag_list_free (old); } } /* update properties */ if (decoder->language) g_free (decoder->language); decoder->language = g_strdup (decoder->k.ki->language); if (decoder->category) g_free (decoder->category); decoder->category = g_strdup (decoder->k.ki->category); decoder->original_canvas_width = decoder->k.ki->original_canvas_width; decoder->original_canvas_height = decoder->k.ki->original_canvas_height; /* we can now send away any event we've delayed, as the src pad now has caps */ gst_kate_util_decoder_base_drain_event_queue (decoder); break; case 0x81: /* Vorbis comments header */ GST_INFO_OBJECT (element, "Parsed comments header"); { gchar *encoder = NULL; GstTagList *old = decoder->tags, *list = gst_tag_list_from_vorbiscomment_buffer (buf, (const guint8 *) "\201kate\0\0\0\0", 9, &encoder); if (list) { decoder->tags = gst_tag_list_merge (decoder->tags, list, GST_TAG_MERGE_REPLACE); gst_tag_list_free (list); } if (!decoder->tags) { GST_ERROR_OBJECT (element, "failed to decode comment header"); decoder->tags = gst_tag_list_new_empty (); } if (encoder) { gst_tag_list_add (decoder->tags, GST_TAG_MERGE_REPLACE, GST_TAG_ENCODER, encoder, NULL); g_free (encoder); } gst_tag_list_add (decoder->tags, GST_TAG_MERGE_REPLACE, GST_TAG_SUBTITLE_CODEC, "Kate", NULL); gst_tag_list_add (decoder->tags, GST_TAG_MERGE_REPLACE, GST_TAG_ENCODER_VERSION, decoder->k.ki->bitstream_version_major, NULL); if (old) gst_tag_list_free (old); if (decoder->initialized) { gst_element_found_tags_for_pad (element, tagpad, decoder->tags); decoder->tags = NULL; } else { /* Only push them as messages for the time being. * * They will be pushed on the pad once the decoder is initialized */ gst_element_post_message (element, gst_message_new_tag (GST_OBJECT (element), gst_tag_list_copy (decoder->tags))); } } break; default: break; } } #if ((KATE_VERSION_MAJOR<<16)|(KATE_VERSION_MINOR<<8)|KATE_VERSION_PATCH) >= 0x000400 else if (*ev && (*ev)->meta) { int count = kate_meta_query_count ((*ev)->meta); if (count > 0) { GstTagList *evtags = gst_tag_list_new_empty (); int idx; GST_DEBUG_OBJECT (decoder, "Kate event has %d attached metadata", count); for (idx = 0; idx < count; ++idx) { const char *tag, *value; size_t len; if (kate_meta_query ((*ev)->meta, idx, &tag, &value, &len) < 0) { GST_WARNING_OBJECT (decoder, "Failed to retrieve metadata %d", idx); } else { if (gst_kate_util_is_utf8_string (value, len)) { gchar *compound = g_strdup_printf ("%s=%s", tag, value); GST_DEBUG_OBJECT (decoder, "Metadata %d: %s=%s (%zu bytes)", idx, tag, value, len); gst_tag_list_add (evtags, GST_TAG_MERGE_APPEND, GST_TAG_EXTENDED_COMMENT, compound, NULL); g_free (compound); } else { GST_INFO_OBJECT (decoder, "Metadata %d, (%s, %zu bytes) is binary, ignored", idx, tag, len); } } } if (gst_tag_list_is_empty (evtags)) gst_tag_list_free (evtags); else gst_element_found_tags_for_pad (element, tagpad, evtags); } } #endif return rflow; }
TagMessagePtr TagMessage::create(const ObjectPtr & source, const TagList & taglist) { GstMessage *m = gst_message_new_tag(source, gst_tag_list_copy(taglist)); return TagMessagePtr::wrap(m, false); }
GstFlowReturn gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder, GstElement * element, GstPad * pad, GstBuffer * buf, GstPad * srcpad, const kate_event ** ev) { kate_packet kp; int ret; GstFlowReturn rflow = GST_FLOW_OK; GST_DEBUG_OBJECT (element, "got kate packet, %u bytes, type %02x", GST_BUFFER_SIZE (buf), GST_BUFFER_SIZE (buf) == 0 ? -1 : GST_BUFFER_DATA (buf)[0]); kate_packet_wrap (&kp, GST_BUFFER_SIZE (buf), GST_BUFFER_DATA (buf)); ret = kate_high_decode_packetin (&decoder->k, &kp, ev); if (G_UNLIKELY (ret < 0)) { GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL), ("Failed to decode Kate packet: %d", ret)); return GST_FLOW_ERROR; } else if (G_UNLIKELY (ret > 0)) { GST_DEBUG_OBJECT (element, "kate_high_decode_packetin has received EOS packet"); return GST_FLOW_OK; } /* headers may be interesting to retrieve information from */ if (G_LIKELY (GST_BUFFER_SIZE (buf) > 0)) switch (GST_BUFFER_DATA (buf)[0]) { GstCaps *caps; case 0x80: /* ID header */ GST_INFO_OBJECT (element, "Parsed ID header: language %s, category %s", decoder->k.ki->language, decoder->k.ki->category); caps = gst_caps_new_simple ("text/x-pango-markup", NULL); gst_pad_set_caps (srcpad, caps); gst_caps_unref (caps); if (decoder->k.ki->language && *decoder->k.ki->language) { GstTagList *old = decoder->tags, *tags = gst_tag_list_new (); if (tags) { gchar *lang_code; /* en_GB -> en */ lang_code = g_ascii_strdown (decoder->k.ki->language, -1); g_strdelimit (lang_code, NULL, '\0'); gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_LANGUAGE_CODE, lang_code, NULL); g_free (lang_code); /* TODO: category - where should it go ? */ decoder->tags = gst_tag_list_merge (decoder->tags, tags, GST_TAG_MERGE_REPLACE); gst_tag_list_free (tags); if (old) gst_tag_list_free (old); } } /* update properties */ if (decoder->language) g_free (decoder->language); decoder->language = g_strdup (decoder->k.ki->language); if (decoder->category) g_free (decoder->category); decoder->category = g_strdup (decoder->k.ki->category); decoder->original_canvas_width = decoder->k.ki->original_canvas_width; decoder->original_canvas_height = decoder->k.ki->original_canvas_height; break; case 0x81: /* Vorbis comments header */ GST_INFO_OBJECT (element, "Parsed comments header"); { gchar *encoder = NULL; GstTagList *old = decoder->tags, *list = gst_tag_list_from_vorbiscomment_buffer (buf, (const guint8 *) "\201kate\0\0\0\0", 9, &encoder); if (list) { decoder->tags = gst_tag_list_merge (decoder->tags, list, GST_TAG_MERGE_REPLACE); gst_tag_list_free (list); } if (!decoder->tags) { GST_ERROR_OBJECT (element, "failed to decode comment header"); decoder->tags = gst_tag_list_new (); } if (encoder) { gst_tag_list_add (decoder->tags, GST_TAG_MERGE_REPLACE, GST_TAG_ENCODER, encoder, NULL); g_free (encoder); } gst_tag_list_add (decoder->tags, GST_TAG_MERGE_REPLACE, GST_TAG_SUBTITLE_CODEC, "Kate", NULL); gst_tag_list_add (decoder->tags, GST_TAG_MERGE_REPLACE, GST_TAG_ENCODER_VERSION, decoder->k.ki->bitstream_version_major, NULL); if (old) gst_tag_list_free (old); if (decoder->initialized) { gst_element_found_tags_for_pad (element, srcpad, decoder->tags); decoder->tags = NULL; } else { /* Only push them as messages for the time being. * * They will be pushed on the pad once the decoder is initialized */ gst_element_post_message (element, gst_message_new_tag (GST_OBJECT (element), gst_tag_list_copy (decoder->tags))); } } break; default: break; } return rflow; }
static GstFlowReturn vorbis_handle_comment_packet (GstVorbisDec * vd, ogg_packet * packet) { guint bitrate = 0; gchar *encoder = NULL; GstTagList *list, *old_list; GstBuffer *buf; GST_DEBUG_OBJECT (vd, "parsing comment packet"); buf = gst_buffer_new (); GST_BUFFER_DATA (buf) = gst_ogg_packet_data (packet); GST_BUFFER_SIZE (buf) = gst_ogg_packet_size (packet); list = gst_tag_list_from_vorbiscomment_buffer (buf, (guint8 *) "\003vorbis", 7, &encoder); old_list = vd->taglist; vd->taglist = gst_tag_list_merge (vd->taglist, list, GST_TAG_MERGE_REPLACE); if (old_list) gst_tag_list_free (old_list); gst_tag_list_free (list); gst_buffer_unref (buf); if (!vd->taglist) { GST_ERROR_OBJECT (vd, "couldn't decode comments"); vd->taglist = gst_tag_list_new (); } if (encoder) { if (encoder[0]) gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE, GST_TAG_ENCODER, encoder, NULL); g_free (encoder); } gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE, GST_TAG_ENCODER_VERSION, vd->vi.version, GST_TAG_AUDIO_CODEC, "Vorbis", NULL); if (vd->vi.bitrate_nominal > 0 && vd->vi.bitrate_nominal <= 0x7FFFFFFF) { gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE, GST_TAG_NOMINAL_BITRATE, (guint) vd->vi.bitrate_nominal, NULL); bitrate = vd->vi.bitrate_nominal; } if (vd->vi.bitrate_upper > 0 && vd->vi.bitrate_upper <= 0x7FFFFFFF) { gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE, (guint) vd->vi.bitrate_upper, NULL); if (!bitrate) bitrate = vd->vi.bitrate_upper; } if (vd->vi.bitrate_lower > 0 && vd->vi.bitrate_lower <= 0x7FFFFFFF) { gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE, GST_TAG_MINIMUM_BITRATE, (guint) vd->vi.bitrate_lower, NULL); if (!bitrate) bitrate = vd->vi.bitrate_lower; } if (bitrate) { gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, (guint) bitrate, NULL); } if (vd->initialized) { gst_element_found_tags_for_pad (GST_ELEMENT_CAST (vd), vd->srcpad, vd->taglist); vd->taglist = NULL; } else { /* Only post them as messages for the time being. * * They will be pushed on the pad once the decoder is initialized */ gst_element_post_message (GST_ELEMENT_CAST (vd), gst_message_new_tag (GST_OBJECT (vd), gst_tag_list_copy (vd->taglist))); } return GST_FLOW_OK; }
static gboolean start_play_tune (GstNsfDec * nsfdec) { gboolean res; nsfdec->nsf = nsf_load (NULL, GST_BUFFER_DATA (nsfdec->tune_buffer), GST_BUFFER_SIZE (nsfdec->tune_buffer)); if (!nsfdec->nsf) goto could_not_load; if (!nsfdec_negotiate (nsfdec)) goto could_not_negotiate; nsfdec->taglist = gst_tag_list_new (); gst_tag_list_add (nsfdec->taglist, GST_TAG_MERGE_REPLACE, GST_TAG_AUDIO_CODEC, "NES Sound Format", NULL); if (nsfdec->nsf->artist_name) gst_tag_list_add (nsfdec->taglist, GST_TAG_MERGE_REPLACE, GST_TAG_ARTIST, nsfdec->nsf->artist_name, NULL); if (nsfdec->nsf->song_name) gst_tag_list_add (nsfdec->taglist, GST_TAG_MERGE_REPLACE, GST_TAG_TITLE, nsfdec->nsf->song_name, NULL); gst_element_post_message (GST_ELEMENT_CAST (nsfdec), gst_message_new_tag (GST_OBJECT (nsfdec), gst_tag_list_copy (nsfdec->taglist))); nsf_playtrack (nsfdec->nsf, nsfdec->tune_number, nsfdec->frequency, nsfdec->bits, nsfdec->stereo); nsf_setfilter (nsfdec->nsf, nsfdec->filter); nsfdec->bps = (nsfdec->bits >> 3) * nsfdec->channels; /* calculate the number of bytes we need to output after each call to * nsf_frame(). */ nsfdec->blocksize = nsfdec->bps * nsfdec->frequency / nsfdec->nsf->playback_rate; gst_pad_push_event (nsfdec->srcpad, gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0)); res = gst_pad_start_task (nsfdec->srcpad, (GstTaskFunction) play_loop, nsfdec->srcpad, NULL); return res; /* ERRORS */ could_not_load: { GST_ELEMENT_ERROR (nsfdec, LIBRARY, INIT, ("Could not load tune"), ("Could not load tune")); return FALSE; } could_not_negotiate: { GST_ELEMENT_ERROR (nsfdec, CORE, NEGOTIATION, ("Could not negotiate format"), ("Could not negotiate format")); return FALSE; } }