diff --git a/libavformat/isom.h b/libavformat/isom.h index 58f0a20062..1aa2091043 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -167,6 +167,8 @@ typedef struct MOVContext { int export_all; int export_xmp; 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 5a46f9440a..194daebc6e 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -950,6 +950,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; time_t creation_time; int version = avio_r8(pb); /* version */ avio_rb24(pb); /* flags */ @@ -973,7 +974,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 */ @@ -2748,13 +2754,23 @@ static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } +// return 1 when matrix is identity, 0 otherwise +#define IS_MATRIX_IDENT(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]) + static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) { - int i; + int i, j, e; int width; int height; int64_t disp_transform[2]; int display_matrix[3][3]; + int res_display_matrix[3][3] = { { 0 } }; AVStream *st; MOVStreamContext *sc; int version; @@ -2804,15 +2820,20 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc->width = width >> 16; sc->height = height >> 16; - // save the matrix 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; + // apply the moov display matrix (after the tkhd one) + for (i = 0; i < 3; i++) { + const int sh[3] = { 16, 16, 30 }; + for (j = 0; j < 3; j++) { + for (e = 0; e < 3; e++) { + res_display_matrix[i][j] += + ((int64_t) display_matrix[i][e] * + c->movie_display_matrix[e][j]) >> sh[e]; + } + } + } + // save the matrix when it is not the default identity + if (!IS_MATRIX_IDENT(res_display_matrix)) { av_freep(&sc->display_matrix); sc->display_matrix = av_malloc(sizeof(int32_t) * 9); if (!sc->display_matrix) @@ -2820,7 +2841,7 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) - sc->display_matrix[i * 3 + j] = display_matrix[i][j]; + sc->display_matrix[i * 3 + j] = res_display_matrix[i][j]; } // transform the display width/height according to the matrix @@ -2829,9 +2850,9 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (width && height && sc->display_matrix) { for (i = 0; i < 2; i++) disp_transform[i] = - (int64_t) width * display_matrix[0][i] + - (int64_t) height * display_matrix[1][i] + - ((int64_t) display_matrix[2][i] << 16); + (int64_t) width * sc->display_matrix[0 + i] + + (int64_t) height * sc->display_matrix[3 + i] + + ((int64_t) sc->display_matrix[6 + i] << 16); //sample aspect ratio is new width/height divided by old width/height if (disp_transform[0] > 0 && disp_transform[1] > 0) diff --git a/tests/ref/fate/mov-dar b/tests/ref/fate/mov-dar index 38a0ac45f8..9ca9a41bbc 100644 --- a/tests/ref/fate/mov-dar +++ b/tests/ref/fate/mov-dar @@ -1 +1 @@ -3:1 +3:2 diff --git a/tests/ref/fate/mov-display-matrix b/tests/ref/fate/mov-display-matrix index 64c95996a6..6498148147 100644 --- a/tests/ref/fate/mov-display-matrix +++ b/tests/ref/fate/mov-display-matrix @@ -1,5 +1,5 @@ 0 -65536 +131072 0 -65536 0 diff --git a/tests/ref/fate/mov-sar b/tests/ref/fate/mov-sar index 9f303fc9cb..291b047df4 100644 --- a/tests/ref/fate/mov-sar +++ b/tests/ref/fate/mov-sar @@ -1 +1 @@ -9:2 +9:4