Sorry Dave... Add mpegversion=1 to mp3 caps everywhere so that the autoplugger uses...
[platform/upstream/gst-plugins-good.git] / gst / matroska / matroska-demux.c
1 /* GStreamer Matroska muxer/demuxer
2  * (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
3  *
4  * matroska-demux.c: matroska file/stream demuxer
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <math.h>
27 #include <string.h>
28
29 /* For AVI compatibility mode... Who did that? */
30 #include <gst/riff/riff-ids.h>
31 #include <gst/riff/riff-media.h>
32
33 #include "matroska-demux.h"
34 #include "matroska-ids.h"
35
36 enum {
37   /* FILL ME */
38   LAST_SIGNAL
39 };
40
41 enum {
42   ARG_0,
43   ARG_METADATA,
44   ARG_STREAMINFO,
45   /* FILL ME */
46 };
47
48 GST_PAD_TEMPLATE_FACTORY (sink_templ,
49   "sink",
50   GST_PAD_SINK,
51   GST_PAD_ALWAYS,
52   GST_CAPS_NEW (
53     "matroskademux_sink",
54      "video/x-matroska",
55        NULL
56   )
57 )
58
59 /* gobject magic foo */
60 static void     gst_matroska_demux_base_init          (GstMatroskaDemuxClass *klass);
61 static void     gst_matroska_demux_class_init         (GstMatroskaDemuxClass *klass);
62 static void     gst_matroska_demux_init               (GstMatroskaDemux *demux);
63
64 /* element functions */
65 static void     gst_matroska_demux_loop               (GstElement  *element);
66 static gboolean gst_matroska_demux_send_event         (GstElement  *element,
67                                                        GstEvent    *event);
68
69 /* pad functions */
70 static const GstEventMask *
71                 gst_matroska_demux_get_event_mask     (GstPad      *pad);
72 static gboolean gst_matroska_demux_handle_src_event   (GstPad      *pad,
73                                                        GstEvent    *event);
74 static const GstFormat *
75                 gst_matroska_demux_get_src_formats    (GstPad      *pad); 
76 static const GstQueryType*
77                 gst_matroska_demux_get_src_query_types(GstPad      *pad);
78 static gboolean gst_matroska_demux_handle_src_query   (GstPad      *pad,
79                                                        GstQueryType type, 
80                                                        GstFormat   *format,
81                                                        gint64      *value);
82
83 /* gst internal change state handler */
84 static GstElementStateReturn
85                 gst_matroska_demux_change_state       (GstElement  *element);
86 static void     gst_matroska_demux_set_clock          (GstElement  *element,
87                                                        GstClock    *clock);
88
89 /* gobject bla bla */
90 static void     gst_matroska_demux_get_property       (GObject     *object,
91                                                        guint        prop_id,    
92                                                        GValue      *value,
93                                                        GParamSpec  *pspec);
94
95 /* caps functions */
96 static GstCaps *gst_matroska_demux_video_caps         (GstMatroskaTrackVideoContext
97                                                                    *videocontext,
98                                                        const gchar *codec_id,
99                                                        gpointer     data,
100                                                        guint        size);
101 static GstCaps *gst_matroska_demux_audio_caps         (GstMatroskaTrackAudioContext
102                                                                    *audiocontext,
103                                                        const gchar *codec_id,
104                                                        gpointer     data,
105                                                        guint        size);
106 static GstCaps *gst_matroska_demux_complex_caps       (GstMatroskaTrackComplexContext
107                                                                    *complexcontext,
108                                                        const gchar *codec_id,
109                                                        gpointer     data,
110                                                        guint        size);
111 static GstCaps *gst_matroska_demux_subtitle_caps      (GstMatroskaTrackSubtitleContext
112                                                                    *subtitlecontext,
113                                                        const gchar *codec_id,
114                                                        gpointer     data,
115                                                        guint        size);
116
117 /* stream methods */
118 static void     gst_matroska_demux_reset              (GstElement  *element);
119
120 static GstEbmlReadClass *parent_class = NULL;
121 static GstPadTemplate *videosrctempl, *audiosrctempl, *subtitlesrctempl;
122 /*static guint gst_matroska_demux_signals[LAST_SIGNAL] = { 0 };*/
123
124 GType
125 gst_matroska_demux_get_type (void) 
126 {
127   static GType gst_matroska_demux_type = 0;
128
129   if (!gst_matroska_demux_type) {
130     static const GTypeInfo gst_matroska_demux_info = {
131       sizeof (GstMatroskaDemuxClass),      
132       (GBaseInitFunc) gst_matroska_demux_base_init,
133       NULL,
134       (GClassInitFunc) gst_matroska_demux_class_init,
135       NULL,
136       NULL,
137       sizeof (GstMatroskaDemux),
138       0,
139       (GInstanceInitFunc) gst_matroska_demux_init,
140     };
141
142     gst_matroska_demux_type =
143         g_type_register_static (GST_TYPE_EBML_READ,
144                                 "GstMatroskaDemux",
145                                 &gst_matroska_demux_info, 0);
146   }
147
148   return gst_matroska_demux_type;
149 }
150
151 static void
152 gst_matroska_demux_base_init (GstMatroskaDemuxClass *klass)
153 {
154   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
155   static GstElementDetails gst_matroska_demux_details = {
156     "Matroska demuxer",
157     "Codec/Demuxer",
158     "Demuxes a Matroska Stream into video/audio/subtitles",
159     "Ronald Bultje <rbultje@ronald.bitfreak.net>"
160   };
161
162   gst_element_class_add_pad_template (element_class, videosrctempl);
163   gst_element_class_add_pad_template (element_class, audiosrctempl);
164   gst_element_class_add_pad_template (element_class, subtitlesrctempl);
165   gst_element_class_add_pad_template (element_class,
166                 GST_PAD_TEMPLATE_GET (sink_templ));
167   gst_element_class_set_details (element_class,
168                 &gst_matroska_demux_details);
169 }
170
171 static void
172 gst_matroska_demux_class_init (GstMatroskaDemuxClass *klass) 
173 {
174   GObjectClass *gobject_class;
175   GstElementClass *gstelement_class;
176
177   gobject_class = (GObjectClass *) klass;
178   gstelement_class = (GstElementClass *) klass;
179
180   g_object_class_install_property (gobject_class, ARG_METADATA,
181     g_param_spec_boxed ("metadata", "Metadata", "Metadata",
182                         GST_TYPE_CAPS, G_PARAM_READABLE));
183   g_object_class_install_property (gobject_class, ARG_STREAMINFO,
184     g_param_spec_boxed ("streaminfo", "Streaminfo", "Streaminfo",
185                         GST_TYPE_CAPS, G_PARAM_READABLE));
186
187   parent_class = g_type_class_ref (GST_TYPE_EBML_READ);
188
189   gobject_class->get_property = gst_matroska_demux_get_property;
190
191   gstelement_class->change_state = gst_matroska_demux_change_state;
192   gstelement_class->send_event = gst_matroska_demux_send_event;
193   gstelement_class->set_clock = gst_matroska_demux_set_clock;
194 }
195
196 static void 
197 gst_matroska_demux_init (GstMatroskaDemux *demux) 
198 {
199   GstElementClass *klass = GST_ELEMENT_GET_CLASS (demux);
200   gint i;
201
202   GST_FLAG_SET (GST_OBJECT (demux), GST_ELEMENT_EVENT_AWARE);
203
204   demux->sinkpad = gst_pad_new_from_template (
205         gst_element_class_get_pad_template (klass, "sink"), "sink");
206   gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
207   GST_EBML_READ (demux)->sinkpad = demux->sinkpad;
208
209   gst_element_set_loop_function (GST_ELEMENT (demux),
210                                  gst_matroska_demux_loop);
211
212   /* initial stream no. */
213   for (i = 0; i < GST_MATROSKA_DEMUX_MAX_STREAMS; i++) {
214     demux->src[i] = NULL;
215   }
216   demux->streaminfo = demux->metadata = NULL;
217   demux->writing_app = demux->muxing_app = NULL;
218   demux->index = NULL;
219
220   /* finish off */
221   gst_matroska_demux_reset (GST_ELEMENT (demux));
222 }
223
224 static void
225 gst_matroska_demux_reset (GstElement *element)
226 {
227   GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
228   guint i;
229
230   /* reset input */
231   demux->state = GST_MATROSKA_DEMUX_STATE_START;
232
233   /* clean up existing streams */
234   for (i = 0; i < GST_MATROSKA_DEMUX_MAX_STREAMS; i++) {
235     if (demux->src[i] != NULL) {
236       if (demux->src[i]->pad != NULL) {
237         gst_element_remove_pad (GST_ELEMENT (demux), demux->src[i]->pad);
238       }
239       g_free (demux->src[i]->codec_id);
240       g_free (demux->src[i]->codec_name);
241       g_free (demux->src[i]->name);
242       g_free (demux->src[i]->language);
243       g_free (demux->src[i]->codec_priv);
244       g_free (demux->src[i]);
245       demux->src[i] = NULL;
246     }
247   }
248   demux->num_streams = 0;
249   demux->num_a_streams = 0;
250   demux->num_t_streams = 0;
251   demux->num_v_streams = 0;
252
253   /* reset media info */
254   gst_caps_replace (&demux->metadata, NULL);
255   gst_caps_replace (&demux->streaminfo, NULL);
256
257   g_free (demux->writing_app);
258   demux->writing_app = NULL;
259   g_free (demux->muxing_app);
260   demux->muxing_app = NULL;
261
262   /* reset indexes */
263   demux->num_indexes = 0;
264   g_free (demux->index);
265   demux->index = NULL;
266
267   /* reset timers */
268   demux->clock = NULL;
269   demux->time_scale = 1000000;
270   demux->duration = 0;
271   demux->pos = 0;
272   demux->created = G_MININT64;
273   demux->seek_pending = GST_CLOCK_TIME_NONE;
274
275   demux->metadata_parsed = FALSE;
276   demux->index_parsed = FALSE;
277 }
278
279 static void
280 gst_matroska_demux_set_clock (GstElement  *element,
281                               GstClock    *clock)
282 {
283   GST_MATROSKA_DEMUX (element)->clock = clock;
284 }
285
286 static gint
287 gst_matroska_demux_stream_from_num (GstMatroskaDemux *demux,
288                                     guint             track_num)
289 {
290   guint n;
291
292   for (n = 0; n < demux->num_streams; n++) {
293     if (demux->src[n] != NULL &&
294         demux->src[n]->num == track_num) {
295       return n;
296     }
297   }
298
299   if (n == demux->num_streams) {
300     GST_WARNING ("Failed to find corresponding pad for tracknum %d",
301                  track_num); 
302   }
303
304   return -1;
305 }
306
307 static gboolean
308 gst_matroska_demux_add_stream (GstMatroskaDemux *demux)
309 {
310   GstElementClass *klass = GST_ELEMENT_GET_CLASS (demux);
311   GstEbmlRead *ebml = GST_EBML_READ (demux);
312   GstMatroskaTrackContext *context;
313   GstPadTemplate *templ = NULL;
314   GstCaps *caps = NULL;
315   gchar *padname = NULL;
316   gboolean res = TRUE;
317   guint32 id;
318
319   if (demux->num_streams >= GST_MATROSKA_DEMUX_MAX_STREAMS) {
320     GST_WARNING ("Maximum number of streams (%d) exceeded, skipping",
321                  GST_MATROSKA_DEMUX_MAX_STREAMS);
322     return gst_ebml_read_skip (ebml); /* skip-and-continue */
323   }
324
325   /* allocate generic... if we know the type, we'll g_renew()
326    * with the precise type */
327   context = g_new0 (GstMatroskaTrackContext, 1);
328   demux->src[demux->num_streams] = context;
329   context->index = demux->num_streams;
330   context->type = 0; /* no type yet */
331   demux->num_streams++;
332
333   /* start with the master */
334   if (!gst_ebml_read_master (ebml, &id))
335     return FALSE;
336
337   /* try reading the trackentry headers */
338   while (res) {
339     if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
340       res = FALSE;
341       break;
342     } else if (demux->level_up > 0) {
343       demux->level_up--;
344       break;
345     }
346
347     switch (id) {
348       /* track number (unique stream ID) */
349       case GST_MATROSKA_ID_TRACKNUMBER: {
350         guint64 num;
351         if (!gst_ebml_read_uint (ebml, &id, &num)) {
352           res = FALSE;
353           break;
354         }
355         context->num = num;
356         break;
357       }
358
359       /* track UID (unique identifier) */
360       case GST_MATROSKA_ID_TRACKUID: {
361         guint64 num;
362         if (!gst_ebml_read_uint (ebml, &id, &num)) {
363           res = FALSE;
364           break;
365         }
366         context->uid = num;
367         break;
368       }
369
370       /* track type (video, audio, combined, subtitle, etc.) */
371       case GST_MATROSKA_ID_TRACKTYPE: {
372         guint64 num;
373         if (context->type != 0) {
374           GST_WARNING ("More than one tracktype defined in a trackentry - skipping");
375           break;
376         }
377         if (!gst_ebml_read_uint (ebml, &id, &num)) {
378           res = FALSE;
379           break;
380         }
381         context->type = num;
382
383         /* ok, so we're actually going to reallocate this thing */
384         switch (context->type) {
385           case GST_MATROSKA_TRACK_TYPE_VIDEO:
386             context = (GstMatroskaTrackContext *)
387                         g_renew (GstMatroskaTrackVideoContext, context, 1);
388             break;
389           case GST_MATROSKA_TRACK_TYPE_AUDIO:
390             context = (GstMatroskaTrackContext *)
391                         g_renew (GstMatroskaTrackAudioContext, context, 1);
392             /* defaults */
393             ((GstMatroskaTrackAudioContext *) context)->channels = 1;
394             ((GstMatroskaTrackAudioContext *) context)->samplerate = 8000;
395             break;
396           case GST_MATROSKA_TRACK_TYPE_COMPLEX:
397             context = (GstMatroskaTrackContext *)
398                         g_renew (GstMatroskaTrackComplexContext, context, 1);
399             break;
400           case GST_MATROSKA_TRACK_TYPE_SUBTITLE:
401             context = (GstMatroskaTrackContext *)
402                         g_renew (GstMatroskaTrackSubtitleContext, context, 1);
403             break;
404           case GST_MATROSKA_TRACK_TYPE_LOGO:
405           case GST_MATROSKA_TRACK_TYPE_CONTROL:
406           default:
407             GST_WARNING ("Unknown or unsupported track type 0x%x",
408                          context->type);
409             context->type = 0;
410             break;
411         }
412         demux->src[demux->num_streams-1] = context;
413         break;
414       }
415
416       /* tracktype specific stuff for video */
417       case GST_MATROSKA_ID_TRACKVIDEO: {
418         GstMatroskaTrackVideoContext *videocontext;
419         if (context->type != GST_MATROSKA_TRACK_TYPE_VIDEO) {
420           GST_WARNING ("trackvideo EBML entry in non-video track - ignoring track");
421           res = FALSE;
422           break;
423         } else if (!gst_ebml_read_master (ebml, &id)) {
424           res = FALSE;
425           break;
426         }
427         videocontext = (GstMatroskaTrackVideoContext *) context;
428
429         while (res) {
430           if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
431             res = FALSE;
432             break;
433           } else if (demux->level_up > 0) {
434             demux->level_up--;
435             break;
436           }
437
438           switch (id) {
439             /* fixme, this should be one-up, but I get it here (?) */
440             case GST_MATROSKA_ID_TRACKDEFAULTDURATION: {
441               guint64 num;
442               if (!gst_ebml_read_uint (ebml, &id, &num)) {
443                 res = FALSE;
444                 break;
445               }
446               context->default_duration = num;
447               break;
448             }
449
450             /* video framerate */
451             case GST_MATROSKA_ID_VIDEOFRAMERATE: {
452               gdouble num;
453               if (!gst_ebml_read_float (ebml, &id, &num)) {
454                 res = FALSE;
455                 break;
456               }
457               context->default_duration = GST_SECOND * (1. / num);
458               break;
459             }
460
461             /* width of the size to display the video at */
462             case GST_MATROSKA_ID_VIDEODISPLAYWIDTH: {
463               guint64 num;
464               if (!gst_ebml_read_uint (ebml, &id, &num)) {
465                 res = FALSE;
466                 break;
467               }
468               videocontext->display_width = num;
469               break;
470             }
471
472             /* height of the size to display the video at */
473             case GST_MATROSKA_ID_VIDEODISPLAYHEIGHT: {
474               guint64 num;
475               if (!gst_ebml_read_uint (ebml, &id, &num)) {
476                 res = FALSE;
477                 break;
478               }
479               videocontext->display_height = num;
480               break;
481             }
482
483             /* width of the video in the file */
484             case GST_MATROSKA_ID_VIDEOPIXELWIDTH: {
485               guint64 num;
486               if (!gst_ebml_read_uint (ebml, &id, &num)) {
487                 res = FALSE;
488                 break;
489               }
490               videocontext->pixel_width = num;
491               break;
492             }
493
494             /* height of the video in the file */
495             case GST_MATROSKA_ID_VIDEOPIXELHEIGHT: {
496               guint64 num;
497               if (!gst_ebml_read_uint (ebml, &id, &num)) {
498                 res = FALSE;
499                 break;
500               }
501               videocontext->pixel_height = num;
502               break;
503             }
504
505             /* whether the video is interlaced */
506             case GST_MATROSKA_ID_VIDEOFLAGINTERLACED: {
507               guint64 num;
508               if (!gst_ebml_read_uint (ebml, &id, &num)) {
509                 res = FALSE;
510                 break;
511               }
512               if (num)
513                 context->flags |= GST_MATROSKA_VIDEOTRACK_INTERLACED;
514               else
515                 context->flags &= ~GST_MATROSKA_VIDEOTRACK_INTERLACED;
516               break;
517             }
518
519              /* stereo mode (whether the video has two streams, where
520               * one is for the left eye and the other for the right eye,
521               * which creates a 3D-like effect) */
522             case GST_MATROSKA_ID_VIDEOSTEREOMODE: {
523               guint64 num;
524               if (!gst_ebml_read_uint (ebml, &id, &num)) {
525                 res = FALSE;
526                 break;
527               }
528               if (num != GST_MATROSKA_EYE_MODE_MONO &&
529                   num != GST_MATROSKA_EYE_MODE_LEFT &&
530                   num != GST_MATROSKA_EYE_MODE_RIGHT &&
531                   num != GST_MATROSKA_EYE_MODE_BOTH) {
532                 GST_WARNING ("Unknown eye mode 0x%x - ignoring",
533                              (guint) num);
534                 break;
535               }
536               videocontext->eye_mode = num;
537               break;
538             }
539
540             /* aspect ratio behaviour */
541             case GST_MATROSKA_ID_VIDEOASPECTRATIO: {
542               guint64 num;
543               if (!gst_ebml_read_uint (ebml, &id, &num)) {
544                 res = FALSE;
545                 break;
546               }
547               if (num != GST_MATROSKA_ASPECT_RATIO_MODE_FREE &&
548                   num != GST_MATROSKA_ASPECT_RATIO_MODE_KEEP &&
549                   num != GST_MATROSKA_ASPECT_RATIO_MODE_FIXED) {
550                 GST_WARNING ("Unknown aspect ratio mode 0x%x - ignoring",
551                              (guint) num);
552                 break;
553               }
554               videocontext->asr_mode = num;
555               break;
556             }
557
558             /* colourspace (only matters for raw video) fourcc */
559             case GST_MATROSKA_ID_VIDEOCOLOURSPACE: {
560               guint64 num;
561               if (!gst_ebml_read_uint (ebml, &id, &num)) {
562                 res = FALSE;
563                 break;
564               }
565               videocontext->fourcc = num;
566               break;
567             }
568
569             default:
570               GST_WARNING ("Unknown video track header entry 0x%x - ignoring",
571                            id);
572               /* pass-through */
573
574             case GST_EBML_ID_VOID:
575               if (!gst_ebml_read_skip (ebml))
576                 res = FALSE;
577               break;
578           }
579
580           if (demux->level_up) {
581             demux->level_up--;
582             break;
583           }
584         }
585         break;
586       }
587
588       /* tracktype specific stuff for audio */
589       case GST_MATROSKA_ID_TRACKAUDIO: {
590         GstMatroskaTrackAudioContext *audiocontext;
591         if (context->type != GST_MATROSKA_TRACK_TYPE_AUDIO) {
592           GST_WARNING ("trackaudio EBML entry in non-audio track - ignoring track");
593           res = FALSE;
594           break;
595         } else if (!gst_ebml_read_master (ebml, &id)) {
596           res = FALSE;
597           break;
598         }
599         audiocontext = (GstMatroskaTrackAudioContext *) context;
600
601         while (res) {
602           if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
603             res = FALSE;
604             break;
605           } else if (demux->level_up > 0) {
606             demux->level_up--;
607             break;
608           }
609
610           switch (id) {
611             /* samplerate */
612             case GST_MATROSKA_ID_AUDIOSAMPLINGFREQ: {
613               gdouble num;
614               if (!gst_ebml_read_float (ebml, &id, &num)) {
615                 res = FALSE;
616                 break;
617               }
618               audiocontext->samplerate = num;
619               break;
620             }
621
622             /* bitdepth */
623             case GST_MATROSKA_ID_AUDIOBITDEPTH: {
624               guint64 num;
625               if (!gst_ebml_read_uint (ebml, &id, &num)) {
626                 res = FALSE;
627                 break;
628               }
629               audiocontext->bitdepth = num;
630               break;
631             }
632
633             /* channels */
634             case GST_MATROSKA_ID_AUDIOCHANNELS: {
635               guint64 num;
636               if (!gst_ebml_read_uint (ebml, &id, &num)) {
637                 res = FALSE;
638                 break;
639               }
640               audiocontext->channels = num;
641               break;
642             }
643
644             default:
645               GST_WARNING ("Unknown audio track header entry 0x%x - ignoring",
646                            id);
647               /* pass-through */
648
649             case GST_EBML_ID_VOID:
650               if (!gst_ebml_read_skip (ebml))
651                 res = FALSE;
652               break;
653           }
654
655           if (demux->level_up) {
656             demux->level_up--;
657             break;
658           }
659         }
660         break;
661       }
662
663       /* codec identifier */
664       case GST_MATROSKA_ID_CODECID: {
665         gchar *text;
666         if (!gst_ebml_read_ascii (ebml, &id, &text)) {
667           res = FALSE;
668           break;
669         }
670         context->codec_id = text;
671         break;
672       }
673
674       /* codec private data */
675       case GST_MATROSKA_ID_CODECPRIVATE: {
676         guint8 *data;
677         guint64 size;
678         if (!gst_ebml_read_binary (ebml, &id, &data, &size)) {
679           res = FALSE;
680           break;
681         }
682         context->codec_priv = data;
683         context->codec_priv_size = size;
684         break;
685       }
686
687       /* name of the codec */
688       case GST_MATROSKA_ID_CODECNAME: {
689         gchar *text;
690         if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
691           res = FALSE;
692           break;
693         }
694         context->codec_name = text;
695         break;
696       }
697
698       /* name of this track */
699       case GST_MATROSKA_ID_TRACKNAME: {
700         gchar *text;
701         if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
702           res = FALSE;
703           break;
704         }
705         context->name = text;
706         break;
707       }
708
709       /* language (matters for audio/subtitles, mostly) */
710       case GST_MATROSKA_ID_TRACKLANGUAGE: {
711         gchar *text;
712         if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
713           res = FALSE;
714           break;
715         }
716         context->language = text;
717         break;
718       }
719
720       /* whether this is actually used */
721       case GST_MATROSKA_ID_TRACKFLAGENABLED: {
722         guint64 num;
723         if (!gst_ebml_read_uint (ebml, &id, &num)) {
724           res = FALSE;
725           break;
726         }
727         if (num)
728           context->flags |= GST_MATROSKA_TRACK_ENABLED;
729         else
730           context->flags &= ~GST_MATROSKA_TRACK_ENABLED;
731         break;
732       }
733
734       /* whether it's the default for this track type */
735       case GST_MATROSKA_ID_TRACKFLAGDEFAULT: {
736         guint64 num;
737         if (!gst_ebml_read_uint (ebml, &id, &num)) {
738           res = FALSE;
739           break;
740         }
741         if (num)
742           context->flags |= GST_MATROSKA_TRACK_DEFAULT;
743         else
744           context->flags &= ~GST_MATROSKA_TRACK_DEFAULT;
745         break;
746       }
747
748       /* lacing (like MPEG, where blocks don't end/start on frame
749        * boundaries) */
750       case GST_MATROSKA_ID_TRACKFLAGLACING: {
751         guint64 num;
752         if (!gst_ebml_read_uint (ebml, &id, &num)) {
753           res = FALSE;
754           break;
755         }
756         if (num)
757           context->flags |= GST_MATROSKA_TRACK_LACING;
758         else
759           context->flags &= ~GST_MATROSKA_TRACK_LACING;
760         break;
761       }
762
763       /* default length (in time) of one data block in this track */
764       case GST_MATROSKA_ID_TRACKDEFAULTDURATION: {
765         guint64 num;
766         if (!gst_ebml_read_uint (ebml, &id, &num)) {
767           res = FALSE;
768           break;
769         }
770         context->default_duration = num;
771         break;
772       }
773
774       default:
775         GST_WARNING ("Unknown track header entry 0x%x - ignoring", id);
776         /* pass-through */
777
778       /* we ignore these because they're nothing useful (i.e. crap). */
779       case GST_MATROSKA_ID_CODECINFOURL:
780       case GST_MATROSKA_ID_CODECDOWNLOADURL:
781       case GST_MATROSKA_ID_TRACKMINCACHE:
782       case GST_MATROSKA_ID_TRACKMAXCACHE:
783       case GST_EBML_ID_VOID:
784         if (!gst_ebml_read_skip (ebml))
785           res = FALSE;
786         break;
787     }
788
789     if (demux->level_up) {
790       demux->level_up--;
791       break;
792     }
793   }
794
795   if (context->type == 0 || context->codec_id == NULL || !res) {
796     if (res)
797       GST_WARNING ("Unknown stream/codec in track entry header");
798
799     demux->num_streams--;
800     demux->src[demux->num_streams] = NULL;
801     if (context) {
802       g_free (context->codec_id);
803       g_free (context->codec_name);
804       g_free (context->name);
805       g_free (context->language);
806       g_free (context->codec_priv);
807       g_free (context);
808     }
809
810     return res;
811   }
812
813   /* now create the GStreamer connectivity */
814   switch (context->type) {
815     case GST_MATROSKA_TRACK_TYPE_VIDEO: {
816       GstMatroskaTrackVideoContext *videocontext =
817         (GstMatroskaTrackVideoContext *) context;
818       padname = g_strdup_printf ("video_%02d", demux->num_v_streams);
819       templ = gst_element_class_get_pad_template (klass, "video_%02d");
820       caps = gst_matroska_demux_video_caps (videocontext,
821                                             context->codec_id,
822                                             context->codec_priv,
823                                             context->codec_priv_size);
824       break;
825     }
826
827     case GST_MATROSKA_TRACK_TYPE_AUDIO: {
828       GstMatroskaTrackAudioContext *audiocontext =
829         (GstMatroskaTrackAudioContext *) context;
830       padname = g_strdup_printf ("audio_%02d", demux->num_a_streams);
831       templ = gst_element_class_get_pad_template (klass, "audio_%02d");
832       caps = gst_matroska_demux_audio_caps (audiocontext,
833                                             context->codec_id,
834                                             context->codec_priv,
835                                             context->codec_priv_size);
836       break;
837     }
838
839     case GST_MATROSKA_TRACK_TYPE_COMPLEX: {
840       GstMatroskaTrackComplexContext *complexcontext =
841         (GstMatroskaTrackComplexContext *) context;
842       padname = g_strdup_printf ("video_%02d", demux->num_v_streams);
843       templ = gst_element_class_get_pad_template (klass, "video_%02d");
844       caps = gst_matroska_demux_complex_caps (complexcontext,
845                                               context->codec_id,
846                                               context->codec_priv,
847                                               context->codec_priv_size);
848       break;
849     }
850
851     case GST_MATROSKA_TRACK_TYPE_SUBTITLE: {
852       GstMatroskaTrackSubtitleContext *subtitlecontext =
853         (GstMatroskaTrackSubtitleContext *) context;
854       padname = g_strdup_printf ("subtitle_%02d", demux->num_t_streams);
855       templ = gst_element_class_get_pad_template (klass, "subtitle_%02d");
856       caps = gst_matroska_demux_subtitle_caps (subtitlecontext,
857                                                context->codec_id,
858                                                context->codec_priv,
859                                                context->codec_priv_size);
860       break;
861     }
862
863     case GST_MATROSKA_TRACK_TYPE_LOGO:
864     case GST_MATROSKA_TRACK_TYPE_CONTROL:
865     default:
866       /* we should already have quit by now */
867       g_assert (0);
868   }
869
870   /* the pad in here */
871   context->pad =  gst_pad_new_from_template (templ, padname);
872
873   if (caps != NULL) {
874     if (gst_pad_try_set_caps (context->pad, caps) <= 0) {
875       GST_WARNING ("Failed to set caps on next element for %s",
876                    padname); 
877     }
878   }
879   g_free (padname);
880
881   /* set some functions */
882   gst_pad_set_formats_function (context->pad,
883                                 gst_matroska_demux_get_src_formats);
884   gst_pad_set_event_mask_function (context->pad,
885                                    gst_matroska_demux_get_event_mask);
886   gst_pad_set_event_function (context->pad,
887                               gst_matroska_demux_handle_src_event);
888   gst_pad_set_query_type_function (context->pad,
889                                    gst_matroska_demux_get_src_query_types);
890   gst_pad_set_query_function (context->pad,
891                               gst_matroska_demux_handle_src_query);
892
893   gst_element_add_pad (GST_ELEMENT (demux), context->pad);
894
895   /* tadaah! */
896   return TRUE;
897 }
898
899 static const GstFormat *
900 gst_matroska_demux_get_src_formats (GstPad *pad) 
901 {
902   /*GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad));*/
903
904   /* we could try to look for units (i.e. samples) in audio streams
905    * or video streams, but both samplerate and framerate are not
906    * always constant, and since we only have a time indication, we
907    * cannot guarantee anything here based purely on index. So, we
908    * only support time for now. */
909   static const GstFormat src_formats[] = {
910     GST_FORMAT_TIME,
911     (GstFormat) 0
912   };
913
914   return src_formats;
915 }
916
917 static const GstQueryType *
918 gst_matroska_demux_get_src_query_types (GstPad *pad) 
919 {
920   static const GstQueryType src_types[] = {
921     GST_QUERY_TOTAL,
922     GST_QUERY_POSITION,
923     (GstQueryType) 0
924   };
925
926   return src_types;
927 }
928
929 static gboolean
930 gst_matroska_demux_handle_src_query (GstPad       *pad,
931                                      GstQueryType  type, 
932                                      GstFormat    *format,
933                                      gint64       *value)
934 {
935   gboolean res = TRUE;
936   GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad));
937
938   switch (type) {
939     case GST_QUERY_TOTAL:
940       switch (*format) {
941         case GST_FORMAT_DEFAULT:
942           *format = GST_FORMAT_TIME;
943           /* fall through */
944         case GST_FORMAT_TIME:
945           *value = demux->duration;
946           break;
947         default:
948           res = FALSE;
949           break;
950       }
951       break;
952
953     case GST_QUERY_POSITION:
954       switch (*format) {
955         case GST_FORMAT_DEFAULT:
956           *format = GST_FORMAT_TIME;
957           /* fall through */
958         case GST_FORMAT_TIME:
959           *value = demux->pos;
960           break;
961         default:
962           res = FALSE;
963           break;
964       }
965       break;
966
967     default:
968       res = FALSE;
969       break;
970   }
971
972   return res;
973 }
974
975 static GstMatroskaIndex *
976 gst_matroskademux_seek (GstMatroskaDemux *demux)
977 {
978   guint entry = (guint) -1;
979   guint64 offset = demux->seek_pending;
980   guint n;
981
982   /* make sure we don't seek twice */
983   demux->seek_pending = GST_CLOCK_TIME_NONE;
984
985   for (n = 0; n < demux->num_indexes; n++) {
986     if (entry == (guint) -1) {
987       entry = n;
988     } else {
989       gfloat diff_old = fabs (1. * (demux->index[entry].time - offset)),
990              diff_new = fabs (1. * (demux->index[n].time - offset));
991
992       if (diff_new < diff_old) {
993         entry = n;
994       }
995     }
996   }
997
998   if (entry != (guint) -1) {
999     return &demux->index[entry];
1000   }
1001
1002   return NULL;
1003 }
1004
1005 static gboolean
1006 gst_matroska_demux_send_event (GstElement *element,
1007                                GstEvent   *event)
1008 {
1009   GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
1010   gboolean res = TRUE;
1011
1012   switch (GST_EVENT_TYPE (event)) {
1013     case GST_EVENT_SEEK:
1014       switch (GST_EVENT_SEEK_FORMAT (event)) {
1015         case GST_FORMAT_TIME:
1016           demux->seek_pending = GST_EVENT_SEEK_OFFSET (event);
1017           break;
1018
1019         default:
1020           GST_WARNING ("Only time seek is supported");
1021           res = FALSE;
1022           break;
1023       }
1024       break;
1025
1026     default:
1027       GST_WARNING ("Unhandled event of type %d",
1028                    GST_EVENT_TYPE (event));
1029       res = FALSE;
1030       break;
1031   }
1032
1033   gst_event_unref (event);
1034
1035   return res;
1036 }
1037
1038 static const GstEventMask *
1039 gst_matroska_demux_get_event_mask (GstPad *pad)
1040 {
1041   static const GstEventMask masks[] = {
1042     { GST_EVENT_SEEK,         (GstEventFlag) ((gint) GST_SEEK_METHOD_SET |
1043                                               (gint) GST_SEEK_FLAG_KEY_UNIT) },
1044     { GST_EVENT_SEEK_SEGMENT, (GstEventFlag) ((gint) GST_SEEK_METHOD_SET |
1045                                               (gint) GST_SEEK_FLAG_KEY_UNIT) },
1046     { (GstEventType) 0,       (GstEventFlag) 0 }
1047   };
1048
1049   return masks;
1050 }
1051         
1052 static gboolean
1053 gst_matroska_demux_handle_src_event (GstPad   *pad,
1054                                      GstEvent *event)
1055 {
1056   GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad));
1057   gboolean res = TRUE;
1058   
1059   switch (GST_EVENT_TYPE (event)) {
1060     case GST_EVENT_SEEK_SEGMENT:
1061     case GST_EVENT_SEEK:
1062       return gst_matroska_demux_send_event (GST_ELEMENT (demux), event);
1063
1064     default:
1065       GST_WARNING ("Unhandled event of type %d",
1066                    GST_EVENT_TYPE (event));
1067       res = FALSE;
1068       break;
1069   }
1070
1071   gst_event_unref (event);
1072
1073   return res;
1074 }
1075
1076 static gboolean
1077 gst_matroska_demux_handle_seek_event (GstMatroskaDemux *demux)
1078 {
1079   GstEbmlRead *ebml = GST_EBML_READ (demux);
1080   GstMatroskaIndex *entry = gst_matroskademux_seek (demux);
1081   GstEvent *event;
1082   guint i;
1083
1084   if (!entry)
1085     return FALSE;
1086
1087   /* seek (relative to segment) */
1088   if (!(event = gst_ebml_read_seek (ebml,
1089                         entry->pos + demux->segment_start)))
1090     return FALSE;
1091   gst_event_unref (event); /* byte - we want time */
1092   event = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
1093                                        entry->time);
1094
1095   /* forward to all src pads */
1096   for (i = 0; i < demux->num_streams; i++) {
1097     if (GST_PAD_IS_USABLE (demux->src[i]->pad)) {
1098       gst_event_ref (event);
1099       gst_pad_push (demux->src[i]->pad, GST_DATA (event));
1100     }
1101   }
1102
1103   gst_event_unref (event);
1104
1105   return TRUE;
1106 }
1107
1108 static gboolean
1109 gst_matroska_demux_init_stream (GstMatroskaDemux *demux)
1110 {
1111   GstEbmlRead *ebml = GST_EBML_READ (demux);
1112   guint32 id;
1113   gchar *doctype;
1114   guint version;
1115
1116   if (!gst_ebml_read_header (ebml, &doctype, &version))
1117     return FALSE;
1118
1119   if (!doctype || strcmp (doctype, "matroska") != 0) {
1120     gst_element_error (GST_ELEMENT (demux),
1121                        "Input is not a matroska stream (doctype=%s)",
1122                        doctype ? doctype : "none");
1123     g_free (doctype);
1124     return FALSE;
1125   }
1126   g_free (doctype);
1127   if (version > 1) {
1128     gst_element_error (GST_ELEMENT (demux),
1129                        "Demuxer version (1) is too old to read stream version %d",
1130                        version);
1131     return FALSE;
1132   }
1133
1134   /* find segment, must be the next element */
1135   while (1) {
1136     guint last_level;
1137
1138     if (!(id = gst_ebml_peek_id (ebml, &last_level)))
1139       return FALSE;
1140
1141     if (id == GST_MATROSKA_ID_SEGMENT)
1142       break;
1143
1144     /* oi! */
1145     GST_WARNING ("Expected a Segment ID (0x%x), but received 0x%x!",
1146                  GST_MATROSKA_ID_SEGMENT, id);
1147     if (!gst_ebml_read_skip (ebml))
1148       return FALSE;
1149   }
1150
1151   /* we now have a EBML segment */
1152   if (!gst_ebml_read_master (ebml, &id))
1153     return FALSE;
1154   /* seeks are from the beginning of the segment,
1155    * after the segment ID/length */
1156   demux->segment_start = gst_bytestream_tell (ebml->bs);
1157
1158   return TRUE;
1159 }
1160
1161 static gboolean
1162 gst_matroska_demux_parse_tracks (GstMatroskaDemux *demux)
1163 {
1164   GstEbmlRead *ebml = GST_EBML_READ (demux);
1165   gboolean res = TRUE;
1166   guint32 id;
1167
1168   while (res) {
1169     if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1170       res = FALSE;
1171       break;
1172     } else if (demux->level_up) {
1173       demux->level_up--;
1174       break;
1175     }
1176
1177     switch (id) {
1178       /* one track within the "all-tracks" header */
1179       case GST_MATROSKA_ID_TRACKENTRY:
1180         if (!gst_matroska_demux_add_stream (demux))
1181           res = FALSE;
1182         break;
1183
1184       default:
1185         GST_WARNING ("Unknown entry 0x%x in track header", id);
1186         /* fall-through */
1187
1188       case GST_EBML_ID_VOID:
1189         if (!gst_ebml_read_skip (ebml))
1190           res = FALSE;
1191         break;
1192     }
1193
1194     if (demux->level_up) {
1195       demux->level_up--;
1196       break;
1197     }
1198   }
1199
1200   return res;
1201 }
1202
1203 static gboolean
1204 gst_matroska_demux_parse_index (GstMatroskaDemux *demux,
1205                                 gboolean          prevent_eos)
1206 {
1207   GstEbmlRead *ebml = GST_EBML_READ (demux);
1208   gboolean res = TRUE;
1209   guint32 id;
1210   GstMatroskaIndex idx;
1211   guint64 length = 0;
1212
1213   if (prevent_eos) {
1214     length = gst_bytestream_length (ebml->bs);
1215     gst_clock_set_active (demux->clock, FALSE);
1216   }
1217
1218   while (res) {
1219     /* We're an element that can be seeked to. If we are, then
1220      * we want to prevent EOS, since that'll kill us. So we cache
1221      * file size and seek until there, and don't call EOS upon os. */
1222     if (prevent_eos && length == gst_bytestream_tell (ebml->bs)) {
1223       res = FALSE;
1224       break;
1225     } else if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1226       res = FALSE;
1227       break;
1228     } else if (demux->level_up) {
1229       demux->level_up--;
1230       break;
1231     }
1232
1233     switch (id) {
1234       /* one single index entry ('point') */
1235       case GST_MATROSKA_ID_POINTENTRY:
1236         if (!gst_ebml_read_master (ebml, &id)) {
1237           res = FALSE;
1238           break;
1239         }
1240
1241         /* in the end, we hope to fill one entry with a
1242          * timestamp, a file position and a tracknum */
1243         idx.pos   = (guint64) -1;
1244         idx.time  = (guint64) -1;
1245         idx.track = (guint16) -1;
1246
1247         while (res) {
1248           if (prevent_eos && length == gst_bytestream_tell (ebml->bs)) {
1249             res = FALSE;
1250             break;
1251           } else if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1252             res = FALSE;
1253             break;
1254           } else if (demux->level_up) {
1255             demux->level_up--;
1256             break;
1257           }
1258
1259           switch (id) {
1260             /* one single index entry ('point') */
1261             case GST_MATROSKA_ID_CUETIME: {
1262               gint64 time;
1263               if (!gst_ebml_read_uint (ebml, &id, &time)) {
1264                 res = FALSE;
1265                 break;
1266               }
1267               idx.time = time * demux->time_scale;
1268               break;
1269             }
1270
1271             /* position in the file + track to which it belongs */
1272             case GST_MATROSKA_ID_CUETRACKPOSITION:
1273               if (!gst_ebml_read_master (ebml, &id)) {
1274                 res = FALSE;
1275                 break;
1276               }
1277
1278               while (res) {
1279                 if (prevent_eos && length == gst_bytestream_tell (ebml->bs)) {
1280                   res = FALSE;
1281                   break;
1282                 } else if (!(id = gst_ebml_peek_id (ebml,
1283                                         &demux->level_up))) {
1284                   res = FALSE;
1285                   break;
1286                 } else if (demux->level_up) {
1287                   demux->level_up--;
1288                   break;
1289                 }
1290
1291                 switch (id) {
1292                   /* track number */
1293                   case GST_MATROSKA_ID_CUETRACK: {
1294                     guint64 num;
1295                     if (!gst_ebml_read_uint (ebml, &id, &num)) {
1296                       res = FALSE;
1297                       break;
1298                     }
1299                     idx.track = num;
1300                     break;
1301                   }
1302
1303                   /* position in file */
1304                   case GST_MATROSKA_ID_CUECLUSTERPOSITION: {
1305                     guint64 num;
1306                     if (!gst_ebml_read_uint (ebml, &id, &num)) {
1307                       res = FALSE;
1308                       break;
1309                     }
1310                     idx.pos = num;
1311                     break;
1312                   }
1313
1314                   default:
1315                     GST_WARNING ("Unknown entry 0x%x in CuesTrackPositions", id);
1316                     /* fall-through */
1317
1318                   case GST_EBML_ID_VOID:
1319                     if (!gst_ebml_read_skip (ebml))
1320                       res = FALSE;
1321                     break;
1322                 }
1323
1324                 if (demux->level_up) {
1325                   demux->level_up--;
1326                   break;
1327                 }
1328               }
1329
1330               break;
1331
1332             default:
1333               GST_WARNING ("Unknown entry 0x%x in cuespoint index", id);
1334               /* fall-through */
1335
1336             case GST_EBML_ID_VOID:
1337               if (!gst_ebml_read_skip (ebml))
1338                 res = FALSE;
1339               break;
1340           }
1341
1342           if (demux->level_up) {
1343             demux->level_up--;
1344             break;
1345           }
1346         }
1347
1348         /* so let's see if we got what we wanted */
1349         if (idx.pos   != (guint64) -1 &&
1350             idx.time  != (guint64) -1 &&
1351             idx.track != (guint16) -1) {
1352           if (demux->num_indexes % 32 == 0) {
1353             /* re-allocate bigger index */
1354             demux->index = g_renew (GstMatroskaIndex, demux->index,
1355                                     demux->num_indexes + 32);
1356           }
1357           demux->index[demux->num_indexes].pos   = idx.pos;
1358           demux->index[demux->num_indexes].time  = idx.time;
1359           demux->index[demux->num_indexes].track = idx.track;
1360           demux->num_indexes++;
1361         }
1362
1363         break;
1364
1365       default:
1366         GST_WARNING ("Unknown entry 0x%x in cues header", id);
1367         /* fall-through */
1368
1369       case GST_EBML_ID_VOID:
1370         if (!gst_ebml_read_skip (ebml))
1371           res = FALSE;
1372         break;
1373     }
1374
1375     if (demux->level_up) {
1376       demux->level_up--;
1377       break;
1378     }
1379   }
1380
1381   if (prevent_eos) {
1382     gst_clock_set_active (demux->clock, TRUE);
1383   }
1384
1385   return res;
1386 }
1387
1388 static gboolean
1389 gst_matroska_demux_parse_info (GstMatroskaDemux *demux)
1390 {
1391   GstEbmlRead *ebml = GST_EBML_READ (demux);
1392   gboolean res = TRUE;
1393   guint32 id;
1394
1395   while (res) {
1396     if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1397       res = FALSE;
1398       break;
1399     } else if (demux->level_up) {
1400       demux->level_up--;
1401       break;
1402     }
1403
1404     switch (id) {
1405       /* cluster timecode */
1406       case GST_MATROSKA_ID_TIMECODESCALE: {
1407         guint64 num;
1408         if (!gst_ebml_read_uint (ebml, &id, &num)) {
1409           res = FALSE;
1410           break;
1411         }
1412         demux->time_scale = num;
1413         break;
1414       }
1415
1416       case GST_MATROSKA_ID_DURATION: {
1417         gdouble num;
1418         if (!gst_ebml_read_float (ebml, &id, &num)) {
1419           res = FALSE;
1420           break;
1421         }
1422         demux->duration = num * demux->time_scale;
1423         break;
1424       }
1425
1426       case GST_MATROSKA_ID_WRITINGAPP: {
1427         gchar *text;
1428         if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
1429           res = FALSE;
1430           break;
1431         }
1432         demux->writing_app = text;
1433         break;
1434       }
1435
1436       case GST_MATROSKA_ID_MUXINGAPP: {
1437         gchar *text;
1438         if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
1439           res = FALSE;
1440           break;
1441         }
1442         demux->muxing_app = text;
1443         break;
1444       }
1445
1446       case GST_MATROSKA_ID_DATEUTC: {
1447         gint64 time;
1448         if (!gst_ebml_read_date (ebml, &id, &time)) {
1449           res = FALSE;
1450           break;
1451         }
1452         demux->created = time;
1453         break;
1454       }
1455
1456       default:
1457         GST_WARNING ("Unknown entry 0x%x in info header", id);
1458         /* fall-through */
1459
1460       case GST_EBML_ID_VOID:
1461         if (!gst_ebml_read_skip (ebml))
1462           res = FALSE;
1463         break;
1464     }
1465
1466     if (demux->level_up) {
1467       demux->level_up--;
1468       break;
1469     }
1470   }
1471
1472   return res;
1473 }
1474
1475 static gboolean
1476 gst_matroska_demux_parse_metadata (GstMatroskaDemux *demux,
1477                                    gboolean          prevent_eos)
1478 {
1479   GstEbmlRead *ebml = GST_EBML_READ (demux);
1480   gboolean res = TRUE;
1481   guint32 id;
1482   guint64 length = 0;
1483
1484   if (prevent_eos) {
1485     length = gst_bytestream_length (ebml->bs);
1486     gst_clock_set_active (demux->clock, FALSE);
1487   }
1488
1489   while (res) {
1490     /* We're an element that can be seeked to. If we are, then
1491      * we want to prevent EOS, since that'll kill us. So we cache
1492      * file size and seek until there, and don't call EOS upon os. */
1493     if (prevent_eos && length == gst_bytestream_tell (ebml->bs)) {
1494       res = FALSE;
1495       break;
1496     } else if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1497       res = FALSE;
1498       break;
1499     } else if (demux->level_up) {
1500       demux->level_up--;
1501       break;
1502     }
1503
1504     switch (id) {
1505       default:
1506         GST_WARNING ("metadata unimplemented");
1507         /* fall-through */
1508
1509       case GST_EBML_ID_VOID:
1510         if (!gst_ebml_read_skip (ebml))
1511           res = FALSE;
1512         break;
1513     }
1514
1515     if (demux->level_up) {
1516       demux->level_up--;
1517       break;
1518     }
1519   }
1520
1521   if (prevent_eos) {
1522     gst_clock_set_active (demux->clock, TRUE);
1523   }
1524
1525   return res;
1526 }
1527
1528 /*
1529  * Read signed/unsigned "EBML" numbers.
1530  * Return: number of bytes processed.
1531  */
1532
1533 static gint
1534 gst_matroska_ebmlnum_uint (guint8  *data,
1535                            guint    size,
1536                            guint64 *num)
1537 {
1538   gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0;
1539   guint64 total;
1540
1541   if (size <= 0) {
1542     return -1;
1543   }
1544                                                                                 
1545   total = data[0];
1546   while (read <= 8 && !(total & len_mask)) {
1547     read++;
1548     len_mask >>= 1;
1549   }
1550   if (read > 8)
1551     return -1;
1552                                                                                 
1553   if ((total &= (len_mask - 1)) == len_mask - 1)
1554     num_ffs++;
1555   if (size < read)
1556     return -1;
1557   while (n < read) {
1558     if (data[n] == 0xff)
1559       num_ffs++;
1560     total = (total << 8) | data[n];
1561     n++;
1562   }
1563
1564   if (!total)
1565     return -1;
1566
1567   if (read == num_ffs)
1568     *num = G_MAXUINT64;
1569   else
1570     *num = total;
1571
1572   return read;
1573 }
1574
1575 static gint
1576 gst_matroska_ebmlnum_sint (guint8 *data,
1577                            guint   size,
1578                            gint64 *num)
1579 {
1580   guint64 unum;
1581   gint res;
1582
1583   /* read as unsigned number first */
1584   if ((res = gst_matroska_ebmlnum_uint (data, size, &unum)) < 0)
1585     return -1;
1586
1587   /* make signed */
1588   if (unum == G_MAXUINT64)
1589     *num = G_MAXINT64;
1590   else
1591     *num = unum - ((1 << ((7 * res) - 1)) - 1);
1592
1593   return res;
1594 }
1595
1596 static gboolean
1597 gst_matroska_demux_parse_blockgroup (GstMatroskaDemux *demux,
1598                                      guint64           cluster_time)
1599 {
1600   GstEbmlRead *ebml = GST_EBML_READ (demux);
1601   gboolean res = TRUE;
1602   guint32 id;
1603
1604   while (res) {
1605     if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1606       res = FALSE;
1607       break;
1608     } else if (demux->level_up) {
1609       demux->level_up--;
1610       break;
1611     }
1612
1613     switch (id) {
1614       /* one block inside the group. Note, block parsing is one
1615        * of the harder things, so this code is a bit complicated.
1616        * See http://www.matroska.org/ for documentation. */
1617       case GST_MATROSKA_ID_BLOCK: {
1618         GstBuffer *buf;
1619         guint8 *data;
1620         gint16 time;
1621         guint size, *lace_size = NULL;
1622         gint n, stream, flags, laces = 0;
1623         guint64 num;
1624
1625         if (!gst_ebml_read_buffer (ebml, &id, &buf)) {
1626           res = FALSE;
1627           break;
1628         }
1629         data = GST_BUFFER_DATA (buf);
1630         size = GST_BUFFER_SIZE (buf);
1631
1632         /* first byte(s): blocknum */
1633         if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0) {
1634           gst_element_error (GST_ELEMENT (demux), "Data error");
1635           gst_buffer_unref (buf);
1636           res = FALSE;
1637           break;
1638         }
1639         data += n; size -= n;
1640
1641         /* fetch stream from num */
1642         stream = gst_matroska_demux_stream_from_num (demux, num);
1643         if (size <= 3 || stream < 0 || stream >= demux->num_streams) {
1644           gst_buffer_unref (buf);
1645           GST_WARNING ("Invalid stream %d or size %u", stream, size);
1646           break;
1647         }
1648         if (!GST_PAD_IS_USABLE (demux->src[stream]->pad)) {
1649           gst_buffer_unref (buf);
1650           break;
1651         }
1652
1653         /* time (relative to cluster time) */
1654         time = (* (gint16 *) data) * demux->time_scale;
1655         time = GINT16_FROM_BE (time);
1656         data += 2; size -= 2;
1657         flags = * (guint8 *) data;
1658         data += 1; size -= 1;
1659         switch ((flags & 0x06) >> 1) {
1660           case 0x0: /* no lacing */
1661             laces = 1;
1662             lace_size = g_new (gint, 1);
1663             lace_size[0] = size;
1664             break;
1665
1666           case 0x1: /* xiph lacing */
1667           case 0x2: /* fixed-size lacing */
1668           case 0x3: /* EBML lacing */
1669             if (size == 0) {
1670               res = FALSE;
1671               break;
1672             }
1673             laces = (* (guint8 *) data) + 1;
1674             data += 1; size -= 1;
1675             lace_size = g_new0 (gint, laces);
1676
1677             switch ((flags & 0x06) >> 1) {
1678               case 0x1: /* xiph lacing */ {
1679                 guint temp, total = 0;
1680                 for (n = 0; res && n < laces - 1; n++) {
1681                   while (1) {
1682                      if (size == 0) {
1683                        res = FALSE;
1684                        break;
1685                      }
1686                      temp = * (guint8 *) data;
1687                      lace_size[n] += temp;
1688                      data += 1; size -= 1;
1689                      if (temp != 0xff)
1690                        break;
1691                   }
1692                   total += lace_size[n];
1693                 }
1694                 lace_size[n] = size - total;
1695                 break;
1696               }
1697
1698               case 0x2: /* fixed-size lacing */
1699                 for (n = 0; n < laces; n++)
1700                   lace_size[n] = size / laces;
1701                 break;
1702
1703               case 0x3: /* EBML lacing */ {
1704                 guint total;
1705                 if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0) {
1706                   gst_element_error (GST_ELEMENT (demux), "Data error");
1707                   res = FALSE;
1708                   break;
1709                 }
1710                 data += n; size -= n;
1711                 total = lace_size[0] = num;
1712                 for (n = 1; res && n < laces - 1; n++) {
1713                   gint64 snum;
1714                   gint r;
1715                   if ((r = gst_matroska_ebmlnum_sint (data, size, &snum)) < 0) {
1716                     gst_element_error (GST_ELEMENT (demux), "Data error");
1717                     res = FALSE;
1718                     break;
1719                   }
1720                   data += r; size -= r;
1721                   lace_size[n] = lace_size[0] + snum;
1722                   total += lace_size[n];
1723                 }
1724                 lace_size[n] = size - total;
1725                 break;
1726               }
1727             }
1728             break;
1729         }
1730
1731         if (res) {
1732           for (n = 0; n < laces; n++) {
1733             GstBuffer *sub = gst_buffer_create_sub (buf,
1734                                                     GST_BUFFER_SIZE (buf) - size,
1735                                                     lace_size[n]);
1736
1737             if (cluster_time != GST_CLOCK_TIME_NONE)
1738               GST_BUFFER_TIMESTAMP (sub) = cluster_time + time;
1739
1740             /* FIXME: duration */
1741
1742             gst_pad_push (demux->src[stream]->pad, GST_DATA (sub));
1743
1744             size -= lace_size[n];
1745           }
1746         }
1747
1748         g_free (lace_size);
1749         gst_buffer_unref (buf);
1750         break;
1751       }
1752
1753       case GST_MATROSKA_ID_BLOCKDURATION: {
1754         guint64 num;
1755         if (!gst_ebml_read_uint (ebml, &id, &num)) {
1756           res = FALSE;
1757           break;
1758         }
1759         GST_WARNING ("FIXME: implement support for BlockDuration");
1760         break;
1761       }
1762
1763       default:
1764         GST_WARNING ("Unknown entry 0x%x in blockgroup data", id);
1765         /* fall-through */
1766
1767       case GST_EBML_ID_VOID:
1768         if (!gst_ebml_read_skip (ebml))
1769           res = FALSE;
1770         break;
1771     }
1772
1773     if (demux->level_up) {
1774       demux->level_up--;
1775       break;
1776     }
1777   }
1778
1779   return res;
1780 }
1781
1782 static gboolean
1783 gst_matroska_demux_parse_cluster (GstMatroskaDemux *demux)
1784 {
1785   GstEbmlRead *ebml = GST_EBML_READ (demux);
1786   gboolean res = TRUE;
1787   guint32 id;
1788   guint64 cluster_time = GST_CLOCK_TIME_NONE;
1789
1790   /* We seek after index/header parsing before doing a new
1791    * buffer. So here. */
1792   if (demux->seek_pending != GST_CLOCK_TIME_NONE) {
1793     if (!gst_matroska_demux_handle_seek_event (demux))
1794       return FALSE;
1795     demux->seek_pending = GST_CLOCK_TIME_NONE;
1796   }
1797
1798   while (res) {
1799     if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1800       res = FALSE;
1801       break;
1802     } else if (demux->level_up) {
1803       demux->level_up--;
1804       break;
1805     }
1806
1807     switch (id) {
1808       /* cluster timecode */
1809       case GST_MATROSKA_ID_CLUSTERTIMECODE: {
1810         guint64 num;
1811         if (!gst_ebml_read_uint (ebml, &id, &num)) {
1812           res = FALSE;
1813           break;
1814         }
1815         cluster_time = num * demux->time_scale;
1816         break;
1817       }
1818
1819       /* a group of blocks inside a cluster */
1820       case GST_MATROSKA_ID_BLOCKGROUP:
1821         if (!gst_ebml_read_master (ebml, &id)) {
1822           res = FALSE;
1823           break;
1824         }
1825         res = gst_matroska_demux_parse_blockgroup (demux, cluster_time);
1826         break;
1827
1828       default:
1829         GST_WARNING ("Unknown entry 0x%x in cluster data", id);
1830         /* fall-through */
1831
1832       case GST_EBML_ID_VOID:
1833         if (!gst_ebml_read_skip (ebml))
1834           res = FALSE;
1835         break;
1836     }
1837
1838     if (demux->level_up) {
1839       demux->level_up--;
1840       break;
1841     }
1842   }
1843
1844   return res;
1845 }
1846
1847 static gboolean
1848 gst_matroska_demux_parse_contents (GstMatroskaDemux *demux)
1849 {
1850   GstEbmlRead *ebml = GST_EBML_READ (demux);
1851   gboolean res = TRUE;
1852   guint32 id;
1853
1854   while (res) {
1855     if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1856       res = FALSE;
1857       break;
1858     } else if (demux->level_up) {
1859       demux->level_up--;
1860       break;
1861     }
1862
1863     switch (id) {
1864       case GST_MATROSKA_ID_SEEKENTRY: {
1865         guint32 seek_id = 0;
1866         guint64 seek_pos = (guint64) -1, t;
1867
1868         if (!gst_ebml_read_master (ebml, &id)) {
1869           res = FALSE;
1870           break;
1871         }
1872
1873         while (res) {
1874           if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1875             res = FALSE;
1876             break;
1877           } else if (demux->level_up) {
1878             demux->level_up--;
1879             break;
1880           }
1881
1882           switch (id) {
1883             case GST_MATROSKA_ID_SEEKID:
1884               if (!gst_ebml_read_uint (ebml, &id, &t))
1885                 res = FALSE;
1886               seek_id = t;
1887               break;
1888
1889             case GST_MATROSKA_ID_SEEKPOSITION:
1890               if (!gst_ebml_read_uint (ebml, &id, &seek_pos))
1891                 res = FALSE;
1892               break;
1893
1894             default:
1895               GST_WARNING ("Unknown seekhead ID 0x%x", id);
1896               /* fall-through */
1897
1898             case GST_EBML_ID_VOID:
1899               if (!gst_ebml_read_skip (ebml))
1900                 res = FALSE;
1901               break;
1902           }
1903
1904           if (demux->level_up) {
1905             demux->level_up--;
1906             break;
1907           }
1908         }
1909
1910         if (!seek_id || seek_pos == (guint64) -1) {
1911           GST_WARNING ("Incomplete seekhead entry (0x%x/%"
1912                        G_GUINT64_FORMAT ")", seek_id, seek_pos);
1913           break;
1914         }
1915
1916         switch (seek_id) {
1917           case GST_MATROSKA_ID_CUES:
1918           case GST_MATROSKA_ID_TAGS: {
1919             guint level_up = demux->level_up;
1920             guint64 before_pos, length;
1921             GstEbmlLevel *level;
1922             GstEvent *event;
1923
1924             /* remember */
1925             length = gst_bytestream_length (ebml->bs);
1926             before_pos = gst_bytestream_tell (ebml->bs);
1927
1928             /* check for validity */
1929             if (seek_pos + demux->segment_start + 12 >= length) {
1930               g_warning ("Seekhead reference lies outside file!");
1931               break;
1932             }
1933
1934             /* seek */
1935             if (!(event = gst_ebml_read_seek (ebml,
1936                                 seek_pos + demux->segment_start)))
1937               return FALSE;
1938             gst_event_unref (event);
1939
1940             /* we don't want to lose our seekhead level, so we add
1941              * a dummy. This is a crude hack. */
1942             level = g_new (GstEbmlLevel, 1);
1943             level->start = 0;
1944             level->length = G_MAXUINT64;
1945             ebml->level = g_list_append (ebml->level, level);
1946
1947             /* check ID */
1948             if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
1949               res = FALSE;
1950               break;
1951             }
1952             if (id != seek_id) {
1953               g_warning ("We looked for ID=0x%x but got ID=0x%x (pos=%llu)",
1954                          seek_id, id, seek_pos + demux->segment_start);
1955               goto finish;
1956             }
1957
1958             /* read master + parse */
1959             switch (id) {
1960               case GST_MATROSKA_ID_CUES:
1961                 if (!gst_ebml_read_master (ebml, &id))
1962                   res = FALSE;
1963                 else if (!gst_matroska_demux_parse_index (demux, TRUE) &&
1964                          gst_bytestream_length (ebml->bs) !=
1965                                 gst_bytestream_tell (ebml->bs))
1966                   res = FALSE;
1967                 else
1968                   demux->index_parsed = TRUE;
1969                 break;
1970               case GST_MATROSKA_ID_TAGS:
1971                 if (!gst_ebml_read_master (ebml, &id))
1972                   res = FALSE;
1973                 else if (!gst_matroska_demux_parse_metadata (demux, TRUE) &&
1974                          gst_bytestream_length (ebml->bs) !=
1975                                 gst_bytestream_tell (ebml->bs))
1976                   res = FALSE;
1977                 else
1978                   demux->metadata_parsed = TRUE;
1979                 break;
1980             }
1981             if (!res)
1982               break;
1983
1984           finish:
1985             /* remove dummy level */
1986             while (ebml->level) {
1987               guint64 length;
1988               level = g_list_last (ebml->level)->data;
1989               ebml->level = g_list_remove (ebml->level, level);
1990               length = level->length;
1991               g_free (level);
1992               if (length == G_MAXUINT64)
1993                 break;
1994             }
1995
1996             /* seek back */
1997             if (!(event = gst_ebml_read_seek (ebml, before_pos)))
1998               return FALSE;
1999             gst_event_unref (event);
2000             demux->level_up = level_up;
2001             break;
2002           }
2003
2004           default:
2005             GST_INFO ("Ignoring seekhead entry for ID=0x%x", seek_id);
2006             break;
2007         }
2008
2009         break;
2010       }
2011
2012       default:
2013         GST_WARNING ("Unknown seekhead ID 0x%x", id);
2014         /* fall-through */
2015
2016       case GST_EBML_ID_VOID:
2017         if (!gst_ebml_read_skip (ebml))
2018           res = FALSE;
2019         break;
2020     }
2021
2022     if (demux->level_up) {
2023       demux->level_up--;
2024       break;
2025     }
2026   }
2027
2028   return res;
2029 }
2030
2031 static gboolean
2032 gst_matroska_demux_loop_stream (GstMatroskaDemux *demux)
2033 {
2034   GstEbmlRead *ebml = GST_EBML_READ (demux);
2035   gboolean res = TRUE;
2036   guint32 id;
2037
2038   /* we've found our segment, start reading the different contents in here */
2039   while (res) {
2040     if (!(id = gst_ebml_peek_id (ebml, &demux->level_up))) {
2041       res = FALSE;
2042       break;
2043     } else if (demux->level_up) {
2044       demux->level_up--;
2045       break;
2046     }
2047
2048     switch (id) {
2049       /* stream info */
2050       case GST_MATROSKA_ID_INFO: {
2051         if (!gst_ebml_read_master (ebml, &id)) {
2052           res = FALSE;
2053           break;
2054         }
2055         res = gst_matroska_demux_parse_info (demux);
2056         break;
2057       }
2058
2059       /* track info headers */
2060       case GST_MATROSKA_ID_TRACKS: {
2061         if (!gst_ebml_read_master (ebml, &id)) {
2062           res = FALSE;
2063           break;
2064         }
2065         res = gst_matroska_demux_parse_tracks (demux);
2066         break;
2067       }
2068
2069       /* stream index */
2070       case GST_MATROSKA_ID_CUES: {
2071         if (!demux->index_parsed) {
2072           if (!gst_ebml_read_master (ebml, &id)) {
2073             res = FALSE;
2074             break;
2075           }
2076           res = gst_matroska_demux_parse_index (demux, FALSE);
2077         } else
2078           res = gst_ebml_read_skip (ebml);
2079         break;
2080       }
2081
2082       /* metadata */
2083       case GST_MATROSKA_ID_TAGS: {
2084         if (!demux->index_parsed) {
2085           if (!gst_ebml_read_master (ebml, &id)) {
2086             res = FALSE;
2087             break;
2088           }
2089           res = gst_matroska_demux_parse_metadata (demux, FALSE);
2090         } else
2091           res = gst_ebml_read_skip (ebml);
2092         break;
2093       }
2094
2095       /* file index (if seekable, seek to Cues/Tags to parse it) */
2096       case GST_MATROSKA_ID_SEEKHEAD: {
2097         if (!gst_ebml_read_master (ebml, &id)) {
2098           res = FALSE;
2099           break;
2100         }
2101         res = gst_matroska_demux_parse_contents (demux);
2102         break;
2103       }
2104
2105       case GST_MATROSKA_ID_CLUSTER: {
2106         if (!gst_ebml_read_master (ebml, &id)) {
2107           res = FALSE;
2108           break;
2109         }
2110         /* The idea is that we parse one cluster per loop and
2111          * then break out of the loop here. In the next call
2112          * of the loopfunc, we will get back here with the
2113          * next cluster. If an error occurs, we didn't
2114          * actually push a buffer, but we still want to break
2115          * out of the loop to handle a possible error. We'll
2116          * get back here if it's recoverable. */
2117         gst_matroska_demux_parse_cluster (demux);
2118         demux->state = GST_MATROSKA_DEMUX_STATE_DATA;
2119         res = FALSE;
2120         break;
2121       }
2122
2123       default:
2124         GST_WARNING ("Unknown matroska file header ID 0x%x", id);
2125         /* fall-through */
2126
2127       case GST_EBML_ID_VOID:
2128         if (!gst_ebml_read_skip (ebml))
2129           res = FALSE;
2130         break;
2131     }
2132
2133     if (demux->level_up) {
2134       demux->level_up--;
2135       break;
2136     }
2137   }
2138
2139   return res;
2140 }
2141
2142 static void
2143 gst_matroska_demux_loop (GstElement *element)
2144 {
2145   GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
2146
2147   /* first, if we're to start, let's actually get starting */
2148   if (demux->state == GST_MATROSKA_DEMUX_STATE_START) {
2149     if (!gst_matroska_demux_init_stream (demux)) {
2150       return;
2151     }
2152     demux->state = GST_MATROSKA_DEMUX_STATE_HEADER;
2153   }
2154
2155   gst_matroska_demux_loop_stream (demux);
2156 }
2157
2158 static GstCaps *
2159 gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *videocontext,
2160                                const gchar                  *codec_id,
2161                                gpointer                      data,
2162                                guint                         size)
2163 {
2164   GstMatroskaTrackContext *context =
2165         (GstMatroskaTrackContext *) videocontext;
2166   GstCaps *caps = NULL;
2167
2168   if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC)) {
2169     gst_riff_strf_vids *vids = NULL;
2170     GstCaps *t;
2171
2172     if (data) {
2173       vids = (gst_riff_strf_vids *) data;
2174
2175       /* assure size is big enough */
2176       if (size < 24) {
2177         GST_WARNING ("Too small BITMAPINFOHEADER (%d bytes)", size);
2178         return NULL;
2179       }
2180       if (size < sizeof (gst_riff_strf_vids)) {
2181         vids = (gst_riff_strf_vids *) g_realloc (vids, sizeof (gst_riff_strf_vids));
2182       }
2183
2184       /* little-endian -> byte-order */
2185       vids->size        = GUINT32_FROM_LE (vids->size);
2186       vids->width       = GUINT32_FROM_LE (vids->width);
2187       vids->height      = GUINT32_FROM_LE (vids->height);
2188       vids->planes      = GUINT16_FROM_LE (vids->planes);
2189       vids->bit_cnt     = GUINT16_FROM_LE (vids->bit_cnt);
2190       vids->compression = GUINT32_FROM_LE (vids->compression);
2191       vids->image_size  = GUINT32_FROM_LE (vids->image_size);
2192       vids->xpels_meter = GUINT32_FROM_LE (vids->xpels_meter);
2193       vids->ypels_meter = GUINT32_FROM_LE (vids->ypels_meter);
2194       vids->num_colors  = GUINT32_FROM_LE (vids->num_colors);
2195       vids->imp_colors  = GUINT32_FROM_LE (vids->imp_colors);
2196
2197       caps = gst_riff_create_video_caps (vids->compression, NULL, vids);
2198     } else {
2199       caps = gst_riff_create_video_template_caps ();
2200     }
2201
2202     for (t = caps; t != NULL; t = t->next) {
2203       gst_props_remove_entry_by_name (t->properties, "width");
2204       gst_props_remove_entry_by_name (t->properties, "height");
2205       gst_props_remove_entry_by_name (t->properties, "framerate");
2206     }
2207   } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED)) {
2208     /* how nice, this is undocumented... */
2209     if (videocontext != NULL) {
2210       guint32 fourcc = 0;
2211
2212       switch (videocontext->fourcc) {
2213         case GST_MAKE_FOURCC ('I','4','2','0'):
2214         case GST_MAKE_FOURCC ('Y','U','Y','2'):
2215           fourcc = videocontext->fourcc;
2216           break;
2217
2218         default:
2219           GST_DEBUG ("Unknown fourcc " GST_FOURCC_FORMAT,
2220                      GST_FOURCC_ARGS (videocontext->fourcc));
2221           return NULL;
2222       }
2223
2224       caps = GST_CAPS_NEW ("matroskademux_src_uncompressed",
2225                            "video/x-raw-yuv",
2226                              "format", GST_PROPS_FOURCC (fourcc));
2227     } else {
2228       caps = GST_CAPS_NEW ("matroskademux_src_uncompressed",
2229                            "video/x-raw-yuv",
2230                              "format", GST_PROPS_LIST (
2231                                 GST_PROPS_FOURCC (GST_MAKE_FOURCC ('I','4','2','0')),
2232                                 GST_PROPS_FOURCC (GST_MAKE_FOURCC ('Y','U','Y','2')),
2233                                 GST_PROPS_FOURCC (GST_MAKE_FOURCC ('Y','V','1','2'))
2234                              )
2235                           );
2236     }
2237   } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_SP)) {
2238     caps = GST_CAPS_NEW ("matroskademux_src_divx4",
2239                          "video/x-divx",
2240                            "divxversion", GST_PROPS_INT (4));
2241   } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP) ||
2242              !strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_AP)) {
2243     caps = GST_CAPS_NEW ("matroskademux_src_divx5",
2244                          "video/x-divx",
2245                            "divxversion", GST_PROPS_INT (5));
2246     caps = gst_caps_append (caps,
2247            GST_CAPS_NEW ("matroskademux_src_xvid",
2248                          "video/x-xvid",
2249                            NULL));
2250     caps = gst_caps_append (caps,
2251            GST_CAPS_NEW ("matroskademux_src_mpeg4asp/ap",
2252                          "video/mpeg",
2253                            "mpegversion",  GST_PROPS_INT (4),
2254                            "systemstream", GST_PROPS_BOOLEAN (FALSE)));
2255   } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3)) {
2256     caps = GST_CAPS_NEW ("matroskademux_src_msmpeg4v3",
2257                          "video/x-divx",
2258                            "divxversion", GST_PROPS_INT (3));
2259     caps = gst_caps_append (caps,
2260            GST_CAPS_NEW ("matroskademux_src_divx3",
2261                          "video/x-msmpeg",
2262                            "msmpegversion", GST_PROPS_INT (43)));
2263   } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG1) ||
2264              !strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG2)) {
2265     gint mpegversion = -1;
2266
2267     if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG1))
2268       mpegversion = 1;
2269     else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG2))
2270       mpegversion = 2;
2271     else
2272       g_assert (0);
2273
2274     caps = GST_CAPS_NEW ("matroska_demux_mpeg1",
2275                          "video/mpeg",
2276                            "systemstream", GST_PROPS_BOOLEAN (FALSE),
2277                            "mpegversion",  GST_PROPS_INT (mpegversion));
2278   } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MJPEG)) {
2279     caps = GST_CAPS_NEW ("matroska_demux_mjpeg",
2280                          "video/x-jpeg",
2281                            NULL);
2282   } else {
2283     GST_WARNING ("Unknown codec '%s', cannot build Caps",
2284                  codec_id);
2285   }
2286
2287   if (caps != NULL) {
2288     GstCaps *one;
2289     GstPropsEntry *fps = NULL;
2290     GstPropsEntry *width = NULL, *height = NULL;
2291     GstPropsEntry *pixel_width = NULL, *pixel_height = NULL;
2292
2293     for (one = caps; one != NULL; one = one->next) { 
2294       if (videocontext != NULL) {
2295         if (videocontext->pixel_width > 0 &&
2296             videocontext->pixel_height > 0) {
2297           gint w = videocontext->pixel_width;
2298           gint h = videocontext->pixel_height;
2299
2300           width = gst_props_entry_new ("width",
2301                                        GST_PROPS_INT (w));
2302           height = gst_props_entry_new ("height",
2303                                         GST_PROPS_INT (h));
2304         }
2305 #if 0
2306         if (videocontext->display_width > 0 &&
2307             videocontext->display_height > 0) {
2308           gint w = 100 * videocontext->display_width / videocontext->pixel_width;
2309           gint h = 100 * videocontext->display_height / videocontext->pixel_height;
2310
2311           pixel_width = gst_props_entry_new ("pixel_width",
2312                                              GST_PROPS_INT (w));
2313           pixel_height = gst_props_entry_new ("pixel_height",
2314                                               GST_PROPS_INT (h));
2315         }
2316 #endif
2317         if (context->default_duration > 0) {
2318           gfloat framerate = 1. * GST_SECOND / context->default_duration;
2319
2320           fps = gst_props_entry_new ("framerate",
2321                                      GST_PROPS_FLOAT (framerate));
2322         } else {
2323           /* sort of a hack to get most codecs to support,
2324            * even if the default_duration is missing */
2325           fps = gst_props_entry_new ("framerate", GST_PROPS_FLOAT (25.));
2326         }
2327       } else {
2328         width = gst_props_entry_new ("width",
2329                                      GST_PROPS_INT_RANGE (16, 4096));
2330         height = gst_props_entry_new ("height",
2331                                       GST_PROPS_INT_RANGE (16, 4096));
2332 #if 0
2333         pixel_width = gst_props_entry_new ("pixel_width",
2334                                            GST_PROPS_INT_RANGE (0, 255));
2335         pixel_height = gst_props_entry_new ("pixel_height",
2336                                             GST_PROPS_INT_RANGE (0, 255));
2337 #endif
2338         fps = gst_props_entry_new ("framerate",
2339                                    GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT));
2340       }
2341
2342       if (one->properties == NULL) {
2343         one->properties = gst_props_empty_new ();
2344       }
2345
2346       if (width != NULL && height != NULL) {
2347         gst_props_add_entry (one->properties, width);
2348         gst_props_add_entry (one->properties, height);
2349       }
2350
2351       if (pixel_width != NULL && pixel_height != NULL) {
2352         gst_props_add_entry (one->properties, pixel_width);
2353         gst_props_add_entry (one->properties, pixel_height);
2354       }
2355
2356       if (fps != NULL) {
2357         gst_props_add_entry (one->properties, fps);
2358       }
2359     }
2360   }
2361
2362   return caps;
2363 }
2364
2365 static GstCaps *
2366 gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext *audiocontext,
2367                                const gchar                  *codec_id,
2368                                gpointer                      data,
2369                                guint                         size)
2370 {
2371   GstMatroskaTrackContext *context =
2372         (GstMatroskaTrackContext *) audiocontext;
2373   GstCaps *caps = NULL;
2374
2375   if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1) ||
2376       !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2) ||
2377       !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3)) {
2378     gint layer = -1;
2379
2380     if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1))
2381       layer = 1;
2382     else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2))
2383       layer = 2;
2384     else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3))
2385       layer = 3;
2386     else
2387       g_assert (0);
2388
2389     caps = GST_CAPS_NEW ("matroskademux_mpeg1-l1",
2390                          "audio/mpeg",
2391                            "mpegversion",  GST_PROPS_INT (1),
2392                            "layer",        GST_PROPS_INT (layer));
2393   } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE) ||
2394              !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE)) {
2395     gint endianness = -1;
2396     GstPropsEntry *depth, *width, *sign;
2397
2398     if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE))
2399       endianness = G_BIG_ENDIAN;
2400     else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE))
2401       endianness = G_LITTLE_ENDIAN;
2402     else
2403       g_assert (0);
2404
2405     if (context != NULL) {
2406       width = gst_props_entry_new ("width",
2407                         GST_PROPS_INT (audiocontext->bitdepth));
2408       depth = gst_props_entry_new ("depth",
2409                         GST_PROPS_INT (audiocontext->bitdepth));
2410       sign = gst_props_entry_new ("signed",
2411                         GST_PROPS_BOOLEAN (audiocontext->bitdepth == 8));
2412     } else {
2413       width = gst_props_entry_new ("width", GST_PROPS_LIST (
2414                         GST_PROPS_INT (8),
2415                         GST_PROPS_INT (16)));
2416       depth = gst_props_entry_new ("depth", GST_PROPS_LIST (
2417                         GST_PROPS_INT (8),
2418                         GST_PROPS_INT (16)));
2419       sign = gst_props_entry_new ("signed", GST_PROPS_LIST (
2420                         GST_PROPS_BOOLEAN (TRUE),
2421                         GST_PROPS_BOOLEAN (FALSE)));
2422     }
2423
2424     caps = GST_CAPS_NEW ("matroskademux_audio_raw",
2425                          "audio/x-raw-int",
2426                            "endianness", GST_PROPS_INT (endianness));
2427     gst_props_add_entry (caps->properties, width);
2428     gst_props_add_entry (caps->properties, depth);
2429     gst_props_add_entry (caps->properties, sign);
2430   } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT)) {
2431     GstPropsEntry *width;
2432
2433     if (audiocontext != NULL) {
2434       width = gst_props_entry_new ("width",
2435                         GST_PROPS_INT (audiocontext->bitdepth));
2436     } else {
2437       width = gst_props_entry_new ("width", GST_PROPS_LIST (
2438                         GST_PROPS_INT (32),
2439                         GST_PROPS_INT (64)));
2440     }
2441
2442     caps = GST_CAPS_NEW ("matroskademux_audio_float",
2443                          "audio/x-raw-float",
2444                            "endianness", GST_PROPS_INT (G_BYTE_ORDER),
2445                            "buffer-frames", GST_PROPS_INT_RANGE (1, G_MAXINT));
2446
2447     gst_props_add_entry (caps->properties, width);
2448   } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_AC3) ||
2449              !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_DTS)) {
2450     caps = GST_CAPS_NEW ("matroskademux_audio_ac3/dts",
2451                          "audio/x-ac3",
2452                            NULL);
2453   } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_VORBIS)) {
2454     caps = GST_CAPS_NEW ("matroskademux_audio_vorbis",
2455                          "audio/x-vorbis",
2456                            NULL);
2457   } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_ACM)) {
2458     gst_riff_strf_auds *auds = NULL;
2459     GstCaps *t;
2460
2461     if (data) {
2462       auds = (gst_riff_strf_auds *) data;
2463
2464       /* little-endian -> byte-order */
2465       auds->format     = GUINT16_FROM_LE (auds->format);
2466       auds->channels   = GUINT16_FROM_LE (auds->channels);
2467       auds->rate       = GUINT32_FROM_LE (auds->rate);
2468       auds->av_bps     = GUINT32_FROM_LE (auds->av_bps);
2469       auds->blockalign = GUINT16_FROM_LE (auds->blockalign);
2470       auds->size       = GUINT16_FROM_LE (auds->size);
2471
2472       caps = gst_riff_create_audio_caps (auds->format, NULL, auds);
2473     } else {
2474       caps = gst_riff_create_audio_template_caps ();
2475     }
2476
2477     for (t = caps; t != NULL; t = t->next) {
2478       gst_props_remove_entry_by_name (t->properties, "rate");
2479       gst_props_remove_entry_by_name (t->properties, "channels");
2480     }
2481   } else if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG2,
2482                        strlen (GST_MATROSKA_CODEC_ID_AUDIO_MPEG2)) ||
2483              !strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG4,
2484                        strlen (GST_MATROSKA_CODEC_ID_AUDIO_MPEG4))) {
2485     gint mpegversion = -1;
2486
2487     if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG2,
2488                        strlen (GST_MATROSKA_CODEC_ID_AUDIO_MPEG2)))
2489       mpegversion = 2;
2490     else if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG4,
2491                        strlen (GST_MATROSKA_CODEC_ID_AUDIO_MPEG4)))
2492       mpegversion = 4;
2493     else
2494       g_assert (0);
2495
2496     caps = GST_CAPS_NEW ("matroska_demux_aac_mpeg2",
2497                          "audio/mpeg",
2498                            "mpegversion",  GST_PROPS_INT (mpegversion));
2499   } else {
2500     GST_WARNING ("Unknown codec '%s', cannot build Caps",
2501                  codec_id);
2502   }
2503
2504   if (caps != NULL) {
2505     GstCaps *one;
2506     GstPropsEntry *chans = NULL, *rate = NULL;
2507
2508     for (one = caps; one != NULL; one = one->next) { 
2509       if (audiocontext != NULL) {
2510         if (audiocontext->samplerate > 0 &&
2511             audiocontext->channels > 0) {
2512           chans = gst_props_entry_new ("channels",
2513                                 GST_PROPS_INT (audiocontext->channels));
2514           rate = gst_props_entry_new ("rate",
2515                                 GST_PROPS_INT (audiocontext->samplerate));
2516         }
2517       } else {
2518         chans = gst_props_entry_new ("channels",
2519                                 GST_PROPS_INT_RANGE (1, 6));
2520         rate = gst_props_entry_new ("rate",
2521                                 GST_PROPS_INT_RANGE (4000, 96000));
2522       }
2523
2524       if (caps->properties == NULL) {
2525         caps->properties = gst_props_empty_new ();
2526       }
2527
2528       if (chans != NULL && rate != NULL) {
2529         gst_props_add_entry (caps->properties, chans);
2530         gst_props_add_entry (caps->properties, rate);
2531       }
2532     }
2533   }
2534
2535   return caps;
2536 }
2537
2538 static GstCaps *
2539 gst_matroska_demux_complex_caps (GstMatroskaTrackComplexContext *complexcontext,
2540                                  const gchar                    *codec_id,
2541                                  gpointer                        data,
2542                                  guint                           size)
2543 {
2544   GstCaps *caps = NULL;
2545
2546   //..
2547
2548   return caps;
2549 }
2550
2551 static GstCaps *
2552 gst_matroska_demux_subtitle_caps (GstMatroskaTrackSubtitleContext *subtitlecontext,
2553                                   const gchar                     *codec_id,
2554                                   gpointer                         data,
2555                                   guint                            size)
2556 {
2557   GstCaps *caps = NULL;
2558
2559   //..
2560
2561   return caps;
2562 }
2563
2564 static GstElementStateReturn
2565 gst_matroska_demux_change_state (GstElement *element)
2566 {
2567   GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
2568
2569   switch (GST_STATE_TRANSITION (element)) {
2570     case GST_STATE_PAUSED_TO_READY:
2571       gst_matroska_demux_reset (GST_ELEMENT (demux));
2572       break;
2573     default:
2574       break;
2575   }
2576
2577   if (((GstElementClass *) parent_class)->change_state)
2578     return ((GstElementClass *) parent_class)->change_state (element);
2579
2580   return GST_STATE_SUCCESS;
2581 }
2582
2583 static void
2584 gst_matroska_demux_get_property (GObject    *object,
2585                                  guint       prop_id,
2586                                  GValue     *value,
2587                                  GParamSpec *pspec)
2588 {
2589   GstMatroskaDemux *demux;
2590
2591   g_return_if_fail (GST_IS_MATROSKA_DEMUX (object));
2592   demux = GST_MATROSKA_DEMUX (object);
2593
2594   switch (prop_id) {
2595     case ARG_STREAMINFO:
2596       g_value_set_boxed (value, demux->streaminfo);
2597       break;
2598     case ARG_METADATA:
2599       g_value_set_boxed (value, demux->metadata);
2600       break;
2601     default:
2602       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2603       break;
2604   }
2605 }
2606
2607 gboolean
2608 gst_matroska_demux_plugin_init (GstPlugin *plugin)
2609 {
2610   gint i;
2611   GstCaps *videosrccaps = NULL, *audiosrccaps = NULL,
2612           *subtitlesrccaps = NULL, *temp;
2613   const gchar *video_id[] = {
2614     GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC,
2615     GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED,
2616     GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_SP,
2617     GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP,
2618     GST_MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3,
2619     GST_MATROSKA_CODEC_ID_VIDEO_MPEG1,
2620     GST_MATROSKA_CODEC_ID_VIDEO_MPEG2,
2621     GST_MATROSKA_CODEC_ID_VIDEO_MJPEG,
2622     /* TODO: Real/Quicktime */
2623     /* FILLME */
2624     NULL,
2625   }, *audio_id[] = {
2626     GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1,
2627     GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2,
2628     GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3,
2629     GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE,
2630     GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE,
2631     GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT,
2632     GST_MATROSKA_CODEC_ID_AUDIO_AC3,
2633     GST_MATROSKA_CODEC_ID_AUDIO_ACM,
2634     GST_MATROSKA_CODEC_ID_AUDIO_VORBIS,
2635     GST_MATROSKA_CODEC_ID_AUDIO_MPEG2,
2636     GST_MATROSKA_CODEC_ID_AUDIO_MPEG4,
2637     /* TODO: AC3-9/10, Real, Musepack, Quicktime */
2638     /* FILLME */
2639     NULL,
2640   }, *complex_id[] = {
2641     /* FILLME */
2642     NULL,
2643   }, *subtitle_id[] = {
2644     /* FILLME */
2645     NULL,
2646   };
2647
2648   /* this filter needs the riff parser */
2649   if (!gst_library_load ("gstbytestream") ||
2650       !gst_library_load ("riff")) /* for fourcc stuff */
2651     return FALSE;
2652
2653   /* video src template */
2654   for (i = 0; video_id[i] != NULL; i++) {
2655     temp = gst_matroska_demux_video_caps (NULL, video_id[i], NULL, 0);
2656     videosrccaps = gst_caps_append (videosrccaps, temp);
2657   }
2658   for (i = 0; complex_id[i] != NULL; i++) {
2659     temp = gst_matroska_demux_complex_caps (NULL, video_id[i], NULL, 0);
2660     videosrccaps = gst_caps_append (videosrccaps, temp);
2661   }
2662   videosrctempl = gst_pad_template_new ("video_%02d",
2663                                         GST_PAD_SRC,
2664                                         GST_PAD_SOMETIMES,
2665                                         videosrccaps, NULL);
2666
2667   /* audio src template */
2668   for (i = 0; audio_id[i] != NULL; i++) {
2669     temp = gst_matroska_demux_audio_caps (NULL, audio_id[i], NULL, 0);
2670     audiosrccaps = gst_caps_append (audiosrccaps, temp);
2671   }
2672   audiosrctempl = gst_pad_template_new ("audio_%02d",
2673                                         GST_PAD_SRC,
2674                                         GST_PAD_SOMETIMES,
2675                                         audiosrccaps, NULL);
2676
2677   /* subtitle src template */
2678   for (i = 0; subtitle_id[i] != NULL; i++) {
2679     temp = gst_matroska_demux_subtitle_caps (NULL, subtitle_id[i], NULL, 0);
2680     subtitlesrccaps = gst_caps_append (subtitlesrccaps, temp);
2681   }
2682   subtitlesrctempl = gst_pad_template_new ("subtitle_%02d",
2683                                            GST_PAD_SRC,
2684                                            GST_PAD_SOMETIMES,
2685                                            subtitlesrccaps, NULL);
2686
2687   /* create an elementfactory for the matroska_demux element */
2688   if (!gst_element_register (plugin, "matroskademux",
2689                              GST_RANK_PRIMARY, GST_TYPE_MATROSKA_DEMUX))
2690     return FALSE;
2691
2692   return TRUE;
2693 }