[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