From patchwork Tue Jan 17 18:50:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leo Izen X-Patchwork-Id: 40067 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:1d43:b0:b8:6755:f97e with SMTP id cs3csp2074960pzb; Tue, 17 Jan 2023 10:51:17 -0800 (PST) X-Google-Smtp-Source: AMrXdXs+QeE+nZg8mX4rnMc5D6DGj/RyDBzdL92AjNeAZYflOPkOBI9JxJiw/7J56StMwSzm0cLQ X-Received: by 2002:a05:6402:4305:b0:47f:6531:dee9 with SMTP id m5-20020a056402430500b0047f6531dee9mr5655013edc.20.1673981477210; Tue, 17 Jan 2023 10:51:17 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1673981477; cv=none; d=google.com; s=arc-20160816; b=xfpFSPjURE10RLmKV3Ty2JsA4PJeFz/gIE+TefK02AFE5ATJf4AFYbUBDJ3ro6p9Db 5SDI1ryCyiFW3U9BMjKFW/zuHoyWlHjcq67LJAQUhRfbhc1mdpENZcCPZu936SN84Y0Q lWJ2QB6x9UyxB7/DGS7OaVc2OF9Kf/APamwPthLxB2rTQJKUkyVBzP6P1q5kNQYascms wGQWUCcLO/meE8GeVxyohhq0+cbSB+dfMPzvk+UY2j1oMT8/bgymJa18OLnCNLp5kbUL oEG3qou3sqfVVWQSbb6A01N7D/S9ah4fzq59T5gUzLTxtsyKQOrIQo+arGf+D97qvE9W Q8sA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=V0UJQZhPg9+S8+Ey9HV4TH0wzYK9uI3TimPqndzN20c=; b=oZ2UNdIffUklyISd0iq3QfaoMUwfE55nfHpSjAvqOKYoClMhvKD0zrmdqs3kn4D3xM y6t+7CVLwnfil9X2vxCjkMgP/aPz2232v3zbzW3J0Z+clxbE4LaAR6mXpyYHXZ5Aechj dczooTY/WqE00H51ixUshCi1uCd35yauLOaugN/0MbVAWddURZuxnWWcjWxfcKSCaY+1 M2IA7TFNd0GJ5vgIMX7fUKG8JSqSb6sFp/RZbzaHT6YbJWIfVXyCwTz72ddDTyAhtESL XtSJiBOzjj8ry7JnFOdV3+SnDSvcGAosGvCXH/8Fdl8FJh04YQQbj/CV1U5Vta43YSSK 70LQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=n3BgS+KN; 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 sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id b14-20020a0564021f0e00b0049e054594e4si9702650edb.397.2023.01.17.10.51.16; Tue, 17 Jan 2023 10:51:17 -0800 (PST) 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 header.s=20210112 header.b=n3BgS+KN; 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 sp=QUARANTINE 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 3AD8C68BEA5; Tue, 17 Jan 2023 20:51:05 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-il1-f174.google.com (mail-il1-f174.google.com [209.85.166.174]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 48D9468BE53 for ; Tue, 17 Jan 2023 20:50:57 +0200 (EET) Received: by mail-il1-f174.google.com with SMTP id m7so3300290ilh.7 for ; Tue, 17 Jan 2023 10:50:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=f01cRZzpZuZVuLpNLZPOHU00bUDX65RsUyfvMSLhNeg=; b=n3BgS+KN1yYiHHFpcsvuygNk4PMto55usQ13GRmEALl+Kgg2ZB/Hw2ylyZrUPJzCT8 RrMXDVQGffuRNoE3MrEndzqeeEanLpVDFODayIIK1yw+0v9zDKmFIMIY/uO/CS/wSdEE XH+Xm38qflLGta7ZfzwTx661eLYN/6KdM6Fs/cOi86ldPK8ivZLRkNbamhYhVPrG8UrK Rd5Fb5J3qV2yYWFUA4BHPXFAQSzTuDrcQOxaWuSUsMqpTooNA+HVUSQW2oZdUvYHYQkb W3haZ30s09LBD9B/dMqdrKsFT31zh4nzZDybkQaUCHjBDAr/HAAgpvNdTtTKYjkQLwWX DDuw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=f01cRZzpZuZVuLpNLZPOHU00bUDX65RsUyfvMSLhNeg=; b=qJExHQx4koy4OBtwJPq7nN/t/TJbjF9tkvbyi5nnfZXpqjlT08KtzLirHQDSBTxKiI QZysD2QqmHRlZuk+at+ZS03CYrCnxQzO+ptmxZQAtoiMbeDtqCvrppKf5KgKXLrYvwul tWVJIrj6OZ7OLs8ZbylqyR1tfVsBdxxVG54auTOFiMGTuZ8PPkV+eNVkAoPoNGuuYhiK N978bIdCuR4AwA6TIGWBQOhpcVJFjyrwYkQKxftyPJCNERP3asiuQ8tc+PErtjTrus09 pZGGc1y3PAEbW7P4CHJzTwXI3syB+KQjedQKqT27b8jlovYzrJqNA+KauUhBcjtX/lzI wmGQ== X-Gm-Message-State: AFqh2koV0LeYP4TQfBpTWRfN8DdfNrVhPKeFENC7KpLYi4KEAAknTqNm XcSL77LQXwIOAQZQcClooZp/OT7RwbQ= X-Received: by 2002:a92:2e0d:0:b0:30e:cfe6:c324 with SMTP id v13-20020a922e0d000000b0030ecfe6c324mr3337413ile.0.1673981455756; Tue, 17 Jan 2023 10:50:55 -0800 (PST) Received: from gauss.local (c-68-41-54-207.hsd1.mi.comcast.net. [68.41.54.207]) by smtp.gmail.com with ESMTPSA id y93-20020a029566000000b003a4894d46e0sm2262223jah.176.2023.01.17.10.50.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Jan 2023 10:50:55 -0800 (PST) From: Leo Izen To: ffmpeg-devel@ffmpeg.org Date: Tue, 17 Jan 2023 13:50:49 -0500 Message-Id: <20230117185051.475157-2-leo.izen@gmail.com> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230117185051.475157-1-leo.izen@gmail.com> References: <20230117185051.475157-1-leo.izen@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v2 1/3] avcodec/png: use libavutil/csp.h for cHRM chunks X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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 Cc: Leo Izen Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: TcpsqeKZmqsk The cHRM chunk is descriptive. That is, it describes the primaries that should be used to interpret the pixel data in the PNG file. This is notably different from Mastering Display Metadata, which describes which subset of the presented gamut is relevant. MDM describes a gamut and says colors outside the gamut are not required to be preserved, but it does not actually describe the gamut that the pixel data from the frame resides in. Thus, to decode a cHRM chunk present in a PNG file to Mastering Display Metadata is incorrect. This commit changes this behavior so the cHRM chunk, if present, is decoded to color metadata. For example, if the cHRM chunk describes BT.709 primaries, the resulting AVFrame will be tagged with AVCOL_PRI_BT709, as a description of its pixel data. To do this, it utilizes libavutil/csp.h, which exposes a funcction av_csp_primaries_id_from_desc, to detect which enum value accurately describes the white point and primaries represented by the cHRM chunk. This commit also changes pngenc.c to utilize the libavuitl/csp.h API, since it previously duplicated code contained in that API. Instead, taking advantage of the API that exists makes more sense. pngenc.c does properly utilize the color tags rather than incorrectly using MDM, so that required no change. Signed-off-by: Leo Izen --- libavcodec/pngdec.c | 46 +++++++++++++++++-------------- libavcodec/pngenc.c | 53 +++++++++++------------------------- tests/ref/fate/png-icc | 2 +- tests/ref/fate/png-side-data | 13 +-------- 4 files changed, 44 insertions(+), 70 deletions(-) diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index f1cad26c52..32e7773bcb 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -26,10 +26,12 @@ #include "libavutil/avassert.h" #include "libavutil/bprint.h" #include "libavutil/crc.h" +#include "libavutil/csp.h" #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" #include "libavutil/stereo3d.h" -#include "libavutil/mastering_display_metadata.h" #include "avcodec.h" #include "bytestream.h" @@ -1472,6 +1474,7 @@ static void clear_frame_metadata(PNGDecContext *s) static int output_frame(PNGDecContext *s, AVFrame *f) { + AVCodecContext *avctx = s->avctx; int ret; if (s->iccp_data) { @@ -1483,8 +1486,30 @@ static int output_frame(PNGDecContext *s, AVFrame *f) memcpy(sd->data, s->iccp_data, s->iccp_data_len); av_dict_set(&sd->metadata, "name", s->iccp_name, 0); + } else if (s->have_chrm) { + AVColorPrimariesDesc desc; + enum AVColorPrimaries prim; + desc.wp.x = av_make_q(s->white_point[0], 100000); + desc.wp.y = av_make_q(s->white_point[1], 100000); + desc.prim.r.x = av_make_q(s->display_primaries[0][0], 100000); + desc.prim.r.y = av_make_q(s->display_primaries[0][1], 100000); + desc.prim.g.x = av_make_q(s->display_primaries[1][0], 100000); + desc.prim.g.y = av_make_q(s->display_primaries[1][1], 100000); + desc.prim.b.x = av_make_q(s->display_primaries[2][0], 100000); + desc.prim.b.y = av_make_q(s->display_primaries[2][1], 100000); + prim = av_csp_primaries_id_from_desc(&desc); + if (prim != AVCOL_PRI_UNSPECIFIED) + avctx->color_primaries = f->color_primaries = prim; + else + av_log(avctx, AV_LOG_WARNING, "unknown cHRM primaries\n"); } + /* this chunk overrides gAMA */ + if (s->iccp_data) + av_dict_set(&s->frame_metadata, "gamma", NULL, 0); + + avctx->colorspace = f->colorspace = AVCOL_SPC_RGB; + if (s->stereo_mode >= 0) { AVStereo3D *stereo3d = av_stereo3d_create_side_data(f); if (!stereo3d) { @@ -1496,25 +1521,6 @@ static int output_frame(PNGDecContext *s, AVFrame *f) stereo3d->flags = s->stereo_mode ? 0 : AV_STEREO3D_FLAG_INVERT; } - if (s->have_chrm) { - AVMasteringDisplayMetadata *mdm = av_mastering_display_metadata_create_side_data(f); - if (!mdm) { - ret = AVERROR(ENOMEM); - goto fail; - } - - mdm->white_point[0] = av_make_q(s->white_point[0], 100000); - mdm->white_point[1] = av_make_q(s->white_point[1], 100000); - - /* RGB Primaries */ - for (int i = 0; i < 3; i++) { - mdm->display_primaries[i][0] = av_make_q(s->display_primaries[i][0], 100000); - mdm->display_primaries[i][1] = av_make_q(s->display_primaries[i][1], 100000); - } - - mdm->has_primaries = 1; - } - FFSWAP(AVDictionary*, f->metadata, s->frame_metadata); return 0; diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c index ca1a186ca8..4333d5837f 100644 --- a/libavcodec/pngenc.c +++ b/libavcodec/pngenc.c @@ -29,10 +29,12 @@ #include "zlib_wrapper.h" #include "libavutil/avassert.h" +#include "libavutil/color_utils.h" #include "libavutil/crc.h" +#include "libavutil/csp.h" #include "libavutil/libm.h" #include "libavutil/opt.h" -#include "libavutil/color_utils.h" +#include "libavutil/rational.h" #include "libavutil/stereo3d.h" #include @@ -294,45 +296,22 @@ static int png_write_row(AVCodecContext *avctx, const uint8_t *data, int size) } #define AV_WB32_PNG(buf, n) AV_WB32(buf, lrint((n) * 100000)) +#define AV_WB32_PNG_D(buf, d) AV_WB32_PNG(buf, av_q2d(d)) static int png_get_chrm(enum AVColorPrimaries prim, uint8_t *buf) { - double rx, ry, gx, gy, bx, by, wx = 0.3127, wy = 0.3290; - switch (prim) { - case AVCOL_PRI_BT709: - rx = 0.640; ry = 0.330; - gx = 0.300; gy = 0.600; - bx = 0.150; by = 0.060; - break; - case AVCOL_PRI_BT470M: - rx = 0.670; ry = 0.330; - gx = 0.210; gy = 0.710; - bx = 0.140; by = 0.080; - wx = 0.310; wy = 0.316; - break; - case AVCOL_PRI_BT470BG: - rx = 0.640; ry = 0.330; - gx = 0.290; gy = 0.600; - bx = 0.150; by = 0.060; - break; - case AVCOL_PRI_SMPTE170M: - case AVCOL_PRI_SMPTE240M: - rx = 0.630; ry = 0.340; - gx = 0.310; gy = 0.595; - bx = 0.155; by = 0.070; - break; - case AVCOL_PRI_BT2020: - rx = 0.708; ry = 0.292; - gx = 0.170; gy = 0.797; - bx = 0.131; by = 0.046; - break; - default: - return 0; - } + const AVColorPrimariesDesc *desc = av_csp_primaries_desc_from_id(prim); + if (!desc) + return 0; + + AV_WB32_PNG_D(buf, desc->wp.x); + AV_WB32_PNG_D(buf + 4, desc->wp.y); + AV_WB32_PNG_D(buf + 8, desc->prim.r.x); + AV_WB32_PNG_D(buf + 12, desc->prim.r.y); + AV_WB32_PNG_D(buf + 16, desc->prim.g.x); + AV_WB32_PNG_D(buf + 20, desc->prim.g.y); + AV_WB32_PNG_D(buf + 24, desc->prim.b.x); + AV_WB32_PNG_D(buf + 28, desc->prim.b.y); - AV_WB32_PNG(buf , wx); AV_WB32_PNG(buf + 4 , wy); - AV_WB32_PNG(buf + 8 , rx); AV_WB32_PNG(buf + 12, ry); - AV_WB32_PNG(buf + 16, gx); AV_WB32_PNG(buf + 20, gy); - AV_WB32_PNG(buf + 24, bx); AV_WB32_PNG(buf + 28, by); return 1; } diff --git a/tests/ref/fate/png-icc b/tests/ref/fate/png-icc index 92fa0e526b..14de544639 100644 --- a/tests/ref/fate/png-icc +++ b/tests/ref/fate/png-icc @@ -33,7 +33,7 @@ interlaced_frame=0 top_field_first=0 repeat_pict=0 color_range=pc -color_space=unknown +color_space=gbr color_primaries=unknown color_transfer=unknown chroma_location=unspecified diff --git a/tests/ref/fate/png-side-data b/tests/ref/fate/png-side-data index f40f14fea1..a4c16eb395 100644 --- a/tests/ref/fate/png-side-data +++ b/tests/ref/fate/png-side-data @@ -25,7 +25,7 @@ interlaced_frame=1 top_field_first=0 repeat_pict=0 color_range=pc -color_space=unknown +color_space=gbr color_primaries=unknown color_transfer=unknown chroma_location=unspecified @@ -34,15 +34,4 @@ side_data_type=ICC profile name=Photoshop ICC profile size=3144 [/SIDE_DATA] -[SIDE_DATA] -side_data_type=Mastering display metadata -red_x=63999/100000 -red_y=33001/100000 -green_x=30000/100000 -green_y=60000/100000 -blue_x=15000/100000 -blue_y=5999/100000 -white_point_x=31269/100000 -white_point_y=32899/100000 -[/SIDE_DATA] [/FRAME]