--- a/gst/isomp4/qtdemux.c
+++ b/gst/isomp4/qtdemux.c
@@ -288,6 +288,7 @@ struct _QtDemuxStream
   gboolean send_global_tags;
 
   GstEvent *pending_event;
+  GstEvent *transform_event;
 
   GstByteReader stco;
   GstByteReader stsz;
@@ -3579,9 +3580,9 @@ gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
   gchar *str;
 
   /* not many cases for now */
-  if (G_UNLIKELY (stream->fourcc == FOURCC_mp4s)) {
+  if (stream->pending_event) {
     /* send a one time dvd clut event */
-    if (stream->pending_event && stream->pad)
+    if (stream->pad)
       gst_pad_push_event (stream->pad, stream->pending_event);
     stream->pending_event = NULL;
     /* no further processing needed */
@@ -5253,6 +5254,10 @@ gst_qtdemux_add_stream (GstQTDemux * qtdemux,
         GST_ELEMENT_CAST (qtdemux), "%u", stream->track_id);
     gst_pad_push_event (stream->pad, gst_event_new_stream_start (stream_id));
     g_free (stream_id);
+    if (stream->transform_event) {
+      gst_pad_push_event (stream->pad, stream->transform_event);
+      stream->transform_event = NULL;
+    }
     gst_pad_set_caps (stream->pad, stream->caps);
 
     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
@@ -6408,6 +6413,48 @@ bad_data:
   return 0;
 }
 
+static gboolean
+_matrix_is_identity (gfloat matrix[9])
+{
+  static const gfloat identity[] = {
+    1, 0, 0,
+    0, 1, 0,
+    0, 0, 1 };
+  gint i;
+
+  for (i = 0; i < 9; i++)
+    if (matrix[i] != identity[i])
+      return FALSE;
+
+  return TRUE;
+}
+
+static GstEvent *
+_make_matrix_event (gfloat matrix[9])
+{
+  GstStructure *s;
+  GValue array = { 0 };
+  GValue f = { 0 };
+  gint i;
+
+  s = gst_structure_new_empty ("transform-matrix-3x3");
+
+  g_value_init (&array, GST_TYPE_ARRAY);
+  g_value_init (&f, G_TYPE_FLOAT);
+
+  for (i = 0; i < 9; i++) {
+    g_value_set_float (&f, matrix[i]);
+    gst_value_array_append_value (&array, &f);
+    g_value_reset (&f);
+  }
+
+  gst_structure_set_value (s, "transform", &array);
+  g_value_unset (&array);
+  g_value_unset (&f);
+
+  return gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_STICKY, s);
+}
+
 /* parse the traks.
  * With each track we associate a new QtDemuxStream that contains all the info
  * about the trak.
@@ -6580,12 +6627,36 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
 
   if (stream->subtype == FOURCC_vide) {
     guint32 w = 0, h = 0;
+    gfloat matrix[9];
+    gint i;
 
     stream->sampled = TRUE;
 
     /* version 1 uses some 64-bit ints */
-    if (!gst_byte_reader_skip (&tkhd, 56 + value_size)
-        || !gst_byte_reader_get_uint32_be (&tkhd, &w)
+    if (gst_byte_reader_skip (&tkhd, 20 + value_size)) {
+      for (i = 0; i < 9; i++) {
+        guint32 fx;
+
+        gst_byte_reader_get_uint32_be (&tkhd, &fx);
+        if ((i + 1) % 3 == 0)
+          matrix[i] = ((gint32)fx >> 30) +
+            ((gfloat)(fx & 0x3fffffff)) / (1U << 30);
+        else
+          matrix[i] = ((gint32)fx >> 16) +
+            ((gfloat)(fx & 0xffff)) / (1U << 16);
+      }
+
+      GST_DEBUG_OBJECT (qtdemux, "TKHD matrix %.2f, %.2f, %.2f | "
+          "%.2f, %.2f, %.2f | %.2f, %.2f, %.2f",
+          matrix[0], matrix[1], matrix[2],
+          matrix[3], matrix[4], matrix[5],
+          matrix[6], matrix[7], matrix[8]);
+    }
+
+    if (!_matrix_is_identity (matrix))
+      stream->transform_event = _make_matrix_event (matrix);
+
+    if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
       goto corrupt_file;
 
