From patchwork Wed Oct 5 21:25:33 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vittorio Giovara X-Patchwork-Id: 893 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.140.66 with SMTP id o63csp548469vsd; Wed, 5 Oct 2016 14:41:48 -0700 (PDT) X-Received: by 10.28.109.207 with SMTP id b76mr10296255wmi.66.1475703708396; Wed, 05 Oct 2016 14:41:48 -0700 (PDT) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id e5si14190394wmd.141.2016.10.05.14.41.47; Wed, 05 Oct 2016 14:41:48 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id E71FB689E4C; Thu, 6 Oct 2016 00:41:30 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-qk0-f194.google.com (mail-qk0-f194.google.com [209.85.220.194]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id B6447689E21 for ; Thu, 6 Oct 2016 00:41:24 +0300 (EEST) Received: by mail-qk0-f194.google.com with SMTP id j129so46203qkd.2 for ; Wed, 05 Oct 2016 14:41:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:subject:date:message-id; bh=vJDbejdCXcvGf9xt8yq+2uj4Uf4UrFtbWFBf3YkM3+c=; b=LsirskeBgqJeMZdQDw6BZbMcqq8TcJ+KPa7FOpzaM5htSjYFheQtTWDvUFYkZiNtfh Le9JY7/poyWnb6xhBaBmEW9dkN8jXwvFbLnsTJ4/0Yd83tSYYnFI6IYa/ITgWrQfzyUX Zlz39DMUM571W1la5Azjly3oMstHfIxngH+mCRQdrRbeQcfhvf4d/O8qPviv+WU4wmN+ KxdEJojqdLG9jehCvN1mdW2icJ+5rktS0/JEbg5Fr4Ul5cgkJypm+4kc3ueDXSpNDVPI uq48ppN2/d5lgayBSPpXrCMucqETy14VcXogA22jUGqAQsQxTaSR1XKy1VCWCzQGGWH4 1nsQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id; bh=vJDbejdCXcvGf9xt8yq+2uj4Uf4UrFtbWFBf3YkM3+c=; b=d2yopGkhgh4hlB/ReWZYwytXdF6R9U7/zEV741dMV48WXXdXbKOwknZEL2SyPnJnRa T2+pCgMiemUPqLwcbaEFjIQBxNY1XdmqZkmnO1Fh1DfyRcYdK2AXPswq2tNkQQ8fdz9D u6jWMFIK4gN1cG7F+T6YUduC1j7qJd1f0n979aBHqnxMB66oU5MUTztjTCweYTB6Ovoc zxBXeThOQI5qoCknDgL2PfGgg7bJigvpdssZceoGbABfuHqQldsdnO2ialE9BZc+85oi XY+erQ3kCMTk9Hf3ZSSOhak0ZSbH6VHA6BXDE1miDVWjjFN+5vjCmQtxcH1gppwAvZX7 kbCQ== X-Gm-Message-State: AA6/9RmS3TxH45DtpVuGjcpEENMSd8Dr1kVI5S1Qv7nLUa8IS5lo+3QdBbRmBkFqVa8aUA== X-Received: by 10.55.67.139 with SMTP id q133mr11429092qka.71.1475702734615; Wed, 05 Oct 2016 14:25:34 -0700 (PDT) Received: from vimacbookpro.iac.corp (nyv-exweb.iac.com. [216.112.252.10]) by smtp.gmail.com with ESMTPSA id 8sm21233942qty.36.2016.10.05.14.25.33 for (version=TLS1 cipher=AES128-SHA bits=128/128); Wed, 05 Oct 2016 14:25:34 -0700 (PDT) From: Vittorio Giovara To: ffmpeg-devel@ffmpeg.org Date: Wed, 5 Oct 2016 17:25:33 -0400 Message-Id: <20161005212533.90669-1-vittorio.giovara@gmail.com> X-Mailer: git-send-email 2.10.0 Subject: [FFmpeg-devel] [PATCH] mov: Evaluate the movie display matrix X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" 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 --- 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; + } + } + } + } + // transform the display width/height according to the matrix // to keep the same scale, use [width height 1<<16] if (width && height && sc->display_matrix) { double disp_transform[2]; for (i = 0; i < 2; i++) - disp_transform[i] = hypot(display_matrix[i][0], display_matrix[i][1]); + disp_transform[i] = hypot(sc->display_matrix[i * 3], + sc->display_matrix[i * 3 + 1]); if (disp_transform[0] > 0 && disp_transform[1] > 0 && disp_transform[0] < (1<<24) && disp_transform[1] < (1<<24) &&