Commit ecd2ec69 authored by Vittorio Giovara's avatar Vittorio Giovara

mov: Evaluate the movie display matrix

This matrix needs to be applied after all others have (currently only
display matrix from trak), but cannot be handled in movie box, since
streams are not allocated yet. So store it in main context, and apply
it when appropriate, that is after parsing the tkhd one.

Fate tests are updated accordingly.
Signed-off-by: 's avatarVittorio Giovara <vittorio.giovara@gmail.com>
parent b90c8a3d
...@@ -167,6 +167,8 @@ typedef struct MOVContext { ...@@ -167,6 +167,8 @@ typedef struct MOVContext {
int export_all; int export_all;
int export_xmp; int export_xmp;
int enable_drefs; int enable_drefs;
int32_t movie_display_matrix[3][3]; ///< display matrix from mvhd
} MOVContext; } MOVContext;
int ff_mp4_read_descr_len(AVIOContext *pb); int ff_mp4_read_descr_len(AVIOContext *pb);
......
...@@ -950,6 +950,7 @@ static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) ...@@ -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) static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{ {
int i;
time_t creation_time; time_t creation_time;
int version = avio_r8(pb); /* version */ int version = avio_r8(pb); /* version */
avio_rb24(pb); /* flags */ avio_rb24(pb); /* flags */
...@@ -973,7 +974,12 @@ static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) ...@@ -973,7 +974,12 @@ static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
avio_skip(pb, 10); /* reserved */ 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 time */
avio_rb32(pb); /* preview duration */ avio_rb32(pb); /* preview duration */
...@@ -2748,13 +2754,23 @@ static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom) ...@@ -2748,13 +2754,23 @@ static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
return 0; 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) static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{ {
int i; int i, j, e;
int width; int width;
int height; int height;
int64_t disp_transform[2]; int64_t disp_transform[2];
int display_matrix[3][3]; int display_matrix[3][3];
int res_display_matrix[3][3] = { { 0 } };
AVStream *st; AVStream *st;
MOVStreamContext *sc; MOVStreamContext *sc;
int version; int version;
...@@ -2804,15 +2820,20 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) ...@@ -2804,15 +2820,20 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
sc->width = width >> 16; sc->width = width >> 16;
sc->height = height >> 16; sc->height = height >> 16;
// save the matrix when it is not the default identity // apply the moov display matrix (after the tkhd one)
if (display_matrix[0][0] != (1 << 16) || for (i = 0; i < 3; i++) {
display_matrix[1][1] != (1 << 16) || const int sh[3] = { 16, 16, 30 };
display_matrix[2][2] != (1 << 30) || for (j = 0; j < 3; j++) {
display_matrix[0][1] || display_matrix[0][2] || for (e = 0; e < 3; e++) {
display_matrix[1][0] || display_matrix[1][2] || res_display_matrix[i][j] +=
display_matrix[2][0] || display_matrix[2][1]) { ((int64_t) display_matrix[i][e] *
int i, j; 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); av_freep(&sc->display_matrix);
sc->display_matrix = av_malloc(sizeof(int32_t) * 9); sc->display_matrix = av_malloc(sizeof(int32_t) * 9);
if (!sc->display_matrix) if (!sc->display_matrix)
...@@ -2820,7 +2841,7 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) ...@@ -2820,7 +2841,7 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++) 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 // transform the display width/height according to the matrix
...@@ -2829,9 +2850,9 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) ...@@ -2829,9 +2850,9 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
if (width && height && sc->display_matrix) { if (width && height && sc->display_matrix) {
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
disp_transform[i] = disp_transform[i] =
(int64_t) width * display_matrix[0][i] + (int64_t) width * sc->display_matrix[0 + i] +
(int64_t) height * display_matrix[1][i] + (int64_t) height * sc->display_matrix[3 + i] +
((int64_t) display_matrix[2][i] << 16); ((int64_t) sc->display_matrix[6 + i] << 16);
//sample aspect ratio is new width/height divided by old width/height //sample aspect ratio is new width/height divided by old width/height
if (disp_transform[0] > 0 && disp_transform[1] > 0) if (disp_transform[0] > 0 && disp_transform[1] > 0)
......
0 0
65536 131072
0 0
-65536 -65536
0 0
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment