2 * Copyright (C) 2008 Vincent Penquerc'h <ogg.k.ogg.k@googlemail.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 /* FIXME: shouldn't all this GstKateDecoderBase stuff really be a base class? */
28 #include <tiger/tiger.h>
30 #include <gst/tag/tag.h>
32 #include "gstkateutil.h"
34 GST_DEBUG_CATEGORY_EXTERN (gst_kateutil_debug);
35 #define GST_CAT_DEFAULT gst_kateutil_debug
37 static void gst_kate_util_decoder_base_free_event_queue (GstKateDecoderBase *
41 gst_kate_util_set_header_on_caps (GstElement * element, GstCaps * caps,
44 GstStructure *structure;
47 GST_LOG_OBJECT (element, "caps: %" GST_PTR_FORMAT, caps);
49 if (G_UNLIKELY (!caps))
51 if (G_UNLIKELY (!headers))
54 caps = gst_caps_make_writable (caps);
55 structure = gst_caps_get_structure (caps, 0);
57 g_value_init (&array, GST_TYPE_ARRAY);
61 GstBuffer *buffer = headers->data;
63 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_IN_CAPS);
64 g_value_init (&value, GST_TYPE_BUFFER);
65 /* as in theoraenc, we need to copy to avoid circular references */
66 buffer = gst_buffer_copy (buffer);
67 gst_value_set_buffer (&value, buffer);
68 gst_buffer_unref (buffer);
69 gst_value_array_append_value (&array, &value);
70 g_value_unset (&value);
71 headers = headers->next;
74 gst_structure_set_value (structure, "streamheader", &array);
75 g_value_unset (&array);
76 GST_LOG_OBJECT (element, "here are the newly set caps: %" GST_PTR_FORMAT,
83 gst_kate_util_install_decoder_base_properties (GObjectClass * gobject_class)
85 g_object_class_install_property (gobject_class, ARG_DEC_BASE_LANGUAGE,
86 g_param_spec_string ("language", "Language", "The language of the stream",
87 "", G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
89 g_object_class_install_property (gobject_class, ARG_DEC_BASE_CATEGORY,
90 g_param_spec_string ("category", "Category", "The category of the stream",
91 "", G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
93 g_object_class_install_property (gobject_class,
94 ARG_DEC_BASE_ORIGINAL_CANVAS_WIDTH,
95 g_param_spec_int ("original-canvas-width",
96 "Original canvas width (0 is unspecified)",
97 "The canvas width this stream was authored for", 0, G_MAXINT, 0,
98 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
100 g_object_class_install_property (gobject_class,
101 ARG_DEC_BASE_ORIGINAL_CANVAS_HEIGHT,
102 g_param_spec_int ("original-canvas-height", "Original canvas height",
103 "The canvas height this stream was authored for (0 is unspecified)",
104 0, G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
108 gst_kate_util_decode_base_init (GstKateDecoderBase * decoder,
109 gboolean delay_events)
111 if (G_UNLIKELY (!decoder))
114 decoder->language = NULL;
115 decoder->category = NULL;
116 decoder->original_canvas_width = 0;
117 decoder->original_canvas_height = 0;
118 decoder->tags = NULL;
119 decoder->initialized = FALSE;
120 decoder->delay_events = delay_events;
121 decoder->event_queue = NULL;
125 gst_kate_util_decode_base_reset (GstKateDecoderBase * decoder)
127 g_free (decoder->language);
128 decoder->language = NULL;
129 g_free (decoder->category);
130 decoder->category = NULL;
132 gst_tag_list_free (decoder->tags);
133 decoder->tags = NULL;
135 decoder->original_canvas_width = 0;
136 decoder->original_canvas_height = 0;
137 if (decoder->event_queue) {
138 gst_kate_util_decoder_base_free_event_queue (decoder);
140 decoder->initialized = FALSE;
144 gst_kate_util_decoder_base_queue_event (GstKateDecoderBase * decoder,
145 GstEvent * event, gboolean (*handler) (GstPad *, GstEvent *), GstPad * pad)
147 gboolean can_be_queued;
149 switch (GST_EVENT_TYPE (event)) {
150 case GST_EVENT_FLUSH_START:
151 case GST_EVENT_FLUSH_STOP:
153 can_be_queued = FALSE;
156 can_be_queued = TRUE;
160 if (decoder->delay_events && can_be_queued) {
161 GstKateDecoderBaseQueuedEvent *item;
162 GST_DEBUG_OBJECT (decoder, "We have to delay the event");
163 item = g_slice_new (GstKateDecoderBaseQueuedEvent);
167 item->handler = handler;
168 g_queue_push_tail (decoder->event_queue, item);
179 gst_kate_util_decoder_base_free_event_queue (GstKateDecoderBase * decoder)
181 while (decoder->event_queue->length) {
182 GstKateDecoderBaseQueuedEvent *item = (GstKateDecoderBaseQueuedEvent *)
183 g_queue_pop_head (decoder->event_queue);
184 g_slice_free (GstKateDecoderBaseQueuedEvent, item);
186 g_queue_free (decoder->event_queue);
187 decoder->event_queue = NULL;
191 gst_kate_util_decoder_base_drain_event_queue (GstKateDecoderBase * decoder)
193 decoder->delay_events = FALSE;
195 if (decoder->event_queue->length == 0)
198 GST_DEBUG_OBJECT (decoder, "We can now drain all events!");
199 while (decoder->event_queue->length) {
200 GstKateDecoderBaseQueuedEvent *item = (GstKateDecoderBaseQueuedEvent *)
201 g_queue_pop_head (decoder->event_queue);
202 (*item->handler) (item->pad, item->event);
203 g_slice_free (GstKateDecoderBaseQueuedEvent, item);
208 gst_kate_util_decoder_base_get_property (GstKateDecoderBase * decoder,
209 GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
213 case ARG_DEC_BASE_LANGUAGE:
214 g_value_set_string (value, decoder->language);
216 case ARG_DEC_BASE_CATEGORY:
217 g_value_set_string (value, decoder->category);
219 case ARG_DEC_BASE_ORIGINAL_CANVAS_WIDTH:
220 g_value_set_int (value, decoder->original_canvas_width);
222 case ARG_DEC_BASE_ORIGINAL_CANVAS_HEIGHT:
223 g_value_set_int (value, decoder->original_canvas_height);
232 static inline gboolean
233 gst_kate_util_is_utf8_string (const char *value, size_t len)
237 if (memchr (value, 0, len - 1))
241 return (kate_text_validate (kate_utf8, value, len) >= 0);
245 gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder,
246 GstElement * element, GstPad * pad, GstBuffer * buf, GstPad * srcpad,
247 GstPad * tagpad, GstCaps ** src_caps, const kate_event ** ev)
251 GstFlowReturn rflow = GST_FLOW_OK;
254 GST_DEBUG_OBJECT (element, "got kate packet, %u bytes, type %02x",
255 GST_BUFFER_SIZE (buf),
256 GST_BUFFER_SIZE (buf) == 0 ? -1 : GST_BUFFER_DATA (buf)[0]);
258 is_header = GST_BUFFER_SIZE (buf) > 0 && (GST_BUFFER_DATA (buf)[0] & 0x80);
260 if (!is_header && decoder->tags) {
261 /* after we've processed headers, send any tags before processing the data packet */
262 GST_DEBUG_OBJECT (element, "Not a header, sending tags for pad %s:%s",
263 GST_DEBUG_PAD_NAME (tagpad));
264 gst_element_found_tags_for_pad (element, tagpad, decoder->tags);
265 decoder->tags = NULL;
268 kate_packet_wrap (&kp, GST_BUFFER_SIZE (buf), GST_BUFFER_DATA (buf));
269 ret = kate_high_decode_packetin (&decoder->k, &kp, ev);
270 if (G_UNLIKELY (ret < 0)) {
271 GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL),
272 ("Failed to decode Kate packet: %s",
273 gst_kate_util_get_error_message (ret)));
274 return GST_FLOW_ERROR;
277 if (G_UNLIKELY (ret > 0)) {
278 GST_DEBUG_OBJECT (element,
279 "kate_high_decode_packetin has received EOS packet");
282 /* headers may be interesting to retrieve information from */
283 if (G_UNLIKELY (is_header)) {
284 switch (GST_BUFFER_DATA (buf)[0]) {
285 case 0x80: /* ID header */
286 GST_INFO_OBJECT (element, "Parsed ID header: language %s, category %s",
287 decoder->k.ki->language, decoder->k.ki->category);
290 gst_caps_unref (*src_caps);
293 if (strcmp (decoder->k.ki->category, "K-SPU") == 0 ||
294 strcmp (decoder->k.ki->category, "spu-subtitles") == 0) {
295 *src_caps = gst_caps_new_simple ("video/x-dvd-subpicture", NULL);
296 } else if (decoder->k.ki->text_markup_type == kate_markup_none) {
297 *src_caps = gst_caps_new_simple ("text/plain", NULL);
299 *src_caps = gst_caps_new_simple ("text/x-pango-markup", NULL);
301 GST_INFO_OBJECT (srcpad, "Setting caps: %" GST_PTR_FORMAT, *src_caps);
302 if (!gst_pad_set_caps (srcpad, *src_caps)) {
303 GST_ERROR_OBJECT (srcpad, "Failed to set caps %" GST_PTR_FORMAT,
307 if (decoder->k.ki->language && *decoder->k.ki->language) {
308 GstTagList *old = decoder->tags, *tags = gst_tag_list_new ();
313 lang_code = g_ascii_strdown (decoder->k.ki->language, -1);
314 g_strdelimit (lang_code, NULL, '\0');
315 gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_LANGUAGE_CODE,
318 /* TODO: category - where should it go ? */
320 gst_tag_list_merge (decoder->tags, tags, GST_TAG_MERGE_REPLACE);
321 gst_tag_list_free (tags);
323 gst_tag_list_free (old);
327 /* update properties */
328 if (decoder->language)
329 g_free (decoder->language);
330 decoder->language = g_strdup (decoder->k.ki->language);
331 if (decoder->category)
332 g_free (decoder->category);
333 decoder->category = g_strdup (decoder->k.ki->category);
334 decoder->original_canvas_width = decoder->k.ki->original_canvas_width;
335 decoder->original_canvas_height = decoder->k.ki->original_canvas_height;
337 /* we can now send away any event we've delayed, as the src pad now has caps */
338 gst_kate_util_decoder_base_drain_event_queue (decoder);
342 case 0x81: /* Vorbis comments header */
343 GST_INFO_OBJECT (element, "Parsed comments header");
345 gchar *encoder = NULL;
346 GstTagList *old = decoder->tags, *list =
347 gst_tag_list_from_vorbiscomment_buffer (buf,
348 (const guint8 *) "\201kate\0\0\0\0", 9, &encoder);
351 gst_tag_list_merge (decoder->tags, list, GST_TAG_MERGE_REPLACE);
352 gst_tag_list_free (list);
355 if (!decoder->tags) {
356 GST_ERROR_OBJECT (element, "failed to decode comment header");
357 decoder->tags = gst_tag_list_new ();
360 gst_tag_list_add (decoder->tags, GST_TAG_MERGE_REPLACE,
361 GST_TAG_ENCODER, encoder, NULL);
364 gst_tag_list_add (decoder->tags, GST_TAG_MERGE_REPLACE,
365 GST_TAG_SUBTITLE_CODEC, "Kate", NULL);
366 gst_tag_list_add (decoder->tags, GST_TAG_MERGE_REPLACE,
367 GST_TAG_ENCODER_VERSION, decoder->k.ki->bitstream_version_major,
371 gst_tag_list_free (old);
373 if (decoder->initialized) {
374 gst_element_found_tags_for_pad (element, tagpad, decoder->tags);
375 decoder->tags = NULL;
377 /* Only push them as messages for the time being. *
378 * They will be pushed on the pad once the decoder is initialized */
379 gst_element_post_message (element,
380 gst_message_new_tag (GST_OBJECT (element),
381 gst_tag_list_copy (decoder->tags)));
390 #if ((KATE_VERSION_MAJOR<<16)|(KATE_VERSION_MINOR<<8)|KATE_VERSION_PATCH) >= 0x000400
391 else if (*ev && (*ev)->meta) {
392 int count = kate_meta_query_count ((*ev)->meta);
394 GstTagList *evtags = gst_tag_list_new ();
396 GST_DEBUG_OBJECT (decoder, "Kate event has %d attached metadata", count);
397 for (idx = 0; idx < count; ++idx) {
398 const char *tag, *value;
400 if (kate_meta_query ((*ev)->meta, idx, &tag, &value, &len) < 0) {
401 GST_WARNING_OBJECT (decoder, "Failed to retrieve metadata %d", idx);
403 if (gst_kate_util_is_utf8_string (value, len)) {
404 gchar *compound = g_strdup_printf ("%s=%s", tag, value);
405 GST_DEBUG_OBJECT (decoder, "Metadata %d: %s=%s (%zu bytes)", idx,
407 gst_tag_list_add (evtags, GST_TAG_MERGE_APPEND,
408 GST_TAG_EXTENDED_COMMENT, compound, NULL);
411 GST_INFO_OBJECT (decoder,
412 "Metadata %d, (%s, %zu bytes) is binary, ignored", idx, tag,
417 if (gst_tag_list_is_empty (evtags))
418 gst_tag_list_free (evtags);
420 gst_element_found_tags_for_pad (element, tagpad, evtags);
429 gst_kate_decoder_base_change_state (GstKateDecoderBase * decoder,
430 GstElement * element, GstElementClass * parent_class,
431 GstStateChange transition)
433 GstStateChangeReturn res;
436 switch (transition) {
437 case GST_STATE_CHANGE_NULL_TO_READY:
439 case GST_STATE_CHANGE_READY_TO_PAUSED:
440 GST_DEBUG_OBJECT (element, "READY -> PAUSED, initializing kate state");
441 ret = kate_high_decode_init (&decoder->k);
443 GST_WARNING_OBJECT (element, "failed to initialize kate state: %s",
444 gst_kate_util_get_error_message (ret));
446 gst_segment_init (&decoder->kate_segment, GST_FORMAT_UNDEFINED);
447 decoder->kate_flushing = FALSE;
448 decoder->initialized = TRUE;
449 decoder->event_queue = g_queue_new ();
451 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
457 res = parent_class->change_state (element, transition);
459 switch (transition) {
460 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
462 case GST_STATE_CHANGE_PAUSED_TO_READY:
463 GST_DEBUG_OBJECT (element, "PAUSED -> READY, clearing kate state");
464 if (decoder->initialized) {
465 kate_high_decode_clear (&decoder->k);
466 decoder->initialized = FALSE;
468 gst_segment_init (&decoder->kate_segment, GST_FORMAT_UNDEFINED);
469 decoder->kate_flushing = TRUE;
470 gst_kate_util_decode_base_reset (decoder);
472 case GST_STATE_CHANGE_READY_TO_NULL:
473 gst_kate_util_decode_base_reset (decoder);
483 gst_kate_util_decoder_base_set_flushing (GstKateDecoderBase * decoder,
486 decoder->kate_flushing = flushing;
487 gst_segment_init (&decoder->kate_segment, GST_FORMAT_UNDEFINED);
491 gst_kate_util_decoder_base_new_segment_event (GstKateDecoderBase * decoder,
497 gint64 start, stop, time;
500 gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
501 &start, &stop, &time);
502 GST_DEBUG_OBJECT (decoder, "kate pad segment:"
503 " Update %d, rate %g arate %g format %d start %" GST_TIME_FORMAT
504 " %" GST_TIME_FORMAT " position %" GST_TIME_FORMAT,
505 update, rate, arate, format, GST_TIME_ARGS (start),
506 GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
508 /* Tiger uses this segment is used to remap the video running time to the
509 Kate running time. The sending of segment updates to keep streams in sync
510 does kinda rain on our parade though, and since we don't need these,
511 we just ignore those here */
512 gst_segment_set_newsegment_full (&decoder->kate_segment, update, rate,
513 arate, format, start, stop, time);
518 gst_kate_util_decoder_base_update_segment (GstKateDecoderBase * decoder,
519 GstElement * element, GstBuffer * buf)
521 gint64 clip_start = 0, clip_stop = 0;
524 if (decoder->kate_flushing) {
525 GST_LOG_OBJECT (element, "Kate pad flushing, buffer ignored");
529 if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (buf))) {
532 if (G_LIKELY (GST_BUFFER_DURATION_IS_VALID (buf)))
533 stop = GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf);
535 stop = GST_CLOCK_TIME_NONE;
537 in_seg = gst_segment_clip (&decoder->kate_segment, GST_FORMAT_TIME,
538 GST_BUFFER_TIMESTAMP (buf), stop, &clip_start, &clip_stop);
544 if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
545 gst_segment_set_last_stop (&decoder->kate_segment, GST_FORMAT_TIME,
549 GST_INFO_OBJECT (element, "Kate buffer not in segment, ignored");
556 gst_kate_util_granule_time (kate_state * k, gint64 granulepos)
558 if (G_UNLIKELY (granulepos == -1))
561 return kate_granule_time (k->ki, granulepos) * GST_SECOND;
565 conversions on the sink:
566 - default is granules at num/den rate (subject to the granule shift)
567 - default -> time is possible
568 - bytes do not mean anything, packets can be any number of bytes, and we
569 have no way to know the number of bytes emitted without decoding
570 conversions on the source:
575 gst_kate_decoder_base_convert (GstKateDecoderBase * decoder,
576 GstElement * element, GstPad * pad, GstFormat src_fmt, gint64 src_val,
577 GstFormat * dest_fmt, gint64 * dest_val)
579 gboolean res = FALSE;
581 if (src_fmt == *dest_fmt) {
586 if (!decoder->initialized) {
587 GST_WARNING_OBJECT (element, "not initialized yet");
591 if (src_fmt == GST_FORMAT_BYTES || *dest_fmt == GST_FORMAT_BYTES) {
592 GST_WARNING_OBJECT (element, "unsupported format");
597 case GST_FORMAT_DEFAULT:
599 case GST_FORMAT_TIME:
600 *dest_val = gst_kate_util_granule_time (&decoder->k, src_val);
614 GST_WARNING_OBJECT (element, "unsupported format");
621 gst_kate_decoder_base_sink_query (GstKateDecoderBase * decoder,
622 GstElement * element, GstPad * pad, GstQuery * query)
624 switch (GST_QUERY_TYPE (query)) {
625 case GST_QUERY_CONVERT:
627 GstFormat src_fmt, dest_fmt;
628 gint64 src_val, dest_val;
630 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
631 if (!gst_kate_decoder_base_convert (decoder, element, pad, src_fmt,
632 src_val, &dest_fmt, &dest_val)) {
633 return gst_pad_query_default (pad, query);
635 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
639 return gst_pad_query_default (pad, query);
644 gst_kate_util_get_error_message (int ret)
647 case KATE_E_NOT_FOUND:
648 return "value not found";
649 case KATE_E_INVALID_PARAMETER:
650 return "invalid parameter";
651 case KATE_E_OUT_OF_MEMORY:
652 return "out of memory";
653 case KATE_E_BAD_GRANULE:
654 return "bad granule";
656 return "initialization error";
657 case KATE_E_BAD_PACKET:
660 return "invalid/truncated text";
662 return "a limit was exceeded";
664 return "unsupported bitstream version";
665 case KATE_E_NOT_KATE:
666 return "not a kate bitstream";
670 return "not implemented";
673 case TIGER_E_NOT_FOUND:
674 return "value not found";
675 case TIGER_E_INVALID_PARAMETER:
676 return "invalid parameter";
677 case TIGER_E_OUT_OF_MEMORY:
678 return "out of memory";
679 case TIGER_E_CAIRO_ERROR:
680 return "Cairo error";
681 case TIGER_E_BAD_SURFACE_TYPE:
682 return "bad surface type";
686 return "unknown error";