diff -ur -x Makefile.in -x aclocal.m4 -x configure -x 'config.*' -x ltmain.sh -x '*.spec' -x po ORG2/gst-plugins-good/gst/matroska/matroska-demux.c NEW2/gst-plugins-good/gst/matroska/matroska-demux.c
--- ORG2/gst-plugins-good/gst/matroska/matroska-demux.c	2008-12-03 14:06:24.000000000 +0000
+++ NEW2/gst-plugins-good/gst/matroska/matroska-demux.c	2008-12-03 14:03:30.000000000 +0000
@@ -106,7 +106,7 @@
     GST_PAD_SRC,
     GST_PAD_SOMETIMES,
     GST_STATIC_CAPS ("text/plain; application/x-ssa; application/x-ass; "
-        "application/x-usf; video/x-dvd-subpicture; "
+        "application/x-usf; video/x-dvd-subpicture; application/x-kate; "
         "application/x-subtitle-unknown")
     );
 
@@ -5562,6 +5562,9 @@
   } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_SUBTITLE_VOBSUB)) {
     caps = gst_caps_new_simple ("video/x-dvd-subpicture", NULL);
     ((GstMatroskaTrackContext *) subtitlecontext)->send_dvd_event = TRUE;
+  } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_SUBTITLE_KATE)) {
+    caps = gst_caps_new_simple ("application/x-kate", NULL);
+    context->send_xiph_headers = TRUE;
   } else {
     GST_DEBUG ("Unknown subtitle stream: codec_id='%s'", codec_id);
     caps = gst_caps_new_simple ("application/x-subtitle-unknown", NULL);
diff -ur -x Makefile.in -x aclocal.m4 -x configure -x 'config.*' -x ltmain.sh -x '*.spec' -x po ORG2/gst-plugins-good/gst/matroska/matroska-ids.h NEW2/gst-plugins-good/gst/matroska/matroska-ids.h
--- ORG2/gst-plugins-good/gst/matroska/matroska-ids.h	2008-12-03 14:06:24.000000000 +0000
+++ NEW2/gst-plugins-good/gst/matroska/matroska-ids.h	2008-12-03 14:03:30.000000000 +0000
@@ -376,6 +376,7 @@
 #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"
+#define GST_MATROSKA_CODEC_ID_SUBTITLE_KATE      "S_KATE"
 
 /*
  * Matroska tags. Strings.
diff -ur -x Makefile.in -x aclocal.m4 -x configure -x 'config.*' -x ltmain.sh -x '*.spec' -x po ORG2/gst-plugins-good/gst/matroska/matroska-mux.c NEW2/gst-plugins-good/gst/matroska/matroska-mux.c
--- ORG2/gst-plugins-good/gst/matroska/matroska-mux.c	2008-12-03 14:06:24.000000000 +0000
+++ NEW2/gst-plugins-good/gst/matroska/matroska-mux.c	2008-12-03 14:03:30.000000000 +0000
@@ -205,6 +205,8 @@
     GstMatroskaTrackContext * context);
 static gboolean vorbis_streamheader_to_codecdata (const GValue * streamheader,
     GstMatroskaTrackContext * context);
+static gboolean kate_streamheader_to_codecdata (const GValue * streamheader,
+    GstMatroskaTrackContext * context);
 static gboolean flac_streamheader_to_codecdata (const GValue * streamheader,
     GstMatroskaTrackContext * context);
 
@@ -808,14 +810,16 @@
   return FALSE;
 }
 
+/* N > 0 to expect a particular number of headers, negative if the
+   number of headers is variable */
 static gboolean
-xiph3_streamheader_to_codecdata (const GValue * streamheader,
-    GstMatroskaTrackContext * context, GstBuffer ** p_buf0)
+xiphN_streamheader_to_codecdata (const GValue * streamheader,
+    GstMatroskaTrackContext * context, GstBuffer ** p_buf0, int N)
 {
-  GstBuffer *buf[3];
+  GstBuffer **buf = NULL;
   GArray *bufarr;
   guint8 *priv_data;
-  guint i, offset, priv_data_size;
+  guint bufi, i, offset, priv_data_size;
 
   if (streamheader == NULL)
     goto no_stream_headers;
@@ -824,44 +828,51 @@
     goto wrong_type;
 
   bufarr = g_value_peek_pointer (streamheader);
-  if (bufarr->len != 3)
+  if (bufarr->len <= 0 || bufarr->len>255) /* at least one header, and count stored in a byte */
+    goto wrong_count;
+  if (N>0 && bufarr->len != N)
     goto wrong_count;
 
   context->xiph_headers_to_skip = bufarr->len;
 
-  for (i = 0; i < 3; i++) {
+  buf = (GstBuffer**) g_malloc0 (sizeof (GstBuffer*) * bufarr->len);
+  for (i = 0; i < bufarr->len; i++) {
     GValue *bufval = &g_array_index (bufarr, GValue, i);
 
-    if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER)
+    if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
+      g_free (buf);
       goto wrong_content_type;
+    }
 
     buf[i] = g_value_peek_pointer (bufval);
   }
 
   priv_data_size = 1;
-  priv_data_size += GST_BUFFER_SIZE (buf[0]) / 0xff + 1;
-  priv_data_size += GST_BUFFER_SIZE (buf[1]) / 0xff + 1;
+  if (bufarr->len > 0) {
+    for (i = 0; i < bufarr->len-1; i++) {
+      priv_data_size += GST_BUFFER_SIZE (buf[i]) / 0xff + 1;
+    }
+  }
 
-  for (i = 0; i < 3; ++i) {
+  for (i = 0; i < bufarr->len; ++i) {
     priv_data_size += GST_BUFFER_SIZE (buf[i]);
   }
 
   priv_data = g_malloc0 (priv_data_size);
 
-  priv_data[0] = 2;
+  priv_data[0] = bufarr->len-1;
   offset = 1;
 
-  for (i = 0; i < GST_BUFFER_SIZE (buf[0]) / 0xff; ++i) {
-    priv_data[offset++] = 0xff;
-  }
-  priv_data[offset++] = GST_BUFFER_SIZE (buf[0]) % 0xff;
-
-  for (i = 0; i < GST_BUFFER_SIZE (buf[1]) / 0xff; ++i) {
-    priv_data[offset++] = 0xff;
+  if (bufarr->len > 0) {
+    for (bufi = 0; bufi < bufarr->len-1; bufi++) {
+      for (i = 0; i < GST_BUFFER_SIZE (buf[bufi]) / 0xff; ++i) {
+        priv_data[offset++] = 0xff;
+      }
+      priv_data[offset++] = GST_BUFFER_SIZE (buf[bufi]) % 0xff;
+    }
   }
-  priv_data[offset++] = GST_BUFFER_SIZE (buf[1]) % 0xff;
 
-  for (i = 0; i < 3; ++i) {
+  for (i = 0; i < bufarr->len; ++i) {
     memcpy (priv_data + offset, GST_BUFFER_DATA (buf[i]),
         GST_BUFFER_SIZE (buf[i]));
     offset += GST_BUFFER_SIZE (buf[i]);
@@ -873,6 +884,8 @@
   if (p_buf0)
     *p_buf0 = gst_buffer_ref (buf[0]);
 
+  g_free (buf);
+
   return TRUE;
 
 /* ERRORS */
@@ -905,7 +918,7 @@
 {
   GstBuffer *buf0 = NULL;
 
-  if (!xiph3_streamheader_to_codecdata (streamheader, context, &buf0))
+  if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, 3))
     return FALSE;
 
   if (buf0 == NULL || GST_BUFFER_SIZE (buf0) < 1 + 6 + 4) {
@@ -934,7 +947,7 @@
 {
   GstBuffer *buf0 = NULL;
 
-  if (!xiph3_streamheader_to_codecdata (streamheader, context, &buf0))
+  if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, 3))
     return FALSE;
 
   if (buf0 == NULL || GST_BUFFER_SIZE (buf0) < 1 + 6 + 26) {
@@ -986,6 +999,27 @@
 }
 
 static gboolean
+kate_streamheader_to_codecdata (const GValue * streamheader,
+    GstMatroskaTrackContext * context)
+{
+  GstBuffer *buf0 = NULL;
+
+  if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, -1))
+    return FALSE;
+
+  if (buf0 == NULL || GST_BUFFER_SIZE (buf0) < 64) { /* Kate ID header is 64 bytes */
+    GST_WARNING ("First kate header too small, ignoring");
+  } else if (memcmp (GST_BUFFER_DATA (buf0), "\200kate\0\0\0", 8) != 0) {
+    GST_WARNING ("First header not a kate identification header, ignoring");
+  }
+
+  if (buf0)
+    gst_buffer_unref (buf0);
+
+  return TRUE;
+}
+
+static gboolean
 flac_streamheader_to_codecdata (const GValue * streamheader,
     GstMatroskaTrackContext * context)
 {
@@ -1368,6 +1402,57 @@
    * no single subtitle creation element in GStreamer,
    * neither do I know how subtitling works at all. */
 
+  /* There is now (at least) one such alement (kateenc), and I'm going
+     to handle it here and claim it works when it can be piped back
+     through GStreamer and VLC */
+
+  GstMatroskaTrackContext *context = NULL;
+  GstMatroskaTrackSubtitleContext *scontext;
+  GstMatroskaMux *mux;
+  GstMatroskaPad *collect_pad;
+  const gchar *mimetype;
+  GstStructure *structure;
+
+  mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
+
+  /* find context */
+  collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad);
+  g_assert (collect_pad);
+  context = collect_pad->track;
+  g_assert (context);
+  g_assert (context->type == GST_MATROSKA_TRACK_TYPE_SUBTITLE);
+  scontext = (GstMatroskaTrackSubtitleContext *) context;
+
+  structure = gst_caps_get_structure (caps, 0);
+  mimetype = gst_structure_get_name (structure);
+
+  /* general setup */
+  scontext->check_utf8 = 1;
+  scontext->invalid_utf8 = 0;
+  context->default_duration = 0;
+
+  /* TODO: - other format than Kate */
+
+  if (!strcmp (mimetype, "application/x-kate")) {
+    const GValue *streamheader;
+
+    context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_SUBTITLE_KATE);
+
+    if (context->codec_priv != NULL) {
+      g_free (context->codec_priv);
+      context->codec_priv = NULL;
+      context->codec_priv_size = 0;
+    }
+
+    streamheader = gst_structure_get_value (structure, "streamheader");
+    if (!kate_streamheader_to_codecdata (streamheader, context)) {
+      GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
+          ("kate stream headers missing or malformed"));
+      return FALSE;
+    }
+    return TRUE;
+  }
+
   return FALSE;
 }
 
