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