diff --git a/libavformat/isom.h b/libavformat/isom.h
index 2246fed..2aeb8fa 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -238,6 +238,8 @@ typedef struct MOVContext {
     uint8_t *decryption_key;
     int decryption_key_len;
     int enable_drefs;
+
+    int32_t movie_display_matrix[3][3]; ///< display matrix from mvhd
 } MOVContext;
 
 int ff_mp4_read_descr_len(AVIOContext *pb);
diff --git a/libavformat/mov.c b/libavformat/mov.c
index a15c8d1..26b332c 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -1211,6 +1211,7 @@ static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 
 static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 {
+    int i;
     int64_t creation_time;
     int version = avio_r8(pb); /* version */
     avio_rb24(pb); /* flags */
@@ -1238,7 +1239,12 @@ static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 
     avio_skip(pb, 10); /* reserved */
 
-    avio_skip(pb, 36); /* display matrix */
+    /* movie display matrix, store it in main context and use it later on */
+    for (i = 0; i < 3; i++) {
+        c->movie_display_matrix[i][0] = avio_rb32(pb); // 16.16 fixed point
+        c->movie_display_matrix[i][1] = avio_rb32(pb); // 16.16 fixed point
+        c->movie_display_matrix[i][2] = avio_rb32(pb); //  2.30 fixed point
+    }
 
     avio_rb32(pb); /* preview time */
     avio_rb32(pb); /* preview duration */
@@ -3798,9 +3804,24 @@ static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     return 0;
 }
 
+// return 0 when matrix is identity, 1 otherwise
+#define IS_MATRIX_FULL(matrix)       \
+    (matrix[0][0] != (1 << 16) ||    \
+     matrix[1][1] != (1 << 16) ||    \
+     matrix[2][2] != (1 << 30) ||    \
+     matrix[0][1] || matrix[0][2] || \
+     matrix[1][0] || matrix[1][2] || \
+     matrix[2][0] || matrix[2][1])
+
+// fixed point to double
+#define CONV_FP(x, sh) ((double) (x)) / (1 << sh)
+
+// double to fixed point
+#define CONV_DB(x, sh) (int32_t) ((x) * (1 << sh))
+
 static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 {
-    int i;
+    int i, j, e;
     int width;
     int height;
     int display_matrix[3][3];
@@ -3855,13 +3876,7 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 
     // save the matrix and add rotate metadata when it is not the default
     // identity
-    if (display_matrix[0][0] != (1 << 16) ||
-        display_matrix[1][1] != (1 << 16) ||
-        display_matrix[2][2] != (1 << 30) ||
-        display_matrix[0][1] || display_matrix[0][2] ||
-        display_matrix[1][0] || display_matrix[1][2] ||
-        display_matrix[2][0] || display_matrix[2][1]) {
-        int i, j;
+    if (IS_MATRIX_FULL(display_matrix)) {
         double rotate;
 
         av_freep(&sc->display_matrix);
@@ -3884,13 +3899,41 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
         }
     }
 
+    // if movie display matrix is not identity, and if this is a video track
+    if (IS_MATRIX_FULL(c->movie_display_matrix) && width && height) {
+        // if trak display matrix was identity, just copy the movie one
+        if (!sc->display_matrix) {
+            sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
+            if (!sc->display_matrix)
+                return AVERROR(ENOMEM);
+
+            for (i = 0; i < 3; i++)
+                for (j = 0; j < 3; j++)
+                    sc->display_matrix[i * 3 + j] = c->movie_display_matrix[i][j];
+        } else { // otherwise multiply the two and store the result
+            double val = 0;
+            for (i = 0; i < 3; i++) {
+                for (j = 0; j < 3; j++) {
+                    int sh = j == 2 ? 30 : 16;
+                    for (e = 0; e < 3; e++) {
+                        val += CONV_FP(display_matrix[i][e], sh) *
+                               CONV_FP(c->movie_display_matrix[e][j], sh);
+                    }
+                    sc->display_matrix[i * 3 + j] = CONV_DB(val, sh);
+                    val = 0;
+                }
+            }
+        }
+    }
+
     // transform the display width/height according to the matrix
     // to keep the same scale, use [width height 1<<16]
     if (width && height && sc->display_matrix) {
         double disp_transform[2];
 
         for (i = 0; i < 2; i++)
-            disp_transform[i] = hypot(display_matrix[i][0], display_matrix[i][1]);
+            disp_transform[i] = hypot(sc->display_matrix[i * 3],
+                                      sc->display_matrix[i * 3 + 1]);
 
         if (disp_transform[0] > 0       && disp_transform[1] > 0 &&
             disp_transform[0] < (1<<24) && disp_transform[1] < (1<<24) &&
