|
@@ -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)
|