1 /* GStreamer
2 * Copyright (C) 2008 Vincent Penquerc'h <ogg.k.ogg.k@googlemail.com>
3 *
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.
8 *
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.
13 *
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., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 /* FIXME: shouldn't all this GstKateDecoderBase stuff really be a base class? */
21
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25
26 #include <string.h>
27 #ifdef HAVE_TIGER
28 #include <tiger/tiger.h>
29 #endif
30 #include <gst/tag/tag.h>
31 #include "gstkateutil.h"
32
33 GST_DEBUG_CATEGORY_EXTERN (gst_kateutil_debug);
34 #define GST_CAT_DEFAULT gst_kateutil_debug
35
36 static void gst_kate_util_decoder_base_free_event_queue (GstKateDecoderBase *
37 decoder);
38
39 GstCaps *
gst_kate_util_set_header_on_caps(GstElement * element,GstCaps * caps,GList * headers)40 gst_kate_util_set_header_on_caps (GstElement * element, GstCaps * caps,
41 GList * headers)
42 {
43 GstStructure *structure;
44 GValue array = { 0 };
45
46 GST_LOG_OBJECT (element, "caps: %" GST_PTR_FORMAT, caps);
47
48 if (G_UNLIKELY (!caps))
49 return NULL;
50 if (G_UNLIKELY (!headers))
51 return NULL;
52
53 caps = gst_caps_make_writable (caps);
54 structure = gst_caps_get_structure (caps, 0);
55
56 g_value_init (&array, GST_TYPE_ARRAY);
57
58 while (headers) {
59 GValue value = { 0 };
60 GstBuffer *buffer = headers->data;
61 g_assert (buffer);
62 g_value_init (&value, GST_TYPE_BUFFER);
63 buffer = gst_buffer_copy (buffer);
64 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_HEADER);
65 gst_value_take_buffer (&value, buffer);
66 gst_value_array_append_value (&array, &value);
67 g_value_unset (&value);
68 headers = headers->next;
69 }
70
71 gst_structure_take_value (structure, "streamheader", &array);
72
73 GST_LOG_OBJECT (element, "here are the newly set caps: %" GST_PTR_FORMAT,
74 caps);
75
76 return caps;
77 }
78
79 void
gst_kate_util_install_decoder_base_properties(GObjectClass * gobject_class)80 gst_kate_util_install_decoder_base_properties (GObjectClass * gobject_class)
81 {
82 g_object_class_install_property (gobject_class, ARG_DEC_BASE_LANGUAGE,
83 g_param_spec_string ("language", "Language", "The language of the stream",
84 "", G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
85
86 g_object_class_install_property (gobject_class, ARG_DEC_BASE_CATEGORY,
87 g_param_spec_string ("category", "Category", "The category of the stream",
88 "", G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
89
90 g_object_class_install_property (gobject_class,
91 ARG_DEC_BASE_ORIGINAL_CANVAS_WIDTH,
92 g_param_spec_int ("original-canvas-width",
93 "Original canvas width (0 is unspecified)",
94 "The canvas width this stream was authored for", 0, G_MAXINT, 0,
95 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
96
97 g_object_class_install_property (gobject_class,
98 ARG_DEC_BASE_ORIGINAL_CANVAS_HEIGHT,
99 g_param_spec_int ("original-canvas-height", "Original canvas height",
100 "The canvas height this stream was authored for (0 is unspecified)",
101 0, G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
102 }
103
104 void
gst_kate_util_decode_base_init(GstKateDecoderBase * decoder,gboolean delay_events)105 gst_kate_util_decode_base_init (GstKateDecoderBase * decoder,
106 gboolean delay_events)
107 {
108 if (G_UNLIKELY (!decoder))
109 return;
110
111 decoder->language = NULL;
112 decoder->category = NULL;
113 decoder->original_canvas_width = 0;
114 decoder->original_canvas_height = 0;
115 decoder->tags = NULL;
116 decoder->tags_changed = FALSE;
117 decoder->initialized = FALSE;
118 decoder->delay_events = delay_events;
119 decoder->event_queue = NULL;
120 }
121
122 static void
gst_kate_util_decode_base_reset(GstKateDecoderBase * decoder)123 gst_kate_util_decode_base_reset (GstKateDecoderBase * decoder)
124 {
125 g_free (decoder->language);
126 decoder->language = NULL;
127 g_free (decoder->category);
128 decoder->category = NULL;
129 if (decoder->tags) {
130 gst_tag_list_unref (decoder->tags);
131 decoder->tags = NULL;
132 }
133 decoder->tags_changed = FALSE;
134 decoder->original_canvas_width = 0;
135 decoder->original_canvas_height = 0;
136 if (decoder->event_queue) {
137 gst_kate_util_decoder_base_free_event_queue (decoder);
138 }
139 decoder->initialized = FALSE;
140 }
141
142 gboolean
gst_kate_util_decoder_base_queue_event(GstKateDecoderBase * decoder,GstEvent * event,gboolean (* handler)(GstPad *,GstObject *,GstEvent *),GstObject * parent,GstPad * pad)143 gst_kate_util_decoder_base_queue_event (GstKateDecoderBase * decoder,
144 GstEvent * event, gboolean (*handler) (GstPad *, GstObject *, GstEvent *),
145 GstObject * parent, GstPad * pad)
146 {
147 gboolean can_be_queued;
148
149 switch (GST_EVENT_TYPE (event)) {
150 case GST_EVENT_FLUSH_START:
151 case GST_EVENT_FLUSH_STOP:
152 case GST_EVENT_EOS:
153 can_be_queued = FALSE;
154 break;
155 case GST_EVENT_SEGMENT:
156 gst_kate_util_decoder_base_segment_event (decoder, event);
157 can_be_queued = TRUE;
158 break;
159 default:
160 can_be_queued = TRUE;
161 break;
162 }
163
164 if (GST_EVENT_IS_STICKY (event) && GST_EVENT_TYPE (event) < GST_EVENT_CAPS)
165 can_be_queued = FALSE;
166
167 if (decoder->delay_events && can_be_queued) {
168 GstKateDecoderBaseQueuedEvent *item;
169 GST_DEBUG_OBJECT (decoder, "We have to delay the event");
170 item = g_slice_new (GstKateDecoderBaseQueuedEvent);
171 if (item) {
172 item->event = event;
173 item->parent = parent;
174 item->pad = pad;
175 item->handler = handler;
176 g_queue_push_tail (decoder->event_queue, item);
177 return TRUE;
178 } else {
179 return FALSE;
180 }
181 } else {
182 return FALSE;
183 }
184 }
185
186 static void
gst_kate_util_decoder_base_free_event_queue(GstKateDecoderBase * decoder)187 gst_kate_util_decoder_base_free_event_queue (GstKateDecoderBase * decoder)
188 {
189 while (decoder->event_queue->length) {
190 GstKateDecoderBaseQueuedEvent *item = (GstKateDecoderBaseQueuedEvent *)
191 g_queue_pop_head (decoder->event_queue);
192 gst_event_unref (item->event);
193 g_slice_free (GstKateDecoderBaseQueuedEvent, item);
194 }
195 g_queue_free (decoder->event_queue);
196 decoder->event_queue = NULL;
197 }
198
199 static void
gst_kate_util_decoder_base_drain_event_queue(GstKateDecoderBase * decoder)200 gst_kate_util_decoder_base_drain_event_queue (GstKateDecoderBase * decoder)
201 {
202 decoder->delay_events = FALSE;
203
204 if (decoder->event_queue->length == 0)
205 return;
206
207 GST_DEBUG_OBJECT (decoder, "We can now drain all events!");
208 while (decoder->event_queue->length) {
209 GstKateDecoderBaseQueuedEvent *item = (GstKateDecoderBaseQueuedEvent *)
210 g_queue_pop_head (decoder->event_queue);
211 (*item->handler) (item->pad, item->parent, item->event);
212 g_slice_free (GstKateDecoderBaseQueuedEvent, item);
213 }
214 }
215
216 void
gst_kate_util_decoder_base_add_tags(GstKateDecoderBase * decoder,GstTagList * tags,gboolean take_ownership_of_tags)217 gst_kate_util_decoder_base_add_tags (GstKateDecoderBase * decoder,
218 GstTagList * tags, gboolean take_ownership_of_tags)
219 {
220 if (!decoder->tags) {
221 if (!take_ownership_of_tags)
222 tags = gst_tag_list_ref (tags);
223 decoder->tags = tags;
224 } else {
225 GstTagList *old = decoder->tags;
226 decoder->tags = gst_tag_list_merge (old, tags, GST_TAG_MERGE_REPLACE);
227 gst_tag_list_unref (old);
228 if (take_ownership_of_tags)
229 gst_tag_list_unref (tags);
230 }
231 decoder->tags_changed = TRUE;
232 }
233
234 GstEvent *
gst_kate_util_decoder_base_get_tag_event(GstKateDecoderBase * decoder)235 gst_kate_util_decoder_base_get_tag_event (GstKateDecoderBase * decoder)
236 {
237 if (!decoder->tags)
238 return NULL;
239 decoder->tags_changed = FALSE;
240 return gst_event_new_tag (gst_tag_list_ref (decoder->tags));
241 }
242
243 gboolean
gst_kate_util_decoder_base_get_property(GstKateDecoderBase * decoder,GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)244 gst_kate_util_decoder_base_get_property (GstKateDecoderBase * decoder,
245 GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
246 {
247 gboolean res = TRUE;
248 switch (prop_id) {
249 case ARG_DEC_BASE_LANGUAGE:
250 g_value_set_string (value, decoder->language);
251 break;
252 case ARG_DEC_BASE_CATEGORY:
253 g_value_set_string (value, decoder->category);
254 break;
255 case ARG_DEC_BASE_ORIGINAL_CANVAS_WIDTH:
256 g_value_set_int (value, decoder->original_canvas_width);
257 break;
258 case ARG_DEC_BASE_ORIGINAL_CANVAS_HEIGHT:
259 g_value_set_int (value, decoder->original_canvas_height);
260 break;
261 default:
262 res = FALSE;
263 break;
264 }
265 return res;
266 }
267
268 static inline gboolean
gst_kate_util_is_utf8_string(const char * value,size_t len)269 gst_kate_util_is_utf8_string (const char *value, size_t len)
270 {
271 if (len == 0)
272 return FALSE;
273 if (memchr (value, 0, len - 1))
274 return FALSE;
275 if (value[len - 1])
276 return FALSE;
277 return (kate_text_validate (kate_utf8, value, len) >= 0);
278 }
279
280 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)281 gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder,
282 GstElement * element, GstPad * pad, GstBuffer * buf, GstPad * srcpad,
283 GstPad * tagpad, GstCaps ** src_caps, const kate_event ** ev)
284 {
285 kate_packet kp;
286 int ret;
287 GstFlowReturn rflow = GST_FLOW_OK;
288 gboolean is_header;
289 GstMapInfo info;
290 gsize header_size;
291 guint8 header[1];
292
293 header_size = gst_buffer_extract (buf, 0, header, 1);
294
295 GST_DEBUG_OBJECT (element,
296 "got kate packet, %" G_GSIZE_FORMAT " bytes, type %02x",
297 gst_buffer_get_size (buf), header_size == 0 ? -1 : header[0]);
298
299 is_header = header_size > 0 && (header[0] & 0x80);
300
301 if (!is_header && decoder->tags_changed) {
302 /* after we've processed headers, send any tags before processing the data packet */
303 GST_DEBUG_OBJECT (element, "Not a header, sending tags for pad %s:%s",
304 GST_DEBUG_PAD_NAME (tagpad));
305 gst_pad_push_event (tagpad,
306 gst_kate_util_decoder_base_get_tag_event (decoder));
307 }
308
309 if (gst_buffer_map (buf, &info, GST_MAP_READ)) {
310 kate_packet_wrap (&kp, info.size, info.data);
311 ret = kate_high_decode_packetin (&decoder->k, &kp, ev);
312 gst_buffer_unmap (buf, &info);
313 } else {
314 GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL),
315 ("Failed to map buffer"));
316 return GST_FLOW_ERROR;
317 }
318
319 if (G_UNLIKELY (ret < 0)) {
320 GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL),
321 ("Failed to decode Kate packet: %s",
322 gst_kate_util_get_error_message (ret)));
323 return GST_FLOW_ERROR;
324 }
325
326 if (G_UNLIKELY (ret > 0)) {
327 GST_DEBUG_OBJECT (element,
328 "kate_high_decode_packetin has received EOS packet");
329 }
330
331 /* headers may be interesting to retrieve information from */
332 if (G_UNLIKELY (is_header)) {
333 switch (header[0]) {
334 case 0x80: /* ID header */
335 GST_INFO_OBJECT (element, "Parsed ID header: language %s, category %s",
336 decoder->k.ki->language, decoder->k.ki->category);
337 if (src_caps) {
338 if (*src_caps) {
339 gst_caps_unref (*src_caps);
340 *src_caps = NULL;
341 }
342 if (strcmp (decoder->k.ki->category, "K-SPU") == 0 ||
343 strcmp (decoder->k.ki->category, "spu-subtitles") == 0) {
344 *src_caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
345 } else if (decoder->k.ki->text_markup_type == kate_markup_none) {
346 *src_caps = gst_caps_new_simple ("text/x-raw", "format",
347 G_TYPE_STRING, "utf8", NULL);
348 } else {
349 *src_caps = gst_caps_new_simple ("text/x-raw", "format",
350 G_TYPE_STRING, "pango-markup", NULL);
351 }
352 GST_INFO_OBJECT (srcpad, "Setting caps: %" GST_PTR_FORMAT, *src_caps);
353 if (!gst_pad_set_caps (srcpad, *src_caps)) {
354 GST_ERROR_OBJECT (srcpad, "Failed to set caps %" GST_PTR_FORMAT,
355 *src_caps);
356 }
357 }
358 if (decoder->k.ki->language && *decoder->k.ki->language) {
359 GstTagList *tags = gst_tag_list_new_empty ();
360 gchar *lang_code;
361
362 /* en_GB -> en */
363 lang_code = g_ascii_strdown (decoder->k.ki->language, -1);
364 g_strdelimit (lang_code, NULL, '\0');
365 gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_LANGUAGE_CODE,
366 lang_code, NULL);
367 g_free (lang_code);
368 /* TODO: category - where should it go ? */
369 gst_kate_util_decoder_base_add_tags (decoder, tags, TRUE);
370 }
371
372 /* update properties */
373 g_free (decoder->language);
374 decoder->language = g_strdup (decoder->k.ki->language);
375 g_free (decoder->category);
376 decoder->category = g_strdup (decoder->k.ki->category);
377 decoder->original_canvas_width = decoder->k.ki->original_canvas_width;
378 decoder->original_canvas_height = decoder->k.ki->original_canvas_height;
379
380 /* we can now send away any event we've delayed, as the src pad now has caps */
381 gst_kate_util_decoder_base_drain_event_queue (decoder);
382
383 break;
384
385 case 0x81: /* Vorbis comments header */
386 GST_INFO_OBJECT (element, "Parsed comments header");
387 {
388 gchar *encoder = NULL;
389 GstTagList *list = gst_tag_list_from_vorbiscomment_buffer (buf,
390 (const guint8 *) "\201kate\0\0\0\0", 9, &encoder);
391 if (!list) {
392 GST_ERROR_OBJECT (element, "failed to decode comment header");
393 list = gst_tag_list_new_empty ();
394 }
395 if (encoder) {
396 gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
397 GST_TAG_ENCODER, encoder, NULL);
398 g_free (encoder);
399 }
400 gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
401 GST_TAG_SUBTITLE_CODEC, "Kate", NULL);
402 gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
403 GST_TAG_ENCODER_VERSION, decoder->k.ki->bitstream_version_major,
404 NULL);
405
406 gst_kate_util_decoder_base_add_tags (decoder, list, TRUE);
407
408 if (decoder->initialized) {
409 gst_pad_push_event (tagpad,
410 gst_event_new_tag (gst_tag_list_ref (decoder->tags)));
411 }
412 }
413 break;
414
415 default:
416 break;
417 }
418 }
419 #if ((KATE_VERSION_MAJOR<<16)|(KATE_VERSION_MINOR<<8)|KATE_VERSION_PATCH) >= 0x000400
420 else if (*ev && (*ev)->meta) {
421 int count = kate_meta_query_count ((*ev)->meta);
422 if (count > 0) {
423 GstTagList *evtags = gst_tag_list_new_empty ();
424 int idx;
425 GST_DEBUG_OBJECT (decoder, "Kate event has %d attached metadata", count);
426 for (idx = 0; idx < count; ++idx) {
427 const char *tag, *value;
428 size_t len;
429 if (kate_meta_query ((*ev)->meta, idx, &tag, &value, &len) < 0) {
430 GST_WARNING_OBJECT (decoder, "Failed to retrieve metadata %d", idx);
431 } else {
432 if (gst_kate_util_is_utf8_string (value, len)) {
433 gchar *compound = g_strdup_printf ("%s=%s", tag, value);
434 GST_DEBUG_OBJECT (decoder,
435 "Metadata %d: %s=%s (%" G_GSIZE_FORMAT " bytes)", idx, tag,
436 value, len);
437 gst_tag_list_add (evtags, GST_TAG_MERGE_APPEND,
438 GST_TAG_EXTENDED_COMMENT, compound, NULL);
439 g_free (compound);
440 } else {
441 GST_INFO_OBJECT (decoder,
442 "Metadata %d, (%s, %" G_GSIZE_FORMAT
443 " bytes) is binary, ignored", idx, tag, len);
444 }
445 }
446 }
447 gst_kate_util_decoder_base_add_tags (decoder, evtags, TRUE);
448 gst_pad_push_event (tagpad,
449 gst_kate_util_decoder_base_get_tag_event (decoder));
450 }
451 }
452 #endif
453
454 return rflow;
455 }
456
457 GstStateChangeReturn
gst_kate_decoder_base_change_state(GstKateDecoderBase * decoder,GstElement * element,GstElementClass * parent_class,GstStateChange transition)458 gst_kate_decoder_base_change_state (GstKateDecoderBase * decoder,
459 GstElement * element, GstElementClass * parent_class,
460 GstStateChange transition)
461 {
462 GstStateChangeReturn res;
463 int ret;
464
465 switch (transition) {
466 case GST_STATE_CHANGE_NULL_TO_READY:
467 break;
468 case GST_STATE_CHANGE_READY_TO_PAUSED:
469 GST_DEBUG_OBJECT (element, "READY -> PAUSED, initializing kate state");
470 ret = kate_high_decode_init (&decoder->k);
471 if (ret < 0) {
472 GST_WARNING_OBJECT (element, "failed to initialize kate state: %s",
473 gst_kate_util_get_error_message (ret));
474 }
475 gst_segment_init (&decoder->kate_segment, GST_FORMAT_UNDEFINED);
476 decoder->kate_flushing = FALSE;
477 decoder->initialized = TRUE;
478 decoder->event_queue = g_queue_new ();
479 break;
480 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
481 break;
482 default:
483 break;
484 }
485
486 res = parent_class->change_state (element, transition);
487
488 switch (transition) {
489 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
490 break;
491 case GST_STATE_CHANGE_PAUSED_TO_READY:
492 GST_DEBUG_OBJECT (element, "PAUSED -> READY, clearing kate state");
493 if (decoder->initialized) {
494 kate_high_decode_clear (&decoder->k);
495 decoder->initialized = FALSE;
496 }
497 gst_segment_init (&decoder->kate_segment, GST_FORMAT_UNDEFINED);
498 decoder->kate_flushing = TRUE;
499 gst_kate_util_decode_base_reset (decoder);
500 break;
501 case GST_STATE_CHANGE_READY_TO_NULL:
502 gst_kate_util_decode_base_reset (decoder);
503 break;
504 default:
505 break;
506 }
507
508 return res;
509 }
510
511 void
gst_kate_util_decoder_base_set_flushing(GstKateDecoderBase * decoder,gboolean flushing)512 gst_kate_util_decoder_base_set_flushing (GstKateDecoderBase * decoder,
513 gboolean flushing)
514 {
515 decoder->kate_flushing = flushing;
516 gst_segment_init (&decoder->kate_segment, GST_FORMAT_UNDEFINED);
517 }
518
519 void
gst_kate_util_decoder_base_segment_event(GstKateDecoderBase * decoder,GstEvent * event)520 gst_kate_util_decoder_base_segment_event (GstKateDecoderBase * decoder,
521 GstEvent * event)
522 {
523 GstSegment seg;
524
525 gst_event_copy_segment (event, &seg);
526
527 GST_DEBUG_OBJECT (decoder, "kate pad segment: %" GST_SEGMENT_FORMAT, &seg);
528
529 decoder->kate_segment = seg;
530 }
531
532 gboolean
gst_kate_util_decoder_base_update_segment(GstKateDecoderBase * decoder,GstElement * element,GstBuffer * buf)533 gst_kate_util_decoder_base_update_segment (GstKateDecoderBase * decoder,
534 GstElement * element, GstBuffer * buf)
535 {
536 guint64 clip_start = 0, clip_stop = 0;
537 gboolean in_seg;
538
539 if (decoder->kate_flushing) {
540 GST_LOG_OBJECT (element, "Kate pad flushing, buffer ignored");
541 return FALSE;
542 }
543
544 if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (buf))) {
545 GstClockTime stop;
546
547 if (G_LIKELY (GST_BUFFER_DURATION_IS_VALID (buf)))
548 stop = GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf);
549 else
550 stop = GST_CLOCK_TIME_NONE;
551
552 in_seg = gst_segment_clip (&decoder->kate_segment, GST_FORMAT_TIME,
553 GST_BUFFER_TIMESTAMP (buf), stop, &clip_start, &clip_stop);
554 } else {
555 in_seg = TRUE;
556 }
557
558 if (in_seg) {
559 if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
560 decoder->kate_segment.position = clip_start;
561 }
562 } else {
563 GST_INFO_OBJECT (element, "Kate buffer not in segment, ignored");
564 }
565
566 return in_seg;
567 }
568
569 static GstClockTime
gst_kate_util_granule_time(kate_state * k,gint64 granulepos)570 gst_kate_util_granule_time (kate_state * k, gint64 granulepos)
571 {
572 if (G_UNLIKELY (granulepos == -1))
573 return -1;
574
575 return kate_granule_time (k->ki, granulepos) * GST_SECOND;
576 }
577
578 /*
579 conversions on the sink:
580 - default is granules at num/den rate (subject to the granule shift)
581 - default -> time is possible
582 - bytes do not mean anything, packets can be any number of bytes, and we
583 have no way to know the number of bytes emitted without decoding
584 conversions on the source:
585 - nothing
586 */
587
588 gboolean
gst_kate_decoder_base_convert(GstKateDecoderBase * decoder,GstElement * element,GstPad * pad,GstFormat src_fmt,gint64 src_val,GstFormat * dest_fmt,gint64 * dest_val)589 gst_kate_decoder_base_convert (GstKateDecoderBase * decoder,
590 GstElement * element, GstPad * pad, GstFormat src_fmt, gint64 src_val,
591 GstFormat * dest_fmt, gint64 * dest_val)
592 {
593 gboolean res = FALSE;
594
595 if (src_fmt == *dest_fmt) {
596 *dest_val = src_val;
597 return TRUE;
598 }
599
600 if (!decoder->initialized) {
601 GST_WARNING_OBJECT (element, "not initialized yet");
602 return FALSE;
603 }
604
605 if (src_fmt == GST_FORMAT_BYTES || *dest_fmt == GST_FORMAT_BYTES) {
606 GST_WARNING_OBJECT (element, "unsupported format");
607 return FALSE;
608 }
609
610 switch (src_fmt) {
611 case GST_FORMAT_DEFAULT:
612 switch (*dest_fmt) {
613 case GST_FORMAT_TIME:
614 *dest_val = gst_kate_util_granule_time (&decoder->k, src_val);
615 res = TRUE;
616 break;
617 default:
618 res = FALSE;
619 break;
620 }
621 break;
622 default:
623 res = FALSE;
624 break;
625 }
626
627 if (!res) {
628 GST_WARNING_OBJECT (element, "unsupported format");
629 }
630
631 return res;
632 }
633
634 gboolean
gst_kate_decoder_base_sink_query(GstKateDecoderBase * decoder,GstElement * element,GstPad * pad,GstObject * parent,GstQuery * query)635 gst_kate_decoder_base_sink_query (GstKateDecoderBase * decoder,
636 GstElement * element, GstPad * pad, GstObject * parent, GstQuery * query)
637 {
638 switch (GST_QUERY_TYPE (query)) {
639 case GST_QUERY_CONVERT:
640 {
641 GstFormat src_fmt, dest_fmt;
642 gint64 src_val, dest_val;
643
644 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
645 if (!gst_kate_decoder_base_convert (decoder, element, pad, src_fmt,
646 src_val, &dest_fmt, &dest_val)) {
647 return gst_pad_query_default (pad, parent, query);
648 }
649 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
650 return TRUE;
651 }
652 default:
653 return gst_pad_query_default (pad, parent, query);
654 }
655 }
656
657 const char *
gst_kate_util_get_error_message(int ret)658 gst_kate_util_get_error_message (int ret)
659 {
660 switch (ret) {
661 case KATE_E_NOT_FOUND:
662 return "value not found";
663 case KATE_E_INVALID_PARAMETER:
664 return "invalid parameter";
665 case KATE_E_OUT_OF_MEMORY:
666 return "out of memory";
667 case KATE_E_BAD_GRANULE:
668 return "bad granule";
669 case KATE_E_INIT:
670 return "initialization error";
671 case KATE_E_BAD_PACKET:
672 return "bad packet";
673 case KATE_E_TEXT:
674 return "invalid/truncated text";
675 case KATE_E_LIMIT:
676 return "a limit was exceeded";
677 case KATE_E_VERSION:
678 return "unsupported bitstream version";
679 case KATE_E_NOT_KATE:
680 return "not a kate bitstream";
681 case KATE_E_BAD_TAG:
682 return "bad tag";
683 case KATE_E_IMPL:
684 return "not implemented";
685
686 #ifdef HAVE_TIGER
687 case TIGER_E_NOT_FOUND:
688 return "value not found";
689 case TIGER_E_INVALID_PARAMETER:
690 return "invalid parameter";
691 case TIGER_E_OUT_OF_MEMORY:
692 return "out of memory";
693 case TIGER_E_CAIRO_ERROR:
694 return "Cairo error";
695 case TIGER_E_BAD_SURFACE_TYPE:
696 return "bad surface type";
697 #endif
698
699 default:
700 return "unknown error";
701 }
702 }
703