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