gst/matroska/ebml-write.c: Use GDOUBLE_TO_BE() instead of (probably slower) custom...
authorSebastian Dröge <slomo@circular-chaos.org>
Tue, 10 Jun 2008 10:44:53 +0000 (10:44 +0000)
committerSebastian Dröge <slomo@circular-chaos.org>
Tue, 10 Jun 2008 10:44:53 +0000 (10:44 +0000)
Original commit message from CVS:
* gst/matroska/ebml-write.c: (gst_ebml_write_float):
Use GDOUBLE_TO_BE() instead of (probably slower) custom code.
* gst/matroska/matroska-demux.c: (gst_matroska_demux_base_init),
(gst_matroska_demux_class_init), (gst_matroska_demux_init),
(gst_matroska_track_free), (gst_matroska_demux_encoding_cmp),
(gst_matroska_demux_read_track_encodings),
(gst_matroska_demux_add_stream),
(gst_matroska_demux_handle_src_query),
(gst_matroska_demux_init_stream),
(gst_matroska_demux_parse_index_cuetrack),
(gst_matroska_demux_parse_index_pointentry),
(gst_matroska_demux_parse_info),
(gst_matroska_demux_parse_metadata_id_simple_tag),
(gst_matroska_demux_parse_metadata),
(gst_matroska_demux_add_wvpk_header), (gst_matroska_decode_buffer),
(gst_matroska_demux_parse_blockgroup_or_simpleblock),
(gst_matroska_demux_parse_cluster),
(gst_matroska_demux_parse_contents_seekentry),
(gst_matroska_demux_loop_stream_parse_id),
(gst_matroska_demux_loop), (gst_matroska_demux_video_caps),
(gst_matroska_demux_audio_caps),
(gst_matroska_demux_subtitle_caps):
* gst/matroska/matroska-demux.h:
* gst/matroska/matroska-ids.c:
(gst_matroska_track_init_subtitle_context):
* gst/matroska/matroska-ids.h:
* gst/matroska/matroska-mux.c: (gst_matroska_mux_base_init),
(gst_matroska_mux_class_init), (gst_matroska_mux_init),
(gst_matroska_mux_create_uid), (gst_matroska_mux_reset),
(gst_matroska_mux_video_pad_setcaps),
(gst_matroska_mux_audio_pad_setcaps),
(gst_matroska_mux_subtitle_pad_setcaps),
(gst_matroska_mux_request_new_pad),
(gst_matroska_mux_track_header), (gst_matroska_mux_start),
(gst_matroska_mux_write_simple_tag), (gst_matroska_mux_finish),
(gst_matroska_mux_write_data), (gst_matroska_mux_collected),
(gst_matroska_mux_set_property):
Add many FIXMEs/TODOs all over the matroska muxer and demuxer
elements, do some checks for valid values in the demuxer, handle
tracktimecodescale in the demuxer, set correct default values for all
settings in the demuxer, review and add all missing matroska
IDs and some more raw YUV formats, and some trivial cleanup.

ChangeLog
gst/matroska/ebml-write.c
gst/matroska/matroska-demux.c
gst/matroska/matroska-demux.h
gst/matroska/matroska-ids.c
gst/matroska/matroska-ids.h
gst/matroska/matroska-mux.c

index 8e9174a..5a66eff 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,51 @@
 2008-06-10  Sebastian Dröge  <slomo@circular-chaos.org>
 
+       * gst/matroska/ebml-write.c: (gst_ebml_write_float):
+       Use GDOUBLE_TO_BE() instead of (probably slower) custom code.
+
+       * gst/matroska/matroska-demux.c: (gst_matroska_demux_base_init),
+       (gst_matroska_demux_class_init), (gst_matroska_demux_init),
+       (gst_matroska_track_free), (gst_matroska_demux_encoding_cmp),
+       (gst_matroska_demux_read_track_encodings),
+       (gst_matroska_demux_add_stream),
+       (gst_matroska_demux_handle_src_query),
+       (gst_matroska_demux_init_stream),
+       (gst_matroska_demux_parse_index_cuetrack),
+       (gst_matroska_demux_parse_index_pointentry),
+       (gst_matroska_demux_parse_info),
+       (gst_matroska_demux_parse_metadata_id_simple_tag),
+       (gst_matroska_demux_parse_metadata),
+       (gst_matroska_demux_add_wvpk_header), (gst_matroska_decode_buffer),
+       (gst_matroska_demux_parse_blockgroup_or_simpleblock),
+       (gst_matroska_demux_parse_cluster),
+       (gst_matroska_demux_parse_contents_seekentry),
+       (gst_matroska_demux_loop_stream_parse_id),
+       (gst_matroska_demux_loop), (gst_matroska_demux_video_caps),
+       (gst_matroska_demux_audio_caps),
+       (gst_matroska_demux_subtitle_caps):
+       * gst/matroska/matroska-demux.h:
+       * gst/matroska/matroska-ids.c:
+       (gst_matroska_track_init_subtitle_context):
+       * gst/matroska/matroska-ids.h:
+       * gst/matroska/matroska-mux.c: (gst_matroska_mux_base_init),
+       (gst_matroska_mux_class_init), (gst_matroska_mux_init),
+       (gst_matroska_mux_create_uid), (gst_matroska_mux_reset),
+       (gst_matroska_mux_video_pad_setcaps),
+       (gst_matroska_mux_audio_pad_setcaps),
+       (gst_matroska_mux_subtitle_pad_setcaps),
+       (gst_matroska_mux_request_new_pad),
+       (gst_matroska_mux_track_header), (gst_matroska_mux_start),
+       (gst_matroska_mux_write_simple_tag), (gst_matroska_mux_finish),
+       (gst_matroska_mux_write_data), (gst_matroska_mux_collected),
+       (gst_matroska_mux_set_property):
+       Add many FIXMEs/TODOs all over the matroska muxer and demuxer
+       elements, do some checks for valid values in the demuxer, handle
+       tracktimecodescale in the demuxer, set correct default values for all
+       settings in the demuxer, review and add all missing matroska
+       IDs and some more raw YUV formats, and some trivial cleanup.
+
+2008-06-10  Sebastian Dröge  <slomo@circular-chaos.org>
+
        * ext/pulse/pulsemixer.c: (gst_pulsemixer_base_init),
        (gst_pulsemixer_class_init):
        * ext/pulse/pulsesink.c: (gst_pulsesink_base_init),
index 7bc5a75..e2a6a2f 100644 (file)
@@ -25,6 +25,7 @@
 #endif
 
 #include <string.h>
+#include <gst/floatcast/floatcast.h>
 
 #include "ebml-write.h"
 #include "ebml-ids.h"
@@ -541,21 +542,12 @@ gst_ebml_write_sint (GstEbmlWrite * ebml, guint32 id, gint64 num)
 void
 gst_ebml_write_float (GstEbmlWrite * ebml, guint32 id, gdouble num)
 {
-#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
-  gint n;
-#endif
   GstBuffer *buf = gst_ebml_write_element_new (ebml, sizeof (num));
 
   gst_ebml_write_element_id (buf, id);
   gst_ebml_write_element_size (buf, 8);
-#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
-  for (n = 0; n < 8; n++) {
-    GST_BUFFER_DATA (buf)[GST_BUFFER_SIZE (buf)] = ((guint8 *) & num)[7 - n];
-    GST_BUFFER_SIZE (buf) += 1;
-  }
-#else
+  num = GDOUBLE_TO_BE (num);
   gst_ebml_write_element_data (buf, (guint8 *) & num, 8);
-#endif
   gst_ebml_write_element_push (ebml, buf);
 }
 
index 85bfcaf..7b4933c 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
+/* TODO: "Unkown track header" & "Unknown entry": implement if useful
+ * TODO: dynamic number of tracks without upper bound
+ * FIXME: uint64 -> int64 overflows!
+ * FIXME: ignore 0xBF aka. CRC32 elements without warning
+ * TODO: check CRC32 if present
+ * FIXME: go out of loops, don't add Track or whatever if something goes wrong
+ *        or required elements are not there
+ * TODO: there can be a segment after the first segment. Handle like
+ *       chained oggs. Fixes #334082
+ * TODO: handle gaps better, especially gaps at the start of a track.
+ *       Needs sending of filler segments, closing of segments and
+ *       other magic... Fixes #429322
+ * TODO: Test samples: http://www.matroska.org/samples/matrix/index.html
+ *                     http://samples.mplayerhq.hu/Matroska/
+ * TODO: check if demuxing is done correct for all codecs according to spec
+ * TODO: seeking with incomplete or without CUE
+ */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -27,8 +45,8 @@
 #include <math.h>
 #include <string.h>
 
-/* For AVI compatibility mode... Who did that? */
-/* and for fourcc stuff */
+/* For AVI compatibility mode
+   and for fourcc stuff */
 #include <gst/riff/riff-read.h>
 #include <gst/riff/riff-ids.h>
 #include <gst/riff/riff-media.h>
@@ -56,6 +74,8 @@ static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_STATIC_CAPS ("video/x-matroska")
     );
 
+/* TODO: fill in caps! */
+
 static GstStaticPadTemplate audio_src_templ =
 GST_STATIC_PAD_TEMPLATE ("audio_%02d",
     GST_PAD_SRC,
@@ -79,10 +99,6 @@ static GstStaticPadTemplate subtitle_src_templ =
         "application/x-subtitle-unknown")
     );
 
-static void gst_matroska_demux_base_init (GstMatroskaDemuxClass * klass);
-static void gst_matroska_demux_class_init (GstMatroskaDemuxClass * klass);
-static void gst_matroska_demux_init (GstMatroskaDemux * demux);
-
 /* element functions */
 static void gst_matroska_demux_loop (GstPad * pad);
 
@@ -93,6 +109,7 @@ static gboolean gst_matroska_demux_element_send_event (GstElement * element,
 static gboolean gst_matroska_demux_sink_activate_pull (GstPad * sinkpad,
     gboolean active);
 static gboolean gst_matroska_demux_sink_activate (GstPad * sinkpad);
+
 static gboolean gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
     GstEvent * event);
 static gboolean gst_matroska_demux_handle_src_event (GstPad * pad,
@@ -113,8 +130,6 @@ static GstCaps *gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext
 static GstCaps *gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext
     * audiocontext,
     const gchar * codec_id, gpointer data, guint size, gchar ** codec_name);
-static GstCaps *gst_matroska_demux_complex_caps (GstMatroskaTrackComplexContext
-    * complexcontext, const gchar * codec_id, gpointer data, guint size);
 static GstCaps
     * gst_matroska_demux_subtitle_caps (GstMatroskaTrackSubtitleContext *
     subtitlecontext, const gchar * codec_id, gpointer data, guint size);
@@ -122,43 +137,13 @@ static GstCaps
 /* stream methods */
 static void gst_matroska_demux_reset (GstElement * element);
 
-static GstEbmlReadClass *parent_class;  /* NULL; */
-
-static GType
-gst_matroska_demux_get_type (void)
-{
-  static GType gst_matroska_demux_type; /* 0 */
-
-  if (!gst_matroska_demux_type) {
-    static const GTypeInfo gst_matroska_demux_info = {
-      sizeof (GstMatroskaDemuxClass),
-      (GBaseInitFunc) gst_matroska_demux_base_init,
-      NULL,
-      (GClassInitFunc) gst_matroska_demux_class_init,
-      NULL,
-      NULL,
-      sizeof (GstMatroskaDemux),
-      0,
-      (GInstanceInitFunc) gst_matroska_demux_init,
-    };
-
-    gst_matroska_demux_type =
-        g_type_register_static (GST_TYPE_EBML_READ,
-        "GstMatroskaDemux", &gst_matroska_demux_info, 0);
-  }
-
-  return gst_matroska_demux_type;
-}
+GST_BOILERPLATE (GstMatroskaDemux, gst_matroska_demux, GstEbmlRead,
+    GST_TYPE_EBML_READ);
 
 static void
-gst_matroska_demux_base_init (GstMatroskaDemuxClass * klass)
+gst_matroska_demux_base_init (gpointer klass)
 {
   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-  static const GstElementDetails gst_matroska_demux_details =
-      GST_ELEMENT_DETAILS ("Matroska demuxer",
-      "Codec/Demuxer",
-      "Demuxes a Matroska Stream into video/audio/subtitles",
-      "Ronald Bultje <rbultje@ronald.bitfreak.net>");
 
   gst_element_class_add_pad_template (element_class,
       gst_static_pad_template_get (&video_src_templ));
@@ -168,20 +153,20 @@ gst_matroska_demux_base_init (GstMatroskaDemuxClass * klass)
       gst_static_pad_template_get (&subtitle_src_templ));
   gst_element_class_add_pad_template (element_class,
       gst_static_pad_template_get (&sink_templ));
-  gst_element_class_set_details (element_class, &gst_matroska_demux_details);
 
-  GST_DEBUG_CATEGORY_INIT (matroskademux_debug, "matroskademux", 0,
-      "Matroska demuxer");
+  gst_element_class_set_details_simple (element_class, "Matroska demuxer",
+      "Codec/Demuxer",
+      "Demuxes a Matroska Stream into video/audio/subtitles",
+      "Ronald Bultje <rbultje@ronald.bitfreak.net>");
 }
 
 static void
 gst_matroska_demux_class_init (GstMatroskaDemuxClass * klass)
 {
-  GstElementClass *gstelement_class;
-
-  gstelement_class = (GstElementClass *) klass;
+  GstElementClass *gstelement_class = (GstElementClass *) klass;;
 
-  parent_class = g_type_class_peek_parent (klass);
+  GST_DEBUG_CATEGORY_INIT (matroskademux_debug, "matroskademux", 0,
+      "Matroska demuxer");
 
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_matroska_demux_change_state);
@@ -190,14 +175,12 @@ gst_matroska_demux_class_init (GstMatroskaDemuxClass * klass)
 }
 
 static void
-gst_matroska_demux_init (GstMatroskaDemux * demux)
+gst_matroska_demux_init (GstMatroskaDemux * demux,
+    GstMatroskaDemuxClass * klass)
 {
-  GstElementClass *klass = GST_ELEMENT_GET_CLASS (demux);
   gint i;
 
-  demux->sinkpad =
-      gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
-          "sink"), "sink");
+  demux->sinkpad = gst_pad_new_from_static_template (&sink_templ, "sink");
   gst_pad_set_activate_function (demux->sinkpad,
       GST_DEBUG_FUNCPTR (gst_matroska_demux_sink_activate));
   gst_pad_set_activatepull_function (demux->sinkpad,
@@ -239,6 +222,9 @@ gst_matroska_track_free (GstMatroskaTrackContext * track)
     g_array_free (track->encodings, TRUE);
   }
 
+  if (track->pending_tags)
+    gst_tag_list_free (track->pending_tags);
+
   g_free (track);
 }
 
@@ -282,6 +268,7 @@ static void
 gst_matroska_demux_reset (GstElement * element)
 {
   GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
+
   guint i;
 
   /* reset input */
@@ -347,11 +334,14 @@ static gint
 gst_matroska_demux_encoding_cmp (gconstpointer a, gconstpointer b)
 {
   const GstMatroskaTrackEncoding *enc_a;
+
   const GstMatroskaTrackEncoding *enc_b;
 
   enc_a = (const GstMatroskaTrackEncoding *) a;
   enc_b = (const GstMatroskaTrackEncoding *) b;
 
+  /* FIXME: give warning if diff == 0, should be unique! */
+
   return (gint) enc_b->order - (gint) enc_a->order;
 }
 
@@ -360,6 +350,7 @@ gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml,
     GstMatroskaDemux * demux, GstMatroskaTrackContext * context)
 {
   GstFlowReturn ret;
+
   guint32 id;
 
   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
@@ -380,6 +371,9 @@ gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml,
       case GST_MATROSKA_ID_CONTENTENCODING:{
         GstMatroskaTrackEncoding enc = { 0, };
 
+        /* Set default values */
+        enc.scope = 1;
+
         if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
           break;
         }
@@ -401,6 +395,7 @@ gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml,
               if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
+              /* FIXME: must be unique, check this! */
               enc.order = num;
               break;
             }
@@ -410,7 +405,7 @@ gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml,
               if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
-              if (num > 7)
+              if (num > 7 && num == 0)
                 GST_WARNING ("Unknown scope value in contents encoding.");
               else
                 enc.scope = num;
@@ -434,6 +429,8 @@ gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml,
                 break;
               }
 
+              /* FIXME: Might be compressed or encrypted, depending on ContentEncodingScope & 0x4
+               * and the previous ContentEncodingOrder */
               while (ret == GST_FLOW_OK) {
 
                 if ((ret =
@@ -454,14 +451,17 @@ gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml,
                                 &num)) != GST_FLOW_OK) {
                       break;
                     }
+                    /* FIXME: maybe don't add tracks at all for which we don't
+                     * support the compression algorithm */
                     if (num > 3)
-                      GST_WARNING ("Unknown scope value in encoding compalgo.");
+                      GST_WARNING ("Unknown value in encoding compalgo.");
                     else
                       enc.comp_algo = num;
                     break;
                   }
                   case GST_MATROSKA_ID_CONTENTCOMPSETTINGS:{
                     guint8 *data;
+
                     guint64 size;
 
 
@@ -491,7 +491,11 @@ gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml,
 
             case GST_MATROSKA_ID_CONTENTENCRYPTION:
               GST_WARNING ("Encrypted tracks not yet supported");
-              /* pass-through */
+              /* FIXME: Might be compressed, depending on ContentEncodingScope & 0x4 
+               * and the previous ContentEncodingOrder */
+              /* FIXME: don't add encrypted tracks at all */
+              ret = gst_ebml_read_skip (ebml);
+              break;
             default:
               GST_WARNING
                   ("Unknown track encoding header entry 0x%x - ignoring", id);
@@ -532,14 +536,23 @@ static GstFlowReturn
 gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
 {
   GstElementClass *klass = GST_ELEMENT_GET_CLASS (demux);
+
   GstEbmlRead *ebml = GST_EBML_READ (demux);
+
   GstMatroskaTrackContext *context;
+
   GstPadTemplate *templ = NULL;
+
   GstCaps *caps = NULL;
+
   gchar *padname = NULL;
+
   GstFlowReturn ret;
+
   guint32 id;
+
   GstTagList *list = NULL;
+
   gchar *codec = NULL;
 
   if (demux->num_streams >= GST_MATROSKA_DEMUX_MAX_STREAMS) {
@@ -557,6 +570,10 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
   context->default_duration = 0;
   context->pos = 0;
   context->set_discont = TRUE;
+  context->timecodescale = 1.0;
+  context->flags =
+      GST_MATROSKA_TRACK_ENABLED | GST_MATROSKA_TRACK_DEFAULT |
+      GST_MATROSKA_TRACK_LACING;
   context->last_flow = GST_FLOW_OK;
   demux->num_streams++;
 
@@ -574,6 +591,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
     }
 
     switch (id) {
+        /* FIXME: check unique */
         /* track number (unique stream ID) */
       case GST_MATROSKA_ID_TRACKNUMBER:{
         guint64 num;
@@ -581,6 +599,12 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
           break;
         }
+        if (num == 0) {
+          GST_WARNING ("Invalid track number (0) - skipping");
+          ret = GST_FLOW_ERROR;
+          break;
+        }
+
         context->num = num;
         break;
       }
@@ -591,6 +615,12 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
           break;
         }
+        if (num == 0) {
+          GST_WARNING ("Invalid track UID (0) - skipping");
+          ret = GST_FLOW_ERROR;
+          break;
+        }
+
         context->uid = num;
         break;
       }
@@ -607,6 +637,10 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
           GST_WARNING
               ("More than one tracktype defined in a trackentry - skipping");
           break;
+        } else if (track_type < 1 || track_type > 254) {
+          GST_WARNING ("Invalid track type (%u) - skipping",
+              (guint) track_type);
+          break;
         }
 
         /* ok, so we're actually going to reallocate this thing */
@@ -617,13 +651,12 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
           case GST_MATROSKA_TRACK_TYPE_AUDIO:
             gst_matroska_track_init_audio_context (&context);
             break;
-          case GST_MATROSKA_TRACK_TYPE_COMPLEX:
-            gst_matroska_track_init_complex_context (&context);
-            break;
           case GST_MATROSKA_TRACK_TYPE_SUBTITLE:
             gst_matroska_track_init_subtitle_context (&context);
             break;
+          case GST_MATROSKA_TRACK_TYPE_COMPLEX:
           case GST_MATROSKA_TRACK_TYPE_LOGO:
+          case GST_MATROSKA_TRACK_TYPE_BUTTONS:
           case GST_MATROSKA_TRACK_TYPE_CONTROL:
           default:
             GST_WARNING ("Unknown or unsupported track type %"
@@ -661,29 +694,43 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
           }
 
           switch (id) {
-              /* fixme, this should be one-up, but I get it here (?) */
+              /* Should be one level up but some broken muxers write it here. */
             case GST_MATROSKA_ID_TRACKDEFAULTDURATION:{
               guint64 num;
 
               if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
+
+              if (num == 0) {
+                GST_WARNING ("Invalid track default duration (0) - ignoring");
+                break;
+              }
+
               context->default_duration = num;
               break;
             }
 
               /* video framerate */
+              /* NOTE: This one is here only for backward compatibility.
+               * Use _TRACKDEFAULDURATION one level up. */
             case GST_MATROSKA_ID_VIDEOFRAMERATE:{
               gdouble num;
 
               if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
-              if (num != 0.0) {
-                context->default_duration =
-                    gst_gdouble_to_guint64 ((gdouble) GST_SECOND / num);
-                videocontext->default_fps = num;
+
+              if (num <= 0.0) {
+                GST_WARNING ("Invalid video framerate (%lf fps) - ignoring",
+                    num);
+                break;
               }
+
+              if (context->default_duration == 0)
+                context->default_duration =
+                    gst_gdouble_to_guint64 ((gdouble) GST_SECOND * (1.0 / num));
+              videocontext->default_fps = num;
               break;
             }
 
@@ -694,6 +741,12 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
               if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
+
+              if (num == 0) {
+                GST_WARNING ("Invalid display width (0) - ignoring");
+                break;
+              }
+
               videocontext->display_width = num;
               GST_DEBUG ("display_width %" G_GUINT64_FORMAT, num);
               break;
@@ -706,6 +759,12 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
               if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
+
+              if (num == 0) {
+                GST_WARNING ("Invalid display height (0) - ignoring");
+                break;
+              }
+
               videocontext->display_height = num;
               GST_DEBUG ("display_height %" G_GUINT64_FORMAT, num);
               break;
@@ -718,6 +777,12 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
               if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
+
+              if (num == 0) {
+                GST_WARNING ("Invalid pixel width (0) - ignoring");
+                break;
+              }
+
               videocontext->pixel_width = num;
               GST_DEBUG ("pixel_width %" G_GUINT64_FORMAT, num);
               break;
@@ -730,6 +795,12 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
               if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
+
+              if (num == 0) {
+                GST_WARNING ("Invalid pixel height (0) - ignoring");
+                break;
+              }
+
               videocontext->pixel_height = num;
               GST_DEBUG ("pixel_height %" G_GUINT64_FORMAT, num);
               break;
@@ -770,7 +841,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
             }
 
               /* aspect ratio behaviour */
-            case GST_MATROSKA_ID_VIDEOASPECTRATIO:{
+            case GST_MATROSKA_ID_VIDEOASPECTRATIOTYPE:{
               guint64 num;
 
               if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
@@ -794,10 +865,22 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
               if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
+
+              if (num > G_MAXUINT32) {
+                GST_WARNING ("Invalid video colourspace (%" G_GUINT64_FORMAT
+                    ") - ignoring", num);
+                break;
+              }
               videocontext->fourcc = num;
               break;
             }
 
+            case GST_MATROSKA_ID_VIDEODISPLAYUNIT:
+            case GST_MATROSKA_ID_VIDEOPIXELCROPBOTTOM:
+            case GST_MATROSKA_ID_VIDEOPIXELCROPTOP:
+            case GST_MATROSKA_ID_VIDEOPIXELCROPLEFT:
+            case GST_MATROSKA_ID_VIDEOPIXELCROPRIGHT:
+            case GST_MATROSKA_ID_VIDEOGAMMAVALUE:
             default:
               GST_WARNING ("Unknown video track header entry 0x%x - ignoring",
                   id);
@@ -849,6 +932,17 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
               if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
+
+              if (num <= 0.0) {
+                GST_WARNING ("Invalid audio sample rate (%lf) - ignoring)",
+                    num);
+                break;
+              }
+
+              if (context->default_duration == 0)
+                context->default_duration =
+                    gst_gdouble_to_guint64 ((gdouble) GST_SECOND * (1.0 / num));
+
               audiocontext->samplerate = num;
               break;
             }
@@ -860,6 +954,12 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
               if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
+
+              if (num == 0) {
+                GST_WARNING ("Invalid audio bit depth (0) - ignoring)");
+                break;
+              }
+
               audiocontext->bitdepth = num;
               break;
             }
@@ -871,10 +971,19 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
               if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
+
+              if (num == 0) {
+                GST_WARNING
+                    ("Invalid number of audio channels (0) - ignoring)");
+                break;
+              }
+
               audiocontext->channels = num;
               break;
             }
 
+            case GST_MATROSKA_ID_AUDIOCHANNELPOSITIONS:
+            case GST_MATROSKA_ID_AUDIOOUTPUTSAMPLINGFREQ:
             default:
               GST_WARNING ("Unknown audio track header entry 0x%x - ignoring",
                   id);
@@ -907,6 +1016,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
         /* codec private data */
       case GST_MATROSKA_ID_CODECPRIVATE:{
         guint8 *data;
+
         guint64 size;
 
         if ((ret =
@@ -914,6 +1024,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
                     &size)) != GST_FLOW_OK) {
           break;
         }
+        /* TODO: might be compressed or encrypted */
         context->codec_priv = data;
         context->codec_priv_size = size;
         GST_LOG_OBJECT (demux, "%u bytes of codec private data", (guint) size);
@@ -988,6 +1099,20 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
         break;
       }
 
+        /* whether the track must be used during playback */
+      case GST_MATROSKA_ID_TRACKFLAGFORCED:{
+        guint64 num;
+
+        if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
+          break;
+
+        if (num)
+          context->flags |= GST_MATROSKA_TRACK_FORCED;
+        else
+          context->flags &= ~GST_MATROSKA_TRACK_FORCED;
+        break;
+      }
+
         /* lacing (like MPEG, where blocks don't end/start on frame
          * boundaries) */
       case GST_MATROSKA_ID_TRACKFLAGLACING:{
@@ -1010,6 +1135,12 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
           break;
         }
+
+        if (num == 0) {
+          GST_WARNING ("Invalid track default duration (0) - ignoring");
+          break;
+        }
+
         context->default_duration = num;
         break;
       }
@@ -1019,15 +1150,38 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
         break;
       }
 
+      case GST_MATROSKA_ID_TRACKTIMECODESCALE:{
+        gdouble num;
+
+        if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK)
+          break;
+
+        if (num <= 0.0) {
+          GST_WARNING ("Invalid track time code scale (%lf) - ignoring", num);
+          break;
+        }
+
+        context->timecodescale = num;
+        break;
+      }
+
       default:
         GST_WARNING ("Unknown track header entry 0x%x - ignoring", id);
         /* pass-through */
 
-        /* we ignore these because they're nothing useful (i.e. crap). */
-      case GST_MATROSKA_ID_CODECINFOURL:
-      case GST_MATROSKA_ID_CODECDOWNLOADURL:
+        /* we ignore these because they're nothing useful (i.e. crap)
+         * or simply not implemented yet. */
       case GST_MATROSKA_ID_TRACKMINCACHE:
       case GST_MATROSKA_ID_TRACKMAXCACHE:
+      case GST_MATROSKA_ID_MAXBLOCKADDITIONID:
+      case GST_MATROSKA_ID_TRACKATTACHMENTLINK:
+      case GST_MATROSKA_ID_TRACKOVERLAY:
+      case GST_MATROSKA_ID_TRACKTRANSLATE:
+      case GST_MATROSKA_ID_TRACKOFFSET:
+      case GST_MATROSKA_ID_CODECSETTINGS:
+      case GST_MATROSKA_ID_CODECINFOURL:
+      case GST_MATROSKA_ID_CODECDOWNLOADURL:
+      case GST_MATROSKA_ID_CODECDECODEALL:
       case GST_EBML_ID_VOID:
         ret = gst_ebml_read_skip (ebml);
         break;
@@ -1088,16 +1242,6 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
       break;
     }
 
-    case GST_MATROSKA_TRACK_TYPE_COMPLEX:{
-      GstMatroskaTrackComplexContext *complexcontext =
-          (GstMatroskaTrackComplexContext *) context;
-      padname = g_strdup_printf ("video_%02d", demux->num_v_streams++);
-      templ = gst_element_class_get_pad_template (klass, "video_%02d");
-      caps = gst_matroska_demux_complex_caps (complexcontext,
-          context->codec_id, context->codec_priv, context->codec_priv_size);
-      break;
-    }
-
     case GST_MATROSKA_TRACK_TYPE_SUBTITLE:{
       GstMatroskaTrackSubtitleContext *subtitlecontext =
           (GstMatroskaTrackSubtitleContext *) context;
@@ -1108,7 +1252,9 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
       break;
     }
 
+    case GST_MATROSKA_TRACK_TYPE_COMPLEX:
     case GST_MATROSKA_TRACK_TYPE_LOGO:
+    case GST_MATROSKA_TRACK_TYPE_BUTTONS:
     case GST_MATROSKA_TRACK_TYPE_CONTROL:
     default:
       /* we should already have quit by now */
@@ -1194,10 +1340,14 @@ static gboolean
 gst_matroska_demux_handle_src_query (GstPad * pad, GstQuery * query)
 {
   GstMatroskaDemux *demux;
+
   gboolean res = FALSE;
 
   demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad));
 
+  /* FIXME: do queries on the Tracks, not on the Segment.
+   * Convert between time and frames if we know the duration
+   * of one frame for the track */
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_POSITION:
     {
@@ -1251,6 +1401,7 @@ gst_matroskademux_do_index_seek (GstMatroskaDemux * demux, gint64 seek_pos,
     gint64 segment_stop, gboolean keyunit)
 {
   guint entry;
+
   guint n = 0;
 
   if (!demux->num_indexes)
@@ -1294,6 +1445,7 @@ static gboolean
 gst_matroska_demux_send_event (GstMatroskaDemux * demux, GstEvent * event)
 {
   gboolean ret = TRUE;
+
   gint i;
 
   g_return_val_if_fail (event != NULL, FALSE);
@@ -1322,6 +1474,7 @@ static gboolean
 gst_matroska_demux_element_send_event (GstElement * element, GstEvent * event)
 {
   GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
+
   gboolean res;
 
   g_return_val_if_fail (event != NULL, FALSE);
@@ -1341,14 +1494,23 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
     GstEvent * event)
 {
   GstMatroskaIndex *entry;
+
   GstSeekFlags flags;
+
   GstSeekType cur_type, stop_type;
+
   GstFormat format;
+
   GstEvent *newsegment_event;
+
   gboolean flush, keyunit;
+
   gdouble rate;
+
   gint64 cur, stop;
+
   gint64 segment_start, segment_stop;
+
   gint i;
 
   gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
@@ -1517,6 +1679,7 @@ static gboolean
 gst_matroska_demux_handle_src_event (GstPad * pad, GstEvent * event)
 {
   GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad));
+
   gboolean res = TRUE;
 
   switch (GST_EVENT_TYPE (event)) {
@@ -1546,9 +1709,13 @@ static GstFlowReturn
 gst_matroska_demux_init_stream (GstMatroskaDemux * demux)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
+
   guint32 id;
+
   gchar *doctype;
+
   guint version;
+
   GstFlowReturn ret;
 
   if ((ret = gst_ebml_read_header (ebml, &doctype, &version)) != GST_FLOW_OK)
@@ -1568,8 +1735,9 @@ gst_matroska_demux_init_stream (GstMatroskaDemux * demux)
     return GST_FLOW_ERROR;
   }
 
-  /* find segment, must be the next element */
-  while (1) {
+  /* find segment, must be the next element but search as long as
+   * we find it anyway */
+  while (TRUE) {
     guint last_level;
 
     if ((ret = gst_ebml_peek_id (ebml, &last_level, &id)) != GST_FLOW_OK) {
@@ -1605,7 +1773,9 @@ static GstFlowReturn
 gst_matroska_demux_parse_tracks (GstMatroskaDemux * demux)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
+
   GstFlowReturn ret = GST_FLOW_OK;
+
   guint32 id;
 
   while (ret == GST_FLOW_OK) {
@@ -1645,7 +1815,9 @@ gst_matroska_demux_parse_index_cuetrack (GstMatroskaDemux * demux,
     gboolean prevent_eos, GstMatroskaIndex * idx, guint64 length)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
+
   guint32 id;
+
   GstFlowReturn ret;
 
   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
@@ -1671,6 +1843,12 @@ gst_matroska_demux_parse_index_cuetrack (GstMatroskaDemux * demux,
 
         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
           goto error;
+        if (num == 0) {
+          idx->track = -1;
+          GST_WARNING ("Invalid cue track number (0)");
+          goto error;
+          break;
+        }
 
         idx->track = num;
         break;
@@ -1684,6 +1862,8 @@ gst_matroska_demux_parse_index_cuetrack (GstMatroskaDemux * demux,
         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
           goto error;
 
+        /* FIXME: may overflow, our seeks, etc are int64 based */
+
         idx->pos = num;
         break;
       }
@@ -1692,6 +1872,9 @@ gst_matroska_demux_parse_index_cuetrack (GstMatroskaDemux * demux,
         GST_WARNING ("Unknown entry 0x%x in CuesTrackPositions", id);
         /* fall-through */
 
+      case GST_MATROSKA_ID_CUEBLOCKNUMBER:
+      case GST_MATROSKA_ID_CUECODECSTATE:
+      case GST_MATROSKA_ID_CUEREFERENCE:
       case GST_EBML_ID_VOID:
         if ((ret = gst_ebml_read_skip (ebml)) != GST_FLOW_OK)
           goto error;
@@ -1718,8 +1901,11 @@ gst_matroska_demux_parse_index_pointentry (GstMatroskaDemux * demux,
     gboolean prevent_eos, guint64 length)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
+
   GstMatroskaIndex idx;
+
   guint32 id;
+
   GstFlowReturn ret;
 
   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
@@ -1756,7 +1942,7 @@ gst_matroska_demux_parse_index_pointentry (GstMatroskaDemux * demux,
       }
 
         /* position in the file + track to which it belongs */
-      case GST_MATROSKA_ID_CUETRACKPOSITION:
+      case GST_MATROSKA_ID_CUETRACKPOSITIONS:
       {
         ret = gst_matroska_demux_parse_index_cuetrack (demux, prevent_eos, &idx,
             length);
@@ -1802,8 +1988,11 @@ static GstFlowReturn
 gst_matroska_demux_parse_index (GstMatroskaDemux * demux, gboolean prevent_eos)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
+
   guint32 id;
+
   guint64 length = 0;
+
   GstFlowReturn ret = GST_FLOW_OK;
 
   if (prevent_eos) {
@@ -1854,7 +2043,9 @@ static GstFlowReturn
 gst_matroska_demux_parse_info (GstMatroskaDemux * demux)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
+
   GstFlowReturn ret = GST_FLOW_OK;
+
   guint32 id;
 
   while (ret == GST_FLOW_OK) {
@@ -1879,11 +2070,18 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux)
 
       case GST_MATROSKA_ID_DURATION:{
         gdouble num;
+
         GstClockTime dur;
 
         if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK) {
           break;
         }
+
+        if (num <= 0.0) {
+          GST_WARNING ("Invalid duration (%lf) - skipping", num);
+          break;
+        }
+
         dur = gst_gdouble_to_guint64 (num *
             gst_guint64_to_gdouble (demux->time_scale));
         if (GST_CLOCK_TIME_IS_VALID (dur) && dur <= G_MAXINT64)
@@ -1921,7 +2119,15 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux)
         break;
       }
 
-      case GST_MATROSKA_ID_SEGMENTUID:{
+      case GST_MATROSKA_ID_SEGMENTUID:
+      case GST_MATROSKA_ID_SEGMENTFILENAME:
+      case GST_MATROSKA_ID_PREVUID:
+      case GST_MATROSKA_ID_PREVFILENAME:
+      case GST_MATROSKA_ID_NEXTUID:
+      case GST_MATROSKA_ID_NEXTFILENAME:
+      case GST_MATROSKA_ID_TITLE:
+      case GST_MATROSKA_ID_SEGMENTFAMILY:
+      case GST_MATROSKA_ID_CHAPTERTRANSLATE:{
         /* TODO not yet implemented. */
         ret = gst_ebml_read_skip (ebml);
         break;
@@ -1949,6 +2155,7 @@ static GstFlowReturn
 gst_matroska_demux_parse_metadata_id_simple_tag (GstMatroskaDemux * demux,
     gboolean prevent_eos, guint64 length, GstTagList ** p_taglist)
 {
+  /* FIXME: check if there are more useful mappings */
   struct
   {
     gchar *matroska_tagname;
@@ -1967,9 +2174,13 @@ gst_matroska_demux_parse_metadata_id_simple_tag (GstMatroskaDemux * demux,
     GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}
   };
   GstEbmlRead *ebml = GST_EBML_READ (demux);
+
   GstFlowReturn ret;
+
   guint32 id;
+
   gchar *value = NULL;
+
   gchar *tag = NULL;
 
   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
@@ -2005,6 +2216,9 @@ gst_matroska_demux_parse_metadata_id_simple_tag (GstMatroskaDemux * demux,
         GST_WARNING ("Unknown entry 0x%x in metadata collection", id);
         /* fall-through */
 
+      case GST_MATROSKA_ID_TAGLANGUAGE:
+      case GST_MATROSKA_ID_TAGDEFAULT:
+      case GST_MATROSKA_ID_TAGBINARY:
       case GST_EBML_ID_VOID:
         ret = gst_ebml_read_skip (ebml);
         break;
@@ -2021,6 +2235,7 @@ gst_matroska_demux_parse_metadata_id_simple_tag (GstMatroskaDemux * demux,
 
     for (i = 0; i < G_N_ELEMENTS (tag_conv); i++) {
       const gchar *tagname_gst = tag_conv[i].gstreamer_tagname;
+
       const gchar *tagname_mkv = tag_conv[i].matroska_tagname;
 
       if (strcmp (tagname_mkv, tag) == 0) {
@@ -2031,10 +2246,10 @@ gst_matroska_demux_parse_metadata_id_simple_tag (GstMatroskaDemux * demux,
         g_value_init (&src, G_TYPE_STRING);
         g_value_set_string (&src, value);
         g_value_init (&dest, dest_type);
-        g_value_transform (&src, &dest);
+        if (g_value_transform (&src, &dest))
+          gst_tag_list_add_values (*p_taglist, GST_TAG_MERGE_APPEND,
+              tagname_gst, &dest, NULL);
         g_value_unset (&src);
-        gst_tag_list_add_values (*p_taglist, GST_TAG_MERGE_APPEND,
-            tagname_gst, &dest, NULL);
         g_value_unset (&dest);
         break;
       }
@@ -2052,7 +2267,9 @@ gst_matroska_demux_parse_metadata_id_tag (GstMatroskaDemux * demux,
     gboolean prevent_eos, guint64 length, GstTagList ** p_taglist)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
+
   guint32 id;
+
   GstFlowReturn ret;
 
   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
@@ -2100,11 +2317,16 @@ gst_matroska_demux_parse_metadata (GstMatroskaDemux * demux,
     gboolean prevent_eos)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
+
   GstTagList *taglist = gst_tag_list_new ();
+
   GstFlowReturn ret = GST_FLOW_OK;
+
   guint64 length = 0;
+
   guint32 id;
 
+  /* TODO: review length/eos logic */
   if (prevent_eos) {
     length = gst_ebml_read_get_length (ebml);
   }
@@ -2135,6 +2357,8 @@ gst_matroska_demux_parse_metadata (GstMatroskaDemux * demux,
         /* fall-through */
 
       case GST_EBML_ID_VOID:
+        /* FIXME: Use to limit the tags to specific pads */
+      case GST_MATROSKA_ID_TARGETS:
         ret = gst_ebml_read_skip (ebml);
         break;
     }
@@ -2163,6 +2387,7 @@ static gint
 gst_matroska_ebmlnum_uint (guint8 * data, guint size, guint64 * num)
 {
   gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0;
+
   guint64 total;
 
   if (size <= 0) {
@@ -2200,6 +2425,7 @@ static gint
 gst_matroska_ebmlnum_sint (guint8 * data, guint size, gint64 * num)
 {
   guint64 unum;
+
   gint res;
 
   /* read as unsigned number first */
@@ -2261,6 +2487,7 @@ gst_matroska_demux_push_hdr_buf (GstMatroskaDemux * demux,
     GstMatroskaTrackContext * stream, guint8 * data, guint len)
 {
   GstFlowReturn ret, cret;
+
   GstBuffer *header_buf = NULL;
 
   ret = gst_pad_alloc_buffer_and_set_caps (stream->pad,
@@ -2300,7 +2527,9 @@ gst_matroska_demux_push_flac_codec_priv_data (GstMatroskaDemux * demux,
     GstMatroskaTrackContext * stream)
 {
   GstFlowReturn ret;
+
   guint8 *pdata;
+
   guint off, len;
 
   GST_LOG_OBJECT (demux, "priv data size = %u", stream->codec_priv_size);
@@ -2345,7 +2574,9 @@ gst_matroska_demux_push_xiph_codec_priv_data (GstMatroskaDemux * demux,
     GstMatroskaTrackContext * stream)
 {
   GstFlowReturn ret;
+
   guint8 *p = (guint8 *) stream->codec_priv;
+
   gint i, offset, length, num_packets;
 
   /* start of the stream and vorbis audio or theora video, need to
@@ -2400,8 +2631,11 @@ gst_matroska_demux_push_dvd_clut_change_event (GstMatroskaDemux * demux,
   start = strstr (stream->codec_priv, "palette:");
   if (start) {
     gint i;
+
     guint32 clut[16];
+
     guint32 col;
+
     guint8 r, g, b, y, u, v;
 
     start += 8;
@@ -2461,13 +2695,19 @@ gst_matroska_demux_add_wvpk_header (GstMatroskaDemux * demux,
     GstMatroskaTrackContext * stream, gint block_length, GstBuffer ** buf)
 {
   GstBuffer *newbuf;
+
   guint8 *data;
+
   guint newlen;
+
   GstFlowReturn ret, cret;
 
   /* we need to reconstruct the header of the wavpack block */
   Wavpack4Header wvh;
 
+  /* FIXME: broken for > 2 channels and hybrid files
+     http://www.matroska.org/technical/specs/codecid/wavpack.html */
+
   wvh.ck_id[0] = 'w';
   wvh.ck_id[1] = 'v';
   wvh.ck_id[2] = 'p';
@@ -2517,10 +2757,15 @@ gst_matroska_demux_check_subtitle_buffer (GstMatroskaDemux * demux,
     GstMatroskaTrackContext * stream, GstBuffer * buf)
 {
   GstMatroskaTrackSubtitleContext *sub_stream;
+
   const gchar *encoding, *data;
+
   GError *err = NULL;
+
   GstBuffer *newbuf;
+
   gchar *utf8;
+
   guint size;
 
   sub_stream = (GstMatroskaTrackSubtitleContext *) stream;
@@ -2590,8 +2835,11 @@ gst_matroska_decode_buffer (GstMatroskaTrackContext * context, GstBuffer * buf)
 
   for (i = 0; i < context->encodings->len; i++) {
     GstMatroskaTrackEncoding *enc;
+
     guint8 *new_data = NULL;
+
     guint new_size = 0;
+
     GstBuffer *new_buf;
 
     enc = &g_array_index (context->encodings, GstMatroskaTrackEncoding, i);
@@ -2600,13 +2848,15 @@ gst_matroska_decode_buffer (GstMatroskaTrackContext * context, GstBuffer * buf)
     if (enc->type != 0)
       break;
 
-    /* FIXME: use enc->scope ? */
+    /* FIXME: use enc->scope ! only necessary to decode buffer if scope & 0x1 */
 
     if (enc->comp_algo == 0) {
 #ifdef HAVE_ZLIB
       /* zlib encoded track */
       z_stream zstream;
+
       guint orig_size;
+
       int result;
 
       orig_size = GST_BUFFER_SIZE (buf);
@@ -2622,6 +2872,7 @@ gst_matroska_decode_buffer (GstMatroskaTrackContext * context, GstBuffer * buf)
       new_size = orig_size;
       new_data = g_malloc (new_size);
       zstream.avail_out = new_size;
+      /* FIXME: not exactly fast, right? */
       do {
         new_size += 4000;
         new_data = g_realloc (new_data, new_size);
@@ -2643,6 +2894,9 @@ gst_matroska_decode_buffer (GstMatroskaTrackContext * context, GstBuffer * buf)
       GST_WARNING ("GZIP encoded tracks not supported.");
       break;
 #endif
+/* FIXME: add bzip/lzo support, what is header stripped?
+ * it's insane and requires deeper knowledge of the used codec
+ */
     } else if (enc->comp_algo == 1) {
       GST_WARNING ("BZIP encoded tracks not supported.");
       break;
@@ -2676,18 +2930,29 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
     guint64 cluster_time, gboolean is_simpleblock)
 {
   GstMatroskaTrackContext *stream = NULL;
+
   GstEbmlRead *ebml = GST_EBML_READ (demux);
+
   GstFlowReturn ret = GST_FLOW_OK;
+
   gboolean readblock = FALSE;
+
   guint32 id;
+
   guint64 block_duration = 0;
+
   GstBuffer *buf = NULL;
-  gint stream_num = 0, n, laces = 0;
+
+  gint stream_num = -1, n, laces = 0;
+
   guint size = 0;
+
   gint *lace_size = NULL;
+
   gint64 time = 0;
-  gint64 lace_time = 0;
+
   gint flags = 0;
+
   gint64 referenceblock = 0;
 
   while (ret == GST_FLOW_OK) {
@@ -2711,6 +2976,7 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
       case GST_MATROSKA_ID_BLOCK:
       {
         guint64 num;
+
         guint8 *data;
 
         if ((ret = gst_ebml_read_buffer (ebml, &id, &buf)) != GST_FLOW_OK)
@@ -2736,13 +3002,14 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
           gst_buffer_unref (buf);
           buf = NULL;
           GST_WARNING ("Invalid stream %d or size %u", stream_num, size);
+          ret = GST_FLOW_ERROR;
           break;
         }
 
         stream = demux->src[stream_num];
 
         /* time (relative to cluster time) */
-        time = ((gint16) GST_READ_UINT16_BE (data)) * demux->time_scale;
+        time = ((gint16) GST_READ_UINT16_BE (data));
         data += 2;
         size -= 2;
         flags = GST_READ_UINT8 (data);
@@ -2814,6 +3081,7 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
                 total = lace_size[0] = num;
                 for (n = 1; ret == GST_FLOW_OK && n < laces - 1; n++) {
                   gint64 snum;
+
                   gint r;
 
                   if ((r = gst_matroska_ebmlnum_sint (data, size, &snum)) < 0) {
@@ -2872,6 +3140,12 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
         GST_WARNING ("Unknown entry 0x%x in blockgroup data", id);
         /* fall-through */
 
+      case GST_MATROSKA_ID_BLOCKVIRTUAL:
+      case GST_MATROSKA_ID_BLOCKADDITIONS:
+      case GST_MATROSKA_ID_REFERENCEPRIORITY:
+      case GST_MATROSKA_ID_REFERENCEVIRTUAL:
+      case GST_MATROSKA_ID_CODECSTATE:
+      case GST_MATROSKA_ID_SLICES:
       case GST_EBML_ID_VOID:
         ret = gst_ebml_read_skip (ebml);
         break;
@@ -2886,18 +3160,7 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
     }
   }
 
-  if (cluster_time != GST_CLOCK_TIME_NONE) {
-    if (time < 0 && (-time) > cluster_time)
-      lace_time = cluster_time;
-    else
-      lace_time = cluster_time + time;
-  } else {
-    lace_time = GST_CLOCK_TIME_NONE;
-  }
-
-  stream = demux->src[stream_num];
-
-  if (referenceblock && readblock && stream->set_discont) {
+  if (referenceblock && readblock && demux->src[stream_num]->set_discont) {
     /* When doing seeks or such, we need to restart on key frames or
        decoders might choke. */
     readblock = FALSE;
@@ -2908,12 +3171,38 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
   if (ret == GST_FLOW_OK && readblock) {
     guint64 duration = 0;
 
+    gint64 lace_time = 0;
+
+    stream = demux->src[stream_num];
+
+    if (cluster_time != GST_CLOCK_TIME_NONE) {
+      /* FIXME: What to do with negative timestamps? Give timestamp 0 or -1?
+       * Drop unless the lace contains timestamp 0? */
+      if (time < 0 && (-time) > cluster_time) {
+        lace_time = 0;
+      } else {
+        if (stream->timecodescale == 1.0)
+          lace_time = (cluster_time + time) * demux->time_scale;
+        else
+          lace_time =
+              gst_util_guint64_to_gdouble ((cluster_time + time) *
+              demux->time_scale) * stream->timecodescale;
+      }
+    } else {
+      lace_time = GST_CLOCK_TIME_NONE;
+    }
+
     if (block_duration) {
-      duration = block_duration * demux->time_scale;
+      if (stream->timecodescale == 1.0)
+        duration = block_duration * demux->time_scale;
+      else
+        duration =
+            gst_util_gdouble_to_guint64 (gst_util_guint64_to_gdouble
+            (block_duration * demux->time_scale) * stream->timecodescale);
     } else if (stream->default_duration) {
       duration = stream->default_duration;
     }
-
+    /* else duration is diff between timecode of this and next block */
     for (n = 0; n < laces; n++) {
       GstBuffer *sub;
 
@@ -2939,7 +3228,8 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
             &sub);
       }
 
-      /* FIXME: do all laces have the same lenght? */
+      /* FIXME: do all laces have the same length? the lenght of a lace should
+       * in theory be default_duration as one lace should contain on frame */
       if (duration) {
         GST_BUFFER_DURATION (sub) = duration / laces;
         stream->pos += GST_BUFFER_DURATION (sub);
@@ -2998,8 +3288,11 @@ static GstFlowReturn
 gst_matroska_demux_parse_cluster (GstMatroskaDemux * demux)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
+
   GstFlowReturn ret = GST_FLOW_OK;
+
   guint64 cluster_time = GST_CLOCK_TIME_NONE;
+
   guint32 id;
 
   while (ret == GST_FLOW_OK) {
@@ -3018,7 +3311,7 @@ gst_matroska_demux_parse_cluster (GstMatroskaDemux * demux)
         guint64 num;
 
         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) == GST_FLOW_OK) {
-          cluster_time = num * demux->time_scale;
+          cluster_time = num;
         }
         break;
       }
@@ -3042,6 +3335,10 @@ gst_matroska_demux_parse_cluster (GstMatroskaDemux * demux)
         GST_WARNING ("Unknown entry 0x%x in cluster data", id);
         /* fall-through */
 
+      case GST_MATROSKA_ID_POSITION:
+      case GST_MATROSKA_ID_PREVSIZE:
+      case GST_MATROSKA_ID_ENCRYPTEDBLOCK:
+      case GST_MATROSKA_ID_SILENTTRACKS:
       case GST_EBML_ID_VOID:
         ret = gst_ebml_read_skip (ebml);
         break;
@@ -3061,9 +3358,13 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux,
     gboolean * p_run_loop)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
+
   GstFlowReturn ret;
+
   guint64 seek_pos = (guint64) - 1;
+
   guint32 seek_id = 0;
+
   guint32 id;
 
   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
@@ -3123,12 +3424,16 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux,
     return GST_FLOW_OK;
   }
 
+  /* FIXME: Do this for the other elements except CLUSTERS too.
+   * We can't know that they will come before the CLUSTERS */
   switch (seek_id) {
     case GST_MATROSKA_ID_CUES:
     case GST_MATROSKA_ID_TAGS:
     {
       guint level_up = demux->level_up;
+
       guint64 before_pos, length;
+
       GstEbmlLevel *level;
 
       /* remember */
@@ -3175,6 +3480,7 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux,
           if ((ret =
                   gst_matroska_demux_parse_index (demux, TRUE)) != GST_FLOW_OK)
             return ret;
+          /* FIXME: why is this here? */
           if (gst_ebml_read_get_length (ebml) == ebml->offset)
             *p_run_loop = FALSE;
           else
@@ -3187,6 +3493,7 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux,
                   gst_matroska_demux_parse_metadata (demux,
                       TRUE)) != GST_FLOW_OK)
             return ret;
+          /* FIXME: why is this here? */
           if (gst_ebml_read_get_length (ebml) == ebml->offset)
             *p_run_loop = FALSE;
           else
@@ -3194,7 +3501,8 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux,
           break;
       }
 
-      /* used to be here in 0.8 version, but makes mewmew sample not work */
+      /* FIXME:
+       * used to be here in 0.8 version, but makes mewmew sample not work */
       /* if (*p_run_loop == FALSE) break; */
 
     finish:
@@ -3229,7 +3537,9 @@ gst_matroska_demux_parse_contents (GstMatroskaDemux * demux,
     gboolean * p_run_loop)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
+
   GstFlowReturn ret = GST_FLOW_OK;
+
   guint32 id;
 
   while (ret == GST_FLOW_OK) {
@@ -3272,17 +3582,23 @@ gst_matroska_demux_loop_stream_parse_id (GstMatroskaDemux * demux,
     guint32 id, gboolean * p_run_loop)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
+
   GstFlowReturn ret;
 
   switch (id) {
+      /* FIXME: not mandatory... will things break? 
+       * Can only happen exactly once, ignore second
+       * occurences! */
       /* stream info */
-    case GST_MATROSKA_ID_INFO:
+    case GST_MATROSKA_ID_SEGMENTINFO:
       if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
         return ret;
       if ((ret = gst_matroska_demux_parse_info (demux)) != GST_FLOW_OK)
         return ret;
       break;
 
+      /* FIXME: might happen more than once, second
+       * occurences must be exactly the same so drop them */
       /* track info headers */
     case GST_MATROSKA_ID_TRACKS:
     {
@@ -3293,6 +3609,8 @@ gst_matroska_demux_loop_stream_parse_id (GstMatroskaDemux * demux,
       break;
     }
 
+      /* FIXME: can only happen once or never but
+       * for the sake of sanity ignore second occurences */
       /* stream index */
     case GST_MATROSKA_ID_CUES:
     {
@@ -3309,10 +3627,12 @@ gst_matroska_demux_loop_stream_parse_id (GstMatroskaDemux * demux,
       break;
     }
 
+      /* FIXME: can be there more than once, why do we have
+       * ->metadata_parsed? */
       /* metadata */
     case GST_MATROSKA_ID_TAGS:
     {
-      if (!demux->index_parsed) {
+      if (!demux->metadata_parsed) {
         if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
           return ret;
         if ((ret =
@@ -3326,6 +3646,8 @@ gst_matroska_demux_loop_stream_parse_id (GstMatroskaDemux * demux,
       break;
     }
 
+      /* FIXME: must not be there but can happen more than once with
+       * different content */
       /* file index (if seekable, seek to Cues/Tags to parse it) */
     case GST_MATROSKA_ID_SEEKHEAD:
     {
@@ -3338,9 +3660,12 @@ gst_matroska_demux_loop_stream_parse_id (GstMatroskaDemux * demux,
       break;
     }
 
+      /* FIXME: must not be there */
     case GST_MATROSKA_ID_CLUSTER:
     {
       if (demux->state != GST_MATROSKA_DEMUX_STATE_DATA) {
+        /* FIXME: Skip first and try to read TRACKS and other things
+         * first, then go back here. */
         demux->state = GST_MATROSKA_DEMUX_STATE_DATA;
         /* FIXME: different streams might have different lengths! */
         /* send initial discont */
@@ -3369,6 +3694,25 @@ gst_matroska_demux_loop_stream_parse_id (GstMatroskaDemux * demux,
       break;
     }
 
+      /* TODO: Implement parsing of attachments and push them
+       * through an attachment pad, one for each attachment */
+      /* FIXME: must not be there but can only be once */
+    case GST_MATROSKA_ID_ATTACHMENTS:{
+      GST_INFO ("Attachments elements are not supported yet");
+      if ((ret = gst_ebml_read_skip (ebml)) != GST_FLOW_OK)
+        return ret;
+      break;
+    }
+
+      /* TODO: Implement parsing of chapters */
+      /* FIXME: Must not be there but can only be once */
+    case GST_MATROSKA_ID_CHAPTERS:{
+      GST_INFO ("Chapters elements are not supported yet");
+      if ((ret = gst_ebml_read_skip (ebml)) != GST_FLOW_OK)
+        return ret;
+      break;
+    }
+
     default:
       GST_WARNING ("Unknown matroska file header ID 0x%x at %"
           G_GUINT64_FORMAT, id, GST_EBML_READ (demux)->offset);
@@ -3388,8 +3732,11 @@ static GstFlowReturn
 gst_matroska_demux_loop_stream (GstMatroskaDemux * demux)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
+
   GstFlowReturn ret = GST_FLOW_OK;
+
   gboolean run_loop = TRUE;
+
   guint32 id;
 
   /* we've found our segment, start reading the different contents in here */
@@ -3415,8 +3762,10 @@ gst_matroska_demux_loop_stream (GstMatroskaDemux * demux)
 static void
 gst_matroska_demux_loop (GstPad * pad)
 {
-  GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad));
+  GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (GST_PAD_PARENT (pad));
+
   GstEbmlRead *ebml = GST_EBML_READ (demux);
+
   GstFlowReturn ret;
 
   /* first, if we're to start, let's actually get starting */
@@ -3454,8 +3803,6 @@ gst_matroska_demux_loop (GstPad * pad)
     goto pause;
   }
 
-  /* all is fine */
-  gst_object_unref (demux);
   return;
 
   /* ERRORS */
@@ -3493,7 +3840,6 @@ pause:
         gst_matroska_demux_send_event (demux, gst_event_new_eos ());
       }
     }
-    gst_object_unref (demux);
     return;
   }
 }
@@ -3531,6 +3877,7 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
     gchar ** codec_name)
 {
   GstMatroskaTrackContext *context = (GstMatroskaTrackContext *) videocontext;
+
   GstCaps *caps = NULL;
 
   g_assert (videocontext != NULL);
@@ -3539,6 +3886,14 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
   context->send_xiph_headers = FALSE;
   context->send_flac_headers = FALSE;
 
+  /* TODO: check if we have all codec types from matroska-ids.h
+   *       check if we have to do more special things with codec_private
+   *
+   * Add support for
+   *  GST_MATROSKA_CODEC_ID_VIDEO_QUICKTIME
+   *  GST_MATROSKA_CODEC_ID_VIDEO_SNOW
+   */
+
   if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC)) {
     gst_riff_strf_vids *vids = NULL;
 
@@ -3587,7 +3942,6 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
   } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED)) {
     guint32 fourcc = 0;
 
-    /* how nice, this is undocumented... */
     switch (videocontext->fourcc) {
       case GST_MAKE_FOURCC ('I', '4', '2', '0'):
         *codec_name = g_strdup ("Raw planar YUV 4:2:0");
@@ -3597,6 +3951,18 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
         *codec_name = g_strdup ("Raw packed YUV 4:2:2");
         fourcc = videocontext->fourcc;
         break;
+      case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
+        *codec_name = g_strdup ("Raw packed YUV 4:2:0");
+        fourcc = videocontext->fourcc;
+        break;
+      case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
+        *codec_name = g_strdup ("Raw packed YUV 4:2:2");
+        fourcc = videocontext->fourcc;
+        break;
+      case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'):
+        *codec_name = g_strdup ("Raw packed YUV 4:4:4 with alpha channel");
+        fourcc = videocontext->fourcc;
+        break;
 
       default:
         GST_DEBUG ("Unknown fourcc %" GST_FOURCC_FORMAT,
@@ -3697,11 +4063,13 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
 
   if (caps != NULL) {
     int i;
+
     GstStructure *structure;
 
     for (i = 0; i < gst_caps_get_size (caps); i++) {
       structure = gst_caps_get_structure (caps, i);
 
+      /* FIXME: use the real unit here! */
       GST_DEBUG ("video size %dx%d, target display size %dx%d (any unit)",
           videocontext->pixel_width,
           videocontext->pixel_height,
@@ -3710,6 +4078,7 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
       /* pixel width and height are the w and h of the video in pixels */
       if (videocontext->pixel_width > 0 && videocontext->pixel_height > 0) {
         gint w = videocontext->pixel_width;
+
         gint h = videocontext->pixel_height;
 
         gst_structure_set (structure,
@@ -3830,6 +4199,7 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext *
     gchar ** codec_name)
 {
   GstMatroskaTrackContext *context = (GstMatroskaTrackContext *) audiocontext;
+
   GstCaps *caps = NULL;
 
   g_assert (audiocontext != NULL);
@@ -3838,6 +4208,17 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext *
   context->send_xiph_headers = FALSE;
   context->send_flac_headers = FALSE;
 
+  /* TODO: check if we have all codec types from matroska-ids.h
+   *       check if we have to do more special things with codec_private
+   *       check if we need bitdepth in different places too
+   *       implement channel position magic
+   * Add support for:
+   *  GST_MATROSKA_CODEC_ID_AUDIO_AC3_BSID9
+   *  GST_MATROSKA_CODEC_ID_AUDIO_AC3_BSID10
+   *  GST_MATROSKA_CODEC_ID_AUDIO_QUICKTIME_QDMC
+   *  GST_MATROSKA_CODEC_ID_AUDIO_QUICKTIME_QDM2
+   */
+
   if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1) ||
       !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2) ||
       !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3)) {
@@ -3876,7 +4257,7 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext *
         audiocontext->bitdepth);
   } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT)) {
     caps = gst_caps_new_simple ("audio/x-raw-float",
-        "endianness", G_TYPE_INT, G_BYTE_ORDER,
+        "endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
         "width", G_TYPE_INT, audiocontext->bitdepth, NULL);
     *codec_name = g_strdup_printf ("Raw %d-bit floating-point audio",
         audiocontext->bitdepth);
@@ -3911,18 +4292,21 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext *
       caps = gst_riff_create_audio_caps (auds->format, NULL, auds, NULL,
           NULL, codec_name);
     }
-  } else if (g_str_has_prefix (codec_id, "A_AAC")) {
+  } else if (g_str_has_prefix (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_AAC)) {
     GstBuffer *priv = NULL;
+
     gint mpegversion = -1;
+
     gint rate_idx, profile;
+
     guint8 *data = NULL;
 
     /* unspecified AAC profile with opaque private codec data */
-    if (strcmp (codec_id, "A_AAC") == 0) {
+    if (strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_AAC) == 0) {
       if (context->codec_priv_size >= 2) {
         guint obj_type, freq_index, explicit_freq_bytes = 0;
 
-        codec_id = GST_MATROSKA_CODEC_ID_AUDIO_MPEG4;
+        codec_id = GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG4;
         freq_index = (GST_READ_UINT16_BE (context->codec_priv) & 0x780) >> 7;
         obj_type = (GST_READ_UINT16_BE (context->codec_priv) & 0xF800) >> 11;
         if (freq_index == 15)
@@ -3939,7 +4323,7 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext *
       } else {
         GST_WARNING ("Opaque A_AAC codec ID, but no codec private data");
         /* just try this and see what happens ... */
-        codec_id = GST_MATROSKA_CODEC_ID_AUDIO_MPEG4;
+        codec_id = GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG4;
       }
     }
 
@@ -3955,11 +4339,11 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext *
       GST_BUFFER_SIZE (priv) = 2;
     }
 
-    if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG2,
-            strlen (GST_MATROSKA_CODEC_ID_AUDIO_MPEG2))) {
+    if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG2,
+            strlen (GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG2))) {
       mpegversion = 2;
-    } else if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG4,
-            strlen (GST_MATROSKA_CODEC_ID_AUDIO_MPEG4))) {
+    } else if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG4,
+            strlen (GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG4))) {
       mpegversion = 4;
 
       if (g_strrstr (codec_id, "SBR")) {
@@ -4037,24 +4421,13 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext *
 }
 
 static GstCaps *
-gst_matroska_demux_complex_caps (GstMatroskaTrackComplexContext *
-    complexcontext, const gchar * codec_id, gpointer data, guint size)
-{
-  GstCaps *caps = NULL;
-
-  GST_DEBUG ("Unknown complex stream: codec_id='%s'", codec_id);
-
-  return caps;
-}
-
-static GstCaps *
 gst_matroska_demux_subtitle_caps (GstMatroskaTrackSubtitleContext *
     subtitlecontext, const gchar * codec_id, gpointer data, guint size)
 {
   GstCaps *caps = NULL;
 
   /* for backwards compatibility */
-  if (!g_ascii_strcasecmp (codec_id, "S_TEXT/ASCII"))
+  if (!g_ascii_strcasecmp (codec_id, GST_MATROSKA_CODEC_ID_SUBTITLE_ASCII))
     codec_id = GST_MATROSKA_CODEC_ID_SUBTITLE_UTF8;
   else if (!g_ascii_strcasecmp (codec_id, "S_SSA"))
     codec_id = GST_MATROSKA_CODEC_ID_SUBTITLE_SSA;
@@ -4063,6 +4436,8 @@ gst_matroska_demux_subtitle_caps (GstMatroskaTrackSubtitleContext *
   else if (!g_ascii_strcasecmp (codec_id, "S_USF"))
     codec_id = GST_MATROSKA_CODEC_ID_SUBTITLE_USF;
 
+  /* TODO: Add GST_MATROSKA_CODEC_ID_SUBTITLE_BMP support
+   * Check if we have to do something with codec_private */
   if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_SUBTITLE_UTF8)) {
     caps = gst_caps_new_simple ("text/plain", NULL);
     subtitlecontext->check_utf8 = TRUE;
@@ -4102,6 +4477,7 @@ gst_matroska_demux_change_state (GstElement * element,
     GstStateChange transition)
 {
   GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
+
   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
 
   /* handle upwards state changes here */
index bccec17..9da5660 100644 (file)
@@ -40,7 +40,9 @@ G_BEGIN_DECLS
 #define GST_IS_MATROSKA_DEMUX_CLASS(klass) \
   (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MATROSKA_DEMUX))
 
-#define GST_MATROSKA_DEMUX_MAX_STREAMS 64       
+/* The spec says that more than 127 stream is discouraged so
+ * take this as a limit for now */
+#define GST_MATROSKA_DEMUX_MAX_STREAMS 127       
 
 typedef enum {
   GST_MATROSKA_DEMUX_STATE_START,
index ec71a56..81cfd04 100644 (file)
@@ -109,25 +109,3 @@ gst_matroska_track_init_subtitle_context (GstMatroskaTrackContext ** p_context)
   subtitle_context->invalid_utf8 = FALSE;
   return TRUE;
 }
-
-gboolean
-gst_matroska_track_init_complex_context (GstMatroskaTrackContext ** p_context)
-{
-  GstMatroskaTrackComplexContext *complex_context;
-
-  g_assert (p_context != NULL && *p_context != NULL);
-
-  /* already set up? (track info might come before track type) */
-  if ((*p_context)->type == GST_MATROSKA_TRACK_TYPE_COMPLEX)
-    return TRUE;
-
-  /* it better not have been set up as some other track type ... */
-  if ((*p_context)->type != 0) {
-    g_return_val_if_reached (FALSE);
-  }
-
-  complex_context = g_renew (GstMatroskaTrackComplexContext, *p_context, 1);
-  *p_context = (GstMatroskaTrackContext *) complex_context;
-  (*p_context)->type = GST_MATROSKA_TRACK_TYPE_COMPLEX;
-  return TRUE;
-}
index 760dca8..b95111a 100644 (file)
  * Matroska element IDs. max. 32-bit.
  */
 
-/* toplevel segment */
-#define GST_MATROSKA_ID_SEGMENT    0x18538067
-
-/* matroska top-level master IDs */
-#define GST_MATROSKA_ID_INFO       0x1549A966
-#define GST_MATROSKA_ID_TRACKS     0x1654AE6B
-#define GST_MATROSKA_ID_CUES       0x1C53BB6B
-#define GST_MATROSKA_ID_TAGS       0x1254C367
-#define GST_MATROSKA_ID_SEEKHEAD   0x114D9B74
-#define GST_MATROSKA_ID_CLUSTER    0x1F43B675
-
-/* IDs in the info master */
-#define GST_MATROSKA_ID_TIMECODESCALE 0x2AD7B1
-#define GST_MATROSKA_ID_DURATION   0x4489
-#define GST_MATROSKA_ID_WRITINGAPP 0x5741
-#define GST_MATROSKA_ID_MUXINGAPP  0x4D80
-#define GST_MATROSKA_ID_DATEUTC    0x4461
-#define GST_MATROSKA_ID_SEGMENTUID 0x73A4
-
-/* ID in the tracks master */
-#define GST_MATROSKA_ID_TRACKENTRY 0xAE
-
-/* IDs in the trackentry master */
-#define GST_MATROSKA_ID_TRACKNUMBER 0xD7
-#define GST_MATROSKA_ID_TRACKUID   0x73C5
-#define GST_MATROSKA_ID_TRACKTYPE  0x83
-#define GST_MATROSKA_ID_TRACKAUDIO 0xE1
-#define GST_MATROSKA_ID_TRACKVIDEO 0xE0
-#define GST_MATROSKA_ID_CODECID    0x86
-#define GST_MATROSKA_ID_CODECPRIVATE 0x63A2
-#define GST_MATROSKA_ID_CODECNAME  0x258688
-#define GST_MATROSKA_ID_CODECINFOURL 0x3B4040
-#define GST_MATROSKA_ID_CODECDOWNLOADURL 0x26B240
-#define GST_MATROSKA_ID_TRACKNAME  0x536E
-#define GST_MATROSKA_ID_TRACKLANGUAGE 0x22B59C
-#define GST_MATROSKA_ID_TRACKFLAGENABLED 0xB9
-#define GST_MATROSKA_ID_TRACKFLAGDEFAULT 0x88
-#define GST_MATROSKA_ID_TRACKFLAGLACING 0x9C
-#define GST_MATROSKA_ID_TRACKMINCACHE 0x6DE7
-#define GST_MATROSKA_ID_TRACKMAXCACHE 0x6DF8
-#define GST_MATROSKA_ID_TRACKDEFAULTDURATION 0x23E383
-#define GST_MATROSKA_ID_CONTENTENCODINGS 0x6D80
-
-/* IDs in the trackvideo master */
-#define GST_MATROSKA_ID_VIDEOFRAMERATE 0x2383E3
-#define GST_MATROSKA_ID_VIDEODISPLAYWIDTH 0x54B0
-#define GST_MATROSKA_ID_VIDEODISPLAYHEIGHT 0x54BA
-#define GST_MATROSKA_ID_VIDEOPIXELWIDTH 0xB0
-#define GST_MATROSKA_ID_VIDEOPIXELHEIGHT 0xBA
-#define GST_MATROSKA_ID_VIDEOFLAGINTERLACED 0x9A
-#define GST_MATROSKA_ID_VIDEOSTEREOMODE 0x53B9
-#define GST_MATROSKA_ID_VIDEOASPECTRATIO 0x54B3
-#define GST_MATROSKA_ID_VIDEOCOLOURSPACE 0x2EB524
-
-/* IDs in the trackaudio master */
-#define GST_MATROSKA_ID_AUDIOSAMPLINGFREQ 0xB5
-#define GST_MATROSKA_ID_AUDIOBITDEPTH 0x6264
-#define GST_MATROSKA_ID_AUDIOCHANNELS 0x9F
-
-/* ID in the cues master */
-#define GST_MATROSKA_ID_POINTENTRY 0xBB
+/* toplevel Segment */
+#define GST_MATROSKA_ID_SEGMENT                    0x18538067
+
+/* matroska top-level master IDs, childs of Segment */
+#define GST_MATROSKA_ID_SEGMENTINFO                0x1549A966
+#define GST_MATROSKA_ID_TRACKS                     0x1654AE6B
+#define GST_MATROSKA_ID_CUES                       0x1C53BB6B
+#define GST_MATROSKA_ID_TAGS                       0x1254C367
+#define GST_MATROSKA_ID_SEEKHEAD                   0x114D9B74
+#define GST_MATROSKA_ID_CLUSTER                    0x1F43B675
+#define GST_MATROSKA_ID_ATTACHMENTS                0x1941A469
+#define GST_MATROSKA_ID_CHAPTERS                   0x1043A770
+
+/* IDs in the SegmentInfo master */
+#define GST_MATROSKA_ID_TIMECODESCALE              0x2AD7B1
+#define GST_MATROSKA_ID_DURATION                   0x4489
+#define GST_MATROSKA_ID_WRITINGAPP                 0x5741
+#define GST_MATROSKA_ID_MUXINGAPP                  0x4D80
+#define GST_MATROSKA_ID_DATEUTC                    0x4461
+#define GST_MATROSKA_ID_SEGMENTUID                 0x73A4
+#define GST_MATROSKA_ID_SEGMENTFILENAME            0x7384
+#define GST_MATROSKA_ID_PREVUID                    0x3CB923
+#define GST_MATROSKA_ID_PREVFILENAME               0x3C83AB
+#define GST_MATROSKA_ID_NEXTUID                    0x3EB923
+#define GST_MATROSKA_ID_NEXTFILENAME               0x3E83BB
+#define GST_MATROSKA_ID_TITLE                      0x7BA9
+#define GST_MATROSKA_ID_SEGMENTFAMILY              0x4444
+#define GST_MATROSKA_ID_CHAPTERTRANSLATE           0x6924
+
+/* IDs in the ChapterTranslate master */
+#define GST_MATROSKA_ID_CHAPTERTRANSLATEEDITIONUID 0x69FC
+#define GST_MATROSKA_ID_CHAPTERTRANSLATECODEC      0x69BF
+#define GST_MATROSKA_ID_CHAPTERTRANSLATEID         0x69A5
+
+/* ID in the Tracks master */
+#define GST_MATROSKA_ID_TRACKENTRY                 0xAE
+
+/* IDs in the TrackEntry master */
+#define GST_MATROSKA_ID_TRACKNUMBER                0xD7
+#define GST_MATROSKA_ID_TRACKUID                   0x73C5
+#define GST_MATROSKA_ID_TRACKTYPE                  0x83
+#define GST_MATROSKA_ID_TRACKAUDIO                 0xE1
+#define GST_MATROSKA_ID_TRACKVIDEO                 0xE0
+#define GST_MATROSKA_ID_CONTENTENCODINGS           0x6D80
+#define GST_MATROSKA_ID_CODECID                    0x86
+#define GST_MATROSKA_ID_CODECPRIVATE               0x63A2
+#define GST_MATROSKA_ID_CODECNAME                  0x258688
+#define GST_MATROSKA_ID_TRACKNAME                  0x536E
+#define GST_MATROSKA_ID_TRACKLANGUAGE              0x22B59C
+#define GST_MATROSKA_ID_TRACKFLAGENABLED           0xB9
+#define GST_MATROSKA_ID_TRACKFLAGDEFAULT           0x88
+#define GST_MATROSKA_ID_TRACKFLAGFORCED            0x55AA
+#define GST_MATROSKA_ID_TRACKFLAGLACING            0x9C
+#define GST_MATROSKA_ID_TRACKMINCACHE              0x6DE7
+#define GST_MATROSKA_ID_TRACKMAXCACHE              0x6DF8
+#define GST_MATROSKA_ID_TRACKDEFAULTDURATION       0x23E383
+#define GST_MATROSKA_ID_TRACKTIMECODESCALE         0x23314F
+#define GST_MATROSKA_ID_MAXBLOCKADDITIONID         0x55EE
+#define GST_MATROSKA_ID_TRACKATTACHMENTLINK        0x7446
+#define GST_MATROSKA_ID_TRACKOVERLAY               0x6FAB
+#define GST_MATROSKA_ID_TRACKTRANSLATE             0x6624
+/* semi-draft */
+#define GST_MATROSKA_ID_TRACKOFFSET                0x537F
+/* semi-draft */
+#define GST_MATROSKA_ID_CODECSETTINGS              0x3A9697
+/* semi-draft */
+#define GST_MATROSKA_ID_CODECINFOURL               0x3B4040
+/* semi-draft */
+#define GST_MATROSKA_ID_CODECDOWNLOADURL           0x26B240
+/* semi-draft */
+#define GST_MATROSKA_ID_CODECDECODEALL             0xAA
+
+/* IDs in the TrackTranslate master */
+#define GST_MATROSKA_ID_TRACKTRANSLATEEDITIONUID   0x66FC
+#define GST_MATROSKA_ID_TRACKTRANSLATECODEC        0x66BF
+#define GST_MATROSKA_ID_TRACKTRANSLATETRACKID      0x66A5
+
+
+/* IDs in the TrackVideo master */
+/* NOTE: This one is here only for backward compatibility.
+ * Use _TRACKDEFAULDURATION */
+#define GST_MATROSKA_ID_VIDEOFRAMERATE             0x2383E3
+#define GST_MATROSKA_ID_VIDEODISPLAYWIDTH          0x54B0
+#define GST_MATROSKA_ID_VIDEODISPLAYHEIGHT         0x54BA
+#define GST_MATROSKA_ID_VIDEODISPLAYUNIT           0x54B2
+#define GST_MATROSKA_ID_VIDEOPIXELWIDTH            0xB0
+#define GST_MATROSKA_ID_VIDEOPIXELHEIGHT           0xBA
+#define GST_MATROSKA_ID_VIDEOPIXELCROPBOTTOM       0x54AA
+#define GST_MATROSKA_ID_VIDEOPIXELCROPTOP          0x54BB
+#define GST_MATROSKA_ID_VIDEOPIXELCROPLEFT         0x54CC
+#define GST_MATROSKA_ID_VIDEOPIXELCROPRIGHT        0x54DD
+#define GST_MATROSKA_ID_VIDEOFLAGINTERLACED        0x9A
+/* semi-draft */
+#define GST_MATROSKA_ID_VIDEOSTEREOMODE            0x53B8
+#define GST_MATROSKA_ID_VIDEOASPECTRATIOTYPE       0x54B3
+#define GST_MATROSKA_ID_VIDEOCOLOURSPACE           0x2EB524
+/* semi-draft */
+#define GST_MATROSKA_ID_VIDEOGAMMAVALUE            0x2FB523
+
+/* IDs in the TrackAudio master */
+#define GST_MATROSKA_ID_AUDIOSAMPLINGFREQ          0xB5
+#define GST_MATROSKA_ID_AUDIOBITDEPTH              0x6264
+#define GST_MATROSKA_ID_AUDIOCHANNELS              0x9F
+/* semi-draft */
+#define GST_MATROSKA_ID_AUDIOCHANNELPOSITIONS      0x7D7B
+#define GST_MATROSKA_ID_AUDIOOUTPUTSAMPLINGFREQ    0x78B5
+
+/* IDs in the TrackContentEncoding master */
+#define GST_MATROSKA_ID_CONTENTENCODING            0x6240
+
+/* IDs in the ContentEncoding master */
+#define GST_MATROSKA_ID_CONTENTENCODINGORDER       0x5031
+#define GST_MATROSKA_ID_CONTENTENCODINGSCOPE       0x5032
+#define GST_MATROSKA_ID_CONTENTENCODINGTYPE        0x5033
+#define GST_MATROSKA_ID_CONTENTCOMPRESSION         0x5034
+#define GST_MATROSKA_ID_CONTENTENCRYPTION          0x5035
+
+/* IDs in the ContentCompression master */
+#define GST_MATROSKA_ID_CONTENTCOMPALGO            0x4254
+#define GST_MATROSKA_ID_CONTENTCOMPSETTINGS        0x4255
+
+/* IDs in the ContentEncryption master */
+#define GST_MATROSKA_ID_CONTENTENCALGO             0x47E1
+#define GST_MATROSKA_ID_CONTENTENCKEYID            0x47E2
+#define GST_MATROSKA_ID_CONTENTSIGNATURE           0x47E3
+#define GST_MATROSKA_ID_CONTENTSIGKEYID            0x47E4
+#define GST_MATROSKA_ID_CONTENTSIGALGO             0x47E5
+#define GST_MATROSKA_ID_CONTENTSIGHASHALGO         0x47E6
+
+/* ID in the CUEs master */
+#define GST_MATROSKA_ID_POINTENTRY                 0xBB
 
 /* IDs in the pointentry master */
-#define GST_MATROSKA_ID_CUETIME    0xB3
-#define GST_MATROSKA_ID_CUETRACKPOSITION 0xB7
-
-/* IDs in the cuetrackposition master */
-#define GST_MATROSKA_ID_CUETRACK   0xF7
-#define GST_MATROSKA_ID_CUECLUSTERPOSITION 0xF1
-
-/* IDs in the tags master */
-#define GST_MATROSKA_ID_TAG        0x7373
-
-/* in the tag master */
-#define GST_MATROSKA_ID_SIMPLETAG  0x67C8
-
-/* in the simpletag master */
-#define GST_MATROSKA_ID_TAGNAME    0x45A3
-#define GST_MATROSKA_ID_TAGSTRING  0x4487
-
-/* IDs in the seekhead master */
-#define GST_MATROSKA_ID_SEEKENTRY  0x4DBB
-
-/* IDs in the seekpoint master */
-#define GST_MATROSKA_ID_SEEKID     0x53AB
-#define GST_MATROSKA_ID_SEEKPOSITION 0x53AC
-
-/* IDs in the cluster master */
-#define GST_MATROSKA_ID_CLUSTERTIMECODE 0xE7
-#define GST_MATROSKA_ID_BLOCKGROUP 0xA0
-#define GST_MATROSKA_ID_SIMPLEBLOCK 0xA3
-#define GST_MATROSKA_ID_REFERENCEBLOCK 0xFB
-
-/* IDs in the blockgroup master */
-#define GST_MATROSKA_ID_BLOCK      0xA1
-#define GST_MATROSKA_ID_BLOCKDURATION 0x9B
-
-/* IDs in the contentencodings master */
-#define GST_MATROSKA_ID_CONTENTENCODING 0x6240
-
-/* IDS IN THE CONTENTENCODING MASTER */
-#define GST_MATROSKA_ID_CONTENTENCODINGORDER 0X5031
-#define GST_MATROSKA_ID_CONTENTENCODINGSCOPE 0X5032
-#define GST_MATROSKA_ID_CONTENTENCODINGTYPE  0X5033
-#define GST_MATROSKA_ID_CONTENTCOMPRESSION   0X5034
-#define GST_MATROSKA_ID_CONTENTENCRYPTION    0X5035
-
-/* IDS IN THE CONTENTCOMPRESSION MASTER */
-#define GST_MATROSKA_ID_CONTENTCOMPALGO      0X4254
-#define GST_MATROSKA_ID_CONTENTCOMPSETTINGS  0X4255
-
+#define GST_MATROSKA_ID_CUETIME                    0xB3
+#define GST_MATROSKA_ID_CUETRACKPOSITIONS          0xB7
+
+/* IDs in the CueTrackPositions master */
+#define GST_MATROSKA_ID_CUETRACK                   0xF7
+#define GST_MATROSKA_ID_CUECLUSTERPOSITION         0xF1
+#define GST_MATROSKA_ID_CUEBLOCKNUMBER             0x5378
+/* semi-draft */
+#define GST_MATROSKA_ID_CUECODECSTATE              0xEA
+/* semi-draft */
+#define GST_MATROSKA_ID_CUEREFERENCE               0xDB
+
+/* IDs in the CueReference master */
+/* semi-draft */
+#define GST_MATROSKA_ID_CUEREFTIME                 0x96
+/* semi-draft */
+#define GST_MATROSKA_ID_CUEREFCLUSTER              0x97
+/* semi-draft */
+#define GST_MATROSKA_ID_CUEREFNUMBER               0x535F
+/* semi-draft */
+#define GST_MATROSKA_ID_CUEREFCODECSTATE           0xEB
+
+/* IDs in the Tags master */
+#define GST_MATROSKA_ID_TAG                        0x7373
+
+/* in the Tag master */
+#define GST_MATROSKA_ID_SIMPLETAG                  0x67C8
+#define GST_MATROSKA_ID_TARGETS                    0x63C0
+
+/* in the SimpleTag master */
+#define GST_MATROSKA_ID_TAGNAME                    0x45A3
+#define GST_MATROSKA_ID_TAGSTRING                  0x4487
+#define GST_MATROSKA_ID_TAGLANGUAGE                0x447A
+#define GST_MATROSKA_ID_TAGDEFAULT                 0x4484
+#define GST_MATROSKA_ID_TAGBINARY                  0x4485
+
+/* in the Targets master */
+#define GST_MATROSKA_ID_TARGETTYPEVALUE            0x68CA
+#define GST_MATROSKA_ID_TARGETTYPE                 0x63CA
+#define GST_MATROSKA_ID_TARGETTRACKUID             0x63C5
+#define GST_MATROSKA_ID_TARGETEDITIONUID           0x63C5
+#define GST_MATROSKA_ID_TARGETCHAPTERUID           0x63C4
+#define GST_MATROSKA_ID_TARGETATTACHMENTUID        0x63C6
+
+/* IDs in the SeekHead master */
+#define GST_MATROSKA_ID_SEEKENTRY                  0x4DBB
+
+/* IDs in the SeekEntry master */
+#define GST_MATROSKA_ID_SEEKID                     0x53AB
+#define GST_MATROSKA_ID_SEEKPOSITION               0x53AC
+
+/* IDs in the Cluster master */
+#define GST_MATROSKA_ID_CLUSTERTIMECODE            0xE7
+#define GST_MATROSKA_ID_BLOCKGROUP                 0xA0
+#define GST_MATROSKA_ID_SIMPLEBLOCK                0xA3
+#define GST_MATROSKA_ID_REFERENCEBLOCK             0xFB
+#define GST_MATROSKA_ID_POSITION                   0xA7
+#define GST_MATROSKA_ID_PREVSIZE                   0xAB
+/* semi-draft */
+#define GST_MATROSKA_ID_ENCRYPTEDBLOCK             0xAF
+#define GST_MATROSKA_ID_SILENTTRACKS               0x5854
+
+/* IDs in the SilentTracks master */
+#define GST_MATROSKA_ID_SILENTTRACKNUMBER          0x58D7
+
+/* IDs in the BlockGroup master */
+#define GST_MATROSKA_ID_BLOCK                      0xA1
+#define GST_MATROSKA_ID_BLOCKDURATION              0x9B
+/* semi-draft */
+#define GST_MATROSKA_ID_BLOCKVIRTUAL               0xA2
+#define GST_MATROSKA_ID_REFERENCEBLOCK             0xFB
+#define GST_MATROSKA_ID_BLOCKADDITIONS             0x75A1
+#define GST_MATROSKA_ID_REFERENCEPRIORITY          0xFA
+/* semi-draft */
+#define GST_MATROSKA_ID_REFERENCEVIRTUAL           0xFD
+/* semi-draft */
+#define GST_MATROSKA_ID_CODECSTATE                 0xA4
+#define GST_MATROSKA_ID_SLICES                     0x8E
+
+/* IDs in the BlockAdditions master */
+#define GST_MATROSKA_ID_BLOCKMORE                  0xA6
+
+/* IDs in the BlockMore master */
+#define GST_MATROSKA_ID_BLOCKADDID                 0xEE
+#define GST_MATROSKA_ID_BLOCKADDITIONAL            0xA5
+
+/* IDs in the Slices master */
+#define GST_MATROSKA_ID_TIMESLICE                  0xE8
+
+/* IDs in the TimeSlice master */
+#define GST_MATROSKA_ID_LACENUMBER                 0xCC
+/* semi-draft */
+#define GST_MATROSKA_ID_FRAMENUMBER                0xCD
+/* semi-draft */
+#define GST_MATROSKA_ID_BLOCKADDITIONID            0xCB
+/* semi-draft */
+#define GST_MATROSKA_ID_TIMESLICEDELAY             0xCE
+#define GST_MATROSKA_ID_TIMESLICEDURATION          0xCF
+
+/* IDs in the Attachments master */
+#define GST_MATROSKA_ID_ATTACHEDFILE               0x61A7
+
+/* IDs in the AttachedFile master */
+#define GST_MATROSKA_ID_FILEDESCRIPTION            0x467E
+#define GST_MATROSKA_ID_FILENAME                   0x466E
+#define GST_MATROSKA_ID_FILEMIMETYPE               0x4660
+#define GST_MATROSKA_ID_FILEDATA                   0x465C
+#define GST_MATROSKA_ID_FILEUID                    0x46AE
+/* semi-draft */
+#define GST_MATROSKA_ID_FILEREFERRAL               0x4675
+
+/* IDs in the Chapters master */
+#define GST_MATROSKA_ID_EDITIONENTRY               0x45B9
+
+/* IDs in the EditionEntry master */
+#define GST_MATROSKA_ID_EDITIONUID                 0x45BC
+#define GST_MATROSKA_ID_EDITIONFLAGHIDDEN          0x45BD
+#define GST_MATROSKA_ID_EDITIONFLAGDEFAULT         0x45DB
+#define GST_MATROSKA_ID_EDITIONFLAGORDERED         0x45DD
+#define GST_MATROSKA_ID_CHAPTERATOM                0xB6
+
+/* IDs in the ChapterAtom master */
+#define GST_MATROSKA_ID_CHAPTERUID                 0x73C4
+#define GST_MATROSKA_ID_CHAPTERTIMESTART           0x91
+#define GST_MATROSKA_ID_CHAPTERTIMESTOP            0x92
+#define GST_MATROSKA_ID_CHAPTERFLAGHIDDEN          0x98
+#define GST_MATROSKA_ID_CHAPTERFLAGENABLED         0x4598
+#define GST_MATROSKA_ID_CHAPTERSEGMENTUID          0x6E67
+#define GST_MATROSKA_ID_CHAPTERSEGMENTEDITIONUID   0x6EBC
+#define GST_MATROSKA_ID_CHAPTERPHYSICALEQUIV       0x63C3
+#define GST_MATROSKA_ID_CHAPTERTRACK               0x8F
+#define GST_MATROSKA_ID_CHAPTERDISPLAY             0x80
+#define GST_MATROSKA_ID_CHAPPROCESS                0x6944
+
+/* IDs in the ChapProcess master */
+#define GST_MATROSKA_ID_CHAPPROCESSCODECID         0x6955
+#define GST_MATROSKA_ID_CHAPPROCESSPRIVATE         0x450D
+#define GST_MATROSKA_ID_CHAPPROCESSCOMMAND         0x6911
+
+/* IDs in the ChapProcessCommand master */
+#define GST_MATROSKA_ID_CHAPPROCESSTIME            0x6922
+#define GST_MATROSKA_ID_CHAPPROCESSDATA            0x6933
+
+/* IDs in the ChapterDisplay master */
+#define GST_MATROSKA_ID_CHAPSTRING                 0x85
+#define GST_MATROSKA_ID_CHAPLANGUAGE               0x437C
+#define GST_MATROSKA_ID_CHAPCOUNTRY                0x437E
+
+/* IDs in the ChapterTrack master */
+#define GST_MATROSKA_ID_CHAPTERTRACKNUMBER         0x89
 
 /*
  * Matroska Codec IDs. Strings.
 #define GST_MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3    "V_MPEG4/MS/V3"
 #define GST_MATROSKA_CODEC_ID_VIDEO_MPEG1        "V_MPEG1"
 #define GST_MATROSKA_CODEC_ID_VIDEO_MPEG2        "V_MPEG2"
+/* FIXME: not (yet) in the spec! */
 #define GST_MATROSKA_CODEC_ID_VIDEO_MJPEG        "V_MJPEG"
 #define GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO1   "V_REAL/RV10"
 #define GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO2   "V_REAL/RV20"
 #define GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO3   "V_REAL/RV30"
 #define GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO4   "V_REAL/RV40"
 #define GST_MATROSKA_CODEC_ID_VIDEO_THEORA       "V_THEORA"
+#define GST_MATROSKA_CODEC_ID_VIDEO_QUICKTIME    "V_QUICKTIME"
+#define GST_MATROSKA_CODEC_ID_VIDEO_SNOW         "V_SNOW"
 #define GST_MATROSKA_CODEC_ID_VIDEO_DIRAC        "V_DIRAC"
-/* TODO: Quicktime */
-
-#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1     "A_MPEG/L1"
-#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2     "A_MPEG/L2"
-#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3     "A_MPEG/L3"
-#define GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE   "A_PCM/INT/BIG"
-#define GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE   "A_PCM/INT/LIT"
-#define GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT    "A_PCM/FLOAT/IEEE"
-#define GST_MATROSKA_CODEC_ID_AUDIO_AC3          "A_AC3"
-#define GST_MATROSKA_CODEC_ID_AUDIO_DTS          "A_DTS"
-#define GST_MATROSKA_CODEC_ID_AUDIO_VORBIS       "A_VORBIS"
-#define GST_MATROSKA_CODEC_ID_AUDIO_FLAC         "A_FLAC"
-#define GST_MATROSKA_CODEC_ID_AUDIO_ACM          "A_MS/ACM"
-#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG2        "A_AAC/MPEG2/"
-#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG4        "A_AAC/MPEG4/"
-#define GST_MATROSKA_CODEC_ID_AUDIO_TTA          "A_TTA1"
-#define GST_MATROSKA_CODEC_ID_AUDIO_WAVPACK4     "A_WAVPACK4"
-#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_14_4    "A_REAL/28_8"
-#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_28_8    "A_REAL/28_8"
-#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_COOK    "A_REAL/COOK"
-#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_SIPR    "A_REAL/SIPR"
-#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_RALF    "A_REAL/RALF"
-#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_ATRC    "A_REAL/ATRC"
-
-/* TODO: AC3-9/10 (?), Musepack, Quicktime */
 
+#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1       "A_MPEG/L1"
+#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2       "A_MPEG/L2"
+#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3       "A_MPEG/L3"
+#define GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE     "A_PCM/INT/BIG"
+#define GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE     "A_PCM/INT/LIT"
+#define GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT      "A_PCM/FLOAT/IEEE"
+#define GST_MATROSKA_CODEC_ID_AUDIO_AC3            "A_AC3"
+#define GST_MATROSKA_CODEC_ID_AUDIO_AC3_BSID9      "A_AC3/BSID9"
+#define GST_MATROSKA_CODEC_ID_AUDIO_AC3_BSID10     "A_AC3/BSID10"
+#define GST_MATROSKA_CODEC_ID_AUDIO_DTS            "A_DTS"
+#define GST_MATROSKA_CODEC_ID_AUDIO_VORBIS         "A_VORBIS"
+#define GST_MATROSKA_CODEC_ID_AUDIO_FLAC           "A_FLAC"
+#define GST_MATROSKA_CODEC_ID_AUDIO_ACM            "A_MS/ACM"
+#define GST_MATROSKA_CODEC_ID_AUDIO_TTA            "A_TTA1"
+#define GST_MATROSKA_CODEC_ID_AUDIO_WAVPACK4       "A_WAVPACK4"
+#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_14_4      "A_REAL/14_4"
+#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_28_8      "A_REAL/28_8"
+#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_COOK      "A_REAL/COOK"
+#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_SIPR      "A_REAL/SIPR"
+#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_RALF      "A_REAL/RALF"
+#define GST_MATROSKA_CODEC_ID_AUDIO_REAL_ATRC      "A_REAL/ATRC"
+#define GST_MATROSKA_CODEC_ID_AUDIO_AAC            "A_AAC"
+#define GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG2      "A_AAC/MPEG2/"
+#define GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG4      "A_AAC/MPEG4/"
+#define GST_MATROSKA_CODEC_ID_AUDIO_QUICKTIME_QDMC "A_QUICKTIME/QDMC"
+#define GST_MATROSKA_CODEC_ID_AUDIO_QUICKTIME_QDM2 "A_QUICKTIME/QDM2"
+/* Undefined for now:
+#define GST_MATROSKA_CODEC_ID_AUDIO_MPC            "A_MPC"
+*/
+
+#define GST_MATROSKA_CODEC_ID_SUBTITLE_ASCII     "S_TEXT/ASCII"
 #define GST_MATROSKA_CODEC_ID_SUBTITLE_UTF8      "S_TEXT/UTF8"
 #define GST_MATROSKA_CODEC_ID_SUBTITLE_SSA       "S_TEXT/SSA"
 #define GST_MATROSKA_CODEC_ID_SUBTITLE_ASS       "S_TEXT/ASS" 
 #define GST_MATROSKA_CODEC_ID_SUBTITLE_USF       "S_TEXT/USF"
 #define GST_MATROSKA_CODEC_ID_SUBTITLE_VOBSUB    "S_VOBSUB"
+#define GST_MATROSKA_CODEC_ID_SUBTITLE_BMP       "S_IMAGE/BMP"
 
 /*
- * Matrodka tags. Strings.
+ * Matroska tags. Strings.
  */
 
+/* TODO: check for other tags */
+
 #define GST_MATROSKA_TAG_ID_TITLE    "TITLE"
 #define GST_MATROSKA_TAG_ID_AUTHOR   "AUTHOR"
 #define GST_MATROSKA_TAG_ID_ALBUM    "ALBUM"
 #define GST_MATROSKA_TAG_ID_COPYRIGHT "COPYRIGHT"
 
 /*
+ * TODO: add this tag & mappings
+ * "URL" -> GST_TAG_LOCATION
+ * "BPS" -> GST_TAG_BITRATE
+ * "BPM" -> GST_TAG_BEATS_PER_MINUTE
+ * "REPLAYGAIN_GAIN" -> GST_TAG_*_GAIN   see http://replaygain.hydrogenaudio.org/rg_data_format.html
+ * "REPLAYGAIN_PEAK" -> GST_TAG_*_PEAK   see http://replaygain.hydrogenaudio.org/peak_data_format.html
+ * "TERMS_OF_USE" -> GST_TAG_LICENSE
+ * "DATE_RECORDED" -> GST_TAG_DATE
+ * "COMPOSER" -> GST_TAG_COMPOSER
+ * "LEAD_PERFORMER" -> GST_TAG_PERFORMER
+ * "GENRE" -> GST_TAG_GENRE
+ *
+ * "TOTAL_PARTS" -> GST_TAG_TRACK_COUNT    depending on target
+ * "PART_NUMBER" -> GST_TAG_TRACK_NUMBER   depending on target
+ *
+ * "EMAIL"       ->
+ * "ADDRESS"     ->
+ * "FAX"         ->  GST_TAG_CONTACT
+ * "PHONE"       ->
+ *
+ * TODO: maybe add custom gstreamer tags for other standard matroska tags
+ */
+
+/*
  * Enumerations for various types (mapping from binary
  * value to what it actually means).
  */
@@ -219,6 +427,7 @@ typedef enum {
   GST_MATROSKA_TRACK_TYPE_COMPLEX  = 0x3,
   GST_MATROSKA_TRACK_TYPE_LOGO     = 0x10,
   GST_MATROSKA_TRACK_TYPE_SUBTITLE = 0x11,
+  GST_MATROSKA_TRACK_TYPE_BUTTONS  = 0x12,
   GST_MATROSKA_TRACK_TYPE_CONTROL  = 0x20,
 } GstMatroskaTrackType;
 
@@ -244,6 +453,7 @@ typedef enum {
   GST_MATROSKA_TRACK_ENABLED = (1<<0),
   GST_MATROSKA_TRACK_DEFAULT = (1<<1),
   GST_MATROSKA_TRACK_LACING  = (1<<2),
+  GST_MATROSKA_TRACK_FORCED  = (1<<3),
   GST_MATROSKA_TRACK_SHIFT   = (1<<16)
 } GstMatroskaTrackFlags;
 
@@ -251,6 +461,7 @@ typedef enum {
   GST_MATROSKA_VIDEOTRACK_INTERLACED = (GST_MATROSKA_TRACK_SHIFT<<0)
 } GstMatroskaVideoTrackFlags;
 
+/* TODO: check if all fields are used */
 typedef struct _GstMatroskaTrackContext {
   GstPad       *pad;
   GstCaps      *caps;
@@ -266,6 +477,7 @@ typedef struct _GstMatroskaTrackContext {
   GstMatroskaTrackFlags flags;
   guint64       default_duration;
   guint64       pos;
+  gdouble       timecodescale;
 
   gboolean      set_discont; /* TRUE = set DISCONT flag on next buffer */
 
@@ -313,12 +525,6 @@ typedef struct _GstMatroskaTrackAudioContext {
   guint         samplerate, channels, bitdepth;
 } GstMatroskaTrackAudioContext;
 
-typedef struct _GstMatroskaTrackComplexContext {
-  GstMatroskaTrackContext parent;
-
-  /* nothing special goes here, apparently */
-} GstMatroskaTrackComplexContext;
-
 typedef struct _GstMatroskaTrackSubtitleContext {
   GstMatroskaTrackContext parent;
 
@@ -357,6 +563,5 @@ typedef struct _GstMatroskaTrackEncoding {
 gboolean gst_matroska_track_init_video_context    (GstMatroskaTrackContext ** p_context);
 gboolean gst_matroska_track_init_audio_context    (GstMatroskaTrackContext ** p_context);
 gboolean gst_matroska_track_init_subtitle_context (GstMatroskaTrackContext ** p_context);
-gboolean gst_matroska_track_init_complex_context  (GstMatroskaTrackContext ** p_context);
 
 #endif /* __GST_MATROSKA_IDS_H__ */
index dd3fbd3..d41ba0a 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
+/* TODO: - check everywhere that we don't write invalid values
+ *       - make sure timestamps are correctly scaled everywhere
+ */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -55,6 +59,10 @@ static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
   "width = (int) [ 16, 4096 ], " \
   "height = (int) [ 16, 4096 ] "
 
+/* FIXME: 
+ * * require codec data, etc as needed
+ */
+
 static GstStaticPadTemplate videosink_templ =
     GST_STATIC_PAD_TEMPLATE ("video_%d",
     GST_PAD_SINK,
@@ -92,6 +100,7 @@ static GstStaticPadTemplate videosink_templ =
 
 /* FIXME:
  * * audio/x-raw-float: endianness needs defining.
+ * * require codec data, etc as needed
  */
 static GstStaticPadTemplate audiosink_templ =
     GST_STATIC_PAD_TEMPLATE ("audio_%d",
@@ -184,11 +193,6 @@ static void
 gst_matroska_mux_base_init (gpointer g_class)
 {
   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-  static const GstElementDetails gst_matroska_mux_details =
-      GST_ELEMENT_DETAILS ("Matroska muxer",
-      "Codec/Muxer",
-      "Muxes video/audio/subtitle streams into a matroska stream",
-      "Ronald Bultje <rbultje@ronald.bitfreak.net>");
 
   gst_element_class_add_pad_template (element_class,
       gst_static_pad_template_get (&videosink_templ));
@@ -198,7 +202,10 @@ gst_matroska_mux_base_init (gpointer g_class)
       gst_static_pad_template_get (&subtitlesink_templ));
   gst_element_class_add_pad_template (element_class,
       gst_static_pad_template_get (&src_templ));
-  gst_element_class_set_details (element_class, &gst_matroska_mux_details);
+  gst_element_class_set_details_simple (element_class, "Matroska muxer",
+      "Codec/Muxer",
+      "Muxes video/audio/subtitle streams into a matroska stream",
+      "Ronald Bultje <rbultje@ronald.bitfreak.net>");
 
   GST_DEBUG_CATEGORY_INIT (matroskamux_debug, "matroskamux", 0,
       "Matroska muxer");
@@ -208,12 +215,13 @@ static void
 gst_matroska_mux_class_init (GstMatroskaMuxClass * klass)
 {
   GObjectClass *gobject_class;
+
   GstElementClass *gstelement_class;
 
   gobject_class = (GObjectClass *) klass;
   gstelement_class = (GstElementClass *) klass;
 
-  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_matroska_mux_finalize);
+  gobject_class->finalize = gst_matroska_mux_finalize;
 
   gobject_class->get_property = gst_matroska_mux_get_property;
   gobject_class->set_property = gst_matroska_mux_set_property;
@@ -246,11 +254,7 @@ gst_matroska_mux_class_init (GstMatroskaMuxClass * klass)
 static void
 gst_matroska_mux_init (GstMatroskaMux * mux, GstMatroskaMuxClass * g_class)
 {
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-
-  mux->srcpad =
-      gst_pad_new_from_template (gst_element_class_get_pad_template
-      (gstelement_class, "src"), "src");
+  mux->srcpad = gst_pad_new_from_static_template (&src_templ, "src");
   gst_pad_set_event_function (mux->srcpad, gst_matroska_mux_handle_src_event);
   gst_element_add_pad (GST_ELEMENT (mux), mux->srcpad);
 
@@ -301,8 +305,10 @@ static guint32
 gst_matroska_mux_create_uid (void)
 {
   guint32 uid = 0;
+
   GRand *rand = g_rand_new ();
 
+  /* FIXME: array needs locking or moved into instance structure */
   while (!uid) {
     guint i;
 
@@ -357,6 +363,7 @@ static void
 gst_matroska_mux_reset (GstElement * element)
 {
   GstMatroskaMux *mux = GST_MATROSKA_MUX (element);
+
   GSList *walk;
 
   /* reset EBML write */
@@ -368,6 +375,7 @@ gst_matroska_mux_reset (GstElement * element)
   /* clean up existing streams */
   while ((walk = mux->collect->data) != NULL) {
     GstMatroskaPad *collect_pad;
+
     GstPad *thepad;
 
     collect_pad = (GstMatroskaPad *) walk->data;
@@ -396,7 +404,7 @@ gst_matroska_mux_reset (GstElement * element)
   mux->index = NULL;
 
   /* reset timers */
-  mux->time_scale = 1000000;
+  mux->time_scale = GST_MSECOND;
   mux->duration = 0;
 
   /* reset uid array */
@@ -463,9 +471,13 @@ static gboolean
 gst_matroska_mux_handle_sink_event (GstPad * pad, GstEvent * event)
 {
   GstMatroskaTrackContext *context;
+
   GstMatroskaPad *collect_pad;
+
   GstMatroskaMux *mux;
+
   GstTagList *list;
+
   gboolean ret;
 
   mux = GST_MATROSKA_MUX (gst_pad_get_parent (pad));
@@ -514,12 +526,19 @@ static gboolean
 gst_matroska_mux_video_pad_setcaps (GstPad * pad, GstCaps * caps)
 {
   GstMatroskaTrackContext *context = NULL;
+
   GstMatroskaTrackVideoContext *videocontext;
+
   GstMatroskaMux *mux;
+
   GstMatroskaPad *collect_pad;
+
   GstStructure *structure;
+
   const gchar *mimetype;
+
   gint width, height, pixel_width, pixel_height;
+
   gint fps_d, fps_n;
 
   mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
@@ -578,6 +597,11 @@ skip_details:
   videocontext->eye_mode = GST_MATROSKA_EYE_MODE_MONO;
   videocontext->fourcc = 0;
 
+  /* TODO: - check if we handle all codecs by the spec, i.e. codec private
+   *         data and other settings
+   *       - add new formats
+   */
+
   /* find type */
   if (!strcmp (mimetype, "video/x-raw-yuv")) {
     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED);
@@ -594,7 +618,9 @@ skip_details:
       || !strcmp (mimetype, "video/x-dv")
       || !strcmp (mimetype, "video/x-h263")) {
     BITMAPINFOHEADER *bih;
+
     const GValue *codec_data;
+
     gint size = sizeof (BITMAPINFOHEADER);
 
     bih = g_new0 (BITMAPINFOHEADER, 1);
@@ -666,6 +692,7 @@ skip_details:
 
     if (codec_data != NULL) {
       guint8 *priv_data = NULL;
+
       guint priv_data_size = 0;
 
       GstBuffer *codec_data_buf = g_value_peek_pointer (codec_data);
@@ -735,8 +762,11 @@ xiph3_streamheader_to_codecdata (const GValue * streamheader,
     GstMatroskaTrackContext * context, GstBuffer ** p_buf0)
 {
   GstBuffer *buf[3];
+
   GArray *bufarr;
+
   guint8 *priv_data;
+
   guint i, offset, priv_data_size;
 
   if (streamheader == NULL)
@@ -835,6 +865,7 @@ vorbis_streamheader_to_codecdata (const GValue * streamheader,
   } else {
     if (memcmp (GST_BUFFER_DATA (buf0) + 1, "vorbis", 6) == 0) {
       GstMatroskaTrackAudioContext *audiocontext;
+
       guint8 *hdr;
 
       hdr = GST_BUFFER_DATA (buf0) + 1 + 6 + 4;
@@ -865,7 +896,9 @@ theora_streamheader_to_codecdata (const GValue * streamheader,
     GST_WARNING ("First header not a theora identification header, ignoring");
   } else {
     GstMatroskaTrackVideoContext *videocontext;
+
     guint fps_num, fps_denom, par_num, par_denom;
+
     guint8 *hdr;
 
     hdr = GST_BUFFER_DATA (buf0) + 1 + 6 + 3 + 2 + 2;
@@ -920,11 +953,17 @@ static gboolean
 gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
 {
   GstMatroskaTrackContext *context = NULL;
+
   GstMatroskaTrackAudioContext *audiocontext;
+
   GstMatroskaMux *mux;
+
   GstMatroskaPad *collect_pad;
+
   const gchar *mimetype;
+
   gint samplerate = 0, channels = 0;
+
   GstStructure *structure;
 
   mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
@@ -949,6 +988,11 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
   audiocontext->bitdepth = 0;
   context->default_duration = 0;
 
+  /* TODO: - check if we handle all codecs by the spec, i.e. codec private
+   *         data and other settings
+   *       - add new formats
+   */
+
   if (!strcmp (mimetype, "audio/mpeg")) {
     gint mpegversion = 0;
 
@@ -957,6 +1001,10 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
       case 1:{
         gint layer;
 
+        /* FIXME: number of samples per frame also depends on the mpegversion
+         * which we don't pass as a caps field
+         */
+
         gst_structure_get_int (structure, "layer", &layer);
         switch (layer) {
           case 1:
@@ -980,10 +1028,12 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
         break;
       }
       case 2:
-        context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_MPEG2 "MAIN");
+        context->codec_id =
+            g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG2 "MAIN");
         break;
       case 4:
-        context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_MPEG4 "MAIN");
+        context->codec_id =
+            g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG4 "MAIN");
         break;
       default:
         return FALSE;
@@ -992,6 +1042,7 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
     return TRUE;
   } else if (!strcmp (mimetype, "audio/x-raw-int")) {
     gint endianness, width, depth;
+
     gboolean signedness;
 
     if (!gst_structure_get_int (structure, "width", &width) ||
@@ -1078,7 +1129,8 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
 static gboolean
 gst_matroska_mux_subtitle_pad_setcaps (GstPad * pad, GstCaps * caps)
 {
-  /* Consider this as boilerplate code for now. There is
+  /* FIXME:
+   * Consider this as boilerplate code for now. There is
    * no single subtitle creation element in GStreamer,
    * neither do I know how subtitling works at all. */
 
@@ -1101,30 +1153,36 @@ gst_matroska_mux_request_new_pad (GstElement * element,
     GstPadTemplate * templ, const gchar * pad_name)
 {
   GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
+
   GstMatroskaMux *mux = GST_MATROSKA_MUX (element);
+
   GstMatroskaPad *collect_pad;
+
   GstPad *newpad = NULL;
+
   gchar *name = NULL;
+
   GstPadSetCapsFunction setcapsfunc = NULL;
+
   GstMatroskaTrackContext *context = NULL;
 
   if (templ == gst_element_class_get_pad_template (klass, "audio_%d")) {
     name = g_strdup_printf ("audio_%d", mux->num_a_streams++);
-    setcapsfunc = gst_matroska_mux_audio_pad_setcaps;
+    setcapsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_audio_pad_setcaps);
     context = (GstMatroskaTrackContext *)
         g_new0 (GstMatroskaTrackAudioContext, 1);
     context->type = GST_MATROSKA_TRACK_TYPE_AUDIO;
     context->name = g_strdup ("Audio");
   } else if (templ == gst_element_class_get_pad_template (klass, "video_%d")) {
     name = g_strdup_printf ("video_%d", mux->num_v_streams++);
-    setcapsfunc = gst_matroska_mux_video_pad_setcaps;
+    setcapsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_video_pad_setcaps);
     context = (GstMatroskaTrackContext *)
         g_new0 (GstMatroskaTrackVideoContext, 1);
     context->type = GST_MATROSKA_TRACK_TYPE_VIDEO;
     context->name = g_strdup ("Video");
   } else if (templ == gst_element_class_get_pad_template (klass, "subtitle_%d")) {
     name = g_strdup_printf ("subtitle_%d", mux->num_t_streams++);
-    setcapsfunc = gst_matroska_mux_subtitle_pad_setcaps;
+    setcapsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_subtitle_pad_setcaps);
     context = (GstMatroskaTrackContext *)
         g_new0 (GstMatroskaTrackSubtitleContext, 1);
     context->type = GST_MATROSKA_TRACK_TYPE_SUBTITLE;
@@ -1138,6 +1196,8 @@ gst_matroska_mux_request_new_pad (GstElement * element,
   g_free (name);
   collect_pad = (GstMatroskaPad *)
       gst_collect_pads_add_pad (mux->collect, newpad, sizeof (GstMatroskaPad));
+
+  /* TODO: check default values for the context */
   context->flags = GST_MATROSKA_TRACK_ENABLED | GST_MATROSKA_TRACK_DEFAULT;
   collect_pad->track = context;
   collect_pad->buffer = NULL;
@@ -1174,12 +1234,14 @@ static void
 gst_matroska_mux_release_pad (GstElement * element, GstPad * pad)
 {
   GstMatroskaMux *mux;
+
   GSList *walk;
 
   mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
 
   for (walk = mux->collect->data; walk; walk = g_slist_next (walk)) {
     GstCollectData *cdata = (GstCollectData *) walk->data;
+
     GstMatroskaPad *collect_pad = (GstMatroskaPad *) cdata;
 
     if (cdata->pad == pad) {
@@ -1219,8 +1281,11 @@ gst_matroska_mux_track_header (GstMatroskaMux * mux,
     GstMatroskaTrackContext * context)
 {
   GstEbmlWrite *ebml = mux->ebml_write;
+
   guint64 master;
 
+  /* TODO: check if everything necessary is written and check default values */
+
   /* track type goes before the type-specific stuff */
   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKNUMBER, context->num);
   gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKTYPE, context->type);
@@ -1298,6 +1363,7 @@ gst_matroska_mux_track_header (GstMatroskaMux * mux,
   /* FIXME: until we have a nice way of getting the codecname
    * out of the caps, I'm not going to enable this. Too much
    * (useless, double, boring) work... */
+  /* TODO: Use value from tags if any */
   /*gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_CODECNAME,
      context->codec_name); */
   gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_TRACKNAME, context->name);
@@ -1314,7 +1380,8 @@ static void
 gst_matroska_mux_start (GstMatroskaMux * mux)
 {
   GstEbmlWrite *ebml = mux->ebml_write;
-  guint32 seekhead_id[] = { GST_MATROSKA_ID_INFO,
+
+  guint32 seekhead_id[] = { GST_MATROSKA_ID_SEGMENTINFO,
     GST_MATROSKA_ID_TRACKS,
     GST_MATROSKA_ID_CUES,
     GST_MATROSKA_ID_SEEKHEAD,
@@ -1322,11 +1389,17 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
     0
   };
   guint64 master, child;
+
   GSList *collected;
+
   int i;
+
   guint tracknum = 1;
+
   GstClockTime duration = 0;
+
   guint32 *segment_uid = (guint32 *) g_malloc (16);
+
   GRand *rand = g_rand_new ();
   GTimeVal time = { 0, 0 };
 
@@ -1354,7 +1427,7 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
 
   /* segment info */
   mux->info_pos = ebml->pos;
-  master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_INFO);
+  master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_SEGMENTINFO);
   for (i = 0; i < 4; i++) {
     segment_uid[i] = g_rand_int (rand);
   }
@@ -1368,8 +1441,11 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
   for (collected = mux->collect->data; collected;
       collected = g_slist_next (collected)) {
     GstMatroskaPad *collect_pad;
+
     GstFormat format = GST_FORMAT_TIME;
+
     GstPad *thepad;
+
     gint64 trackduration;
 
     collect_pad = (GstMatroskaPad *) collected->data;
@@ -1406,6 +1482,7 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
       collected = g_slist_next (collected)) {
 
     GstMatroskaPad *collect_pad;
+
     GstPad *thepad;
 
     collect_pad = (GstMatroskaPad *) collected->data;
@@ -1429,6 +1506,7 @@ static void
 gst_matroska_mux_write_simple_tag (const GstTagList * list, const gchar * tag,
     gpointer data)
 {
+  /* TODO: more sensible tag mappings */
   struct
   {
     gchar *matroska_tagname;
@@ -1446,11 +1524,14 @@ gst_matroska_mux_write_simple_tag (const GstTagList * list, const gchar * tag,
     GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}
   };
   GstEbmlWrite *ebml = (GstEbmlWrite *) data;
+
   guint i;
+
   guint64 simpletag_master;
 
   for (i = 0; i < G_N_ELEMENTS (tag_conv); i++) {
     const gchar *tagname_gst = tag_conv[i].gstreamer_tagname;
+
     const gchar *tagname_mkv = tag_conv[i].matroska_tagname;
 
     if (strcmp (tagname_gst, tag) == 0) {
@@ -1486,9 +1567,13 @@ static void
 gst_matroska_mux_finish (GstMatroskaMux * mux)
 {
   GstEbmlWrite *ebml = mux->ebml_write;
+
   guint64 pos;
+
   guint64 duration = 0;
+
   GSList *collected;
+
   GstTagList *tags;
 
   /* finish last cluster */
@@ -1499,6 +1584,7 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
   /* cues */
   if (mux->index != NULL) {
     guint n;
+
     guint64 master, pointentry_master, trackpos_master;
 
     mux->cues_pos = ebml->pos;
@@ -1513,7 +1599,7 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUETIME,
           idx->time / mux->time_scale);
       trackpos_master = gst_ebml_write_master_start (ebml,
-          GST_MATROSKA_ID_CUETRACKPOSITION);
+          GST_MATROSKA_ID_CUETRACKPOSITIONS);
       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUETRACK, idx->track);
       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CUECLUSTERPOSITION,
           idx->pos - mux->segment_master);
@@ -1527,6 +1613,7 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
 
   if (mux->meta_index != NULL) {
     guint n;
+
     guint64 master, seekentry_master;
 
     mux->meta_pos = ebml->pos;
@@ -1554,6 +1641,7 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
   if (tags != NULL) {
     guint64 master_tags, master_tag;
 
+    /* TODO: maybe limit via the TARGETS id by looking at the source pad */
     mux->tags_pos = ebml->pos;
     master_tags = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAGS);
     master_tag = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAG);
@@ -1618,6 +1706,7 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
   for (collected = mux->collect->data; collected;
       collected = g_slist_next (collected)) {
     GstMatroskaPad *collect_pad;
+
     GstClockTime min_duration;  /* observed minimum duration */
 
     collect_pad = (GstMatroskaPad *) collected->data;
@@ -1650,6 +1739,13 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
         gst_guint64_to_gdouble (duration) /
         gst_guint64_to_gdouble (mux->time_scale));
     gst_ebml_write_seek (ebml, pos);
+  } else {
+    /* void'ify */
+    guint64 my_pos = ebml->pos;
+
+    gst_ebml_write_seek (ebml, mux->duration_pos);
+    gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 8);
+    gst_ebml_write_seek (ebml, my_pos);
   }
 
   /* finish segment - this also writes element length */
@@ -1671,6 +1767,7 @@ static GstMatroskaPad *
 gst_matroska_mux_best_pad (GstMatroskaMux * mux, gboolean * popped)
 {
   GSList *collected;
+
   GstMatroskaPad *best = NULL;
 
   *popped = FALSE;
@@ -1743,12 +1840,19 @@ static GstFlowReturn
 gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
 {
   GstEbmlWrite *ebml = mux->ebml_write;
+
   GstBuffer *buf, *hdr;
+
   guint64 cluster, blockgroup;
+
   gboolean write_duration;
+
   gint16 relative_timestamp;
+
   gint64 relative_timestamp64;
+
   guint64 block_duration;
+
   gboolean is_video_keyframe = FALSE;
 
   /* write data */
@@ -1765,6 +1869,8 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
 
   /* hm, invalid timestamp (due to --to be fixed--- element upstream);
    * this would wreak havoc with time stored in matroska file */
+  /* TODO: maybe calculate a timestamp by using the previous timestamp
+   * and default duration */
   if (!GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
     GST_WARNING_OBJECT (collect_pad->collect.pad,
         "Invalid buffer timestamp; dropping buffer");
@@ -1871,7 +1977,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
 
   /* write the block, for matroska v2 use SimpleBlock if possible
    * one slice (*breath*).
-   * FIXME: lacing, etc. */
+   * FIXME: Need to do correct lacing! */
   relative_timestamp64 = GST_BUFFER_TIMESTAMP (buf) - mux->cluster_time;
   if (relative_timestamp64 >= 0) {
     /* round the timestamp */
@@ -1926,8 +2032,11 @@ static GstFlowReturn
 gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data)
 {
   GstMatroskaMux *mux = GST_MATROSKA_MUX (user_data);
+
   GstMatroskaPad *best;
+
   gboolean popped;
+
   GstFlowReturn ret;
 
   GST_DEBUG_OBJECT (mux, "Collected pads");
@@ -1965,6 +2074,7 @@ gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data)
      * the actual duration later when we send an updated header on eos */
     if (GST_BUFFER_TIMESTAMP_IS_VALID (best->buffer)) {
       GstClockTime start_ts = GST_BUFFER_TIMESTAMP (best->buffer);
+
       GstClockTime end_ts = start_ts;
 
       if (GST_BUFFER_DURATION_IS_VALID (best->buffer))
@@ -2001,6 +2111,7 @@ static GstStateChangeReturn
 gst_matroska_mux_change_state (GstElement * element, GstStateChange transition)
 {
   GstStateChangeReturn ret;
+
   GstMatroskaMux *mux = GST_MATROSKA_MUX (element);
 
   switch (transition) {
@@ -2051,7 +2162,7 @@ gst_matroska_mux_set_property (GObject * object,
         break;
       }
       g_free (mux->writing_app);
-      mux->writing_app = g_strdup (g_value_get_string (value));
+      mux->writing_app = g_value_dup_string (value);
       break;
     case ARG_MATROSKA_VERSION:
       mux->matroska_version = g_value_get_int (value);