summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVittorio Giovara <vittorio.giovara@gmail.com>2016-10-24 17:46:47 -0400
committerVittorio Giovara <vittorio.giovara@gmail.com>2016-11-01 12:19:00 -0400
commitecd2ec69ce10e13f6ede353d2def7ce9f45c1a7d (patch)
treec8a6e37b50a9ad68c4ebe319a440eb9314e6c963
parentb90c8a3d08e3f9ad4de1253376d2d1d93abb8b8c (diff)
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: Vittorio Giovara <vittorio.giovara@gmail.com>
-rw-r--r--libavformat/isom.h2
-rw-r--r--libavformat/mov.c49
-rw-r--r--tests/ref/fate/mov-dar2
-rw-r--r--tests/ref/fate/mov-display-matrix2
-rw-r--r--tests/ref/fate/mov-sar2
5 files changed, 40 insertions, 17 deletions
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