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