upload tizen1.0 source
[framework/multimedia/gst-plugins-good0.10.git] / gst / matroska / matroska-parse.c
1 /* GStreamer Matroska muxer/demuxer
2  * (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
3  * (c) 2006 Tim-Philipp Müller <tim centricular net>
4  * (c) 2008 Sebastian Dröge <slomo@circular-chaos.org>
5  *
6  * matroska-parse.c: matroska file/stream parser
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 /* TODO: check CRC32 if present
25  * TODO: there can be a segment after the first segment. Handle like
26  *       chained oggs. Fixes #334082
27  * TODO: Test samples: http://www.matroska.org/samples/matrix/index.html
28  *                     http://samples.mplayerhq.hu/Matroska/
29  * TODO: check if parseing is done correct for all codecs according to spec
30  * TODO: seeking with incomplete or without CUE
31  */
32
33 /**
34  * SECTION:element-matroskaparse
35  *
36  * matroskaparse parsees a Matroska file into the different contained streams.
37  *
38  * <refsect2>
39  * <title>Example launch line</title>
40  * |[
41  * gst-launch -v filesrc location=/path/to/mkv ! matroskaparse ! vorbisdec ! audioconvert ! audioresample ! autoaudiosink
42  * ]| This pipeline parsees a Matroska file and outputs the contained Vorbis audio.
43  * </refsect2>
44  */
45
46
47 #ifdef HAVE_CONFIG_H
48 #include "config.h"
49 #endif
50
51 #include <math.h>
52 #include <string.h>
53 #include <glib/gprintf.h>
54
55 /* For AVI compatibility mode
56    and for fourcc stuff */
57 #include <gst/riff/riff-read.h>
58 #include <gst/riff/riff-ids.h>
59 #include <gst/riff/riff-media.h>
60
61 #include <gst/tag/tag.h>
62
63 #include <gst/base/gsttypefindhelper.h>
64
65 #ifdef HAVE_ZLIB
66 #include <zlib.h>
67 #endif
68
69 #ifdef HAVE_BZ2
70 #include <bzlib.h>
71 #endif
72
73 #include <gst/pbutils/pbutils.h>
74
75 #include "lzo.h"
76
77 #include "matroska-parse.h"
78 #include "matroska-ids.h"
79
80 GST_DEBUG_CATEGORY_STATIC (matroskaparse_debug);
81 #define GST_CAT_DEFAULT matroskaparse_debug
82
83 #define DEBUG_ELEMENT_START(parse, ebml, element) \
84     GST_DEBUG_OBJECT (parse, "Parsing " element " element at offset %" \
85         G_GUINT64_FORMAT, gst_ebml_read_get_pos (ebml))
86
87 #define DEBUG_ELEMENT_STOP(parse, ebml, element, ret) \
88     GST_DEBUG_OBJECT (parse, "Parsing " element " element " \
89         " finished with '%s'", gst_flow_get_name (ret))
90
91 enum
92 {
93   ARG_0,
94   ARG_METADATA,
95   ARG_STREAMINFO
96 };
97
98 static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
99     GST_PAD_SINK,
100     GST_PAD_ALWAYS,
101     GST_STATIC_CAPS ("video/x-matroska; video/webm")
102     );
103
104 static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
105     GST_PAD_SRC,
106     GST_PAD_ALWAYS,
107     GST_STATIC_CAPS ("video/x-matroska; video/webm")
108     );
109
110 static GstFlowReturn gst_matroska_parse_parse_id (GstMatroskaParse * parse,
111     guint32 id, guint64 length, guint needed);
112
113 /* element functions */
114 //static void gst_matroska_parse_loop (GstPad * pad);
115
116 static gboolean gst_matroska_parse_element_send_event (GstElement * element,
117     GstEvent * event);
118 static gboolean gst_matroska_parse_element_query (GstElement * element,
119     GstQuery * query);
120
121 /* pad functions */
122 static gboolean gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse,
123     GstPad * pad, GstEvent * event);
124 static gboolean gst_matroska_parse_handle_src_event (GstPad * pad,
125     GstEvent * event);
126 static const GstQueryType *gst_matroska_parse_get_src_query_types (GstPad *
127     pad);
128 static gboolean gst_matroska_parse_handle_src_query (GstPad * pad,
129     GstQuery * query);
130
131 static gboolean gst_matroska_parse_handle_sink_event (GstPad * pad,
132     GstEvent * event);
133 static GstFlowReturn gst_matroska_parse_chain (GstPad * pad,
134     GstBuffer * buffer);
135
136 static GstStateChangeReturn
137 gst_matroska_parse_change_state (GstElement * element,
138     GstStateChange transition);
139 static void
140 gst_matroska_parse_set_index (GstElement * element, GstIndex * index);
141 static GstIndex *gst_matroska_parse_get_index (GstElement * element);
142
143 /* stream methods */
144 static void gst_matroska_parse_reset (GstElement * element);
145 static gboolean perform_seek_to_offset (GstMatroskaParse * parse,
146     guint64 offset);
147
148 GType gst_matroska_parse_get_type (void);
149 GST_BOILERPLATE (GstMatroskaParse, gst_matroska_parse, GstElement,
150     GST_TYPE_ELEMENT);
151
152 static void
153 gst_matroska_parse_base_init (gpointer klass)
154 {
155   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
156
157   gst_element_class_add_pad_template (element_class,
158       gst_static_pad_template_get (&src_templ));
159   gst_element_class_add_pad_template (element_class,
160       gst_static_pad_template_get (&sink_templ));
161
162   gst_element_class_set_details_simple (element_class, "Matroska parser",
163       "Codec/Parser",
164       "Parses Matroska/WebM streams into video/audio/subtitles",
165       "GStreamer maintainers <gstreamer-devel@lists.sourceforge.net>");
166 }
167
168 static void
169 gst_matroska_parse_finalize (GObject * object)
170 {
171   GstMatroskaParse *parse = GST_MATROSKA_PARSE (object);
172
173   if (parse->src) {
174     g_ptr_array_free (parse->src, TRUE);
175     parse->src = NULL;
176   }
177
178   if (parse->global_tags) {
179     gst_tag_list_free (parse->global_tags);
180     parse->global_tags = NULL;
181   }
182
183   g_object_unref (parse->adapter);
184
185   G_OBJECT_CLASS (parent_class)->finalize (object);
186 }
187
188 static void
189 gst_matroska_parse_class_init (GstMatroskaParseClass * klass)
190 {
191   GObjectClass *gobject_class = (GObjectClass *) klass;
192   GstElementClass *gstelement_class = (GstElementClass *) klass;
193
194   GST_DEBUG_CATEGORY_INIT (matroskaparse_debug, "matroskaparse", 0,
195       "Matroska parser");
196
197   gobject_class->finalize = gst_matroska_parse_finalize;
198
199   gstelement_class->change_state =
200       GST_DEBUG_FUNCPTR (gst_matroska_parse_change_state);
201   gstelement_class->send_event =
202       GST_DEBUG_FUNCPTR (gst_matroska_parse_element_send_event);
203   gstelement_class->query =
204       GST_DEBUG_FUNCPTR (gst_matroska_parse_element_query);
205
206   gstelement_class->set_index =
207       GST_DEBUG_FUNCPTR (gst_matroska_parse_set_index);
208   gstelement_class->get_index =
209       GST_DEBUG_FUNCPTR (gst_matroska_parse_get_index);
210 }
211
212 static void
213 gst_matroska_parse_init (GstMatroskaParse * parse,
214     GstMatroskaParseClass * klass)
215 {
216   parse->sinkpad = gst_pad_new_from_static_template (&sink_templ, "sink");
217   gst_pad_set_chain_function (parse->sinkpad,
218       GST_DEBUG_FUNCPTR (gst_matroska_parse_chain));
219   gst_pad_set_event_function (parse->sinkpad,
220       GST_DEBUG_FUNCPTR (gst_matroska_parse_handle_sink_event));
221   gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad);
222
223   parse->srcpad = gst_pad_new_from_static_template (&src_templ, "src");
224   gst_pad_set_event_function (parse->srcpad,
225       GST_DEBUG_FUNCPTR (gst_matroska_parse_handle_src_event));
226   gst_pad_set_query_type_function (parse->srcpad,
227       GST_DEBUG_FUNCPTR (gst_matroska_parse_get_src_query_types));
228   gst_pad_set_query_function (parse->srcpad,
229       GST_DEBUG_FUNCPTR (gst_matroska_parse_handle_src_query));
230   gst_pad_use_fixed_caps (parse->srcpad);
231
232   gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad);
233
234   /* initial stream no. */
235   parse->src = NULL;
236
237   parse->writing_app = NULL;
238   parse->muxing_app = NULL;
239   parse->index = NULL;
240   parse->global_tags = NULL;
241
242   parse->adapter = gst_adapter_new ();
243
244   /* finish off */
245   gst_matroska_parse_reset (GST_ELEMENT (parse));
246 }
247
248 static void
249 gst_matroska_track_free (GstMatroskaTrackContext * track)
250 {
251   g_free (track->codec_id);
252   g_free (track->codec_name);
253   g_free (track->name);
254   g_free (track->language);
255   g_free (track->codec_priv);
256   g_free (track->codec_state);
257
258   if (track->encodings != NULL) {
259     int i;
260
261     for (i = 0; i < track->encodings->len; ++i) {
262       GstMatroskaTrackEncoding *enc = &g_array_index (track->encodings,
263           GstMatroskaTrackEncoding,
264           i);
265
266       g_free (enc->comp_settings);
267     }
268     g_array_free (track->encodings, TRUE);
269   }
270
271   if (track->pending_tags)
272     gst_tag_list_free (track->pending_tags);
273
274   if (track->index_table)
275     g_array_free (track->index_table, TRUE);
276
277   g_free (track);
278 }
279
280 static void
281 gst_matroska_parse_free_parsed_el (gpointer mem, gpointer user_data)
282 {
283   g_slice_free (guint64, mem);
284 }
285
286 static void
287 gst_matroska_parse_reset (GstElement * element)
288 {
289   GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
290   guint i;
291
292   GST_DEBUG_OBJECT (parse, "Resetting state");
293
294   /* reset input */
295   parse->state = GST_MATROSKA_PARSE_STATE_START;
296
297   /* clean up existing streams */
298   if (parse->src) {
299     g_assert (parse->src->len == parse->num_streams);
300     for (i = 0; i < parse->src->len; i++) {
301       GstMatroskaTrackContext *context = g_ptr_array_index (parse->src, i);
302
303       gst_caps_replace (&context->caps, NULL);
304       gst_matroska_track_free (context);
305     }
306     g_ptr_array_free (parse->src, TRUE);
307   }
308   parse->src = g_ptr_array_new ();
309
310   parse->num_streams = 0;
311   parse->num_a_streams = 0;
312   parse->num_t_streams = 0;
313   parse->num_v_streams = 0;
314
315   /* reset media info */
316   g_free (parse->writing_app);
317   parse->writing_app = NULL;
318   g_free (parse->muxing_app);
319   parse->muxing_app = NULL;
320
321   /* reset indexes */
322   if (parse->index) {
323     g_array_free (parse->index, TRUE);
324     parse->index = NULL;
325   }
326
327   /* reset timers */
328   parse->clock = NULL;
329   parse->time_scale = 1000000;
330   parse->created = G_MININT64;
331
332   parse->index_parsed = FALSE;
333   parse->tracks_parsed = FALSE;
334   parse->segmentinfo_parsed = FALSE;
335   parse->attachments_parsed = FALSE;
336
337   g_list_foreach (parse->tags_parsed,
338       (GFunc) gst_matroska_parse_free_parsed_el, NULL);
339   g_list_free (parse->tags_parsed);
340   parse->tags_parsed = NULL;
341
342   g_list_foreach (parse->seek_parsed,
343       (GFunc) gst_matroska_parse_free_parsed_el, NULL);
344   g_list_free (parse->seek_parsed);
345   parse->seek_parsed = NULL;
346
347   gst_segment_init (&parse->segment, GST_FORMAT_TIME);
348   parse->last_stop_end = GST_CLOCK_TIME_NONE;
349   parse->seek_block = 0;
350
351   parse->offset = 0;
352   parse->cluster_time = GST_CLOCK_TIME_NONE;
353   parse->cluster_offset = 0;
354   parse->next_cluster_offset = 0;
355   parse->index_offset = 0;
356   parse->seekable = FALSE;
357   parse->need_newsegment = FALSE;
358   parse->building_index = FALSE;
359   if (parse->seek_event) {
360     gst_event_unref (parse->seek_event);
361     parse->seek_event = NULL;
362   }
363
364   parse->seek_index = NULL;
365   parse->seek_entry = 0;
366
367   if (parse->close_segment) {
368     gst_event_unref (parse->close_segment);
369     parse->close_segment = NULL;
370   }
371
372   if (parse->new_segment) {
373     gst_event_unref (parse->new_segment);
374     parse->new_segment = NULL;
375   }
376
377   if (parse->element_index) {
378     gst_object_unref (parse->element_index);
379     parse->element_index = NULL;
380   }
381   parse->element_index_writer_id = -1;
382
383   if (parse->global_tags) {
384     gst_tag_list_free (parse->global_tags);
385   }
386   parse->global_tags = gst_tag_list_new ();
387
388   if (parse->cached_buffer) {
389     gst_buffer_unref (parse->cached_buffer);
390     parse->cached_buffer = NULL;
391   }
392 }
393
394 /*
395  * Calls pull_range for (offset,size) without advancing our offset
396  */
397 static GstFlowReturn
398 gst_matroska_parse_peek_bytes (GstMatroskaParse * parse, guint64 offset,
399     guint size, GstBuffer ** p_buf, guint8 ** bytes)
400 {
401   GstFlowReturn ret;
402
403   /* Caching here actually makes much less difference than one would expect.
404    * We do it mainly to avoid pulling buffers of 1 byte all the time */
405   if (parse->cached_buffer) {
406     guint64 cache_offset = GST_BUFFER_OFFSET (parse->cached_buffer);
407     guint cache_size = GST_BUFFER_SIZE (parse->cached_buffer);
408
409     if (cache_offset <= parse->offset &&
410         (parse->offset + size) <= (cache_offset + cache_size)) {
411       if (p_buf)
412         *p_buf = gst_buffer_create_sub (parse->cached_buffer,
413             parse->offset - cache_offset, size);
414       if (bytes)
415         *bytes = GST_BUFFER_DATA (parse->cached_buffer) + parse->offset -
416             cache_offset;
417       return GST_FLOW_OK;
418     }
419     /* not enough data in the cache, free cache and get a new one */
420     gst_buffer_unref (parse->cached_buffer);
421     parse->cached_buffer = NULL;
422   }
423
424   /* refill the cache */
425   ret = gst_pad_pull_range (parse->sinkpad, parse->offset,
426       MAX (size, 64 * 1024), &parse->cached_buffer);
427   if (ret != GST_FLOW_OK) {
428     parse->cached_buffer = NULL;
429     return ret;
430   }
431
432   if (GST_BUFFER_SIZE (parse->cached_buffer) >= size) {
433     if (p_buf)
434       *p_buf = gst_buffer_create_sub (parse->cached_buffer, 0, size);
435     if (bytes)
436       *bytes = GST_BUFFER_DATA (parse->cached_buffer);
437     return GST_FLOW_OK;
438   }
439
440   /* Not possible to get enough data, try a last time with
441    * requesting exactly the size we need */
442   gst_buffer_unref (parse->cached_buffer);
443   parse->cached_buffer = NULL;
444
445   ret =
446       gst_pad_pull_range (parse->sinkpad, parse->offset, size,
447       &parse->cached_buffer);
448   if (ret != GST_FLOW_OK) {
449     GST_DEBUG_OBJECT (parse, "pull_range returned %d", ret);
450     if (p_buf)
451       *p_buf = NULL;
452     if (bytes)
453       *bytes = NULL;
454     return ret;
455   }
456
457   if (GST_BUFFER_SIZE (parse->cached_buffer) < size) {
458     GST_WARNING_OBJECT (parse, "Dropping short buffer at offset %"
459         G_GUINT64_FORMAT ": wanted %u bytes, got %u bytes", parse->offset,
460         size, GST_BUFFER_SIZE (parse->cached_buffer));
461
462     gst_buffer_unref (parse->cached_buffer);
463     parse->cached_buffer = NULL;
464     if (p_buf)
465       *p_buf = NULL;
466     if (bytes)
467       *bytes = NULL;
468     return GST_FLOW_UNEXPECTED;
469   }
470
471   if (p_buf)
472     *p_buf = gst_buffer_create_sub (parse->cached_buffer, 0, size);
473   if (bytes)
474     *bytes = GST_BUFFER_DATA (parse->cached_buffer);
475
476   return GST_FLOW_OK;
477 }
478
479 static const guint8 *
480 gst_matroska_parse_peek_pull (GstMatroskaParse * parse, guint peek)
481 {
482   guint8 *data = NULL;
483
484   gst_matroska_parse_peek_bytes (parse, parse->offset, peek, NULL, &data);
485   return data;
486 }
487
488 static GstFlowReturn
489 gst_matroska_parse_peek_id_length_pull (GstMatroskaParse * parse, guint32 * _id,
490     guint64 * _length, guint * _needed)
491 {
492   return gst_ebml_peek_id_length (_id, _length, _needed,
493       (GstPeekData) gst_matroska_parse_peek_pull, (gpointer) parse,
494       GST_ELEMENT_CAST (parse), parse->offset);
495 }
496
497 static gint64
498 gst_matroska_parse_get_length (GstMatroskaParse * parse)
499 {
500   GstFormat fmt = GST_FORMAT_BYTES;
501   gint64 end = -1;
502
503   if (!gst_pad_query_peer_duration (parse->sinkpad, &fmt, &end) ||
504       fmt != GST_FORMAT_BYTES || end < 0)
505     GST_DEBUG_OBJECT (parse, "no upstream length");
506
507   return end;
508 }
509
510 static gint
511 gst_matroska_parse_stream_from_num (GstMatroskaParse * parse, guint track_num)
512 {
513   guint n;
514
515   g_assert (parse->src->len == parse->num_streams);
516   for (n = 0; n < parse->src->len; n++) {
517     GstMatroskaTrackContext *context = g_ptr_array_index (parse->src, n);
518
519     if (context->num == track_num) {
520       return n;
521     }
522   }
523
524   if (n == parse->num_streams)
525     GST_WARNING_OBJECT (parse,
526         "Failed to find corresponding pad for tracknum %d", track_num);
527
528   return -1;
529 }
530
531 static gint
532 gst_matroska_parse_encoding_cmp (GstMatroskaTrackEncoding * a,
533     GstMatroskaTrackEncoding * b)
534 {
535   if (b->order > a->order)
536     return 1;
537   else if (b->order < a->order)
538     return -1;
539   else
540     return 0;
541 }
542
543 static gboolean
544 gst_matroska_parse_encoding_order_unique (GArray * encodings, guint64 order)
545 {
546   gint i;
547
548   if (encodings == NULL || encodings->len == 0)
549     return TRUE;
550
551   for (i = 0; i < encodings->len; i++)
552     if (g_array_index (encodings, GstMatroskaTrackEncoding, i).order == order)
553       return FALSE;
554
555   return TRUE;
556 }
557
558 static GstFlowReturn
559 gst_matroska_parse_read_track_encoding (GstMatroskaParse * parse,
560     GstEbmlRead * ebml, GstMatroskaTrackContext * context)
561 {
562   GstMatroskaTrackEncoding enc = { 0, };
563   GstFlowReturn ret;
564   guint32 id;
565
566   DEBUG_ELEMENT_START (parse, ebml, "ContentEncoding");
567   /* Set default values */
568   enc.scope = 1;
569   /* All other default values are 0 */
570
571   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
572     DEBUG_ELEMENT_STOP (parse, ebml, "ContentEncoding", ret);
573     return ret;
574   }
575
576   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
577     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
578       break;
579
580     switch (id) {
581       case GST_MATROSKA_ID_CONTENTENCODINGORDER:{
582         guint64 num;
583
584         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
585           break;
586
587         if (!gst_matroska_parse_encoding_order_unique (context->encodings, num)) {
588           GST_ERROR_OBJECT (parse, "ContentEncodingOrder %" G_GUINT64_FORMAT
589               "is not unique for track %d", num, context->num);
590           ret = GST_FLOW_ERROR;
591           break;
592         }
593
594         GST_DEBUG_OBJECT (parse, "ContentEncodingOrder: %" G_GUINT64_FORMAT,
595             num);
596         enc.order = num;
597         break;
598       }
599       case GST_MATROSKA_ID_CONTENTENCODINGSCOPE:{
600         guint64 num;
601
602         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
603           break;
604
605         if (num > 7 && num == 0) {
606           GST_ERROR_OBJECT (parse, "Invalid ContentEncodingScope %"
607               G_GUINT64_FORMAT, num);
608           ret = GST_FLOW_ERROR;
609           break;
610         }
611
612         GST_DEBUG_OBJECT (parse, "ContentEncodingScope: %" G_GUINT64_FORMAT,
613             num);
614         enc.scope = num;
615
616         break;
617       }
618       case GST_MATROSKA_ID_CONTENTENCODINGTYPE:{
619         guint64 num;
620
621         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
622           break;
623
624         if (num > 1) {
625           GST_ERROR_OBJECT (parse, "Invalid ContentEncodingType %"
626               G_GUINT64_FORMAT, num);
627           ret = GST_FLOW_ERROR;
628           break;
629         } else if (num != 0) {
630           GST_ERROR_OBJECT (parse, "Encrypted tracks are not supported yet");
631           ret = GST_FLOW_ERROR;
632           break;
633         }
634         GST_DEBUG_OBJECT (parse, "ContentEncodingType: %" G_GUINT64_FORMAT,
635             num);
636         enc.type = num;
637         break;
638       }
639       case GST_MATROSKA_ID_CONTENTCOMPRESSION:{
640
641         DEBUG_ELEMENT_START (parse, ebml, "ContentCompression");
642
643         if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
644           break;
645
646         while (ret == GST_FLOW_OK &&
647             gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
648           if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
649             break;
650
651           switch (id) {
652             case GST_MATROSKA_ID_CONTENTCOMPALGO:{
653               guint64 num;
654
655               if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
656                 break;
657               }
658               if (num > 3) {
659                 GST_ERROR_OBJECT (parse, "Invalid ContentCompAlgo %"
660                     G_GUINT64_FORMAT, num);
661                 ret = GST_FLOW_ERROR;
662                 break;
663               }
664               GST_DEBUG_OBJECT (parse, "ContentCompAlgo: %" G_GUINT64_FORMAT,
665                   num);
666               enc.comp_algo = num;
667
668               break;
669             }
670             case GST_MATROSKA_ID_CONTENTCOMPSETTINGS:{
671               guint8 *data;
672               guint64 size;
673
674               if ((ret =
675                       gst_ebml_read_binary (ebml, &id, &data,
676                           &size)) != GST_FLOW_OK) {
677                 break;
678               }
679               enc.comp_settings = data;
680               enc.comp_settings_length = size;
681               GST_DEBUG_OBJECT (parse,
682                   "ContentCompSettings of size %" G_GUINT64_FORMAT, size);
683               break;
684             }
685             default:
686               GST_WARNING_OBJECT (parse,
687                   "Unknown ContentCompression subelement 0x%x - ignoring", id);
688               ret = gst_ebml_read_skip (ebml);
689               break;
690           }
691         }
692         DEBUG_ELEMENT_STOP (parse, ebml, "ContentCompression", ret);
693         break;
694       }
695
696       case GST_MATROSKA_ID_CONTENTENCRYPTION:
697         GST_ERROR_OBJECT (parse, "Encrypted tracks not yet supported");
698         gst_ebml_read_skip (ebml);
699         ret = GST_FLOW_ERROR;
700         break;
701       default:
702         GST_WARNING_OBJECT (parse,
703             "Unknown ContentEncoding subelement 0x%x - ignoring", id);
704         ret = gst_ebml_read_skip (ebml);
705         break;
706     }
707   }
708
709   DEBUG_ELEMENT_STOP (parse, ebml, "ContentEncoding", ret);
710   if (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED)
711     return ret;
712
713   /* TODO: Check if the combination of values is valid */
714
715   g_array_append_val (context->encodings, enc);
716
717   return ret;
718 }
719
720 static gboolean
721 gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
722     guint8 ** data_out, guint * size_out,
723     GstMatroskaTrackCompressionAlgorithm algo)
724 {
725   guint8 *new_data = NULL;
726   guint new_size = 0;
727   guint8 *data = *data_out;
728   guint size = *size_out;
729   gboolean ret = TRUE;
730
731   if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_ZLIB) {
732 #ifdef HAVE_ZLIB
733     /* zlib encoded data */
734     z_stream zstream;
735     guint orig_size;
736     int result;
737
738     orig_size = size;
739     zstream.zalloc = (alloc_func) 0;
740     zstream.zfree = (free_func) 0;
741     zstream.opaque = (voidpf) 0;
742     if (inflateInit (&zstream) != Z_OK) {
743       GST_WARNING ("zlib initialization failed.");
744       ret = FALSE;
745       goto out;
746     }
747     zstream.next_in = (Bytef *) data;
748     zstream.avail_in = orig_size;
749     new_size = orig_size;
750     new_data = g_malloc (new_size);
751     zstream.avail_out = new_size;
752     zstream.next_out = (Bytef *) new_data;
753
754     do {
755       result = inflate (&zstream, Z_NO_FLUSH);
756       if (result != Z_OK && result != Z_STREAM_END) {
757         GST_WARNING ("zlib decompression failed.");
758         g_free (new_data);
759         inflateEnd (&zstream);
760         break;
761       }
762       new_size += 4000;
763       new_data = g_realloc (new_data, new_size);
764       zstream.next_out = (Bytef *) (new_data + zstream.total_out);
765       zstream.avail_out += 4000;
766     } while (zstream.avail_in != 0 && result != Z_STREAM_END);
767
768     if (result != Z_STREAM_END) {
769       ret = FALSE;
770       goto out;
771     } else {
772       new_size = zstream.total_out;
773       inflateEnd (&zstream);
774     }
775 #else
776     GST_WARNING ("zlib encoded tracks not supported.");
777     ret = FALSE;
778     goto out;
779 #endif
780   } else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_BZLIB) {
781 #ifdef HAVE_BZ2
782     /* bzip2 encoded data */
783     bz_stream bzstream;
784     guint orig_size;
785     int result;
786
787     bzstream.bzalloc = NULL;
788     bzstream.bzfree = NULL;
789     bzstream.opaque = NULL;
790     orig_size = size;
791
792     if (BZ2_bzDecompressInit (&bzstream, 0, 0) != BZ_OK) {
793       GST_WARNING ("bzip2 initialization failed.");
794       ret = FALSE;
795       goto out;
796     }
797
798     bzstream.next_in = (char *) data;
799     bzstream.avail_in = orig_size;
800     new_size = orig_size;
801     new_data = g_malloc (new_size);
802     bzstream.avail_out = new_size;
803     bzstream.next_out = (char *) new_data;
804
805     do {
806       result = BZ2_bzDecompress (&bzstream);
807       if (result != BZ_OK && result != BZ_STREAM_END) {
808         GST_WARNING ("bzip2 decompression failed.");
809         g_free (new_data);
810         BZ2_bzDecompressEnd (&bzstream);
811         break;
812       }
813       new_size += 4000;
814       new_data = g_realloc (new_data, new_size);
815       bzstream.next_out = (char *) (new_data + bzstream.total_out_lo32);
816       bzstream.avail_out += 4000;
817     } while (bzstream.avail_in != 0 && result != BZ_STREAM_END);
818
819     if (result != BZ_STREAM_END) {
820       ret = FALSE;
821       goto out;
822     } else {
823       new_size = bzstream.total_out_lo32;
824       BZ2_bzDecompressEnd (&bzstream);
825     }
826 #else
827     GST_WARNING ("bzip2 encoded tracks not supported.");
828     ret = FALSE;
829     goto out;
830 #endif
831   } else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_LZO1X) {
832     /* lzo encoded data */
833     int result;
834     int orig_size, out_size;
835
836     orig_size = size;
837     out_size = size;
838     new_size = size;
839     new_data = g_malloc (new_size);
840
841     do {
842       orig_size = size;
843       out_size = new_size;
844
845       result = lzo1x_decode (new_data, &out_size, data, &orig_size);
846
847       if (orig_size > 0) {
848         new_size += 4000;
849         new_data = g_realloc (new_data, new_size);
850       }
851     } while (orig_size > 0 && result == LZO_OUTPUT_FULL);
852
853     new_size -= out_size;
854
855     if (result != LZO_OUTPUT_FULL) {
856       GST_WARNING ("lzo decompression failed");
857       g_free (new_data);
858
859       ret = FALSE;
860       goto out;
861     }
862
863   } else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_HEADERSTRIP) {
864     /* header stripped encoded data */
865     if (enc->comp_settings_length > 0) {
866       new_data = g_malloc (size + enc->comp_settings_length);
867       new_size = size + enc->comp_settings_length;
868
869       memcpy (new_data, enc->comp_settings, enc->comp_settings_length);
870       memcpy (new_data + enc->comp_settings_length, data, size);
871     }
872   } else {
873     GST_ERROR ("invalid compression algorithm %d", algo);
874     ret = FALSE;
875   }
876
877 out:
878
879   if (!ret) {
880     *data_out = NULL;
881     *size_out = 0;
882   } else {
883     *data_out = new_data;
884     *size_out = new_size;
885   }
886
887   return ret;
888 }
889
890 static gboolean
891 gst_matroska_decode_data (GArray * encodings, guint8 ** data_out,
892     guint * size_out, GstMatroskaTrackEncodingScope scope, gboolean free)
893 {
894   guint8 *data;
895   guint size;
896   gboolean ret = TRUE;
897   gint i;
898
899   g_return_val_if_fail (encodings != NULL, FALSE);
900   g_return_val_if_fail (data_out != NULL && *data_out != NULL, FALSE);
901   g_return_val_if_fail (size_out != NULL, FALSE);
902
903   data = *data_out;
904   size = *size_out;
905
906   for (i = 0; i < encodings->len; i++) {
907     GstMatroskaTrackEncoding *enc =
908         &g_array_index (encodings, GstMatroskaTrackEncoding, i);
909     guint8 *new_data = NULL;
910     guint new_size = 0;
911
912     if ((enc->scope & scope) == 0)
913       continue;
914
915     /* Encryption not supported yet */
916     if (enc->type != 0) {
917       ret = FALSE;
918       break;
919     }
920
921     new_data = data;
922     new_size = size;
923
924     ret =
925         gst_matroska_decompress_data (enc, &new_data, &new_size,
926         enc->comp_algo);
927
928     if (!ret)
929       break;
930
931     if ((data == *data_out && free) || (data != *data_out))
932       g_free (data);
933
934     data = new_data;
935     size = new_size;
936   }
937
938   if (!ret) {
939     if ((data == *data_out && free) || (data != *data_out))
940       g_free (data);
941
942     *data_out = NULL;
943     *size_out = 0;
944   } else {
945     *data_out = data;
946     *size_out = size;
947   }
948
949   return ret;
950 }
951
952 static GstFlowReturn
953 gst_matroska_decode_content_encodings (GArray * encodings)
954 {
955   gint i;
956
957   if (encodings == NULL)
958     return GST_FLOW_OK;
959
960   for (i = 0; i < encodings->len; i++) {
961     GstMatroskaTrackEncoding *enc =
962         &g_array_index (encodings, GstMatroskaTrackEncoding, i);
963     guint8 *data = NULL;
964     guint size;
965
966     if ((enc->scope & GST_MATROSKA_TRACK_ENCODING_SCOPE_NEXT_CONTENT_ENCODING)
967         == 0)
968       continue;
969
970     /* Encryption not supported yet */
971     if (enc->type != 0)
972       return GST_FLOW_ERROR;
973
974     if (i + 1 >= encodings->len)
975       return GST_FLOW_ERROR;
976
977     if (enc->comp_settings_length == 0)
978       continue;
979
980     data = enc->comp_settings;
981     size = enc->comp_settings_length;
982
983     if (!gst_matroska_decompress_data (enc, &data, &size, enc->comp_algo))
984       return GST_FLOW_ERROR;
985
986     g_free (enc->comp_settings);
987
988     enc->comp_settings = data;
989     enc->comp_settings_length = size;
990   }
991
992   return GST_FLOW_OK;
993 }
994
995 static GstFlowReturn
996 gst_matroska_parse_read_track_encodings (GstMatroskaParse * parse,
997     GstEbmlRead * ebml, GstMatroskaTrackContext * context)
998 {
999   GstFlowReturn ret;
1000   guint32 id;
1001
1002   DEBUG_ELEMENT_START (parse, ebml, "ContentEncodings");
1003
1004   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1005     DEBUG_ELEMENT_STOP (parse, ebml, "ContentEncodings", ret);
1006     return ret;
1007   }
1008
1009   context->encodings =
1010       g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaTrackEncoding), 1);
1011
1012   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1013     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1014       break;
1015
1016     switch (id) {
1017       case GST_MATROSKA_ID_CONTENTENCODING:
1018         ret = gst_matroska_parse_read_track_encoding (parse, ebml, context);
1019         break;
1020       default:
1021         GST_WARNING_OBJECT (parse,
1022             "Unknown ContentEncodings subelement 0x%x - ignoring", id);
1023         ret = gst_ebml_read_skip (ebml);
1024         break;
1025     }
1026   }
1027
1028   DEBUG_ELEMENT_STOP (parse, ebml, "ContentEncodings", ret);
1029   if (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED)
1030     return ret;
1031
1032   /* Sort encodings according to their order */
1033   g_array_sort (context->encodings,
1034       (GCompareFunc) gst_matroska_parse_encoding_cmp);
1035
1036   return gst_matroska_decode_content_encodings (context->encodings);
1037 }
1038
1039 static gboolean
1040 gst_matroska_parse_tracknumber_unique (GstMatroskaParse * parse, guint64 num)
1041 {
1042   gint i;
1043
1044   g_assert (parse->src->len == parse->num_streams);
1045   for (i = 0; i < parse->src->len; i++) {
1046     GstMatroskaTrackContext *context = g_ptr_array_index (parse->src, i);
1047
1048     if (context->num == num)
1049       return FALSE;
1050   }
1051
1052   return TRUE;
1053 }
1054
1055 static GstFlowReturn
1056 gst_matroska_parse_add_stream (GstMatroskaParse * parse, GstEbmlRead * ebml)
1057 {
1058   GstMatroskaTrackContext *context;
1059   GstFlowReturn ret;
1060   guint32 id;
1061
1062   DEBUG_ELEMENT_START (parse, ebml, "TrackEntry");
1063
1064   /* start with the master */
1065   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1066     DEBUG_ELEMENT_STOP (parse, ebml, "TrackEntry", ret);
1067     return ret;
1068   }
1069
1070   /* allocate generic... if we know the type, we'll g_renew()
1071    * with the precise type */
1072   context = g_new0 (GstMatroskaTrackContext, 1);
1073   g_ptr_array_add (parse->src, context);
1074   context->index = parse->num_streams;
1075   context->index_writer_id = -1;
1076   context->type = 0;            /* no type yet */
1077   context->default_duration = 0;
1078   context->pos = 0;
1079   context->set_discont = TRUE;
1080   context->timecodescale = 1.0;
1081   context->flags =
1082       GST_MATROSKA_TRACK_ENABLED | GST_MATROSKA_TRACK_DEFAULT |
1083       GST_MATROSKA_TRACK_LACING;
1084   context->last_flow = GST_FLOW_OK;
1085   context->to_offset = G_MAXINT64;
1086   parse->num_streams++;
1087   g_assert (parse->src->len == parse->num_streams);
1088
1089   GST_DEBUG_OBJECT (parse, "Stream number %d", context->index);
1090
1091   /* try reading the trackentry headers */
1092   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1093     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1094       break;
1095
1096     switch (id) {
1097         /* track number (unique stream ID) */
1098       case GST_MATROSKA_ID_TRACKNUMBER:{
1099         guint64 num;
1100
1101         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1102           break;
1103
1104         if (num == 0) {
1105           GST_ERROR_OBJECT (parse, "Invalid TrackNumber 0");
1106           ret = GST_FLOW_ERROR;
1107           break;
1108         } else if (!gst_matroska_parse_tracknumber_unique (parse, num)) {
1109           GST_ERROR_OBJECT (parse, "TrackNumber %" G_GUINT64_FORMAT
1110               " is not unique", num);
1111           ret = GST_FLOW_ERROR;
1112           break;
1113         }
1114
1115         GST_DEBUG_OBJECT (parse, "TrackNumber: %" G_GUINT64_FORMAT, num);
1116         context->num = num;
1117         break;
1118       }
1119         /* track UID (unique identifier) */
1120       case GST_MATROSKA_ID_TRACKUID:{
1121         guint64 num;
1122
1123         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1124           break;
1125
1126         if (num == 0) {
1127           GST_ERROR_OBJECT (parse, "Invalid TrackUID 0");
1128           ret = GST_FLOW_ERROR;
1129           break;
1130         }
1131
1132         GST_DEBUG_OBJECT (parse, "TrackUID: %" G_GUINT64_FORMAT, num);
1133         context->uid = num;
1134         break;
1135       }
1136
1137         /* track type (video, audio, combined, subtitle, etc.) */
1138       case GST_MATROSKA_ID_TRACKTYPE:{
1139         guint64 track_type;
1140
1141         if ((ret = gst_ebml_read_uint (ebml, &id, &track_type)) != GST_FLOW_OK) {
1142           break;
1143         }
1144
1145         if (context->type != 0 && context->type != track_type) {
1146           GST_WARNING_OBJECT (parse,
1147               "More than one tracktype defined in a TrackEntry - skipping");
1148           break;
1149         } else if (track_type < 1 || track_type > 254) {
1150           GST_WARNING_OBJECT (parse, "Invalid TrackType %" G_GUINT64_FORMAT,
1151               track_type);
1152           break;
1153         }
1154
1155         GST_DEBUG_OBJECT (parse, "TrackType: %" G_GUINT64_FORMAT, track_type);
1156
1157         /* ok, so we're actually going to reallocate this thing */
1158         switch (track_type) {
1159           case GST_MATROSKA_TRACK_TYPE_VIDEO:
1160             gst_matroska_track_init_video_context (&context);
1161             break;
1162           case GST_MATROSKA_TRACK_TYPE_AUDIO:
1163             gst_matroska_track_init_audio_context (&context);
1164             break;
1165           case GST_MATROSKA_TRACK_TYPE_SUBTITLE:
1166             gst_matroska_track_init_subtitle_context (&context);
1167             break;
1168           case GST_MATROSKA_TRACK_TYPE_COMPLEX:
1169           case GST_MATROSKA_TRACK_TYPE_LOGO:
1170           case GST_MATROSKA_TRACK_TYPE_BUTTONS:
1171           case GST_MATROSKA_TRACK_TYPE_CONTROL:
1172           default:
1173             GST_WARNING_OBJECT (parse,
1174                 "Unknown or unsupported TrackType %" G_GUINT64_FORMAT,
1175                 track_type);
1176             context->type = 0;
1177             break;
1178         }
1179         g_ptr_array_index (parse->src, parse->num_streams - 1) = context;
1180         break;
1181       }
1182
1183         /* tracktype specific stuff for video */
1184       case GST_MATROSKA_ID_TRACKVIDEO:{
1185         GstMatroskaTrackVideoContext *videocontext;
1186
1187         DEBUG_ELEMENT_START (parse, ebml, "TrackVideo");
1188
1189         if (!gst_matroska_track_init_video_context (&context)) {
1190           GST_WARNING_OBJECT (parse,
1191               "TrackVideo element in non-video track - ignoring track");
1192           ret = GST_FLOW_ERROR;
1193           break;
1194         } else if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1195           break;
1196         }
1197         videocontext = (GstMatroskaTrackVideoContext *) context;
1198         g_ptr_array_index (parse->src, parse->num_streams - 1) = context;
1199
1200         while (ret == GST_FLOW_OK &&
1201             gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1202           if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1203             break;
1204
1205           switch (id) {
1206               /* Should be one level up but some broken muxers write it here. */
1207             case GST_MATROSKA_ID_TRACKDEFAULTDURATION:{
1208               guint64 num;
1209
1210               if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1211                 break;
1212
1213               if (num == 0) {
1214                 GST_WARNING_OBJECT (parse, "Invalid TrackDefaultDuration 0");
1215                 break;
1216               }
1217
1218               GST_DEBUG_OBJECT (parse,
1219                   "TrackDefaultDuration: %" G_GUINT64_FORMAT, num);
1220               context->default_duration = num;
1221               break;
1222             }
1223
1224               /* video framerate */
1225               /* NOTE: This one is here only for backward compatibility.
1226                * Use _TRACKDEFAULDURATION one level up. */
1227             case GST_MATROSKA_ID_VIDEOFRAMERATE:{
1228               gdouble num;
1229
1230               if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
1231                 break;
1232
1233               if (num <= 0.0) {
1234                 GST_WARNING_OBJECT (parse, "Invalid TrackVideoFPS %lf", num);
1235                 break;
1236               }
1237
1238               GST_DEBUG_OBJECT (parse, "TrackVideoFrameRate: %lf", num);
1239               if (context->default_duration == 0)
1240                 context->default_duration =
1241                     gst_gdouble_to_guint64 ((gdouble) GST_SECOND * (1.0 / num));
1242               videocontext->default_fps = num;
1243               break;
1244             }
1245
1246               /* width of the size to display the video at */
1247             case GST_MATROSKA_ID_VIDEODISPLAYWIDTH:{
1248               guint64 num;
1249
1250               if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1251                 break;
1252
1253               if (num == 0) {
1254                 GST_WARNING_OBJECT (parse, "Invalid TrackVideoDisplayWidth 0");
1255                 break;
1256               }
1257
1258               GST_DEBUG_OBJECT (parse,
1259                   "TrackVideoDisplayWidth: %" G_GUINT64_FORMAT, num);
1260               videocontext->display_width = num;
1261               break;
1262             }
1263
1264               /* height of the size to display the video at */
1265             case GST_MATROSKA_ID_VIDEODISPLAYHEIGHT:{
1266               guint64 num;
1267
1268               if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1269                 break;
1270
1271               if (num == 0) {
1272                 GST_WARNING_OBJECT (parse, "Invalid TrackVideoDisplayHeight 0");
1273                 break;
1274               }
1275
1276               GST_DEBUG_OBJECT (parse,
1277                   "TrackVideoDisplayHeight: %" G_GUINT64_FORMAT, num);
1278               videocontext->display_height = num;
1279               break;
1280             }
1281
1282               /* width of the video in the file */
1283             case GST_MATROSKA_ID_VIDEOPIXELWIDTH:{
1284               guint64 num;
1285
1286               if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1287                 break;
1288
1289               if (num == 0) {
1290                 GST_WARNING_OBJECT (parse, "Invalid TrackVideoPixelWidth 0");
1291                 break;
1292               }
1293
1294               GST_DEBUG_OBJECT (parse,
1295                   "TrackVideoPixelWidth: %" G_GUINT64_FORMAT, num);
1296               videocontext->pixel_width = num;
1297               break;
1298             }
1299
1300               /* height of the video in the file */
1301             case GST_MATROSKA_ID_VIDEOPIXELHEIGHT:{
1302               guint64 num;
1303
1304               if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1305                 break;
1306
1307               if (num == 0) {
1308                 GST_WARNING_OBJECT (parse, "Invalid TrackVideoPixelHeight 0");
1309                 break;
1310               }
1311
1312               GST_DEBUG_OBJECT (parse,
1313                   "TrackVideoPixelHeight: %" G_GUINT64_FORMAT, num);
1314               videocontext->pixel_height = num;
1315               break;
1316             }
1317
1318               /* whether the video is interlaced */
1319             case GST_MATROSKA_ID_VIDEOFLAGINTERLACED:{
1320               guint64 num;
1321
1322               if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1323                 break;
1324
1325               if (num)
1326                 context->flags |= GST_MATROSKA_VIDEOTRACK_INTERLACED;
1327               else
1328                 context->flags &= ~GST_MATROSKA_VIDEOTRACK_INTERLACED;
1329               GST_DEBUG_OBJECT (parse, "TrackVideoInterlaced: %d",
1330                   (context->flags & GST_MATROSKA_VIDEOTRACK_INTERLACED) ? 1 :
1331                   0);
1332               break;
1333             }
1334
1335               /* aspect ratio behaviour */
1336             case GST_MATROSKA_ID_VIDEOASPECTRATIOTYPE:{
1337               guint64 num;
1338
1339               if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1340                 break;
1341
1342               if (num != GST_MATROSKA_ASPECT_RATIO_MODE_FREE &&
1343                   num != GST_MATROSKA_ASPECT_RATIO_MODE_KEEP &&
1344                   num != GST_MATROSKA_ASPECT_RATIO_MODE_FIXED) {
1345                 GST_WARNING_OBJECT (parse,
1346                     "Unknown TrackVideoAspectRatioType 0x%x", (guint) num);
1347                 break;
1348               }
1349               GST_DEBUG_OBJECT (parse,
1350                   "TrackVideoAspectRatioType: %" G_GUINT64_FORMAT, num);
1351               videocontext->asr_mode = num;
1352               break;
1353             }
1354
1355               /* colourspace (only matters for raw video) fourcc */
1356             case GST_MATROSKA_ID_VIDEOCOLOURSPACE:{
1357               guint8 *data;
1358               guint64 datalen;
1359
1360               if ((ret =
1361                       gst_ebml_read_binary (ebml, &id, &data,
1362                           &datalen)) != GST_FLOW_OK)
1363                 break;
1364
1365               if (datalen != 4) {
1366                 g_free (data);
1367                 GST_WARNING_OBJECT (parse,
1368                     "Invalid TrackVideoColourSpace length %" G_GUINT64_FORMAT,
1369                     datalen);
1370                 break;
1371               }
1372
1373               memcpy (&videocontext->fourcc, data, 4);
1374               GST_DEBUG_OBJECT (parse,
1375                   "TrackVideoColourSpace: %" GST_FOURCC_FORMAT,
1376                   GST_FOURCC_ARGS (videocontext->fourcc));
1377               g_free (data);
1378               break;
1379             }
1380
1381             default:
1382               GST_WARNING_OBJECT (parse,
1383                   "Unknown TrackVideo subelement 0x%x - ignoring", id);
1384               /* fall through */
1385             case GST_MATROSKA_ID_VIDEOSTEREOMODE:
1386             case GST_MATROSKA_ID_VIDEODISPLAYUNIT:
1387             case GST_MATROSKA_ID_VIDEOPIXELCROPBOTTOM:
1388             case GST_MATROSKA_ID_VIDEOPIXELCROPTOP:
1389             case GST_MATROSKA_ID_VIDEOPIXELCROPLEFT:
1390             case GST_MATROSKA_ID_VIDEOPIXELCROPRIGHT:
1391             case GST_MATROSKA_ID_VIDEOGAMMAVALUE:
1392               ret = gst_ebml_read_skip (ebml);
1393               break;
1394           }
1395         }
1396
1397         DEBUG_ELEMENT_STOP (parse, ebml, "TrackVideo", ret);
1398         break;
1399       }
1400
1401         /* tracktype specific stuff for audio */
1402       case GST_MATROSKA_ID_TRACKAUDIO:{
1403         GstMatroskaTrackAudioContext *audiocontext;
1404
1405         DEBUG_ELEMENT_START (parse, ebml, "TrackAudio");
1406
1407         if (!gst_matroska_track_init_audio_context (&context)) {
1408           GST_WARNING_OBJECT (parse,
1409               "TrackAudio element in non-audio track - ignoring track");
1410           ret = GST_FLOW_ERROR;
1411           break;
1412         }
1413
1414         if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
1415           break;
1416
1417         audiocontext = (GstMatroskaTrackAudioContext *) context;
1418         g_ptr_array_index (parse->src, parse->num_streams - 1) = context;
1419
1420         while (ret == GST_FLOW_OK &&
1421             gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1422           if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1423             break;
1424
1425           switch (id) {
1426               /* samplerate */
1427             case GST_MATROSKA_ID_AUDIOSAMPLINGFREQ:{
1428               gdouble num;
1429
1430               if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
1431                 break;
1432
1433
1434               if (num <= 0.0) {
1435                 GST_WARNING_OBJECT (parse,
1436                     "Invalid TrackAudioSamplingFrequency %lf", num);
1437                 break;
1438               }
1439
1440               GST_DEBUG_OBJECT (parse, "TrackAudioSamplingFrequency: %lf", num);
1441               audiocontext->samplerate = num;
1442               break;
1443             }
1444
1445               /* bitdepth */
1446             case GST_MATROSKA_ID_AUDIOBITDEPTH:{
1447               guint64 num;
1448
1449               if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1450                 break;
1451
1452               if (num == 0) {
1453                 GST_WARNING_OBJECT (parse, "Invalid TrackAudioBitDepth 0");
1454                 break;
1455               }
1456
1457               GST_DEBUG_OBJECT (parse, "TrackAudioBitDepth: %" G_GUINT64_FORMAT,
1458                   num);
1459               audiocontext->bitdepth = num;
1460               break;
1461             }
1462
1463               /* channels */
1464             case GST_MATROSKA_ID_AUDIOCHANNELS:{
1465               guint64 num;
1466
1467               if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1468                 break;
1469
1470               if (num == 0) {
1471                 GST_WARNING_OBJECT (parse, "Invalid TrackAudioChannels 0");
1472                 break;
1473               }
1474
1475               GST_DEBUG_OBJECT (parse, "TrackAudioChannels: %" G_GUINT64_FORMAT,
1476                   num);
1477               audiocontext->channels = num;
1478               break;
1479             }
1480
1481             default:
1482               GST_WARNING_OBJECT (parse,
1483                   "Unknown TrackAudio subelement 0x%x - ignoring", id);
1484               /* fall through */
1485             case GST_MATROSKA_ID_AUDIOCHANNELPOSITIONS:
1486             case GST_MATROSKA_ID_AUDIOOUTPUTSAMPLINGFREQ:
1487               ret = gst_ebml_read_skip (ebml);
1488               break;
1489           }
1490         }
1491
1492         DEBUG_ELEMENT_STOP (parse, ebml, "TrackAudio", ret);
1493
1494         break;
1495       }
1496
1497         /* codec identifier */
1498       case GST_MATROSKA_ID_CODECID:{
1499         gchar *text;
1500
1501         if ((ret = gst_ebml_read_ascii (ebml, &id, &text)) != GST_FLOW_OK)
1502           break;
1503
1504         GST_DEBUG_OBJECT (parse, "CodecID: %s", GST_STR_NULL (text));
1505         context->codec_id = text;
1506         break;
1507       }
1508
1509         /* codec private data */
1510       case GST_MATROSKA_ID_CODECPRIVATE:{
1511         guint8 *data;
1512         guint64 size;
1513
1514         if ((ret =
1515                 gst_ebml_read_binary (ebml, &id, &data, &size)) != GST_FLOW_OK)
1516           break;
1517
1518         context->codec_priv = data;
1519         context->codec_priv_size = size;
1520
1521         GST_DEBUG_OBJECT (parse, "CodecPrivate of size %" G_GUINT64_FORMAT,
1522             size);
1523         break;
1524       }
1525
1526         /* name of the codec */
1527       case GST_MATROSKA_ID_CODECNAME:{
1528         gchar *text;
1529
1530         if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1531           break;
1532
1533         GST_DEBUG_OBJECT (parse, "CodecName: %s", GST_STR_NULL (text));
1534         context->codec_name = text;
1535         break;
1536       }
1537
1538         /* name of this track */
1539       case GST_MATROSKA_ID_TRACKNAME:{
1540         gchar *text;
1541
1542         if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1543           break;
1544
1545         context->name = text;
1546         GST_DEBUG_OBJECT (parse, "TrackName: %s", GST_STR_NULL (text));
1547         break;
1548       }
1549
1550         /* language (matters for audio/subtitles, mostly) */
1551       case GST_MATROSKA_ID_TRACKLANGUAGE:{
1552         gchar *text;
1553
1554         if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1555           break;
1556
1557
1558         context->language = text;
1559
1560         /* fre-ca => fre */
1561         if (strlen (context->language) >= 4 && context->language[3] == '-')
1562           context->language[3] = '\0';
1563
1564         GST_DEBUG_OBJECT (parse, "TrackLanguage: %s",
1565             GST_STR_NULL (context->language));
1566         break;
1567       }
1568
1569         /* whether this is actually used */
1570       case GST_MATROSKA_ID_TRACKFLAGENABLED:{
1571         guint64 num;
1572
1573         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1574           break;
1575
1576         if (num)
1577           context->flags |= GST_MATROSKA_TRACK_ENABLED;
1578         else
1579           context->flags &= ~GST_MATROSKA_TRACK_ENABLED;
1580
1581         GST_DEBUG_OBJECT (parse, "TrackEnabled: %d",
1582             (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
1583         break;
1584       }
1585
1586         /* whether it's the default for this track type */
1587       case GST_MATROSKA_ID_TRACKFLAGDEFAULT:{
1588         guint64 num;
1589
1590         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1591           break;
1592
1593         if (num)
1594           context->flags |= GST_MATROSKA_TRACK_DEFAULT;
1595         else
1596           context->flags &= ~GST_MATROSKA_TRACK_DEFAULT;
1597
1598         GST_DEBUG_OBJECT (parse, "TrackDefault: %d",
1599             (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
1600         break;
1601       }
1602
1603         /* whether the track must be used during playback */
1604       case GST_MATROSKA_ID_TRACKFLAGFORCED:{
1605         guint64 num;
1606
1607         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1608           break;
1609
1610         if (num)
1611           context->flags |= GST_MATROSKA_TRACK_FORCED;
1612         else
1613           context->flags &= ~GST_MATROSKA_TRACK_FORCED;
1614
1615         GST_DEBUG_OBJECT (parse, "TrackForced: %d",
1616             (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
1617         break;
1618       }
1619
1620         /* lacing (like MPEG, where blocks don't end/start on frame
1621          * boundaries) */
1622       case GST_MATROSKA_ID_TRACKFLAGLACING:{
1623         guint64 num;
1624
1625         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1626           break;
1627
1628         if (num)
1629           context->flags |= GST_MATROSKA_TRACK_LACING;
1630         else
1631           context->flags &= ~GST_MATROSKA_TRACK_LACING;
1632
1633         GST_DEBUG_OBJECT (parse, "TrackLacing: %d",
1634             (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0);
1635         break;
1636       }
1637
1638         /* default length (in time) of one data block in this track */
1639       case GST_MATROSKA_ID_TRACKDEFAULTDURATION:{
1640         guint64 num;
1641
1642         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1643           break;
1644
1645
1646         if (num == 0) {
1647           GST_WARNING_OBJECT (parse, "Invalid TrackDefaultDuration 0");
1648           break;
1649         }
1650
1651         GST_DEBUG_OBJECT (parse, "TrackDefaultDuration: %" G_GUINT64_FORMAT,
1652             num);
1653         context->default_duration = num;
1654         break;
1655       }
1656
1657       case GST_MATROSKA_ID_CONTENTENCODINGS:{
1658         ret = gst_matroska_parse_read_track_encodings (parse, ebml, context);
1659         break;
1660       }
1661
1662       case GST_MATROSKA_ID_TRACKTIMECODESCALE:{
1663         gdouble num;
1664
1665         if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
1666           break;
1667
1668         if (num <= 0.0) {
1669           GST_WARNING_OBJECT (parse, "Invalid TrackTimeCodeScale %lf", num);
1670           break;
1671         }
1672
1673         GST_DEBUG_OBJECT (parse, "TrackTimeCodeScale: %lf", num);
1674         context->timecodescale = num;
1675         break;
1676       }
1677
1678       default:
1679         GST_WARNING ("Unknown TrackEntry subelement 0x%x - ignoring", id);
1680         /* pass-through */
1681
1682         /* we ignore these because they're nothing useful (i.e. crap)
1683          * or simply not implemented yet. */
1684       case GST_MATROSKA_ID_TRACKMINCACHE:
1685       case GST_MATROSKA_ID_TRACKMAXCACHE:
1686       case GST_MATROSKA_ID_MAXBLOCKADDITIONID:
1687       case GST_MATROSKA_ID_TRACKATTACHMENTLINK:
1688       case GST_MATROSKA_ID_TRACKOVERLAY:
1689       case GST_MATROSKA_ID_TRACKTRANSLATE:
1690       case GST_MATROSKA_ID_TRACKOFFSET:
1691       case GST_MATROSKA_ID_CODECSETTINGS:
1692       case GST_MATROSKA_ID_CODECINFOURL:
1693       case GST_MATROSKA_ID_CODECDOWNLOADURL:
1694       case GST_MATROSKA_ID_CODECDECODEALL:
1695         ret = gst_ebml_read_skip (ebml);
1696         break;
1697     }
1698   }
1699
1700   DEBUG_ELEMENT_STOP (parse, ebml, "TrackEntry", ret);
1701
1702   /* Decode codec private data if necessary */
1703   if (context->encodings && context->encodings->len > 0 && context->codec_priv
1704       && context->codec_priv_size > 0) {
1705     if (!gst_matroska_decode_data (context->encodings,
1706             &context->codec_priv, &context->codec_priv_size,
1707             GST_MATROSKA_TRACK_ENCODING_SCOPE_CODEC_DATA, TRUE)) {
1708       GST_WARNING_OBJECT (parse, "Decoding codec private data failed");
1709       ret = GST_FLOW_ERROR;
1710     }
1711   }
1712
1713   if (context->type == 0 || context->codec_id == NULL || (ret != GST_FLOW_OK
1714           && ret != GST_FLOW_UNEXPECTED)) {
1715     if (ret == GST_FLOW_OK || ret == GST_FLOW_UNEXPECTED)
1716       GST_WARNING_OBJECT (ebml, "Unknown stream/codec in track entry header");
1717
1718     parse->num_streams--;
1719     g_ptr_array_remove_index (parse->src, parse->num_streams);
1720     g_assert (parse->src->len == parse->num_streams);
1721     if (context) {
1722       gst_matroska_track_free (context);
1723     }
1724
1725     return ret;
1726   }
1727
1728   if ((context->language == NULL || *context->language == '\0') &&
1729       (context->type == GST_MATROSKA_TRACK_TYPE_AUDIO ||
1730           context->type == GST_MATROSKA_TRACK_TYPE_SUBTITLE)) {
1731     GST_LOG ("stream %d: language=eng (assuming default)", context->index);
1732     context->language = g_strdup ("eng");
1733   }
1734
1735
1736   /* tadaah! */
1737   return ret;
1738 }
1739
1740 static const GstQueryType *
1741 gst_matroska_parse_get_src_query_types (GstPad * pad)
1742 {
1743   static const GstQueryType query_types[] = {
1744     GST_QUERY_POSITION,
1745     GST_QUERY_DURATION,
1746     GST_QUERY_SEEKING,
1747     0
1748   };
1749
1750   return query_types;
1751 }
1752
1753 static gboolean
1754 gst_matroska_parse_query (GstMatroskaParse * parse, GstPad * pad,
1755     GstQuery * query)
1756 {
1757   gboolean res = FALSE;
1758   GstMatroskaTrackContext *context = NULL;
1759
1760   if (pad) {
1761     context = gst_pad_get_element_private (pad);
1762   }
1763
1764   switch (GST_QUERY_TYPE (query)) {
1765     case GST_QUERY_POSITION:
1766     {
1767       GstFormat format;
1768
1769       gst_query_parse_position (query, &format, NULL);
1770
1771       if (format == GST_FORMAT_TIME) {
1772         GST_OBJECT_LOCK (parse);
1773         if (context)
1774           gst_query_set_position (query, GST_FORMAT_TIME, context->pos);
1775         else
1776           gst_query_set_position (query, GST_FORMAT_TIME,
1777               parse->segment.last_stop);
1778         GST_OBJECT_UNLOCK (parse);
1779       } else if (format == GST_FORMAT_DEFAULT && context
1780           && context->default_duration) {
1781         GST_OBJECT_LOCK (parse);
1782         gst_query_set_position (query, GST_FORMAT_DEFAULT,
1783             context->pos / context->default_duration);
1784         GST_OBJECT_UNLOCK (parse);
1785       } else {
1786         GST_DEBUG_OBJECT (parse,
1787             "only position query in TIME and DEFAULT format is supported");
1788       }
1789
1790       res = TRUE;
1791       break;
1792     }
1793     case GST_QUERY_DURATION:
1794     {
1795       GstFormat format;
1796
1797       gst_query_parse_duration (query, &format, NULL);
1798
1799       if (format == GST_FORMAT_TIME) {
1800         GST_OBJECT_LOCK (parse);
1801         gst_query_set_duration (query, GST_FORMAT_TIME,
1802             parse->segment.duration);
1803         GST_OBJECT_UNLOCK (parse);
1804       } else if (format == GST_FORMAT_DEFAULT && context
1805           && context->default_duration) {
1806         GST_OBJECT_LOCK (parse);
1807         gst_query_set_duration (query, GST_FORMAT_DEFAULT,
1808             parse->segment.duration / context->default_duration);
1809         GST_OBJECT_UNLOCK (parse);
1810       } else {
1811         GST_DEBUG_OBJECT (parse,
1812             "only duration query in TIME and DEFAULT format is supported");
1813       }
1814
1815       res = TRUE;
1816       break;
1817     }
1818
1819     case GST_QUERY_SEEKING:
1820     {
1821       GstFormat fmt;
1822
1823       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1824       if (fmt == GST_FORMAT_TIME) {
1825         gboolean seekable;
1826
1827         /* assuming we'll be able to get an index ... */
1828         seekable = parse->seekable;
1829
1830         gst_query_set_seeking (query, GST_FORMAT_TIME, seekable,
1831             0, parse->segment.duration);
1832         res = TRUE;
1833       }
1834       break;
1835     }
1836     default:
1837       res = gst_pad_query_default (pad, query);
1838       break;
1839   }
1840
1841   return res;
1842 }
1843
1844 static gboolean
1845 gst_matroska_parse_element_query (GstElement * element, GstQuery * query)
1846 {
1847   return gst_matroska_parse_query (GST_MATROSKA_PARSE (element), NULL, query);
1848 }
1849
1850 static gboolean
1851 gst_matroska_parse_handle_src_query (GstPad * pad, GstQuery * query)
1852 {
1853   gboolean ret;
1854   GstMatroskaParse *parse = GST_MATROSKA_PARSE (gst_pad_get_parent (pad));
1855
1856   ret = gst_matroska_parse_query (parse, pad, query);
1857
1858   gst_object_unref (parse);
1859
1860   return ret;
1861 }
1862
1863 static gint
1864 gst_matroska_index_seek_find (GstMatroskaIndex * i1, GstClockTime * time,
1865     gpointer user_data)
1866 {
1867   if (i1->time < *time)
1868     return -1;
1869   else if (i1->time > *time)
1870     return 1;
1871   else
1872     return 0;
1873 }
1874
1875 static GstMatroskaIndex *
1876 gst_matroskaparse_do_index_seek (GstMatroskaParse * parse,
1877     GstMatroskaTrackContext * track, gint64 seek_pos, GArray ** _index,
1878     gint * _entry_index)
1879 {
1880   GstMatroskaIndex *entry = NULL;
1881   GArray *index;
1882
1883   if (!parse->index || !parse->index->len)
1884     return NULL;
1885
1886   /* find entry just before or at the requested position */
1887   if (track && track->index_table)
1888     index = track->index_table;
1889   else
1890     index = parse->index;
1891
1892   entry =
1893       gst_util_array_binary_search (index->data, index->len,
1894       sizeof (GstMatroskaIndex),
1895       (GCompareDataFunc) gst_matroska_index_seek_find, GST_SEARCH_MODE_BEFORE,
1896       &seek_pos, NULL);
1897
1898   if (entry == NULL)
1899     entry = &g_array_index (index, GstMatroskaIndex, 0);
1900
1901   if (_index)
1902     *_index = index;
1903   if (_entry_index)
1904     *_entry_index = entry - (GstMatroskaIndex *) index->data;
1905
1906   return entry;
1907 }
1908
1909 /* takes ownership of taglist */
1910 static void
1911 gst_matroska_parse_found_global_tag (GstMatroskaParse * parse,
1912     GstTagList * taglist)
1913 {
1914   if (parse->global_tags) {
1915     /* nothing sent yet, add to cache */
1916     gst_tag_list_insert (parse->global_tags, taglist, GST_TAG_MERGE_APPEND);
1917     gst_tag_list_free (taglist);
1918   } else {
1919     /* hm, already sent, no need to cache and wait anymore */
1920     GST_DEBUG_OBJECT (parse, "Sending late global tags %" GST_PTR_FORMAT,
1921         taglist);
1922     gst_element_found_tags (GST_ELEMENT (parse), taglist);
1923   }
1924 }
1925
1926 /* returns FALSE if there are no pads to deliver event to,
1927  * otherwise TRUE (whatever the outcome of event sending),
1928  * takes ownership of the passed event! */
1929 static gboolean
1930 gst_matroska_parse_send_event (GstMatroskaParse * parse, GstEvent * event)
1931 {
1932   gboolean ret = FALSE;
1933
1934   g_return_val_if_fail (event != NULL, FALSE);
1935
1936   GST_DEBUG_OBJECT (parse, "Sending event of type %s to all source pads",
1937       GST_EVENT_TYPE_NAME (event));
1938
1939   gst_pad_push_event (parse->srcpad, event);
1940
1941   return ret;
1942 }
1943
1944 static gboolean
1945 gst_matroska_parse_element_send_event (GstElement * element, GstEvent * event)
1946 {
1947   GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
1948   gboolean res;
1949
1950   g_return_val_if_fail (event != NULL, FALSE);
1951
1952   if (GST_EVENT_TYPE (event) == GST_EVENT_SEEK) {
1953     res = gst_matroska_parse_handle_seek_event (parse, NULL, event);
1954   } else {
1955     GST_WARNING_OBJECT (parse, "Unhandled event of type %s",
1956         GST_EVENT_TYPE_NAME (event));
1957     res = FALSE;
1958   }
1959   gst_event_unref (event);
1960   return res;
1961 }
1962
1963 /* determine track to seek in */
1964 static GstMatroskaTrackContext *
1965 gst_matroska_parse_get_seek_track (GstMatroskaParse * parse,
1966     GstMatroskaTrackContext * track)
1967 {
1968   gint i;
1969
1970   if (track && track->type == GST_MATROSKA_TRACK_TYPE_VIDEO)
1971     return track;
1972
1973   for (i = 0; i < parse->src->len; i++) {
1974     GstMatroskaTrackContext *stream;
1975
1976     stream = g_ptr_array_index (parse->src, i);
1977     if (stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO && stream->index_table)
1978       track = stream;
1979   }
1980
1981   return track;
1982 }
1983
1984 static void
1985 gst_matroska_parse_reset_streams (GstMatroskaParse * parse, GstClockTime time,
1986     gboolean full)
1987 {
1988   gint i;
1989
1990   GST_DEBUG_OBJECT (parse, "resetting stream state");
1991
1992   g_assert (parse->src->len == parse->num_streams);
1993   for (i = 0; i < parse->src->len; i++) {
1994     GstMatroskaTrackContext *context = g_ptr_array_index (parse->src, i);
1995     context->pos = time;
1996     context->set_discont = TRUE;
1997     context->eos = FALSE;
1998     context->from_time = GST_CLOCK_TIME_NONE;
1999     if (full)
2000       context->last_flow = GST_FLOW_OK;
2001     if (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO) {
2002       GstMatroskaTrackVideoContext *videocontext =
2003           (GstMatroskaTrackVideoContext *) context;
2004       /* parse object lock held by caller */
2005       videocontext->earliest_time = GST_CLOCK_TIME_NONE;
2006     }
2007   }
2008 }
2009
2010 /* searches for a cluster start from @pos,
2011  * return GST_FLOW_OK and cluster position in @pos if found */
2012 static GstFlowReturn
2013 gst_matroska_parse_search_cluster (GstMatroskaParse * parse, gint64 * pos)
2014 {
2015   gint64 newpos = *pos;
2016   gint64 orig_offset;
2017   GstFlowReturn ret = GST_FLOW_OK;
2018   const guint chunk = 64 * 1024;
2019   GstBuffer *buf = NULL;
2020   guint64 length;
2021   guint32 id;
2022   guint needed;
2023
2024   orig_offset = parse->offset;
2025
2026   /* read in at newpos and scan for ebml cluster id */
2027   while (1) {
2028     GstByteReader reader;
2029     gint cluster_pos;
2030
2031     ret = gst_pad_pull_range (parse->sinkpad, newpos, chunk, &buf);
2032     if (ret != GST_FLOW_OK)
2033       break;
2034     GST_DEBUG_OBJECT (parse, "read buffer size %d at offset %" G_GINT64_FORMAT,
2035         GST_BUFFER_SIZE (buf), newpos);
2036     gst_byte_reader_init_from_buffer (&reader, buf);
2037     cluster_pos = 0;
2038   resume:
2039     cluster_pos = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff,
2040         GST_MATROSKA_ID_CLUSTER, cluster_pos,
2041         GST_BUFFER_SIZE (buf) - cluster_pos);
2042     if (cluster_pos >= 0) {
2043       newpos += cluster_pos;
2044       GST_DEBUG_OBJECT (parse,
2045           "found cluster ebml id at offset %" G_GINT64_FORMAT, newpos);
2046       /* extra checks whether we really sync'ed to a cluster:
2047        * - either it is the first and only cluster
2048        * - either there is a cluster after this one
2049        * - either cluster length is undefined
2050        */
2051       /* ok if first cluster (there may not a subsequent one) */
2052       if (newpos == parse->first_cluster_offset) {
2053         GST_DEBUG_OBJECT (parse, "cluster is first cluster -> OK");
2054         break;
2055       }
2056       parse->offset = newpos;
2057       ret =
2058           gst_matroska_parse_peek_id_length_pull (parse, &id, &length, &needed);
2059       if (ret != GST_FLOW_OK)
2060         goto resume;
2061       g_assert (id == GST_MATROSKA_ID_CLUSTER);
2062       GST_DEBUG_OBJECT (parse, "cluster size %" G_GUINT64_FORMAT ", prefix %d",
2063           length, needed);
2064       /* ok if undefined length or first cluster */
2065       if (length == G_MAXUINT64) {
2066         GST_DEBUG_OBJECT (parse, "cluster has undefined length -> OK");
2067         break;
2068       }
2069       /* skip cluster */
2070       parse->offset += length + needed;
2071       ret =
2072           gst_matroska_parse_peek_id_length_pull (parse, &id, &length, &needed);
2073       if (ret != GST_FLOW_OK)
2074         goto resume;
2075       GST_DEBUG_OBJECT (parse, "next element is %scluster",
2076           id == GST_MATROSKA_ID_CLUSTER ? "" : "not ");
2077       if (id == GST_MATROSKA_ID_CLUSTER)
2078         break;
2079       /* not ok, resume */
2080       goto resume;
2081     } else {
2082       /* partial cluster id may have been in tail of buffer */
2083       newpos += MAX (GST_BUFFER_SIZE (buf), 4) - 3;
2084       gst_buffer_unref (buf);
2085       buf = NULL;
2086     }
2087   }
2088
2089   if (buf) {
2090     gst_buffer_unref (buf);
2091     buf = NULL;
2092   }
2093
2094   parse->offset = orig_offset;
2095   *pos = newpos;
2096   return ret;
2097 }
2098
2099
2100 static gboolean
2101 gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse,
2102     GstPad * pad, GstEvent * event)
2103 {
2104   GstMatroskaIndex *entry = NULL;
2105   GstSeekFlags flags;
2106   GstSeekType cur_type, stop_type;
2107   GstFormat format;
2108   gdouble rate;
2109   gint64 cur, stop;
2110   GstMatroskaTrackContext *track = NULL;
2111   GstSegment seeksegment = { 0, };
2112   gboolean update;
2113
2114   if (pad)
2115     track = gst_pad_get_element_private (pad);
2116
2117   track = gst_matroska_parse_get_seek_track (parse, track);
2118
2119   gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
2120       &stop_type, &stop);
2121
2122   /* we can only seek on time */
2123   if (format != GST_FORMAT_TIME) {
2124     GST_DEBUG_OBJECT (parse, "Can only seek on TIME");
2125     return FALSE;
2126   }
2127
2128   /* copy segment, we need this because we still need the old
2129    * segment when we close the current segment. */
2130   memcpy (&seeksegment, &parse->segment, sizeof (GstSegment));
2131
2132   if (event) {
2133     GST_DEBUG_OBJECT (parse, "configuring seek");
2134     gst_segment_set_seek (&seeksegment, rate, format, flags,
2135         cur_type, cur, stop_type, stop, &update);
2136   }
2137
2138   GST_DEBUG_OBJECT (parse, "New segment %" GST_SEGMENT_FORMAT, &seeksegment);
2139
2140   /* check sanity before we start flushing and all that */
2141   GST_OBJECT_LOCK (parse);
2142   if ((entry = gst_matroskaparse_do_index_seek (parse, track,
2143               seeksegment.last_stop, &parse->seek_index, &parse->seek_entry)) ==
2144       NULL) {
2145     /* pull mode without index can scan later on */
2146     GST_DEBUG_OBJECT (parse, "No matching seek entry in index");
2147     GST_OBJECT_UNLOCK (parse);
2148     return FALSE;
2149   }
2150   GST_DEBUG_OBJECT (parse, "Seek position looks sane");
2151   GST_OBJECT_UNLOCK (parse);
2152
2153   /* need to seek to cluster start to pick up cluster time */
2154   /* upstream takes care of flushing and all that
2155    * ... and newsegment event handling takes care of the rest */
2156   return perform_seek_to_offset (parse, entry->pos + parse->ebml_segment_start);
2157 }
2158
2159 /*
2160  * Handle whether we can perform the seek event or if we have to let the chain
2161  * function handle seeks to build the seek indexes first.
2162  */
2163 static gboolean
2164 gst_matroska_parse_handle_seek_push (GstMatroskaParse * parse, GstPad * pad,
2165     GstEvent * event)
2166 {
2167   GstSeekFlags flags;
2168   GstSeekType cur_type, stop_type;
2169   GstFormat format;
2170   gdouble rate;
2171   gint64 cur, stop;
2172
2173   gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
2174       &stop_type, &stop);
2175
2176   /* sanity checks */
2177
2178   /* we can only seek on time */
2179   if (format != GST_FORMAT_TIME) {
2180     GST_DEBUG_OBJECT (parse, "Can only seek on TIME");
2181     return FALSE;
2182   }
2183
2184   if (stop_type != GST_SEEK_TYPE_NONE && stop != GST_CLOCK_TIME_NONE) {
2185     GST_DEBUG_OBJECT (parse, "Seek end-time not supported in streaming mode");
2186     return FALSE;
2187   }
2188
2189   if (!(flags & GST_SEEK_FLAG_FLUSH)) {
2190     GST_DEBUG_OBJECT (parse,
2191         "Non-flushing seek not supported in streaming mode");
2192     return FALSE;
2193   }
2194
2195   if (flags & GST_SEEK_FLAG_SEGMENT) {
2196     GST_DEBUG_OBJECT (parse, "Segment seek not supported in streaming mode");
2197     return FALSE;
2198   }
2199
2200   /* check for having parsed index already */
2201   if (!parse->index_parsed) {
2202     gboolean building_index;
2203     guint64 offset = 0;
2204
2205     if (!parse->index_offset) {
2206       GST_DEBUG_OBJECT (parse, "no index (location); no seek in push mode");
2207       return FALSE;
2208     }
2209
2210     GST_OBJECT_LOCK (parse);
2211     /* handle the seek event in the chain function */
2212     parse->state = GST_MATROSKA_PARSE_STATE_SEEK;
2213     /* no more seek can be issued until state reset to _DATA */
2214
2215     /* copy the event */
2216     if (parse->seek_event)
2217       gst_event_unref (parse->seek_event);
2218     parse->seek_event = gst_event_ref (event);
2219
2220     /* set the building_index flag so that only one thread can setup the
2221      * structures for index seeking. */
2222     building_index = parse->building_index;
2223     if (!building_index) {
2224       parse->building_index = TRUE;
2225       offset = parse->index_offset;
2226     }
2227     GST_OBJECT_UNLOCK (parse);
2228
2229     if (!building_index) {
2230       /* seek to the first subindex or legacy index */
2231       GST_INFO_OBJECT (parse, "Seeking to Cues at %" G_GUINT64_FORMAT, offset);
2232       return perform_seek_to_offset (parse, offset);
2233     }
2234
2235     /* well, we are handling it already */
2236     return TRUE;
2237   }
2238
2239   /* delegate to tweaked regular seek */
2240   return gst_matroska_parse_handle_seek_event (parse, pad, event);
2241 }
2242
2243 static gboolean
2244 gst_matroska_parse_handle_src_event (GstPad * pad, GstEvent * event)
2245 {
2246   GstMatroskaParse *parse = GST_MATROSKA_PARSE (gst_pad_get_parent (pad));
2247   gboolean res = TRUE;
2248
2249   switch (GST_EVENT_TYPE (event)) {
2250     case GST_EVENT_SEEK:
2251       /* no seeking until we are (safely) ready */
2252       if (parse->state != GST_MATROSKA_PARSE_STATE_DATA) {
2253         GST_DEBUG_OBJECT (parse, "not ready for seeking yet");
2254         return FALSE;
2255       }
2256       res = gst_matroska_parse_handle_seek_push (parse, pad, event);
2257       gst_event_unref (event);
2258       break;
2259
2260     case GST_EVENT_QOS:
2261     {
2262       GstMatroskaTrackContext *context = gst_pad_get_element_private (pad);
2263       if (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO) {
2264         GstMatroskaTrackVideoContext *videocontext =
2265             (GstMatroskaTrackVideoContext *) context;
2266         gdouble proportion;
2267         GstClockTimeDiff diff;
2268         GstClockTime timestamp;
2269
2270         gst_event_parse_qos (event, &proportion, &diff, &timestamp);
2271
2272         GST_OBJECT_LOCK (parse);
2273         videocontext->earliest_time = timestamp + diff;
2274         GST_OBJECT_UNLOCK (parse);
2275       }
2276       res = TRUE;
2277       gst_event_unref (event);
2278       break;
2279     }
2280
2281       /* events we don't need to handle */
2282     case GST_EVENT_NAVIGATION:
2283       gst_event_unref (event);
2284       res = FALSE;
2285       break;
2286
2287     case GST_EVENT_LATENCY:
2288     default:
2289       res = gst_pad_push_event (parse->sinkpad, event);
2290       break;
2291   }
2292
2293   gst_object_unref (parse);
2294
2295   return res;
2296 }
2297
2298
2299 /* skip unknown or alike element */
2300 static GstFlowReturn
2301 gst_matroska_parse_parse_skip (GstMatroskaParse * parse, GstEbmlRead * ebml,
2302     const gchar * parent_name, guint id)
2303 {
2304   if (id == GST_EBML_ID_VOID) {
2305     GST_DEBUG_OBJECT (parse, "Skipping EBML Void element");
2306   } else if (id == GST_EBML_ID_CRC32) {
2307     GST_DEBUG_OBJECT (parse, "Skipping EBML CRC32 element");
2308   } else {
2309     GST_WARNING_OBJECT (parse,
2310         "Unknown %s subelement 0x%x - ignoring", parent_name, id);
2311   }
2312
2313   return gst_ebml_read_skip (ebml);
2314 }
2315
2316 static GstFlowReturn
2317 gst_matroska_parse_parse_header (GstMatroskaParse * parse, GstEbmlRead * ebml)
2318 {
2319   GstFlowReturn ret;
2320   gchar *doctype;
2321   guint version;
2322   guint32 id;
2323
2324   /* this function is the first to be called */
2325
2326   /* default init */
2327   doctype = NULL;
2328   version = 1;
2329
2330   ret = gst_ebml_peek_id (ebml, &id);
2331   if (ret != GST_FLOW_OK)
2332     return ret;
2333
2334   GST_DEBUG_OBJECT (parse, "id: %08x", id);
2335
2336   if (id != GST_EBML_ID_HEADER) {
2337     GST_ERROR_OBJECT (parse, "Failed to read header");
2338     goto exit;
2339   }
2340
2341   ret = gst_ebml_read_master (ebml, &id);
2342   if (ret != GST_FLOW_OK)
2343     return ret;
2344
2345   while (gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2346     ret = gst_ebml_peek_id (ebml, &id);
2347     if (ret != GST_FLOW_OK)
2348       return ret;
2349
2350     switch (id) {
2351         /* is our read version uptodate? */
2352       case GST_EBML_ID_EBMLREADVERSION:{
2353         guint64 num;
2354
2355         ret = gst_ebml_read_uint (ebml, &id, &num);
2356         if (ret != GST_FLOW_OK)
2357           return ret;
2358         if (num != GST_EBML_VERSION) {
2359           GST_ERROR_OBJECT (ebml, "Unsupported EBML version %" G_GUINT64_FORMAT,
2360               num);
2361           return GST_FLOW_ERROR;
2362         }
2363
2364         GST_DEBUG_OBJECT (ebml, "EbmlReadVersion: %" G_GUINT64_FORMAT, num);
2365         break;
2366       }
2367
2368         /* we only handle 8 byte lengths at max */
2369       case GST_EBML_ID_EBMLMAXSIZELENGTH:{
2370         guint64 num;
2371
2372         ret = gst_ebml_read_uint (ebml, &id, &num);
2373         if (ret != GST_FLOW_OK)
2374           return ret;
2375         if (num > sizeof (guint64)) {
2376           GST_ERROR_OBJECT (ebml,
2377               "Unsupported EBML maximum size %" G_GUINT64_FORMAT, num);
2378           return GST_FLOW_ERROR;
2379         }
2380         GST_DEBUG_OBJECT (ebml, "EbmlMaxSizeLength: %" G_GUINT64_FORMAT, num);
2381         break;
2382       }
2383
2384         /* we handle 4 byte IDs at max */
2385       case GST_EBML_ID_EBMLMAXIDLENGTH:{
2386         guint64 num;
2387
2388         ret = gst_ebml_read_uint (ebml, &id, &num);
2389         if (ret != GST_FLOW_OK)
2390           return ret;
2391         if (num > sizeof (guint32)) {
2392           GST_ERROR_OBJECT (ebml,
2393               "Unsupported EBML maximum ID %" G_GUINT64_FORMAT, num);
2394           return GST_FLOW_ERROR;
2395         }
2396         GST_DEBUG_OBJECT (ebml, "EbmlMaxIdLength: %" G_GUINT64_FORMAT, num);
2397         break;
2398       }
2399
2400       case GST_EBML_ID_DOCTYPE:{
2401         gchar *text;
2402
2403         ret = gst_ebml_read_ascii (ebml, &id, &text);
2404         if (ret != GST_FLOW_OK)
2405           return ret;
2406
2407         GST_DEBUG_OBJECT (ebml, "EbmlDocType: %s", GST_STR_NULL (text));
2408
2409         if (doctype)
2410           g_free (doctype);
2411         doctype = text;
2412         break;
2413       }
2414
2415       case GST_EBML_ID_DOCTYPEREADVERSION:{
2416         guint64 num;
2417
2418         ret = gst_ebml_read_uint (ebml, &id, &num);
2419         if (ret != GST_FLOW_OK)
2420           return ret;
2421         version = num;
2422         GST_DEBUG_OBJECT (ebml, "EbmlReadVersion: %" G_GUINT64_FORMAT, num);
2423         break;
2424       }
2425
2426       default:
2427         ret = gst_matroska_parse_parse_skip (parse, ebml, "EBML header", id);
2428         if (ret != GST_FLOW_OK)
2429           return ret;
2430         break;
2431
2432         /* we ignore these two, as they don't tell us anything we care about */
2433       case GST_EBML_ID_EBMLVERSION:
2434       case GST_EBML_ID_DOCTYPEVERSION:
2435         ret = gst_ebml_read_skip (ebml);
2436         if (ret != GST_FLOW_OK)
2437           return ret;
2438         break;
2439     }
2440   }
2441
2442 exit:
2443
2444   if ((doctype != NULL && !strcmp (doctype, GST_MATROSKA_DOCTYPE_MATROSKA)) ||
2445       (doctype != NULL && !strcmp (doctype, GST_MATROSKA_DOCTYPE_WEBM)) ||
2446       (doctype == NULL)) {
2447     if (version <= 2) {
2448       if (doctype) {
2449         GST_INFO_OBJECT (parse, "Input is %s version %d", doctype, version);
2450       } else {
2451         GST_WARNING_OBJECT (parse, "Input is EBML without doctype, assuming "
2452             "matroska (version %d)", version);
2453       }
2454       ret = GST_FLOW_OK;
2455     } else {
2456       GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
2457           ("Parser version (2) is too old to read %s version %d",
2458               GST_STR_NULL (doctype), version));
2459       ret = GST_FLOW_ERROR;
2460     }
2461     g_free (doctype);
2462   } else {
2463     GST_ELEMENT_ERROR (parse, STREAM, WRONG_TYPE, (NULL),
2464         ("Input is not a matroska stream (doctype=%s)", doctype));
2465     ret = GST_FLOW_ERROR;
2466     g_free (doctype);
2467   }
2468
2469   return ret;
2470 }
2471
2472 static GstFlowReturn
2473 gst_matroska_parse_parse_tracks (GstMatroskaParse * parse, GstEbmlRead * ebml)
2474 {
2475   GstFlowReturn ret = GST_FLOW_OK;
2476   guint32 id;
2477
2478   DEBUG_ELEMENT_START (parse, ebml, "Tracks");
2479
2480   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2481     DEBUG_ELEMENT_STOP (parse, ebml, "Tracks", ret);
2482     return ret;
2483   }
2484
2485   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2486     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2487       break;
2488
2489     switch (id) {
2490         /* one track within the "all-tracks" header */
2491       case GST_MATROSKA_ID_TRACKENTRY:
2492         ret = gst_matroska_parse_add_stream (parse, ebml);
2493         break;
2494
2495       default:
2496         ret = gst_matroska_parse_parse_skip (parse, ebml, "Track", id);
2497         break;
2498     }
2499   }
2500   DEBUG_ELEMENT_STOP (parse, ebml, "Tracks", ret);
2501
2502   parse->tracks_parsed = TRUE;
2503
2504   return ret;
2505 }
2506
2507 static GstFlowReturn
2508 gst_matroska_parse_parse_index_cuetrack (GstMatroskaParse * parse,
2509     GstEbmlRead * ebml, guint * nentries)
2510 {
2511   guint32 id;
2512   GstFlowReturn ret;
2513   GstMatroskaIndex idx;
2514
2515   idx.pos = (guint64) - 1;
2516   idx.track = 0;
2517   idx.time = GST_CLOCK_TIME_NONE;
2518   idx.block = 1;
2519
2520   DEBUG_ELEMENT_START (parse, ebml, "CueTrackPositions");
2521
2522   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2523     DEBUG_ELEMENT_STOP (parse, ebml, "CueTrackPositions", ret);
2524     return ret;
2525   }
2526
2527   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2528     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2529       break;
2530
2531     switch (id) {
2532         /* track number */
2533       case GST_MATROSKA_ID_CUETRACK:
2534       {
2535         guint64 num;
2536
2537         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2538           break;
2539
2540         if (num == 0) {
2541           idx.track = 0;
2542           GST_WARNING_OBJECT (parse, "Invalid CueTrack 0");
2543           break;
2544         }
2545
2546         GST_DEBUG_OBJECT (parse, "CueTrack: %" G_GUINT64_FORMAT, num);
2547         idx.track = num;
2548         break;
2549       }
2550
2551         /* position in file */
2552       case GST_MATROSKA_ID_CUECLUSTERPOSITION:
2553       {
2554         guint64 num;
2555
2556         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2557           break;
2558
2559         if (num > G_MAXINT64) {
2560           GST_WARNING_OBJECT (parse, "CueClusterPosition %" G_GUINT64_FORMAT
2561               " too large", num);
2562           break;
2563         }
2564
2565         idx.pos = num;
2566         break;
2567       }
2568
2569         /* number of block in the cluster */
2570       case GST_MATROSKA_ID_CUEBLOCKNUMBER:
2571       {
2572         guint64 num;
2573
2574         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2575           break;
2576
2577         if (num == 0) {
2578           GST_WARNING_OBJECT (parse, "Invalid CueBlockNumber 0");
2579           break;
2580         }
2581
2582         GST_DEBUG_OBJECT (parse, "CueBlockNumber: %" G_GUINT64_FORMAT, num);
2583         idx.block = num;
2584
2585         /* mild sanity check, disregard strange cases ... */
2586         if (idx.block > G_MAXUINT16) {
2587           GST_DEBUG_OBJECT (parse, "... looks suspicious, ignoring");
2588           idx.block = 1;
2589         }
2590         break;
2591       }
2592
2593       default:
2594         ret = gst_matroska_parse_parse_skip (parse, ebml, "CueTrackPositions",
2595             id);
2596         break;
2597
2598       case GST_MATROSKA_ID_CUECODECSTATE:
2599       case GST_MATROSKA_ID_CUEREFERENCE:
2600         ret = gst_ebml_read_skip (ebml);
2601         break;
2602     }
2603   }
2604
2605   DEBUG_ELEMENT_STOP (parse, ebml, "CueTrackPositions", ret);
2606
2607   if ((ret == GST_FLOW_OK || ret == GST_FLOW_UNEXPECTED)
2608       && idx.pos != (guint64) - 1 && idx.track > 0) {
2609     g_array_append_val (parse->index, idx);
2610     (*nentries)++;
2611   } else if (ret == GST_FLOW_OK || ret == GST_FLOW_UNEXPECTED) {
2612     GST_DEBUG_OBJECT (parse, "CueTrackPositions without valid content");
2613   }
2614
2615   return ret;
2616 }
2617
2618 static GstFlowReturn
2619 gst_matroska_parse_parse_index_pointentry (GstMatroskaParse * parse,
2620     GstEbmlRead * ebml)
2621 {
2622   guint32 id;
2623   GstFlowReturn ret;
2624   GstClockTime time = GST_CLOCK_TIME_NONE;
2625   guint nentries = 0;
2626
2627   DEBUG_ELEMENT_START (parse, ebml, "CuePoint");
2628
2629   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2630     DEBUG_ELEMENT_STOP (parse, ebml, "CuePoint", ret);
2631     return ret;
2632   }
2633
2634   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2635     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2636       break;
2637
2638     switch (id) {
2639         /* one single index entry ('point') */
2640       case GST_MATROSKA_ID_CUETIME:
2641       {
2642         if ((ret = gst_ebml_read_uint (ebml, &id, &time)) != GST_FLOW_OK)
2643           break;
2644
2645         GST_DEBUG_OBJECT (parse, "CueTime: %" G_GUINT64_FORMAT, time);
2646         time = time * parse->time_scale;
2647         break;
2648       }
2649
2650         /* position in the file + track to which it belongs */
2651       case GST_MATROSKA_ID_CUETRACKPOSITIONS:
2652       {
2653         if ((ret =
2654                 gst_matroska_parse_parse_index_cuetrack (parse, ebml,
2655                     &nentries)) != GST_FLOW_OK)
2656           break;
2657         break;
2658       }
2659
2660       default:
2661         ret = gst_matroska_parse_parse_skip (parse, ebml, "CuePoint", id);
2662         break;
2663     }
2664   }
2665
2666   DEBUG_ELEMENT_STOP (parse, ebml, "CuePoint", ret);
2667
2668   if (nentries > 0) {
2669     if (time == GST_CLOCK_TIME_NONE) {
2670       GST_WARNING_OBJECT (parse, "CuePoint without valid time");
2671       g_array_remove_range (parse->index, parse->index->len - nentries,
2672           nentries);
2673     } else {
2674       gint i;
2675
2676       for (i = parse->index->len - nentries; i < parse->index->len; i++) {
2677         GstMatroskaIndex *idx =
2678             &g_array_index (parse->index, GstMatroskaIndex, i);
2679
2680         idx->time = time;
2681         GST_DEBUG_OBJECT (parse, "Index entry: pos=%" G_GUINT64_FORMAT
2682             ", time=%" GST_TIME_FORMAT ", track=%u, block=%u", idx->pos,
2683             GST_TIME_ARGS (idx->time), (guint) idx->track, (guint) idx->block);
2684       }
2685     }
2686   } else {
2687     GST_DEBUG_OBJECT (parse, "Empty CuePoint");
2688   }
2689
2690   return ret;
2691 }
2692
2693 static gint
2694 gst_matroska_index_compare (GstMatroskaIndex * i1, GstMatroskaIndex * i2)
2695 {
2696   if (i1->time < i2->time)
2697     return -1;
2698   else if (i1->time > i2->time)
2699     return 1;
2700   else if (i1->block < i2->block)
2701     return -1;
2702   else if (i1->block > i2->block)
2703     return 1;
2704   else
2705     return 0;
2706 }
2707
2708 static GstFlowReturn
2709 gst_matroska_parse_parse_index (GstMatroskaParse * parse, GstEbmlRead * ebml)
2710 {
2711   guint32 id;
2712   GstFlowReturn ret = GST_FLOW_OK;
2713   guint i;
2714
2715   if (parse->index)
2716     g_array_free (parse->index, TRUE);
2717   parse->index =
2718       g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaIndex), 128);
2719
2720   DEBUG_ELEMENT_START (parse, ebml, "Cues");
2721
2722   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2723     DEBUG_ELEMENT_STOP (parse, ebml, "Cues", ret);
2724     return ret;
2725   }
2726
2727   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2728     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2729       break;
2730
2731     switch (id) {
2732         /* one single index entry ('point') */
2733       case GST_MATROSKA_ID_POINTENTRY:
2734         ret = gst_matroska_parse_parse_index_pointentry (parse, ebml);
2735         break;
2736
2737       default:
2738         ret = gst_matroska_parse_parse_skip (parse, ebml, "Cues", id);
2739         break;
2740     }
2741   }
2742   DEBUG_ELEMENT_STOP (parse, ebml, "Cues", ret);
2743
2744   /* Sort index by time, smallest time first, for easier searching */
2745   g_array_sort (parse->index, (GCompareFunc) gst_matroska_index_compare);
2746
2747   /* Now sort the track specific index entries into their own arrays */
2748   for (i = 0; i < parse->index->len; i++) {
2749     GstMatroskaIndex *idx = &g_array_index (parse->index, GstMatroskaIndex, i);
2750     gint track_num;
2751     GstMatroskaTrackContext *ctx;
2752
2753     if (parse->element_index) {
2754       gint writer_id;
2755
2756       if (idx->track != 0 &&
2757           (track_num =
2758               gst_matroska_parse_stream_from_num (parse, idx->track)) != -1) {
2759         ctx = g_ptr_array_index (parse->src, track_num);
2760
2761         if (ctx->index_writer_id == -1)
2762           gst_index_get_writer_id (parse->element_index, GST_OBJECT (ctx->pad),
2763               &ctx->index_writer_id);
2764         writer_id = ctx->index_writer_id;
2765       } else {
2766         if (parse->element_index_writer_id == -1)
2767           gst_index_get_writer_id (parse->element_index, GST_OBJECT (parse),
2768               &parse->element_index_writer_id);
2769         writer_id = parse->element_index_writer_id;
2770       }
2771
2772       GST_LOG_OBJECT (parse, "adding association %" GST_TIME_FORMAT "-> %"
2773           G_GUINT64_FORMAT " for writer id %d", GST_TIME_ARGS (idx->time),
2774           idx->pos, writer_id);
2775       gst_index_add_association (parse->element_index, writer_id,
2776           GST_ASSOCIATION_FLAG_KEY_UNIT, GST_FORMAT_TIME, idx->time,
2777           GST_FORMAT_BYTES, idx->pos + parse->ebml_segment_start, NULL);
2778     }
2779
2780     if (idx->track == 0)
2781       continue;
2782
2783     track_num = gst_matroska_parse_stream_from_num (parse, idx->track);
2784     if (track_num == -1)
2785       continue;
2786
2787     ctx = g_ptr_array_index (parse->src, track_num);
2788
2789     if (ctx->index_table == NULL)
2790       ctx->index_table =
2791           g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaIndex), 128);
2792
2793     g_array_append_vals (ctx->index_table, idx, 1);
2794   }
2795
2796   parse->index_parsed = TRUE;
2797
2798   /* sanity check; empty index normalizes to no index */
2799   if (parse->index->len == 0) {
2800     g_array_free (parse->index, TRUE);
2801     parse->index = NULL;
2802   }
2803
2804   return ret;
2805 }
2806
2807 static GstFlowReturn
2808 gst_matroska_parse_parse_info (GstMatroskaParse * parse, GstEbmlRead * ebml)
2809 {
2810   GstFlowReturn ret = GST_FLOW_OK;
2811   guint32 id;
2812
2813   DEBUG_ELEMENT_START (parse, ebml, "SegmentInfo");
2814
2815   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2816     DEBUG_ELEMENT_STOP (parse, ebml, "SegmentInfo", ret);
2817     return ret;
2818   }
2819
2820   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2821     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2822       break;
2823
2824     switch (id) {
2825         /* cluster timecode */
2826       case GST_MATROSKA_ID_TIMECODESCALE:{
2827         guint64 num;
2828
2829         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2830           break;
2831
2832
2833         GST_DEBUG_OBJECT (parse, "TimeCodeScale: %" G_GUINT64_FORMAT, num);
2834         parse->time_scale = num;
2835         break;
2836       }
2837
2838       case GST_MATROSKA_ID_DURATION:{
2839         gdouble num;
2840         GstClockTime dur;
2841
2842         if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
2843           break;
2844
2845         if (num <= 0.0) {
2846           GST_WARNING_OBJECT (parse, "Invalid duration %lf", num);
2847           break;
2848         }
2849
2850         GST_DEBUG_OBJECT (parse, "Duration: %lf", num);
2851
2852         dur = gst_gdouble_to_guint64 (num *
2853             gst_guint64_to_gdouble (parse->time_scale));
2854         if (GST_CLOCK_TIME_IS_VALID (dur) && dur <= G_MAXINT64)
2855           gst_segment_set_duration (&parse->segment, GST_FORMAT_TIME, dur);
2856         break;
2857       }
2858
2859       case GST_MATROSKA_ID_WRITINGAPP:{
2860         gchar *text;
2861
2862         if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
2863           break;
2864
2865         GST_DEBUG_OBJECT (parse, "WritingApp: %s", GST_STR_NULL (text));
2866         parse->writing_app = text;
2867         break;
2868       }
2869
2870       case GST_MATROSKA_ID_MUXINGAPP:{
2871         gchar *text;
2872
2873         if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
2874           break;
2875
2876         GST_DEBUG_OBJECT (parse, "MuxingApp: %s", GST_STR_NULL (text));
2877         parse->muxing_app = text;
2878         break;
2879       }
2880
2881       case GST_MATROSKA_ID_DATEUTC:{
2882         gint64 time;
2883
2884         if ((ret = gst_ebml_read_date (ebml, &id, &time)) != GST_FLOW_OK)
2885           break;
2886
2887         GST_DEBUG_OBJECT (parse, "DateUTC: %" G_GINT64_FORMAT, time);
2888         parse->created = time;
2889         break;
2890       }
2891
2892       case GST_MATROSKA_ID_TITLE:{
2893         gchar *text;
2894         GstTagList *taglist;
2895
2896         if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
2897           break;
2898
2899         GST_DEBUG_OBJECT (parse, "Title: %s", GST_STR_NULL (text));
2900         taglist = gst_tag_list_new ();
2901         gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, text,
2902             NULL);
2903         gst_matroska_parse_found_global_tag (parse, taglist);
2904         g_free (text);
2905         break;
2906       }
2907
2908       default:
2909         ret = gst_matroska_parse_parse_skip (parse, ebml, "SegmentInfo", id);
2910         break;
2911
2912         /* fall through */
2913       case GST_MATROSKA_ID_SEGMENTUID:
2914       case GST_MATROSKA_ID_SEGMENTFILENAME:
2915       case GST_MATROSKA_ID_PREVUID:
2916       case GST_MATROSKA_ID_PREVFILENAME:
2917       case GST_MATROSKA_ID_NEXTUID:
2918       case GST_MATROSKA_ID_NEXTFILENAME:
2919       case GST_MATROSKA_ID_SEGMENTFAMILY:
2920       case GST_MATROSKA_ID_CHAPTERTRANSLATE:
2921         ret = gst_ebml_read_skip (ebml);
2922         break;
2923     }
2924   }
2925
2926   DEBUG_ELEMENT_STOP (parse, ebml, "SegmentInfo", ret);
2927
2928   parse->segmentinfo_parsed = TRUE;
2929
2930   return ret;
2931 }
2932
2933 static GstFlowReturn
2934 gst_matroska_parse_parse_metadata_id_simple_tag (GstMatroskaParse * parse,
2935     GstEbmlRead * ebml, GstTagList ** p_taglist)
2936 {
2937   /* FIXME: check if there are more useful mappings */
2938   struct
2939   {
2940     const gchar *matroska_tagname;
2941     const gchar *gstreamer_tagname;
2942   }
2943   tag_conv[] = {
2944     {
2945     GST_MATROSKA_TAG_ID_TITLE, GST_TAG_TITLE}, {
2946     GST_MATROSKA_TAG_ID_AUTHOR, GST_TAG_ARTIST}, {
2947     GST_MATROSKA_TAG_ID_ALBUM, GST_TAG_ALBUM}, {
2948     GST_MATROSKA_TAG_ID_COMMENTS, GST_TAG_COMMENT}, {
2949     GST_MATROSKA_TAG_ID_BITSPS, GST_TAG_BITRATE}, {
2950     GST_MATROSKA_TAG_ID_BPS, GST_TAG_BITRATE}, {
2951     GST_MATROSKA_TAG_ID_ENCODER, GST_TAG_ENCODER}, {
2952     GST_MATROSKA_TAG_ID_DATE, GST_TAG_DATE}, {
2953     GST_MATROSKA_TAG_ID_ISRC, GST_TAG_ISRC}, {
2954     GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}, {
2955     GST_MATROSKA_TAG_ID_BPM, GST_TAG_BEATS_PER_MINUTE}, {
2956     GST_MATROSKA_TAG_ID_TERMS_OF_USE, GST_TAG_LICENSE}, {
2957     GST_MATROSKA_TAG_ID_COMPOSER, GST_TAG_COMPOSER}, {
2958     GST_MATROSKA_TAG_ID_LEAD_PERFORMER, GST_TAG_PERFORMER}, {
2959     GST_MATROSKA_TAG_ID_GENRE, GST_TAG_GENRE}
2960   };
2961   GstFlowReturn ret;
2962   guint32 id;
2963   gchar *value = NULL;
2964   gchar *tag = NULL;
2965
2966   DEBUG_ELEMENT_START (parse, ebml, "SimpleTag");
2967
2968   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2969     DEBUG_ELEMENT_STOP (parse, ebml, "SimpleTag", ret);
2970     return ret;
2971   }
2972
2973   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2974     /* read all sub-entries */
2975
2976     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2977       break;
2978
2979     switch (id) {
2980       case GST_MATROSKA_ID_TAGNAME:
2981         g_free (tag);
2982         tag = NULL;
2983         ret = gst_ebml_read_ascii (ebml, &id, &tag);
2984         GST_DEBUG_OBJECT (parse, "TagName: %s", GST_STR_NULL (tag));
2985         break;
2986
2987       case GST_MATROSKA_ID_TAGSTRING:
2988         g_free (value);
2989         value = NULL;
2990         ret = gst_ebml_read_utf8 (ebml, &id, &value);
2991         GST_DEBUG_OBJECT (parse, "TagString: %s", GST_STR_NULL (value));
2992         break;
2993
2994       default:
2995         ret = gst_matroska_parse_parse_skip (parse, ebml, "SimpleTag", id);
2996         break;
2997         /* fall-through */
2998
2999       case GST_MATROSKA_ID_TAGLANGUAGE:
3000       case GST_MATROSKA_ID_TAGDEFAULT:
3001       case GST_MATROSKA_ID_TAGBINARY:
3002         ret = gst_ebml_read_skip (ebml);
3003         break;
3004     }
3005   }
3006
3007   DEBUG_ELEMENT_STOP (parse, ebml, "SimpleTag", ret);
3008
3009   if (tag && value) {
3010     guint i;
3011
3012     for (i = 0; i < G_N_ELEMENTS (tag_conv); i++) {
3013       const gchar *tagname_gst = tag_conv[i].gstreamer_tagname;
3014
3015       const gchar *tagname_mkv = tag_conv[i].matroska_tagname;
3016
3017       if (strcmp (tagname_mkv, tag) == 0) {
3018         GValue dest = { 0, };
3019         GType dest_type = gst_tag_get_type (tagname_gst);
3020
3021         /* Ensure that any date string is complete */
3022         if (dest_type == GST_TYPE_DATE) {
3023           guint year = 1901, month = 1, day = 1;
3024
3025           /* Dates can be yyyy-MM-dd, yyyy-MM or yyyy, but we need
3026            * the first type */
3027           if (sscanf (value, "%04u-%02u-%02u", &year, &month, &day) != 0) {
3028             g_free (value);
3029             value = g_strdup_printf ("%04u-%02u-%02u", year, month, day);
3030           }
3031         }
3032
3033         g_value_init (&dest, dest_type);
3034         if (gst_value_deserialize (&dest, value)) {
3035           gst_tag_list_add_values (*p_taglist, GST_TAG_MERGE_APPEND,
3036               tagname_gst, &dest, NULL);
3037         } else {
3038           GST_WARNING_OBJECT (parse, "Can't transform tag '%s' with "
3039               "value '%s' to target type '%s'", tag, value,
3040               g_type_name (dest_type));
3041         }
3042         g_value_unset (&dest);
3043         break;
3044       }
3045     }
3046   }
3047
3048   g_free (tag);
3049   g_free (value);
3050
3051   return ret;
3052 }
3053
3054 static GstFlowReturn
3055 gst_matroska_parse_parse_metadata_id_tag (GstMatroskaParse * parse,
3056     GstEbmlRead * ebml, GstTagList ** p_taglist)
3057 {
3058   guint32 id;
3059   GstFlowReturn ret;
3060
3061   DEBUG_ELEMENT_START (parse, ebml, "Tag");
3062
3063   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
3064     DEBUG_ELEMENT_STOP (parse, ebml, "Tag", ret);
3065     return ret;
3066   }
3067
3068   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
3069     /* read all sub-entries */
3070
3071     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
3072       break;
3073
3074     switch (id) {
3075       case GST_MATROSKA_ID_SIMPLETAG:
3076         ret = gst_matroska_parse_parse_metadata_id_simple_tag (parse, ebml,
3077             p_taglist);
3078         break;
3079
3080       default:
3081         ret = gst_matroska_parse_parse_skip (parse, ebml, "Tag", id);
3082         break;
3083     }
3084   }
3085
3086   DEBUG_ELEMENT_STOP (parse, ebml, "Tag", ret);
3087
3088   return ret;
3089 }
3090
3091 static GstFlowReturn
3092 gst_matroska_parse_parse_metadata (GstMatroskaParse * parse, GstEbmlRead * ebml)
3093 {
3094   GstTagList *taglist;
3095   GstFlowReturn ret = GST_FLOW_OK;
3096   guint32 id;
3097   GList *l;
3098   guint64 curpos;
3099
3100   curpos = gst_ebml_read_get_pos (ebml);
3101
3102   /* Make sure we don't parse a tags element twice and
3103    * post it's tags twice */
3104   curpos = gst_ebml_read_get_pos (ebml);
3105   for (l = parse->tags_parsed; l; l = l->next) {
3106     guint64 *pos = l->data;
3107
3108     if (*pos == curpos) {
3109       GST_DEBUG_OBJECT (parse, "Skipping already parsed Tags at offset %"
3110           G_GUINT64_FORMAT, curpos);
3111       return GST_FLOW_OK;
3112     }
3113   }
3114
3115   parse->tags_parsed =
3116       g_list_prepend (parse->tags_parsed, g_slice_new (guint64));
3117   *((guint64 *) parse->tags_parsed->data) = curpos;
3118   /* fall-through */
3119
3120   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
3121     DEBUG_ELEMENT_STOP (parse, ebml, "Tags", ret);
3122     return ret;
3123   }
3124
3125   taglist = gst_tag_list_new ();
3126
3127   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
3128     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
3129       break;
3130
3131     switch (id) {
3132       case GST_MATROSKA_ID_TAG:
3133         ret = gst_matroska_parse_parse_metadata_id_tag (parse, ebml, &taglist);
3134         break;
3135
3136       default:
3137         ret = gst_matroska_parse_parse_skip (parse, ebml, "Tags", id);
3138         break;
3139         /* FIXME: Use to limit the tags to specific pads */
3140       case GST_MATROSKA_ID_TARGETS:
3141         ret = gst_ebml_read_skip (ebml);
3142         break;
3143     }
3144   }
3145
3146   DEBUG_ELEMENT_STOP (parse, ebml, "Tags", ret);
3147
3148   gst_matroska_parse_found_global_tag (parse, taglist);
3149
3150   return ret;
3151 }
3152
3153 static GstFlowReturn
3154 gst_matroska_parse_parse_attached_file (GstMatroskaParse * parse,
3155     GstEbmlRead * ebml, GstTagList * taglist)
3156 {
3157   guint32 id;
3158   GstFlowReturn ret;
3159   gchar *description = NULL;
3160   gchar *filename = NULL;
3161   gchar *mimetype = NULL;
3162   guint8 *data = NULL;
3163   guint64 datalen = 0;
3164
3165   DEBUG_ELEMENT_START (parse, ebml, "AttachedFile");
3166
3167   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
3168     DEBUG_ELEMENT_STOP (parse, ebml, "AttachedFile", ret);
3169     return ret;
3170   }
3171
3172   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
3173     /* read all sub-entries */
3174
3175     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
3176       break;
3177
3178     switch (id) {
3179       case GST_MATROSKA_ID_FILEDESCRIPTION:
3180         if (description) {
3181           GST_WARNING_OBJECT (parse, "FileDescription can only appear once");
3182           break;
3183         }
3184
3185         ret = gst_ebml_read_utf8 (ebml, &id, &description);
3186         GST_DEBUG_OBJECT (parse, "FileDescription: %s",
3187             GST_STR_NULL (description));
3188         break;
3189       case GST_MATROSKA_ID_FILENAME:
3190         if (filename) {
3191           GST_WARNING_OBJECT (parse, "FileName can only appear once");
3192           break;
3193         }
3194
3195         ret = gst_ebml_read_utf8 (ebml, &id, &filename);
3196
3197         GST_DEBUG_OBJECT (parse, "FileName: %s", GST_STR_NULL (filename));
3198         break;
3199       case GST_MATROSKA_ID_FILEMIMETYPE:
3200         if (mimetype) {
3201           GST_WARNING_OBJECT (parse, "FileMimeType can only appear once");
3202           break;
3203         }
3204
3205         ret = gst_ebml_read_ascii (ebml, &id, &mimetype);
3206         GST_DEBUG_OBJECT (parse, "FileMimeType: %s", GST_STR_NULL (mimetype));
3207         break;
3208       case GST_MATROSKA_ID_FILEDATA:
3209         if (data) {
3210           GST_WARNING_OBJECT (parse, "FileData can only appear once");
3211           break;
3212         }
3213
3214         ret = gst_ebml_read_binary (ebml, &id, &data, &datalen);
3215         GST_DEBUG_OBJECT (parse, "FileData of size %" G_GUINT64_FORMAT,
3216             datalen);
3217         break;
3218
3219       default:
3220         ret = gst_matroska_parse_parse_skip (parse, ebml, "AttachedFile", id);
3221         break;
3222       case GST_MATROSKA_ID_FILEUID:
3223         ret = gst_ebml_read_skip (ebml);
3224         break;
3225     }
3226   }
3227
3228   DEBUG_ELEMENT_STOP (parse, ebml, "AttachedFile", ret);
3229
3230   if (filename && mimetype && data && datalen > 0) {
3231     GstTagImageType image_type = GST_TAG_IMAGE_TYPE_NONE;
3232     GstBuffer *tagbuffer = NULL;
3233     GstCaps *caps;
3234     gchar *filename_lc = g_utf8_strdown (filename, -1);
3235
3236     GST_DEBUG_OBJECT (parse, "Creating tag for attachment with filename '%s', "
3237         "mimetype '%s', description '%s', size %" G_GUINT64_FORMAT, filename,
3238         mimetype, GST_STR_NULL (description), datalen);
3239
3240     /* TODO: better heuristics for different image types */
3241     if (strstr (filename_lc, "cover")) {
3242       if (strstr (filename_lc, "back"))
3243         image_type = GST_TAG_IMAGE_TYPE_BACK_COVER;
3244       else
3245         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
3246     } else if (g_str_has_prefix (mimetype, "image/") ||
3247         g_str_has_suffix (filename_lc, "png") ||
3248         g_str_has_suffix (filename_lc, "jpg") ||
3249         g_str_has_suffix (filename_lc, "jpeg") ||
3250         g_str_has_suffix (filename_lc, "gif") ||
3251         g_str_has_suffix (filename_lc, "bmp")) {
3252       image_type = GST_TAG_IMAGE_TYPE_UNDEFINED;
3253     }
3254     g_free (filename_lc);
3255
3256     /* First try to create an image tag buffer from this */
3257     if (image_type != GST_TAG_IMAGE_TYPE_NONE) {
3258       tagbuffer =
3259           gst_tag_image_data_to_image_buffer (data, datalen, image_type);
3260
3261       if (!tagbuffer)
3262         image_type = GST_TAG_IMAGE_TYPE_NONE;
3263     }
3264
3265     /* if this failed create an attachment buffer */
3266     if (!tagbuffer) {
3267       tagbuffer = gst_buffer_new_and_alloc (datalen);
3268
3269       memcpy (GST_BUFFER_DATA (tagbuffer), data, datalen);
3270       GST_BUFFER_SIZE (tagbuffer) = datalen;
3271
3272       caps = gst_type_find_helper_for_buffer (NULL, tagbuffer, NULL);
3273       if (caps == NULL)
3274         caps = gst_caps_new_simple (mimetype, NULL);
3275       gst_buffer_set_caps (tagbuffer, caps);
3276       gst_caps_unref (caps);
3277     }
3278
3279     /* Set filename and description on the caps */
3280     caps = GST_BUFFER_CAPS (tagbuffer);
3281     gst_caps_set_simple (caps, "filename", G_TYPE_STRING, filename, NULL);
3282     if (description)
3283       gst_caps_set_simple (caps, "description", G_TYPE_STRING, description,
3284           NULL);
3285
3286     GST_DEBUG_OBJECT (parse,
3287         "Created attachment buffer with caps: %" GST_PTR_FORMAT, caps);
3288
3289     /* and append to the tag list */
3290     if (image_type != GST_TAG_IMAGE_TYPE_NONE)
3291       gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, tagbuffer,
3292           NULL);
3293     else
3294       gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_ATTACHMENT,
3295           tagbuffer, NULL);
3296   }
3297
3298   g_free (filename);
3299   g_free (mimetype);
3300   g_free (data);
3301   g_free (description);
3302
3303   return ret;
3304 }
3305
3306 static GstFlowReturn
3307 gst_matroska_parse_parse_attachments (GstMatroskaParse * parse,
3308     GstEbmlRead * ebml)
3309 {
3310   guint32 id;
3311   GstFlowReturn ret = GST_FLOW_OK;
3312   GstTagList *taglist;
3313
3314   DEBUG_ELEMENT_START (parse, ebml, "Attachments");
3315
3316   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
3317     DEBUG_ELEMENT_STOP (parse, ebml, "Attachments", ret);
3318     return ret;
3319   }
3320
3321   taglist = gst_tag_list_new ();
3322
3323   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
3324     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
3325       break;
3326
3327     switch (id) {
3328       case GST_MATROSKA_ID_ATTACHEDFILE:
3329         ret = gst_matroska_parse_parse_attached_file (parse, ebml, taglist);
3330         break;
3331
3332       default:
3333         ret = gst_matroska_parse_parse_skip (parse, ebml, "Attachments", id);
3334         break;
3335     }
3336   }
3337   DEBUG_ELEMENT_STOP (parse, ebml, "Attachments", ret);
3338
3339   if (gst_structure_n_fields (GST_STRUCTURE (taglist)) > 0) {
3340     GST_DEBUG_OBJECT (parse, "Storing attachment tags");
3341     gst_matroska_parse_found_global_tag (parse, taglist);
3342   } else {
3343     GST_DEBUG_OBJECT (parse, "No valid attachments found");
3344     gst_tag_list_free (taglist);
3345   }
3346
3347   parse->attachments_parsed = TRUE;
3348
3349   return ret;
3350 }
3351
3352 static GstFlowReturn
3353 gst_matroska_parse_parse_chapters (GstMatroskaParse * parse, GstEbmlRead * ebml)
3354 {
3355   guint32 id;
3356   GstFlowReturn ret = GST_FLOW_OK;
3357
3358   GST_WARNING_OBJECT (parse, "Parsing of chapters not implemented yet");
3359
3360   /* TODO: implement parsing of chapters */
3361
3362   DEBUG_ELEMENT_START (parse, ebml, "Chapters");
3363
3364   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
3365     DEBUG_ELEMENT_STOP (parse, ebml, "Chapters", ret);
3366     return ret;
3367   }
3368
3369   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
3370     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
3371       break;
3372
3373     switch (id) {
3374       default:
3375         ret = gst_ebml_read_skip (ebml);
3376         break;
3377     }
3378   }
3379
3380   DEBUG_ELEMENT_STOP (parse, ebml, "Chapters", ret);
3381   return ret;
3382 }
3383
3384 /*
3385  * Read signed/unsigned "EBML" numbers.
3386  * Return: number of bytes processed.
3387  */
3388
3389 static gint
3390 gst_matroska_ebmlnum_uint (guint8 * data, guint size, guint64 * num)
3391 {
3392   gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0;
3393   guint64 total;
3394
3395   if (size <= 0) {
3396     return -1;
3397   }
3398
3399   total = data[0];
3400   while (read <= 8 && !(total & len_mask)) {
3401     read++;
3402     len_mask >>= 1;
3403   }
3404   if (read > 8)
3405     return -1;
3406
3407   if ((total &= (len_mask - 1)) == len_mask - 1)
3408     num_ffs++;
3409   if (size < read)
3410     return -1;
3411   while (n < read) {
3412     if (data[n] == 0xff)
3413       num_ffs++;
3414     total = (total << 8) | data[n];
3415     n++;
3416   }
3417
3418   if (read == num_ffs && total != 0)
3419     *num = G_MAXUINT64;
3420   else
3421     *num = total;
3422
3423   return read;
3424 }
3425
3426 static gint
3427 gst_matroska_ebmlnum_sint (guint8 * data, guint size, gint64 * num)
3428 {
3429   guint64 unum;
3430   gint res;
3431
3432   /* read as unsigned number first */
3433   if ((res = gst_matroska_ebmlnum_uint (data, size, &unum)) < 0)
3434     return -1;
3435
3436   /* make signed */
3437   if (unum == G_MAXUINT64)
3438     *num = G_MAXINT64;
3439   else
3440     *num = unum - ((1 << ((7 * res) - 1)) - 1);
3441
3442   return res;
3443 }
3444
3445 static GstFlowReturn
3446 gst_matroska_parse_parse_blockgroup_or_simpleblock (GstMatroskaParse * parse,
3447     GstEbmlRead * ebml, guint64 cluster_time, guint64 cluster_offset,
3448     gboolean is_simpleblock)
3449 {
3450   GstMatroskaTrackContext *stream = NULL;
3451   GstFlowReturn ret = GST_FLOW_OK;
3452   gboolean readblock = FALSE;
3453   guint32 id;
3454   guint64 block_duration = 0;
3455   GstBuffer *buf = NULL;
3456   gint stream_num = -1, n, laces = 0;
3457   guint size = 0;
3458   gint *lace_size = NULL;
3459   gint64 time = 0;
3460   gint flags = 0;
3461   gint64 referenceblock = 0;
3462
3463   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
3464     if (!is_simpleblock) {
3465       if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) {
3466         goto data_error;
3467       }
3468     } else {
3469       id = GST_MATROSKA_ID_SIMPLEBLOCK;
3470     }
3471
3472     switch (id) {
3473         /* one block inside the group. Note, block parsing is one
3474          * of the harder things, so this code is a bit complicated.
3475          * See http://www.matroska.org/ for documentation. */
3476       case GST_MATROSKA_ID_SIMPLEBLOCK:
3477       case GST_MATROSKA_ID_BLOCK:
3478       {
3479         guint64 num;
3480         guint8 *data;
3481
3482         if (buf) {
3483           gst_buffer_unref (buf);
3484           buf = NULL;
3485         }
3486         if ((ret = gst_ebml_read_buffer (ebml, &id, &buf)) != GST_FLOW_OK)
3487           break;
3488
3489         data = GST_BUFFER_DATA (buf);
3490         size = GST_BUFFER_SIZE (buf);
3491
3492         /* first byte(s): blocknum */
3493         if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0)
3494           goto data_error;
3495         data += n;
3496         size -= n;
3497
3498         /* fetch stream from num */
3499         stream_num = gst_matroska_parse_stream_from_num (parse, num);
3500         if (G_UNLIKELY (size < 3)) {
3501           GST_WARNING_OBJECT (parse, "Invalid size %u", size);
3502           /* non-fatal, try next block(group) */
3503           ret = GST_FLOW_OK;
3504           goto done;
3505         } else if (G_UNLIKELY (stream_num < 0 ||
3506                 stream_num >= parse->num_streams)) {
3507           /* let's not give up on a stray invalid track number */
3508           GST_WARNING_OBJECT (parse,
3509               "Invalid stream %d for track number %" G_GUINT64_FORMAT
3510               "; ignoring block", stream_num, num);
3511           goto done;
3512         }
3513
3514         stream = g_ptr_array_index (parse->src, stream_num);
3515
3516         /* time (relative to cluster time) */
3517         time = ((gint16) GST_READ_UINT16_BE (data));
3518         data += 2;
3519         size -= 2;
3520         flags = GST_READ_UINT8 (data);
3521         data += 1;
3522         size -= 1;
3523
3524         GST_LOG_OBJECT (parse, "time %" G_GUINT64_FORMAT ", flags %d", time,
3525             flags);
3526
3527         switch ((flags & 0x06) >> 1) {
3528           case 0x0:            /* no lacing */
3529             laces = 1;
3530             lace_size = g_new (gint, 1);
3531             lace_size[0] = size;
3532             break;
3533
3534           case 0x1:            /* xiph lacing */
3535           case 0x2:            /* fixed-size lacing */
3536           case 0x3:            /* EBML lacing */
3537             if (size == 0)
3538               goto invalid_lacing;
3539             laces = GST_READ_UINT8 (data) + 1;
3540             data += 1;
3541             size -= 1;
3542             lace_size = g_new0 (gint, laces);
3543
3544             switch ((flags & 0x06) >> 1) {
3545               case 0x1:        /* xiph lacing */  {
3546                 guint temp, total = 0;
3547
3548                 for (n = 0; ret == GST_FLOW_OK && n < laces - 1; n++) {
3549                   while (1) {
3550                     if (size == 0)
3551                       goto invalid_lacing;
3552                     temp = GST_READ_UINT8 (data);
3553                     lace_size[n] += temp;
3554                     data += 1;
3555                     size -= 1;
3556                     if (temp != 0xff)
3557                       break;
3558                   }
3559                   total += lace_size[n];
3560                 }
3561                 lace_size[n] = size - total;
3562                 break;
3563               }
3564
3565               case 0x2:        /* fixed-size lacing */
3566                 for (n = 0; n < laces; n++)
3567                   lace_size[n] = size / laces;
3568                 break;
3569
3570               case 0x3:        /* EBML lacing */  {
3571                 guint total;
3572
3573                 if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0)
3574                   goto data_error;
3575                 data += n;
3576                 size -= n;
3577                 total = lace_size[0] = num;
3578                 for (n = 1; ret == GST_FLOW_OK && n < laces - 1; n++) {
3579                   gint64 snum;
3580                   gint r;
3581
3582                   if ((r = gst_matroska_ebmlnum_sint (data, size, &snum)) < 0)
3583                     goto data_error;
3584                   data += r;
3585                   size -= r;
3586                   lace_size[n] = lace_size[n - 1] + snum;
3587                   total += lace_size[n];
3588                 }
3589                 if (n < laces)
3590                   lace_size[n] = size - total;
3591                 break;
3592               }
3593             }
3594             break;
3595         }
3596
3597         if (ret != GST_FLOW_OK)
3598           break;
3599
3600         readblock = TRUE;
3601         break;
3602       }
3603
3604       case GST_MATROSKA_ID_BLOCKDURATION:{
3605         ret = gst_ebml_read_uint (ebml, &id, &block_duration);
3606         GST_DEBUG_OBJECT (parse, "BlockDuration: %" G_GUINT64_FORMAT,
3607             block_duration);
3608         break;
3609       }
3610
3611       case GST_MATROSKA_ID_REFERENCEBLOCK:{
3612         ret = gst_ebml_read_sint (ebml, &id, &referenceblock);
3613         GST_DEBUG_OBJECT (parse, "ReferenceBlock: %" G_GINT64_FORMAT,
3614             referenceblock);
3615         break;
3616       }
3617
3618       case GST_MATROSKA_ID_CODECSTATE:{
3619         guint8 *data;
3620         guint64 data_len = 0;
3621
3622         if ((ret =
3623                 gst_ebml_read_binary (ebml, &id, &data,
3624                     &data_len)) != GST_FLOW_OK)
3625           break;
3626
3627         if (G_UNLIKELY (stream == NULL)) {
3628           GST_WARNING_OBJECT (parse,
3629               "Unexpected CodecState subelement - ignoring");
3630           break;
3631         }
3632
3633         g_free (stream->codec_state);
3634         stream->codec_state = data;
3635         stream->codec_state_size = data_len;
3636
3637         break;
3638       }
3639
3640       default:
3641         ret = gst_matroska_parse_parse_skip (parse, ebml, "BlockGroup", id);
3642         break;
3643
3644       case GST_MATROSKA_ID_BLOCKVIRTUAL:
3645       case GST_MATROSKA_ID_BLOCKADDITIONS:
3646       case GST_MATROSKA_ID_REFERENCEPRIORITY:
3647       case GST_MATROSKA_ID_REFERENCEVIRTUAL:
3648       case GST_MATROSKA_ID_SLICES:
3649         GST_DEBUG_OBJECT (parse,
3650             "Skipping BlockGroup subelement 0x%x - ignoring", id);
3651         ret = gst_ebml_read_skip (ebml);
3652         break;
3653     }
3654
3655     if (is_simpleblock)
3656       break;
3657   }
3658
3659   /* reading a number or so could have failed */
3660   if (ret != GST_FLOW_OK)
3661     goto data_error;
3662
3663   if (ret == GST_FLOW_OK && readblock) {
3664     guint64 duration = 0;
3665     gint64 lace_time = 0;
3666     gboolean delta_unit;
3667
3668     stream = g_ptr_array_index (parse->src, stream_num);
3669
3670     if (cluster_time != GST_CLOCK_TIME_NONE) {
3671       /* FIXME: What to do with negative timestamps? Give timestamp 0 or -1?
3672        * Drop unless the lace contains timestamp 0? */
3673       if (time < 0 && (-time) > cluster_time) {
3674         lace_time = 0;
3675       } else {
3676         if (stream->timecodescale == 1.0)
3677           lace_time = (cluster_time + time) * parse->time_scale;
3678         else
3679           lace_time =
3680               gst_util_guint64_to_gdouble ((cluster_time + time) *
3681               parse->time_scale) * stream->timecodescale;
3682       }
3683     } else {
3684       lace_time = GST_CLOCK_TIME_NONE;
3685     }
3686
3687     if (lace_time != GST_CLOCK_TIME_NONE) {
3688       parse->last_timestamp = lace_time;
3689     }
3690     /* need to refresh segment info ASAP */
3691     if (GST_CLOCK_TIME_IS_VALID (lace_time) && parse->need_newsegment) {
3692       GST_DEBUG_OBJECT (parse,
3693           "generating segment starting at %" GST_TIME_FORMAT,
3694           GST_TIME_ARGS (lace_time));
3695       /* pretend we seeked here */
3696       gst_segment_set_seek (&parse->segment, parse->segment.rate,
3697           GST_FORMAT_TIME, 0, GST_SEEK_TYPE_SET, lace_time,
3698           GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE, NULL);
3699       /* now convey our segment notion downstream */
3700       gst_matroska_parse_send_event (parse, gst_event_new_new_segment (FALSE,
3701               parse->segment.rate, parse->segment.format, parse->segment.start,
3702               parse->segment.stop, parse->segment.start));
3703       parse->need_newsegment = FALSE;
3704     }
3705
3706     if (block_duration) {
3707       if (stream->timecodescale == 1.0)
3708         duration = gst_util_uint64_scale (block_duration, parse->time_scale, 1);
3709       else
3710         duration =
3711             gst_util_gdouble_to_guint64 (gst_util_guint64_to_gdouble
3712             (gst_util_uint64_scale (block_duration, parse->time_scale,
3713                     1)) * stream->timecodescale);
3714     } else if (stream->default_duration) {
3715       duration = stream->default_duration * laces;
3716     }
3717     /* else duration is diff between timecode of this and next block */
3718
3719     /* For SimpleBlock, look at the keyframe bit in flags. Otherwise,
3720        a ReferenceBlock implies that this is not a keyframe. In either
3721        case, it only makes sense for video streams. */
3722     delta_unit = stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO &&
3723         ((is_simpleblock && !(flags & 0x80)) || referenceblock);
3724
3725     if (delta_unit && stream->set_discont) {
3726       /* When doing seeks or such, we need to restart on key frames or
3727        * decoders might choke. */
3728       GST_DEBUG_OBJECT (parse, "skipping delta unit");
3729       goto done;
3730     }
3731
3732     for (n = 0; n < laces; n++) {
3733       if (G_UNLIKELY (lace_size[n] > size)) {
3734         GST_WARNING_OBJECT (parse, "Invalid lace size");
3735         break;
3736       }
3737
3738       /* QoS for video track with an index. the assumption is that
3739          index entries point to keyframes, but if that is not true we
3740          will instad skip until the next keyframe. */
3741       if (GST_CLOCK_TIME_IS_VALID (lace_time) &&
3742           stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO &&
3743           stream->index_table && parse->segment.rate > 0.0) {
3744         GstMatroskaTrackVideoContext *videocontext =
3745             (GstMatroskaTrackVideoContext *) stream;
3746         GstClockTime earliest_time;
3747         GstClockTime earliest_stream_time;
3748
3749         GST_OBJECT_LOCK (parse);
3750         earliest_time = videocontext->earliest_time;
3751         GST_OBJECT_UNLOCK (parse);
3752         earliest_stream_time = gst_segment_to_position (&parse->segment,
3753             GST_FORMAT_TIME, earliest_time);
3754
3755         if (GST_CLOCK_TIME_IS_VALID (lace_time) &&
3756             GST_CLOCK_TIME_IS_VALID (earliest_stream_time) &&
3757             lace_time <= earliest_stream_time) {
3758           /* find index entry (keyframe) <= earliest_stream_time */
3759           GstMatroskaIndex *entry =
3760               gst_util_array_binary_search (stream->index_table->data,
3761               stream->index_table->len, sizeof (GstMatroskaIndex),
3762               (GCompareDataFunc) gst_matroska_index_seek_find,
3763               GST_SEARCH_MODE_BEFORE, &earliest_stream_time, NULL);
3764
3765           /* if that entry (keyframe) is after the current the current
3766              buffer, we can skip pushing (and thus decoding) all
3767              buffers until that keyframe. */
3768           if (entry && GST_CLOCK_TIME_IS_VALID (entry->time) &&
3769               entry->time > lace_time) {
3770             GST_LOG_OBJECT (parse, "Skipping lace before late keyframe");
3771             stream->set_discont = TRUE;
3772             goto next_lace;
3773           }
3774         }
3775       }
3776 #if 0
3777       sub = gst_buffer_create_sub (buf,
3778           GST_BUFFER_SIZE (buf) - size, lace_size[n]);
3779       GST_DEBUG_OBJECT (parse, "created subbuffer %p", sub);
3780
3781       if (delta_unit)
3782         GST_BUFFER_FLAG_SET (sub, GST_BUFFER_FLAG_DELTA_UNIT);
3783       else
3784         GST_BUFFER_FLAG_UNSET (sub, GST_BUFFER_FLAG_DELTA_UNIT);
3785
3786       if (stream->encodings != NULL && stream->encodings->len > 0)
3787         sub = gst_matroska_decode_buffer (stream, sub);
3788
3789       if (sub == NULL) {
3790         GST_WARNING_OBJECT (parse, "Decoding buffer failed");
3791         goto next_lace;
3792       }
3793
3794       GST_BUFFER_TIMESTAMP (sub) = lace_time;
3795
3796       if (GST_CLOCK_TIME_IS_VALID (lace_time)) {
3797         GstClockTime last_stop_end;
3798
3799         /* Check if this stream is after segment stop */
3800         if (GST_CLOCK_TIME_IS_VALID (parse->segment.stop) &&
3801             lace_time >= parse->segment.stop) {
3802           GST_DEBUG_OBJECT (parse,
3803               "Stream %d after segment stop %" GST_TIME_FORMAT, stream->index,
3804               GST_TIME_ARGS (parse->segment.stop));
3805           gst_buffer_unref (sub);
3806           goto eos;
3807         }
3808         if (offset >= stream->to_offset) {
3809           GST_DEBUG_OBJECT (parse, "Stream %d after playback section",
3810               stream->index);
3811           gst_buffer_unref (sub);
3812           goto eos;
3813         }
3814
3815         /* handle gaps, e.g. non-zero start-time, or an cue index entry
3816          * that landed us with timestamps not quite intended */
3817         if (GST_CLOCK_TIME_IS_VALID (parse->segment.last_stop) &&
3818             parse->segment.rate > 0.0) {
3819           GstClockTimeDiff diff;
3820
3821           /* only send newsegments with increasing start times,
3822            * otherwise if these go back and forth downstream (sinks) increase
3823            * accumulated time and running_time */
3824           diff = GST_CLOCK_DIFF (parse->segment.last_stop, lace_time);
3825           if (diff > 2 * GST_SECOND && lace_time > parse->segment.start &&
3826               (!GST_CLOCK_TIME_IS_VALID (parse->segment.stop) ||
3827                   lace_time < parse->segment.stop)) {
3828             GST_DEBUG_OBJECT (parse,
3829                 "Gap of %" G_GINT64_FORMAT " ns detected in"
3830                 "stream %d (%" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "). "
3831                 "Sending updated NEWSEGMENT events", diff,
3832                 stream->index, GST_TIME_ARGS (stream->pos),
3833                 GST_TIME_ARGS (lace_time));
3834             /* send newsegment events such that the gap is not accounted in
3835              * accum time, hence running_time */
3836             /* close ahead of gap */
3837             gst_matroska_parse_send_event (parse,
3838                 gst_event_new_new_segment (TRUE, parse->segment.rate,
3839                     parse->segment.format, parse->segment.last_stop,
3840                     parse->segment.last_stop, parse->segment.last_stop));
3841             /* skip gap */
3842             gst_matroska_parse_send_event (parse,
3843                 gst_event_new_new_segment (FALSE, parse->segment.rate,
3844                     parse->segment.format, lace_time, parse->segment.stop,
3845                     lace_time));
3846             /* align segment view with downstream,
3847              * prevents double-counting accum when closing segment */
3848             gst_segment_set_newsegment (&parse->segment, FALSE,
3849                 parse->segment.rate, parse->segment.format, lace_time,
3850                 parse->segment.stop, lace_time);
3851             parse->segment.last_stop = lace_time;
3852           }
3853         }
3854
3855         if (!GST_CLOCK_TIME_IS_VALID (parse->segment.last_stop)
3856             || parse->segment.last_stop < lace_time) {
3857           parse->segment.last_stop = lace_time;
3858         }
3859
3860         last_stop_end = lace_time;
3861         if (duration) {
3862           GST_BUFFER_DURATION (sub) = duration / laces;
3863           last_stop_end += GST_BUFFER_DURATION (sub);
3864         }
3865
3866         if (!GST_CLOCK_TIME_IS_VALID (parse->last_stop_end) ||
3867             parse->last_stop_end < last_stop_end)
3868           parse->last_stop_end = last_stop_end;
3869
3870         if (parse->segment.duration == -1 ||
3871             parse->segment.duration < lace_time) {
3872           gst_segment_set_duration (&parse->segment, GST_FORMAT_TIME,
3873               last_stop_end);
3874           gst_element_post_message (GST_ELEMENT_CAST (parse),
3875               gst_message_new_duration (GST_OBJECT_CAST (parse),
3876                   GST_FORMAT_TIME, GST_CLOCK_TIME_NONE));
3877         }
3878       }
3879
3880       stream->pos = lace_time;
3881
3882       gst_matroska_parse_sync_streams (parse);
3883
3884       if (stream->set_discont) {
3885         GST_DEBUG_OBJECT (parse, "marking DISCONT");
3886         GST_BUFFER_FLAG_SET (sub, GST_BUFFER_FLAG_DISCONT);
3887         stream->set_discont = FALSE;
3888       }
3889
3890       /* reverse playback book-keeping */
3891       if (!GST_CLOCK_TIME_IS_VALID (stream->from_time))
3892         stream->from_time = lace_time;
3893       if (stream->from_offset == -1)
3894         stream->from_offset = offset;
3895
3896       GST_DEBUG_OBJECT (parse,
3897           "Pushing lace %d, data of size %d for stream %d, time=%"
3898           GST_TIME_FORMAT " and duration=%" GST_TIME_FORMAT, n,
3899           GST_BUFFER_SIZE (sub), stream_num,
3900           GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (sub)),
3901           GST_TIME_ARGS (GST_BUFFER_DURATION (sub)));
3902
3903       if (parse->element_index) {
3904         if (stream->index_writer_id == -1)
3905           gst_index_get_writer_id (parse->element_index,
3906               GST_OBJECT (stream->pad), &stream->index_writer_id);
3907
3908         GST_LOG_OBJECT (parse, "adding association %" GST_TIME_FORMAT "-> %"
3909             G_GUINT64_FORMAT " for writer id %d",
3910             GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (sub)), cluster_offset,
3911             stream->index_writer_id);
3912         gst_index_add_association (parse->element_index,
3913             stream->index_writer_id, GST_BUFFER_FLAG_IS_SET (sub,
3914                 GST_BUFFER_FLAG_DELTA_UNIT) ? 0 : GST_ASSOCIATION_FLAG_KEY_UNIT,
3915             GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (sub), GST_FORMAT_BYTES,
3916             cluster_offset, NULL);
3917       }
3918
3919       gst_buffer_set_caps (sub, GST_PAD_CAPS (parse->srcpad));
3920
3921       /* Postprocess the buffers depending on the codec used */
3922       if (stream->postprocess_frame) {
3923         GST_LOG_OBJECT (parse, "running post process");
3924         ret = stream->postprocess_frame (GST_ELEMENT (parse), stream, &sub);
3925       }
3926
3927       ret = gst_pad_push (stream->pad, sub);
3928       if (parse->segment.rate < 0) {
3929         if (lace_time > parse->segment.stop && ret == GST_FLOW_UNEXPECTED) {
3930           /* In reverse playback we can get a GST_FLOW_UNEXPECTED when
3931            * we are at the end of the segment, so we just need to jump
3932            * back to the previous section. */
3933           GST_DEBUG_OBJECT (parse, "downstream has reached end of segment");
3934           ret = GST_FLOW_OK;
3935         }
3936       }
3937       /* combine flows */
3938       ret = gst_matroska_parse_combine_flows (parse, stream, ret);
3939 #endif
3940
3941     next_lace:
3942       size -= lace_size[n];
3943       if (lace_time != GST_CLOCK_TIME_NONE && duration)
3944         lace_time += duration / laces;
3945       else
3946         lace_time = GST_CLOCK_TIME_NONE;
3947     }
3948   }
3949
3950 done:
3951   if (buf)
3952     gst_buffer_unref (buf);
3953   g_free (lace_size);
3954
3955   return ret;
3956
3957   /* EXITS */
3958 invalid_lacing:
3959   {
3960     GST_ELEMENT_WARNING (parse, STREAM, DEMUX, (NULL), ("Invalid lacing size"));
3961     /* non-fatal, try next block(group) */
3962     ret = GST_FLOW_OK;
3963     goto done;
3964   }
3965 data_error:
3966   {
3967     GST_ELEMENT_WARNING (parse, STREAM, DEMUX, (NULL), ("Data error"));
3968     /* non-fatal, try next block(group) */
3969     ret = GST_FLOW_OK;
3970     goto done;
3971   }
3972 }
3973
3974 /* return FALSE if block(group) should be skipped (due to a seek) */
3975 static inline gboolean
3976 gst_matroska_parse_seek_block (GstMatroskaParse * parse)
3977 {
3978   if (G_UNLIKELY (parse->seek_block)) {
3979     if (!(--parse->seek_block)) {
3980       return TRUE;
3981     } else {
3982       GST_LOG_OBJECT (parse, "should skip block due to seek");
3983       return FALSE;
3984     }
3985   } else {
3986     return TRUE;
3987   }
3988 }
3989
3990 static GstFlowReturn
3991 gst_matroska_parse_parse_contents_seekentry (GstMatroskaParse * parse,
3992     GstEbmlRead * ebml)
3993 {
3994   GstFlowReturn ret;
3995   guint64 seek_pos = (guint64) - 1;
3996   guint32 seek_id = 0;
3997   guint32 id;
3998
3999   DEBUG_ELEMENT_START (parse, ebml, "Seek");
4000
4001   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
4002     DEBUG_ELEMENT_STOP (parse, ebml, "Seek", ret);
4003     return ret;
4004   }
4005
4006   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
4007     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
4008       break;
4009
4010     switch (id) {
4011       case GST_MATROSKA_ID_SEEKID:
4012       {
4013         guint64 t;
4014
4015         if ((ret = gst_ebml_read_uint (ebml, &id, &t)) != GST_FLOW_OK)
4016           break;
4017
4018         GST_DEBUG_OBJECT (parse, "SeekID: %" G_GUINT64_FORMAT, t);
4019         seek_id = t;
4020         break;
4021       }
4022
4023       case GST_MATROSKA_ID_SEEKPOSITION:
4024       {
4025         guint64 t;
4026
4027         if ((ret = gst_ebml_read_uint (ebml, &id, &t)) != GST_FLOW_OK)
4028           break;
4029
4030         if (t > G_MAXINT64) {
4031           GST_WARNING_OBJECT (parse,
4032               "Too large SeekPosition %" G_GUINT64_FORMAT, t);
4033           break;
4034         }
4035
4036         GST_DEBUG_OBJECT (parse, "SeekPosition: %" G_GUINT64_FORMAT, t);
4037         seek_pos = t;
4038         break;
4039       }
4040
4041       default:
4042         ret = gst_matroska_parse_parse_skip (parse, ebml, "SeekHead", id);
4043         break;
4044     }
4045   }
4046
4047   if (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED)
4048     return ret;
4049
4050   if (!seek_id || seek_pos == (guint64) - 1) {
4051     GST_WARNING_OBJECT (parse, "Incomplete seekhead entry (0x%x/%"
4052         G_GUINT64_FORMAT ")", seek_id, seek_pos);
4053     return GST_FLOW_OK;
4054   }
4055
4056   switch (seek_id) {
4057     case GST_MATROSKA_ID_SEEKHEAD:
4058     {
4059     }
4060     case GST_MATROSKA_ID_CUES:
4061     case GST_MATROSKA_ID_TAGS:
4062     case GST_MATROSKA_ID_TRACKS:
4063     case GST_MATROSKA_ID_SEGMENTINFO:
4064     case GST_MATROSKA_ID_ATTACHMENTS:
4065     case GST_MATROSKA_ID_CHAPTERS:
4066     {
4067       guint64 length;
4068
4069       /* remember */
4070       length = gst_matroska_parse_get_length (parse);
4071
4072       if (length == (guint64) - 1) {
4073         GST_DEBUG_OBJECT (parse, "no upstream length, skipping SeakHead entry");
4074         break;
4075       }
4076
4077       /* check for validity */
4078       if (seek_pos + parse->ebml_segment_start + 12 >= length) {
4079         GST_WARNING_OBJECT (parse,
4080             "SeekHead reference lies outside file!" " (%"
4081             G_GUINT64_FORMAT "+%" G_GUINT64_FORMAT "+12 >= %"
4082             G_GUINT64_FORMAT ")", seek_pos, parse->ebml_segment_start, length);
4083         break;
4084       }
4085
4086       /* only pick up index location when streaming */
4087       if (seek_id == GST_MATROSKA_ID_CUES) {
4088         parse->index_offset = seek_pos + parse->ebml_segment_start;
4089         GST_DEBUG_OBJECT (parse, "Cues located at offset %" G_GUINT64_FORMAT,
4090             parse->index_offset);
4091       }
4092       break;
4093     }
4094
4095     default:
4096       GST_DEBUG_OBJECT (parse, "Ignoring Seek entry for ID=0x%x", seek_id);
4097       break;
4098   }
4099   DEBUG_ELEMENT_STOP (parse, ebml, "Seek", ret);
4100
4101   return ret;
4102 }
4103
4104 static GstFlowReturn
4105 gst_matroska_parse_parse_contents (GstMatroskaParse * parse, GstEbmlRead * ebml)
4106 {
4107   GstFlowReturn ret = GST_FLOW_OK;
4108   guint32 id;
4109
4110   DEBUG_ELEMENT_START (parse, ebml, "SeekHead");
4111
4112   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
4113     DEBUG_ELEMENT_STOP (parse, ebml, "SeekHead", ret);
4114     return ret;
4115   }
4116
4117   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
4118     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
4119       break;
4120
4121     switch (id) {
4122       case GST_MATROSKA_ID_SEEKENTRY:
4123       {
4124         ret = gst_matroska_parse_parse_contents_seekentry (parse, ebml);
4125         /* Ignore EOS and errors here */
4126         if (ret != GST_FLOW_OK) {
4127           GST_DEBUG_OBJECT (parse, "Ignoring %s", gst_flow_get_name (ret));
4128           ret = GST_FLOW_OK;
4129         }
4130         break;
4131       }
4132
4133       default:
4134         ret = gst_matroska_parse_parse_skip (parse, ebml, "SeekHead", id);
4135         break;
4136     }
4137   }
4138
4139   DEBUG_ELEMENT_STOP (parse, ebml, "SeekHead", ret);
4140
4141   return ret;
4142 }
4143
4144 #define GST_FLOW_OVERFLOW   GST_FLOW_CUSTOM_ERROR
4145
4146 #define MAX_BLOCK_SIZE (15 * 1024 * 1024)
4147
4148 static inline GstFlowReturn
4149 gst_matroska_parse_check_read_size (GstMatroskaParse * parse, guint64 bytes)
4150 {
4151   if (G_UNLIKELY (bytes > MAX_BLOCK_SIZE)) {
4152     /* only a few blocks are expected/allowed to be large,
4153      * and will be recursed into, whereas others will be read and must fit */
4154     /* fatal in streaming case, as we can't step over easily */
4155     GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
4156         ("reading large block of size %" G_GUINT64_FORMAT " not supported; "
4157             "file might be corrupt.", bytes));
4158     return GST_FLOW_ERROR;
4159   } else {
4160     return GST_FLOW_OK;
4161   }
4162 }
4163
4164 /* returns TRUE if we truely are in error state, and should give up */
4165 static inline gboolean
4166 gst_matroska_parse_check_parse_error (GstMatroskaParse * parse)
4167 {
4168   gint64 pos;
4169
4170   /* sigh, one last attempt above and beyond call of duty ...;
4171    * search for cluster mark following current pos */
4172   pos = parse->offset;
4173   GST_WARNING_OBJECT (parse, "parse error, looking for next cluster");
4174   if (gst_matroska_parse_search_cluster (parse, &pos) != GST_FLOW_OK) {
4175     /* did not work, give up */
4176     return TRUE;
4177   } else {
4178     GST_DEBUG_OBJECT (parse, "... found at  %" G_GUINT64_FORMAT, pos);
4179     /* try that position */
4180     parse->offset = pos;
4181     return FALSE;
4182   }
4183 }
4184
4185 /* initializes @ebml with @bytes from input stream at current offset.
4186  * Returns UNEXPECTED if insufficient available,
4187  * ERROR if too much was attempted to read. */
4188 static inline GstFlowReturn
4189 gst_matroska_parse_take (GstMatroskaParse * parse, guint64 bytes,
4190     GstEbmlRead * ebml)
4191 {
4192   GstBuffer *buffer = NULL;
4193   GstFlowReturn ret = GST_FLOW_OK;
4194
4195   GST_LOG_OBJECT (parse, "taking %" G_GUINT64_FORMAT " bytes for parsing",
4196       bytes);
4197   ret = gst_matroska_parse_check_read_size (parse, bytes);
4198   if (G_UNLIKELY (ret != GST_FLOW_OK)) {
4199     /* otherwise fatal */
4200     ret = GST_FLOW_ERROR;
4201     goto exit;
4202   }
4203   if (gst_adapter_available (parse->adapter) >= bytes)
4204     buffer = gst_adapter_take_buffer (parse->adapter, bytes);
4205   else
4206     ret = GST_FLOW_UNEXPECTED;
4207   if (G_LIKELY (buffer)) {
4208     gst_ebml_read_init (ebml, GST_ELEMENT_CAST (parse), buffer, parse->offset);
4209     parse->offset += bytes;
4210   }
4211 exit:
4212   return ret;
4213 }
4214
4215 static void
4216 gst_matroska_parse_check_seekability (GstMatroskaParse * parse)
4217 {
4218   GstQuery *query;
4219   gboolean seekable = FALSE;
4220   gint64 start = -1, stop = -1;
4221
4222   query = gst_query_new_seeking (GST_FORMAT_BYTES);
4223   if (!gst_pad_peer_query (parse->sinkpad, query)) {
4224     GST_DEBUG_OBJECT (parse, "seeking query failed");
4225     goto done;
4226   }
4227
4228   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
4229
4230   /* try harder to query upstream size if we didn't get it the first time */
4231   if (seekable && stop == -1) {
4232     GstFormat fmt = GST_FORMAT_BYTES;
4233
4234     GST_DEBUG_OBJECT (parse, "doing duration query to fix up unset stop");
4235     gst_pad_query_peer_duration (parse->sinkpad, &fmt, &stop);
4236   }
4237
4238   /* if upstream doesn't know the size, it's likely that it's not seekable in
4239    * practice even if it technically may be seekable */
4240   if (seekable && (start != 0 || stop <= start)) {
4241     GST_DEBUG_OBJECT (parse, "seekable but unknown start/stop -> disable");
4242     seekable = FALSE;
4243   }
4244
4245 done:
4246   GST_INFO_OBJECT (parse, "seekable: %d (%" G_GUINT64_FORMAT " - %"
4247       G_GUINT64_FORMAT ")", seekable, start, stop);
4248   parse->seekable = seekable;
4249
4250   gst_query_unref (query);
4251 }
4252
4253 #if 0
4254 static GstFlowReturn
4255 gst_matroska_parse_find_tracks (GstMatroskaParse * parse)
4256 {
4257   guint32 id;
4258   guint64 before_pos;
4259   guint64 length;
4260   guint needed;
4261   GstFlowReturn ret = GST_FLOW_OK;
4262
4263   GST_WARNING_OBJECT (parse,
4264       "Found Cluster element before Tracks, searching Tracks");
4265
4266   /* remember */
4267   before_pos = parse->offset;
4268
4269   /* Search Tracks element */
4270   while (TRUE) {
4271     ret = gst_matroska_parse_peek_id_length_pull (parse, &id, &length, &needed);
4272     if (ret != GST_FLOW_OK)
4273       break;
4274
4275     if (id != GST_MATROSKA_ID_TRACKS) {
4276       /* we may be skipping large cluster here, so forego size check etc */
4277       /* ... but we can't skip undefined size; force error */
4278       if (length == G_MAXUINT64) {
4279         ret = gst_matroska_parse_check_read_size (parse, length);
4280         break;
4281       } else {
4282         parse->offset += needed;
4283         parse->offset += length;
4284       }
4285       continue;
4286     }
4287
4288     /* will lead to track parsing ... */
4289     ret = gst_matroska_parse_parse_id (parse, id, length, needed);
4290     break;
4291   }
4292
4293   /* seek back */
4294   parse->offset = before_pos;
4295
4296   return ret;
4297 }
4298 #endif
4299
4300 #define GST_READ_CHECK(stmt)  \
4301 G_STMT_START { \
4302   if (G_UNLIKELY ((ret = (stmt)) != GST_FLOW_OK)) { \
4303     if (ret == GST_FLOW_OVERFLOW) { \
4304       ret = GST_FLOW_OK; \
4305     } \
4306     goto read_error; \
4307   } \
4308 } G_STMT_END
4309
4310 static void
4311 gst_matroska_parse_accumulate_streamheader (GstMatroskaParse * parse,
4312     GstBuffer * buffer)
4313 {
4314   if (parse->streamheader) {
4315     GstBuffer *buf;
4316
4317     buf = gst_buffer_span (parse->streamheader, 0, buffer,
4318         GST_BUFFER_SIZE (parse->streamheader) + GST_BUFFER_SIZE (buffer));
4319     gst_buffer_unref (parse->streamheader);
4320     parse->streamheader = buf;
4321   } else {
4322     parse->streamheader = gst_buffer_ref (buffer);
4323   }
4324
4325   GST_DEBUG ("%d", GST_BUFFER_SIZE (parse->streamheader));
4326 }
4327
4328 static GstFlowReturn
4329 gst_matroska_parse_output (GstMatroskaParse * parse, GstBuffer * buffer,
4330     gboolean keyframe)
4331 {
4332   GstFlowReturn ret = GST_FLOW_OK;
4333
4334   if (!parse->pushed_headers) {
4335     GstCaps *caps;
4336     GstStructure *s;
4337     GValue streamheader = { 0 };
4338     GValue bufval = { 0 };
4339     GstBuffer *buf;
4340
4341     caps = gst_caps_new_simple ("video/x-matroska", NULL);
4342     s = gst_caps_get_structure (caps, 0);
4343     g_value_init (&streamheader, GST_TYPE_ARRAY);
4344     g_value_init (&bufval, GST_TYPE_BUFFER);
4345     GST_BUFFER_FLAG_SET (parse->streamheader, GST_BUFFER_FLAG_IN_CAPS);
4346     gst_value_set_buffer (&bufval, parse->streamheader);
4347     gst_value_array_append_value (&streamheader, &bufval);
4348     g_value_unset (&bufval);
4349     gst_structure_set_value (s, "streamheader", &streamheader);
4350     g_value_unset (&streamheader);
4351     //gst_caps_replace (parse->caps, caps);
4352     gst_pad_set_caps (parse->srcpad, caps);
4353
4354     buf = gst_buffer_make_metadata_writable (parse->streamheader);
4355     gst_buffer_set_caps (buf, caps);
4356     gst_caps_unref (caps);
4357
4358     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
4359     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
4360     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
4361
4362     ret = gst_pad_push (parse->srcpad, buf);
4363
4364     parse->pushed_headers = TRUE;
4365   }
4366
4367   if (!keyframe) {
4368     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
4369   } else {
4370     GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
4371   }
4372   if (GST_BUFFER_TIMESTAMP (buffer) != GST_CLOCK_TIME_NONE) {
4373     parse->last_timestamp = GST_BUFFER_TIMESTAMP (buffer);
4374   } else {
4375     GST_BUFFER_TIMESTAMP (buffer) = parse->last_timestamp;
4376   }
4377   gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad));
4378   ret = gst_pad_push (parse->srcpad, gst_buffer_ref (buffer));
4379
4380   return ret;
4381 }
4382
4383 static GstFlowReturn
4384 gst_matroska_parse_parse_id (GstMatroskaParse * parse, guint32 id,
4385     guint64 length, guint needed)
4386 {
4387   GstEbmlRead ebml = { 0, };
4388   GstFlowReturn ret = GST_FLOW_OK;
4389   guint64 read;
4390   //GstBuffer *buffer;
4391
4392   GST_DEBUG_OBJECT (parse, "Parsing Element id 0x%x, "
4393       "size %" G_GUINT64_FORMAT ", prefix %d", id, length, needed);
4394
4395 #if 0
4396   if (gst_adapter_available (parse->adapter) >= length + needed) {
4397     buffer = gst_adapter_take_buffer (parse->adapter, length + needed);
4398     gst_pad_push (parse->srcpad, buffer);
4399   } else {
4400     ret = GST_FLOW_UNEXPECTED;
4401   }
4402   //GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4403
4404   return ret;
4405 #endif
4406
4407
4408
4409   /* if we plan to read and parse this element, we need prefix (id + length)
4410    * and the contents */
4411   /* mind about overflow wrap-around when dealing with undefined size */
4412   read = length;
4413   if (G_LIKELY (length != G_MAXUINT64))
4414     read += needed;
4415
4416   switch (parse->state) {
4417     case GST_MATROSKA_PARSE_STATE_START:
4418       switch (id) {
4419         case GST_EBML_ID_HEADER:
4420           GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4421           ret = gst_matroska_parse_parse_header (parse, &ebml);
4422           if (ret != GST_FLOW_OK)
4423             goto parse_failed;
4424           parse->state = GST_MATROSKA_PARSE_STATE_SEGMENT;
4425           gst_matroska_parse_check_seekability (parse);
4426           gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
4427           break;
4428         default:
4429           goto invalid_header;
4430           break;
4431       }
4432       break;
4433     case GST_MATROSKA_PARSE_STATE_SEGMENT:
4434       switch (id) {
4435         case GST_MATROSKA_ID_SEGMENT:
4436           /* eat segment prefix */
4437           GST_READ_CHECK (gst_matroska_parse_take (parse, needed, &ebml));
4438           GST_DEBUG_OBJECT (parse,
4439               "Found Segment start at offset %" G_GUINT64_FORMAT,
4440               parse->offset);
4441           /* seeks are from the beginning of the segment,
4442            * after the segment ID/length */
4443           parse->ebml_segment_start = parse->offset;
4444           parse->state = GST_MATROSKA_PARSE_STATE_HEADER;
4445           gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
4446           break;
4447         default:
4448           GST_WARNING_OBJECT (parse,
4449               "Expected a Segment ID (0x%x), but received 0x%x!",
4450               GST_MATROSKA_ID_SEGMENT, id);
4451           GST_READ_CHECK (gst_matroska_parse_take (parse, needed, &ebml));
4452           gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
4453           break;
4454       }
4455       break;
4456     case GST_MATROSKA_PARSE_STATE_SCANNING:
4457       if (id != GST_MATROSKA_ID_CLUSTER &&
4458           id != GST_MATROSKA_ID_CLUSTERTIMECODE)
4459         goto skip;
4460       /* fall-through */
4461     case GST_MATROSKA_PARSE_STATE_HEADER:
4462     case GST_MATROSKA_PARSE_STATE_DATA:
4463     case GST_MATROSKA_PARSE_STATE_SEEK:
4464       switch (id) {
4465         case GST_MATROSKA_ID_SEGMENTINFO:
4466           GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4467           if (!parse->segmentinfo_parsed) {
4468             ret = gst_matroska_parse_parse_info (parse, &ebml);
4469           }
4470           gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
4471           break;
4472         case GST_MATROSKA_ID_TRACKS:
4473           GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4474           if (!parse->tracks_parsed) {
4475             ret = gst_matroska_parse_parse_tracks (parse, &ebml);
4476           }
4477           gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
4478           break;
4479         case GST_MATROSKA_ID_CLUSTER:
4480           if (G_UNLIKELY (!parse->tracks_parsed)) {
4481             GST_DEBUG_OBJECT (parse, "Cluster before Track");
4482             goto not_streamable;
4483           }
4484           if (G_UNLIKELY (parse->state == GST_MATROSKA_PARSE_STATE_HEADER)) {
4485             parse->state = GST_MATROSKA_PARSE_STATE_DATA;
4486             parse->first_cluster_offset = parse->offset;
4487             GST_DEBUG_OBJECT (parse, "signaling no more pads");
4488           }
4489           parse->cluster_time = GST_CLOCK_TIME_NONE;
4490           parse->cluster_offset = parse->offset;
4491           if (G_UNLIKELY (!parse->seek_first && parse->seek_block)) {
4492             GST_DEBUG_OBJECT (parse, "seek target block %" G_GUINT64_FORMAT
4493                 " not found in Cluster, trying next Cluster's first block instead",
4494                 parse->seek_block);
4495             parse->seek_block = 0;
4496           }
4497           parse->seek_first = FALSE;
4498           /* record next cluster for recovery */
4499           if (read != G_MAXUINT64)
4500             parse->next_cluster_offset = parse->cluster_offset + read;
4501           /* eat cluster prefix */
4502           GST_READ_CHECK (gst_matroska_parse_take (parse, needed, &ebml));
4503           ret = gst_matroska_parse_output (parse, ebml.buf, TRUE);
4504           //gst_matroska_parse_accumulate_streamheader (parse, ebml.buf);
4505           break;
4506         case GST_MATROSKA_ID_CLUSTERTIMECODE:
4507         {
4508           guint64 num;
4509
4510           GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4511           if ((ret = gst_ebml_read_uint (&ebml, &id, &num)) != GST_FLOW_OK)
4512             goto parse_failed;
4513           GST_DEBUG_OBJECT (parse, "ClusterTimeCode: %" G_GUINT64_FORMAT, num);
4514           parse->cluster_time = num;
4515           if (parse->element_index) {
4516             if (parse->element_index_writer_id == -1)
4517               gst_index_get_writer_id (parse->element_index,
4518                   GST_OBJECT (parse), &parse->element_index_writer_id);
4519             GST_LOG_OBJECT (parse, "adding association %" GST_TIME_FORMAT "-> %"
4520                 G_GUINT64_FORMAT " for writer id %d",
4521                 GST_TIME_ARGS (parse->cluster_time), parse->cluster_offset,
4522                 parse->element_index_writer_id);
4523             gst_index_add_association (parse->element_index,
4524                 parse->element_index_writer_id, GST_ASSOCIATION_FLAG_KEY_UNIT,
4525                 GST_FORMAT_TIME, parse->cluster_time,
4526                 GST_FORMAT_BYTES, parse->cluster_offset, NULL);
4527           }
4528           gst_matroska_parse_output (parse, ebml.buf, FALSE);
4529           break;
4530         }
4531         case GST_MATROSKA_ID_BLOCKGROUP:
4532           if (!gst_matroska_parse_seek_block (parse))
4533             goto skip;
4534           GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4535           DEBUG_ELEMENT_START (parse, &ebml, "BlockGroup");
4536           if ((ret = gst_ebml_read_master (&ebml, &id)) == GST_FLOW_OK) {
4537             ret = gst_matroska_parse_parse_blockgroup_or_simpleblock (parse,
4538                 &ebml, parse->cluster_time, parse->cluster_offset, FALSE);
4539           }
4540           DEBUG_ELEMENT_STOP (parse, &ebml, "BlockGroup", ret);
4541           gst_matroska_parse_output (parse, ebml.buf, FALSE);
4542           break;
4543         case GST_MATROSKA_ID_SIMPLEBLOCK:
4544           if (!gst_matroska_parse_seek_block (parse))
4545             goto skip;
4546           GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4547           DEBUG_ELEMENT_START (parse, &ebml, "SimpleBlock");
4548           ret = gst_matroska_parse_parse_blockgroup_or_simpleblock (parse,
4549               &ebml, parse->cluster_time, parse->cluster_offset, TRUE);
4550           DEBUG_ELEMENT_STOP (parse, &ebml, "SimpleBlock", ret);
4551           gst_matroska_parse_output (parse, ebml.buf, FALSE);
4552           break;
4553         case GST_MATROSKA_ID_ATTACHMENTS:
4554           GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4555           if (!parse->attachments_parsed) {
4556             ret = gst_matroska_parse_parse_attachments (parse, &ebml);
4557           }
4558           gst_matroska_parse_output (parse, ebml.buf, FALSE);
4559           break;
4560         case GST_MATROSKA_ID_TAGS:
4561           GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4562           ret = gst_matroska_parse_parse_metadata (parse, &ebml);
4563           gst_matroska_parse_output (parse, ebml.buf, FALSE);
4564           break;
4565         case GST_MATROSKA_ID_CHAPTERS:
4566           GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4567           ret = gst_matroska_parse_parse_chapters (parse, &ebml);
4568           gst_matroska_parse_output (parse, ebml.buf, FALSE);
4569           break;
4570         case GST_MATROSKA_ID_SEEKHEAD:
4571           GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4572           ret = gst_matroska_parse_parse_contents (parse, &ebml);
4573           gst_matroska_parse_output (parse, ebml.buf, FALSE);
4574           break;
4575         case GST_MATROSKA_ID_CUES:
4576           GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4577           if (!parse->index_parsed) {
4578             ret = gst_matroska_parse_parse_index (parse, &ebml);
4579             /* only push based; delayed index building */
4580             if (ret == GST_FLOW_OK
4581                 && parse->state == GST_MATROSKA_PARSE_STATE_SEEK) {
4582               GstEvent *event;
4583
4584               GST_OBJECT_LOCK (parse);
4585               event = parse->seek_event;
4586               parse->seek_event = NULL;
4587               GST_OBJECT_UNLOCK (parse);
4588
4589               g_assert (event);
4590               /* unlikely to fail, since we managed to seek to this point */
4591               if (!gst_matroska_parse_handle_seek_event (parse, NULL, event))
4592                 goto seek_failed;
4593               /* resume data handling, main thread clear to seek again */
4594               GST_OBJECT_LOCK (parse);
4595               parse->state = GST_MATROSKA_PARSE_STATE_DATA;
4596               GST_OBJECT_UNLOCK (parse);
4597             }
4598           }
4599           gst_matroska_parse_output (parse, ebml.buf, FALSE);
4600           break;
4601         case GST_MATROSKA_ID_POSITION:
4602         case GST_MATROSKA_ID_PREVSIZE:
4603         case GST_MATROSKA_ID_ENCRYPTEDBLOCK:
4604         case GST_MATROSKA_ID_SILENTTRACKS:
4605           GST_DEBUG_OBJECT (parse,
4606               "Skipping Cluster subelement 0x%x - ignoring", id);
4607           /* fall-through */
4608         default:
4609         skip:
4610           GST_DEBUG_OBJECT (parse, "skipping Element 0x%x", id);
4611           GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml));
4612           gst_matroska_parse_output (parse, ebml.buf, FALSE);
4613           break;
4614       }
4615       break;
4616   }
4617
4618   if (ret == GST_FLOW_PARSE)
4619     goto parse_failed;
4620
4621 exit:
4622   gst_ebml_read_clear (&ebml);
4623   return ret;
4624
4625   /* ERRORS */
4626 read_error:
4627   {
4628     /* simply exit, maybe not enough data yet */
4629     /* no ebml to clear if read error */
4630     return ret;
4631   }
4632 parse_failed:
4633   {
4634     GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
4635         ("Failed to parse Element 0x%x", id));
4636     ret = GST_FLOW_ERROR;
4637     goto exit;
4638   }
4639 not_streamable:
4640   {
4641     GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
4642         ("File layout does not permit streaming"));
4643     ret = GST_FLOW_ERROR;
4644     goto exit;
4645   }
4646 #if 0
4647 no_tracks:
4648   {
4649     GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL),
4650         ("No Tracks element found"));
4651     ret = GST_FLOW_ERROR;
4652     goto exit;
4653   }
4654 #endif
4655 invalid_header:
4656   {
4657     GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL), ("Invalid header"));
4658     ret = GST_FLOW_ERROR;
4659     goto exit;
4660   }
4661 seek_failed:
4662   {
4663     GST_ELEMENT_ERROR (parse, STREAM, DEMUX, (NULL), ("Failed to seek"));
4664     ret = GST_FLOW_ERROR;
4665     goto exit;
4666   }
4667 }
4668
4669 #if 0
4670 static void
4671 gst_matroska_parse_loop (GstPad * pad)
4672 {
4673   GstMatroskaParse *parse = GST_MATROSKA_PARSE (GST_PAD_PARENT (pad));
4674   GstFlowReturn ret;
4675   guint32 id;
4676   guint64 length;
4677   guint needed;
4678
4679   /* If we have to close a segment, send a new segment to do this now */
4680   if (G_LIKELY (parse->state == GST_MATROSKA_PARSE_STATE_DATA)) {
4681     if (G_UNLIKELY (parse->close_segment)) {
4682       gst_matroska_parse_send_event (parse, parse->close_segment);
4683       parse->close_segment = NULL;
4684     }
4685     if (G_UNLIKELY (parse->new_segment)) {
4686       gst_matroska_parse_send_event (parse, parse->new_segment);
4687       parse->new_segment = NULL;
4688     }
4689   }
4690
4691   ret = gst_matroska_parse_peek_id_length_pull (parse, &id, &length, &needed);
4692   if (ret == GST_FLOW_UNEXPECTED)
4693     goto eos;
4694   if (ret != GST_FLOW_OK) {
4695     if (gst_matroska_parse_check_parse_error (parse))
4696       goto pause;
4697     else
4698       return;
4699   }
4700
4701   GST_LOG_OBJECT (parse, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
4702       "size %" G_GUINT64_FORMAT ", needed %d", parse->offset, id,
4703       length, needed);
4704
4705   ret = gst_matroska_parse_parse_id (parse, id, length, needed);
4706   if (ret == GST_FLOW_UNEXPECTED)
4707     goto eos;
4708   if (ret != GST_FLOW_OK)
4709     goto pause;
4710
4711   /* check if we're at the end of a configured segment */
4712   if (G_LIKELY (parse->src->len)) {
4713     guint i;
4714
4715     g_assert (parse->num_streams == parse->src->len);
4716     for (i = 0; i < parse->src->len; i++) {
4717       GstMatroskaTrackContext *context = g_ptr_array_index (parse->src, i);
4718       GST_DEBUG_OBJECT (context->pad, "pos %" GST_TIME_FORMAT,
4719           GST_TIME_ARGS (context->pos));
4720       if (context->eos == FALSE)
4721         goto next;
4722     }
4723
4724     GST_INFO_OBJECT (parse, "All streams are EOS");
4725     ret = GST_FLOW_UNEXPECTED;
4726     goto eos;
4727   }
4728
4729 next:
4730   if (G_UNLIKELY (parse->offset == gst_matroska_parse_get_length (parse))) {
4731     GST_LOG_OBJECT (parse, "Reached end of stream");
4732     ret = GST_FLOW_UNEXPECTED;
4733     goto eos;
4734   }
4735
4736   return;
4737
4738   /* ERRORS */
4739 eos:
4740   {
4741     if (parse->segment.rate < 0.0) {
4742       ret = gst_matroska_parse_seek_to_previous_keyframe (parse);
4743       if (ret == GST_FLOW_OK)
4744         return;
4745     }
4746     /* fall-through */
4747   }
4748 pause:
4749   {
4750     const gchar *reason = gst_flow_get_name (ret);
4751     gboolean push_eos = FALSE;
4752
4753     GST_LOG_OBJECT (parse, "pausing task, reason %s", reason);
4754     parse->segment_running = FALSE;
4755     gst_pad_pause_task (parse->sinkpad);
4756
4757     if (ret == GST_FLOW_UNEXPECTED) {
4758       /* perform EOS logic */
4759
4760       /* Close the segment, i.e. update segment stop with the duration
4761        * if no stop was set */
4762       if (GST_CLOCK_TIME_IS_VALID (parse->last_stop_end) &&
4763           !GST_CLOCK_TIME_IS_VALID (parse->segment.stop)) {
4764         GstEvent *event =
4765             gst_event_new_new_segment_full (TRUE, parse->segment.rate,
4766             parse->segment.applied_rate, parse->segment.format,
4767             parse->segment.start,
4768             MAX (parse->last_stop_end, parse->segment.start),
4769             parse->segment.time);
4770         gst_matroska_parse_send_event (parse, event);
4771       }
4772
4773       if (parse->segment.flags & GST_SEEK_FLAG_SEGMENT) {
4774         gint64 stop;
4775
4776         /* for segment playback we need to post when (in stream time)
4777          * we stopped, this is either stop (when set) or the duration. */
4778         if ((stop = parse->segment.stop) == -1)
4779           stop = parse->last_stop_end;
4780
4781         GST_LOG_OBJECT (parse, "Sending segment done, at end of segment");
4782         gst_element_post_message (GST_ELEMENT (parse),
4783             gst_message_new_segment_done (GST_OBJECT (parse), GST_FORMAT_TIME,
4784                 stop));
4785       } else {
4786         push_eos = TRUE;
4787       }
4788     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED) {
4789       /* for fatal errors we post an error message */
4790       GST_ELEMENT_ERROR (parse, STREAM, FAILED, (NULL),
4791           ("stream stopped, reason %s", reason));
4792       push_eos = TRUE;
4793     }
4794     if (push_eos) {
4795       /* send EOS, and prevent hanging if no streams yet */
4796       GST_LOG_OBJECT (parse, "Sending EOS, at end of stream");
4797       if (!gst_matroska_parse_send_event (parse, gst_event_new_eos ()) &&
4798           (ret == GST_FLOW_UNEXPECTED)) {
4799         GST_ELEMENT_ERROR (parse, STREAM, DEMUX,
4800             (NULL), ("got eos but no streams (yet)"));
4801       }
4802     }
4803     return;
4804   }
4805 }
4806 #endif
4807
4808 /*
4809  * Create and push a flushing seek event upstream
4810  */
4811 static gboolean
4812 perform_seek_to_offset (GstMatroskaParse * parse, guint64 offset)
4813 {
4814   GstEvent *event;
4815   gboolean res = 0;
4816
4817   GST_DEBUG_OBJECT (parse, "Seeking to %" G_GUINT64_FORMAT, offset);
4818
4819   event =
4820       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
4821       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
4822       GST_SEEK_TYPE_NONE, -1);
4823
4824   res = gst_pad_push_event (parse->sinkpad, event);
4825
4826   /* newsegment event will update offset */
4827   return res;
4828 }
4829
4830 static const guint8 *
4831 gst_matroska_parse_peek_adapter (GstMatroskaParse * parse, guint peek)
4832 {
4833   return gst_adapter_peek (parse->adapter, peek);
4834 }
4835
4836 static GstFlowReturn
4837 gst_matroska_parse_peek_id_length_push (GstMatroskaParse * parse, guint32 * _id,
4838     guint64 * _length, guint * _needed)
4839 {
4840   return gst_ebml_peek_id_length (_id, _length, _needed,
4841       (GstPeekData) gst_matroska_parse_peek_adapter, (gpointer) parse,
4842       GST_ELEMENT_CAST (parse), parse->offset);
4843 }
4844
4845 static GstFlowReturn
4846 gst_matroska_parse_chain (GstPad * pad, GstBuffer * buffer)
4847 {
4848   GstMatroskaParse *parse = GST_MATROSKA_PARSE (GST_PAD_PARENT (pad));
4849   guint available;
4850   GstFlowReturn ret = GST_FLOW_OK;
4851   guint needed = 0;
4852   guint32 id;
4853   guint64 length;
4854
4855   if (G_UNLIKELY (GST_BUFFER_IS_DISCONT (buffer))) {
4856     GST_DEBUG_OBJECT (parse, "got DISCONT");
4857     gst_adapter_clear (parse->adapter);
4858     GST_OBJECT_LOCK (parse);
4859     gst_matroska_parse_reset_streams (parse, GST_CLOCK_TIME_NONE, FALSE);
4860     GST_OBJECT_UNLOCK (parse);
4861   }
4862
4863   gst_adapter_push (parse->adapter, buffer);
4864   buffer = NULL;
4865
4866 next:
4867   available = gst_adapter_available (parse->adapter);
4868
4869   ret = gst_matroska_parse_peek_id_length_push (parse, &id, &length, &needed);
4870   if (G_UNLIKELY (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED))
4871     return ret;
4872
4873   GST_LOG_OBJECT (parse, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
4874       "size %" G_GUINT64_FORMAT ", needed %d, available %d", parse->offset, id,
4875       length, needed, available);
4876
4877   if (needed > available)
4878     return GST_FLOW_OK;
4879
4880   ret = gst_matroska_parse_parse_id (parse, id, length, needed);
4881   if (ret == GST_FLOW_UNEXPECTED) {
4882     /* need more data */
4883     return GST_FLOW_OK;
4884   } else if (ret != GST_FLOW_OK) {
4885     return ret;
4886   } else
4887     goto next;
4888 }
4889
4890 static gboolean
4891 gst_matroska_parse_handle_sink_event (GstPad * pad, GstEvent * event)
4892 {
4893   gboolean res = TRUE;
4894   GstMatroskaParse *parse = GST_MATROSKA_PARSE (GST_PAD_PARENT (pad));
4895
4896   GST_DEBUG_OBJECT (parse,
4897       "have event type %s: %p on sink pad", GST_EVENT_TYPE_NAME (event), event);
4898
4899   switch (GST_EVENT_TYPE (event)) {
4900     case GST_EVENT_NEWSEGMENT:
4901     {
4902       GstFormat format;
4903       gdouble rate, arate;
4904       gint64 start, stop, time = 0;
4905       gboolean update;
4906       GstSegment segment;
4907
4908       /* some debug output */
4909       gst_segment_init (&segment, GST_FORMAT_UNDEFINED);
4910       gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
4911           &start, &stop, &time);
4912       gst_segment_set_newsegment_full (&segment, update, rate, arate, format,
4913           start, stop, time);
4914       GST_DEBUG_OBJECT (parse,
4915           "received format %d newsegment %" GST_SEGMENT_FORMAT, format,
4916           &segment);
4917
4918       if (parse->state < GST_MATROSKA_PARSE_STATE_DATA) {
4919         GST_DEBUG_OBJECT (parse, "still starting");
4920         goto exit;
4921       }
4922
4923       /* we only expect a BYTE segment, e.g. following a seek */
4924       if (format != GST_FORMAT_BYTES) {
4925         GST_DEBUG_OBJECT (parse, "unsupported segment format, ignoring");
4926         goto exit;
4927       }
4928
4929       GST_DEBUG_OBJECT (parse, "clearing segment state");
4930       /* clear current segment leftover */
4931       gst_adapter_clear (parse->adapter);
4932       /* and some streaming setup */
4933       parse->offset = start;
4934       /* do not know where we are;
4935        * need to come across a cluster and generate newsegment */
4936       parse->segment.last_stop = GST_CLOCK_TIME_NONE;
4937       parse->cluster_time = GST_CLOCK_TIME_NONE;
4938       parse->cluster_offset = 0;
4939       parse->need_newsegment = TRUE;
4940       /* but keep some of the upstream segment */
4941       parse->segment.rate = rate;
4942     exit:
4943       /* chain will send initial newsegment after pads have been added,
4944        * or otherwise come up with one */
4945       GST_DEBUG_OBJECT (parse, "eating event");
4946       gst_event_unref (event);
4947       res = TRUE;
4948       break;
4949     }
4950     case GST_EVENT_EOS:
4951     {
4952       if (parse->state != GST_MATROSKA_PARSE_STATE_DATA) {
4953         gst_event_unref (event);
4954         GST_ELEMENT_ERROR (parse, STREAM, DEMUX,
4955             (NULL), ("got eos and didn't receive a complete header object"));
4956       } else if (parse->num_streams == 0) {
4957         GST_ELEMENT_ERROR (parse, STREAM, DEMUX,
4958             (NULL), ("got eos but no streams (yet)"));
4959       } else {
4960         gst_matroska_parse_send_event (parse, event);
4961       }
4962       break;
4963     }
4964     case GST_EVENT_FLUSH_STOP:
4965     {
4966       gst_adapter_clear (parse->adapter);
4967       GST_OBJECT_LOCK (parse);
4968       gst_matroska_parse_reset_streams (parse, GST_CLOCK_TIME_NONE, TRUE);
4969       GST_OBJECT_UNLOCK (parse);
4970       parse->segment.last_stop = GST_CLOCK_TIME_NONE;
4971       parse->cluster_time = GST_CLOCK_TIME_NONE;
4972       parse->cluster_offset = 0;
4973       /* fall-through */
4974     }
4975     default:
4976       res = gst_pad_event_default (pad, event);
4977       break;
4978   }
4979
4980   return res;
4981 }
4982
4983 static void
4984 gst_matroska_parse_set_index (GstElement * element, GstIndex * index)
4985 {
4986   GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
4987
4988   GST_OBJECT_LOCK (parse);
4989   if (parse->element_index)
4990     gst_object_unref (parse->element_index);
4991   parse->element_index = index ? gst_object_ref (index) : NULL;
4992   GST_OBJECT_UNLOCK (parse);
4993   GST_DEBUG_OBJECT (parse, "Set index %" GST_PTR_FORMAT, parse->element_index);
4994 }
4995
4996 static GstIndex *
4997 gst_matroska_parse_get_index (GstElement * element)
4998 {
4999   GstIndex *result = NULL;
5000   GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
5001
5002   GST_OBJECT_LOCK (parse);
5003   if (parse->element_index)
5004     result = gst_object_ref (parse->element_index);
5005   GST_OBJECT_UNLOCK (parse);
5006
5007   GST_DEBUG_OBJECT (parse, "Returning index %" GST_PTR_FORMAT, result);
5008
5009   return result;
5010 }
5011
5012 static GstStateChangeReturn
5013 gst_matroska_parse_change_state (GstElement * element,
5014     GstStateChange transition)
5015 {
5016   GstMatroskaParse *parse = GST_MATROSKA_PARSE (element);
5017   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
5018
5019   /* handle upwards state changes here */
5020   switch (transition) {
5021     default:
5022       break;
5023   }
5024
5025   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
5026
5027   /* handle downwards state changes */
5028   switch (transition) {
5029     case GST_STATE_CHANGE_PAUSED_TO_READY:
5030       gst_matroska_parse_reset (GST_ELEMENT (parse));
5031       break;
5032     default:
5033       break;
5034   }
5035
5036   return ret;
5037 }
5038
5039 gboolean
5040 gst_matroska_parse_plugin_init (GstPlugin * plugin)
5041 {
5042   gst_riff_init ();
5043
5044   /* create an elementfactory for the matroska_parse element */
5045   if (!gst_element_register (plugin, "matroskaparse",
5046           GST_RANK_NONE, GST_TYPE_MATROSKA_PARSE))
5047     return FALSE;
5048
5049   return TRUE;
5050 }