[FFmpeg-devel] [PATCH] mov: Evaluate the movie display matrix
Michael Niedermayer
michael at niedermayer.cc
Fri Oct 7 02:10:39 EEST 2016
On Wed, Oct 05, 2016 at 05:25:33PM -0400, Vittorio Giovara wrote:
> 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 if not identity, apply it when appropriate,
> handling the case when trak display matrix is identity and when it is not.
>
> Signed-off-by: Vittorio Giovara <vittorio.giovara at gmail.com>
> ---
> Please keep my in CC.
> Vittorio
>
> libavformat/isom.h | 2 ++
> libavformat/mov.c | 63 +++++++++++++++++++++++++++++++++++++++++++++---------
> 2 files changed, 55 insertions(+), 10 deletions(-)
>
> 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;
the matrixes are 32bit the product of their entries would thus fit in
64bit and double should not be needed, int64_t should work and
avoid rounding errors
ive also uploaded your sample to fatesamples, please add a fate test
so this doesnt break in the future
(mov/moviedispmat.mp4)
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
He who knows, does not speak. He who speaks, does not know. -- Lao Tsu
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20161007/ae32ff60/attachment.sig>
More information about the ffmpeg-devel
mailing list