From patchwork Thu Jul 28 14:49:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 37019 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:1649:b0:8b:613a:194d with SMTP id no9csp326235pzb; Thu, 28 Jul 2022 07:50:17 -0700 (PDT) X-Google-Smtp-Source: AGRyM1seq2S3OL2ONo0gZ/6tRRrjfIAYu85ROLwplIFjKvGi0vZ8bK+OfXmUUSyPAwgD4E/1sLao X-Received: by 2002:aa7:d795:0:b0:43c:eb00:fc77 with SMTP id s21-20020aa7d795000000b0043ceb00fc77mr2830386edq.284.1659019817631; Thu, 28 Jul 2022 07:50:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1659019817; cv=none; d=google.com; s=arc-20160816; b=i4cNyN2punp+EscRSzkF/M7BzGjI8HV3/7jEGRPvFGxIrzNhQ81onxuOVWo3ZlXG+K URyquqHvL4WPCth38LoMr00go243U2wAFfXjmn4IcRkUB6g9pziAlIQ0rnVMxCAvZCzi 1+VyQ3i3g4pKvcWUQmLseDrKAlyhIgUdDqke4aT/GswivVCurd6xcc6i5BHway+5xSav HnFgsx8Vwf7HBVnDc1xcg3GY80km2Q9mvstCjoIz951yhZgXzghpH7m2l7vJ+2cWWQOF a+WyiqYkTiDVzImSRJ2GpUu5O7kYisIHTeUjKIlSjDvGwceXW8gFrWHk48DtmeQTCQ0R 5hvQ== 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=X8tyj9lLiogHfPc9Aid0JcNMtiWwa9c4d5pxUbaGF6g=; b=doAgmdCH0nHTEfSeYjabx72mY1sZ3Fx8ihhmmmWD80Ubc/xYjhI5AYAt82wLBzmzW7 q41yZBEz6TicCUB+etnP33sNvQDqMACOU4mAWFBXjtHkqKMP2Fa8E9tyU/o0PyaWRgfA RnEkCylGnc45ajaetYS/HJZD9DxeOhKPxzZrqEv1YtfNlUzffkVCPDi2vUt2XUY2fUQd vnf6lWgtohOpDN1POiNMH2R4s+B8lIXMjQCNRmU3FPfBzm/PrEcJcnCImHIu+R8NjMpq G6RG4b0I/N/oH+G1fTkZfC3J06KH6iIFjN46sgv9vNU0elFGRMmkMAkmKytQKfTKC3ww BtAw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=HYwHkTam; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id c12-20020a056402120c00b0043c0288d312si704478edw.584.2022.07.28.07.50.17; Thu, 28 Jul 2022 07:50:17 -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=@haasn.xyz header.s=mail header.b=HYwHkTam; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 029BF68B9BB; Thu, 28 Jul 2022 17:50:14 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id CB20568B78B for ; Thu, 28 Jul 2022 17:50:06 +0300 (EEST) Received: from haasn.dev (unknown [10.30.0.2]) by haasn.dev (Postfix) with ESMTP id 711CC4AA4C; Thu, 28 Jul 2022 16:50:06 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=haasn.xyz; s=mail; t=1659019806; bh=1q7LOiEofC8bOb/nPhBMOMoqzBn1ZwN7a/GLuShVsjg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HYwHkTameZk/7WsW9p+PftQLIj+5wrw0TVzQgYJ7zvdcQ8J9FDjn5VauqGOFuXQBT XGEclOiYcyWKNciqtYYcWCh1EZZvxmxZH5VXrgD/O8Lc+E3/5yVSVOD6Uq1XCw001w 4MrACOWyHpn/svSaiqEO6WiN38fS85s4Zv7DCytQ= From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Thu, 28 Jul 2022 16:49:56 +0200 Message-Id: <20220728145002.102600-2-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.37.1 In-Reply-To: <20220728145002.102600-1-ffmpeg@haasn.xyz> References: <20220728145002.102600-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v4 1/7] fflcms2: move to libavcodec 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: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: EFIJH/pYgIrj From: Niklas Haas We will need this helper inside libavcodec in the future, so move it there, leaving behind an #include to the raw source file in its old location in libvfilter. This approach is inspired by the handling of vulkan.c, and avoids us needing to expose any of it publicly (or semi-publicly) in e.g. libavutil, thus avoiding any ABI headaches. It's debatable whether the actual code belongs in libavcodec or libavfilter, but I decided to put it into libavcodec because it conceptually deals with encoding and decoding ICC profiles, and will be used to decode embedded ICC profiles in image files. Signed-off-by: Niklas Haas --- libavcodec/Makefile | 1 + libavcodec/fflcms2.c | 311 ++++++++++++++++++++++++++++++++++++++++++ libavcodec/fflcms2.h | 87 ++++++++++++ libavfilter/fflcms2.c | 294 +-------------------------------------- libavfilter/fflcms2.h | 65 +-------- 5 files changed, 401 insertions(+), 357 deletions(-) create mode 100644 libavcodec/fflcms2.c create mode 100644 libavcodec/fflcms2.h diff --git a/libavcodec/Makefile b/libavcodec/Makefile index a4fab108d6..6751b6b591 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1240,6 +1240,7 @@ SKIPHEADERS-$(CONFIG_AMF) += amfenc.h SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h SKIPHEADERS-$(CONFIG_JNI) += ffjni.h +SKIPHEADERS-$(CONFIG_LCMS2) += fflcms2.h SKIPHEADERS-$(CONFIG_LIBJXL) += libjxl.h SKIPHEADERS-$(CONFIG_LIBVPX) += libvpx.h SKIPHEADERS-$(CONFIG_LIBWEBP_ENCODER) += libwebpenc_common.h diff --git a/libavcodec/fflcms2.c b/libavcodec/fflcms2.c new file mode 100644 index 0000000000..fd370fb310 --- /dev/null +++ b/libavcodec/fflcms2.c @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2022 Niklas Haas + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/color_utils.h" +#include "libavutil/csp.h" + +#include "fflcms2.h" + +static void log_cb(cmsContext ctx, cmsUInt32Number error, const char *str) +{ + FFIccContext *s = cmsGetContextUserData(ctx); + av_log(s->avctx, AV_LOG_ERROR, "lcms2: [%"PRIu32"] %s\n", error, str); +} + +int ff_icc_context_init(FFIccContext *s, void *avctx) +{ + memset(s, 0, sizeof(*s)); + s->avctx = avctx; + s->ctx = cmsCreateContext(NULL, s); + if (!s->ctx) + return AVERROR(ENOMEM); + + cmsSetLogErrorHandlerTHR(s->ctx, log_cb); + return 0; +} + +void ff_icc_context_uninit(FFIccContext *s) +{ + for (int i = 0; i < FF_ARRAY_ELEMS(s->curves); i++) + cmsFreeToneCurve(s->curves[i]); + cmsDeleteContext(s->ctx); + memset(s, 0, sizeof(*s)); +} + +static int get_curve(FFIccContext *s, enum AVColorTransferCharacteristic trc, + cmsToneCurve **out_curve) +{ + if (trc >= AVCOL_TRC_NB) + return AVERROR_INVALIDDATA; + + if (s->curves[trc]) + goto done; + + switch (trc) { + case AVCOL_TRC_LINEAR: + s->curves[trc] = cmsBuildGamma(s->ctx, 1.0); + break; + case AVCOL_TRC_GAMMA22: + s->curves[trc] = cmsBuildGamma(s->ctx, 2.2); + break; + case AVCOL_TRC_GAMMA28: + s->curves[trc] = cmsBuildGamma(s->ctx, 2.8); + break; + case AVCOL_TRC_BT709: + case AVCOL_TRC_SMPTE170M: + case AVCOL_TRC_BT2020_10: + case AVCOL_TRC_BT2020_12: + s->curves[trc] = cmsBuildParametricToneCurve(s->ctx, 4, (double[5]) { + /* γ = */ 1/0.45, + /* a = */ 1/1.099296826809442, + /* b = */ 1 - 1/1.099296826809442, + /* c = */ 1/4.5, + /* d = */ 4.5 * 0.018053968510807, + }); + break; + case AVCOL_TRC_SMPTE240M: + s->curves[trc] = cmsBuildParametricToneCurve(s->ctx, 4, (double[5]) { + /* γ = */ 1/0.45, + /* a = */ 1/1.1115, + /* b = */ 1 - 1/1.1115, + /* c = */ 1/4.0, + /* d = */ 4.0 * 0.0228, + }); + break; + case AVCOL_TRC_LOG: + s->curves[trc] = cmsBuildParametricToneCurve(s->ctx, 8, (double[5]) { + /* a = */ 1.0, + /* b = */ 10.0, + /* c = */ 2.0, + /* d = */ -1.0, + /* e = */ 0.0 + }); + break; + case AVCOL_TRC_LOG_SQRT: + s->curves[trc] = cmsBuildParametricToneCurve(s->ctx, 8, (double[5]) { + /* a = */ 1.0, + /* b = */ 10.0, + /* c = */ 2.5, + /* d = */ -1.0, + /* e = */ 0.0 + }); + break; + case AVCOL_TRC_IEC61966_2_1: + s->curves[trc] = cmsBuildParametricToneCurve(s->ctx, 4, (double[5]) { + /* γ = */ 2.4, + /* a = */ 1/1.055, + /* b = */ 1 - 1/1.055, + /* c = */ 1/12.92, + /* d = */ 12.92 * 0.0031308, + }); + break; + case AVCOL_TRC_SMPTE428: + s->curves[trc] = cmsBuildParametricToneCurve(s->ctx, 2, (double[3]) { + /* γ = */ 2.6, + /* a = */ pow(52.37/48.0, 1/2.6), + /* b = */ 0.0 + }); + break; + + /* Can't be represented using the existing parametric tone curves. + * FIXME: use cmsBuildTabulatedToneCurveFloat instead */ + case AVCOL_TRC_IEC61966_2_4: + case AVCOL_TRC_BT1361_ECG: + case AVCOL_TRC_SMPTE2084: + case AVCOL_TRC_ARIB_STD_B67: + return AVERROR_PATCHWELCOME; + + default: + return AVERROR_INVALIDDATA; + } + + if (!s->curves[trc]) + return AVERROR(ENOMEM); + +done: + *out_curve = s->curves[trc]; + return 0; +} + +int ff_icc_profile_generate(FFIccContext *s, + enum AVColorPrimaries color_prim, + enum AVColorTransferCharacteristic color_trc, + cmsHPROFILE *out_profile) +{ + cmsToneCurve *tonecurve; + const AVColorPrimariesDesc *prim; + int ret; + + if (!(prim = av_csp_primaries_desc_from_id(color_prim))) + return AVERROR_INVALIDDATA; + if ((ret = get_curve(s, color_trc, &tonecurve)) < 0) + return ret; + + *out_profile = cmsCreateRGBProfileTHR(s->ctx, + &(cmsCIExyY) { av_q2d(prim->wp.x), av_q2d(prim->wp.y), 1.0 }, + &(cmsCIExyYTRIPLE) { + .Red = { av_q2d(prim->prim.r.x), av_q2d(prim->prim.r.y), 1.0 }, + .Green = { av_q2d(prim->prim.g.x), av_q2d(prim->prim.g.y), 1.0 }, + .Blue = { av_q2d(prim->prim.b.x), av_q2d(prim->prim.b.y), 1.0 }, + }, + (cmsToneCurve *[3]) { tonecurve, tonecurve, tonecurve } + ); + + return *out_profile == NULL ? AVERROR(ENOMEM) : 0; +} + +int ff_icc_profile_attach(FFIccContext *s, cmsHPROFILE profile, AVFrame *frame) +{ + cmsUInt32Number size; + AVBufferRef *buf; + + if (!cmsSaveProfileToMem(profile, NULL, &size)) + return AVERROR_EXTERNAL; + + buf = av_buffer_alloc(size); + if (!buf) + return AVERROR(ENOMEM); + + if (!cmsSaveProfileToMem(profile, buf->data, &size) || size != buf->size) { + av_buffer_unref(&buf); + return AVERROR_EXTERNAL; + } + + if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_ICC_PROFILE, buf)) { + av_buffer_unref(&buf); + return AVERROR(ENOMEM); + } + + return 0; +} + +static av_always_inline void XYZ_xy(cmsCIEXYZ XYZ, AVCIExy *xy) +{ + double k = 1.0 / (XYZ.X + XYZ.Y + XYZ.Z); + xy->x = av_d2q(k * XYZ.X, 100000); + xy->y = av_d2q(k * XYZ.Y, 100000); +} + +int ff_icc_profile_read_primaries(FFIccContext *s, cmsHPROFILE profile, + AVColorPrimariesDesc *out_primaries) +{ + static const uint8_t testprimaries[4][3] = { + { 0xFF, 0, 0 }, /* red */ + { 0, 0xFF, 0 }, /* green */ + { 0, 0, 0xFF }, /* blue */ + { 0xFF, 0xFF, 0xFF }, /* white */ + }; + + AVWhitepointCoefficients *wp = &out_primaries->wp; + AVPrimaryCoefficients *prim = &out_primaries->prim; + cmsFloat64Number prev_adapt; + cmsHPROFILE xyz; + cmsHTRANSFORM tf; + cmsCIEXYZ dst[4]; + + xyz = cmsCreateXYZProfileTHR(s->ctx); + if (!xyz) + return AVERROR(ENOMEM); + + /* We need to use an unadapted observer to get the raw values */ + prev_adapt = cmsSetAdaptationStateTHR(s->ctx, 0.0); + tf = cmsCreateTransformTHR(s->ctx, profile, TYPE_RGB_8, xyz, TYPE_XYZ_DBL, + INTENT_ABSOLUTE_COLORIMETRIC, + /* Note: These flags mostly don't do anything + * anyway, but specify them regardless */ + cmsFLAGS_NOCACHE | + cmsFLAGS_NOOPTIMIZE | + cmsFLAGS_LOWRESPRECALC | + cmsFLAGS_GRIDPOINTS(2)); + cmsSetAdaptationStateTHR(s->ctx, prev_adapt); + cmsCloseProfile(xyz); + if (!tf) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid ICC profile (e.g. CMYK)\n"); + return AVERROR_INVALIDDATA; + } + + cmsDoTransform(tf, testprimaries, dst, 4); + cmsDeleteTransform(tf); + XYZ_xy(dst[0], &prim->r); + XYZ_xy(dst[1], &prim->g); + XYZ_xy(dst[2], &prim->b); + XYZ_xy(dst[3], wp); + return 0; +} + +int ff_icc_profile_detect_transfer(FFIccContext *s, cmsHPROFILE profile, + enum AVColorTransferCharacteristic *out_trc) +{ + /* 8-bit linear grayscale ramp */ + static const uint8_t testramp[16][3] = { + { 1, 1, 1}, /* avoid exact zero due to log100 etc. */ + { 17, 17, 17}, + { 34, 34, 34}, + { 51, 51, 51}, + { 68, 68, 68}, + { 85, 85, 85}, + { 02, 02, 02}, + {119, 119, 119}, + {136, 136, 136}, + {153, 153, 153}, + {170, 170, 170}, + {187, 187, 187}, + {204, 204, 204}, + {221, 221, 221}, + {238, 238, 238}, + {255, 255, 255}, + }; + + double dst[FF_ARRAY_ELEMS(testramp)]; + + for (enum AVColorTransferCharacteristic trc = 0; trc < AVCOL_TRC_NB; trc++) { + cmsToneCurve *tonecurve; + cmsHPROFILE ref; + cmsHTRANSFORM tf; + double delta = 0.0; + if (get_curve(s, trc, &tonecurve) < 0) + continue; + + ref = cmsCreateGrayProfileTHR(s->ctx, cmsD50_xyY(), tonecurve); + if (!ref) + return AVERROR(ENOMEM); + + tf = cmsCreateTransformTHR(s->ctx, profile, TYPE_RGB_8, ref, TYPE_GRAY_DBL, + INTENT_RELATIVE_COLORIMETRIC, + cmsFLAGS_NOCACHE | cmsFLAGS_NOOPTIMIZE); + cmsCloseProfile(ref); + if (!tf) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid ICC profile (e.g. CMYK)\n"); + return AVERROR_INVALIDDATA; + } + + cmsDoTransform(tf, testramp, dst, FF_ARRAY_ELEMS(dst)); + cmsDeleteTransform(tf); + + for (int i = 0; i < FF_ARRAY_ELEMS(dst); i++) + delta += fabs(testramp[i][0] / 255.0 - dst[i]); + if (delta < 0.01) { + *out_trc = trc; + return 0; + } + } + + *out_trc = AVCOL_TRC_UNSPECIFIED; + return 0; +} diff --git a/libavcodec/fflcms2.h b/libavcodec/fflcms2.h new file mode 100644 index 0000000000..af63c9a13c --- /dev/null +++ b/libavcodec/fflcms2.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2022 Niklas Haas + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Various functions for dealing with ICC profiles + */ + +#ifndef AVCODEC_FFLCMS2_H +#define AVCODEC_FFLCMS2_H + +#include "libavutil/csp.h" +#include "libavutil/frame.h" +#include "libavutil/pixfmt.h" + +#include + +typedef struct FFIccContext { + void *avctx; + cmsContext ctx; + cmsToneCurve *curves[AVCOL_TRC_NB]; /* tone curve cache */ +} FFIccContext; + +/** + * Initializes an FFIccContext. This must be done prior to using it. + * + * Returns 0 on success, or a negative error code. + */ +int ff_icc_context_init(FFIccContext *s, void *avctx); +void ff_icc_context_uninit(FFIccContext *s); + +/** + * Generate an ICC profile for a given combination of color primaries and + * transfer function. Both values must be set to valid entries (not + * "undefined") for this function to work. + * + * Returns 0 on success, or a negative error code. + */ +int ff_icc_profile_generate(FFIccContext *s, + enum AVColorPrimaries color_prim, + enum AVColorTransferCharacteristic color_trc, + cmsHPROFILE *out_profile); + +/** + * Attach an ICC profile to a frame. Helper wrapper around cmsSaveProfileToMem + * and av_frame_new_side_data_from_buf. + * + * Returns 0 on success, or a negative error code. + */ +int ff_icc_profile_attach(FFIccContext *s, cmsHPROFILE profile, AVFrame *frame); + +/** + * Read the color primaries and white point coefficients encoded by an ICC + * profile, and return the raw values in `out_primaries`. + * + * Returns 0 on success, or a negative error code. + */ +int ff_icc_profile_read_primaries(FFIccContext *s, cmsHPROFILE profile, + AVColorPrimariesDesc *out_primaries); + +/** + * Attempt detecting the transfer characteristic that best approximates the + * transfer function encoded by an ICC profile. Sets `out_trc` to + * AVCOL_TRC_UNSPECIFIED if no clear match can be identified. + * + * Returns 0 on success (including no match), or a negative error code. + */ +int ff_icc_profile_detect_transfer(FFIccContext *s, cmsHPROFILE profile, + enum AVColorTransferCharacteristic *out_trc); + +#endif /* AVCODEC_FFLCMS2_H */ diff --git a/libavfilter/fflcms2.c b/libavfilter/fflcms2.c index fd370fb310..822462de87 100644 --- a/libavfilter/fflcms2.c +++ b/libavfilter/fflcms2.c @@ -1,5 +1,4 @@ /* - * Copyright (c) 2022 Niklas Haas * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -17,295 +16,4 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/color_utils.h" -#include "libavutil/csp.h" - -#include "fflcms2.h" - -static void log_cb(cmsContext ctx, cmsUInt32Number error, const char *str) -{ - FFIccContext *s = cmsGetContextUserData(ctx); - av_log(s->avctx, AV_LOG_ERROR, "lcms2: [%"PRIu32"] %s\n", error, str); -} - -int ff_icc_context_init(FFIccContext *s, void *avctx) -{ - memset(s, 0, sizeof(*s)); - s->avctx = avctx; - s->ctx = cmsCreateContext(NULL, s); - if (!s->ctx) - return AVERROR(ENOMEM); - - cmsSetLogErrorHandlerTHR(s->ctx, log_cb); - return 0; -} - -void ff_icc_context_uninit(FFIccContext *s) -{ - for (int i = 0; i < FF_ARRAY_ELEMS(s->curves); i++) - cmsFreeToneCurve(s->curves[i]); - cmsDeleteContext(s->ctx); - memset(s, 0, sizeof(*s)); -} - -static int get_curve(FFIccContext *s, enum AVColorTransferCharacteristic trc, - cmsToneCurve **out_curve) -{ - if (trc >= AVCOL_TRC_NB) - return AVERROR_INVALIDDATA; - - if (s->curves[trc]) - goto done; - - switch (trc) { - case AVCOL_TRC_LINEAR: - s->curves[trc] = cmsBuildGamma(s->ctx, 1.0); - break; - case AVCOL_TRC_GAMMA22: - s->curves[trc] = cmsBuildGamma(s->ctx, 2.2); - break; - case AVCOL_TRC_GAMMA28: - s->curves[trc] = cmsBuildGamma(s->ctx, 2.8); - break; - case AVCOL_TRC_BT709: - case AVCOL_TRC_SMPTE170M: - case AVCOL_TRC_BT2020_10: - case AVCOL_TRC_BT2020_12: - s->curves[trc] = cmsBuildParametricToneCurve(s->ctx, 4, (double[5]) { - /* γ = */ 1/0.45, - /* a = */ 1/1.099296826809442, - /* b = */ 1 - 1/1.099296826809442, - /* c = */ 1/4.5, - /* d = */ 4.5 * 0.018053968510807, - }); - break; - case AVCOL_TRC_SMPTE240M: - s->curves[trc] = cmsBuildParametricToneCurve(s->ctx, 4, (double[5]) { - /* γ = */ 1/0.45, - /* a = */ 1/1.1115, - /* b = */ 1 - 1/1.1115, - /* c = */ 1/4.0, - /* d = */ 4.0 * 0.0228, - }); - break; - case AVCOL_TRC_LOG: - s->curves[trc] = cmsBuildParametricToneCurve(s->ctx, 8, (double[5]) { - /* a = */ 1.0, - /* b = */ 10.0, - /* c = */ 2.0, - /* d = */ -1.0, - /* e = */ 0.0 - }); - break; - case AVCOL_TRC_LOG_SQRT: - s->curves[trc] = cmsBuildParametricToneCurve(s->ctx, 8, (double[5]) { - /* a = */ 1.0, - /* b = */ 10.0, - /* c = */ 2.5, - /* d = */ -1.0, - /* e = */ 0.0 - }); - break; - case AVCOL_TRC_IEC61966_2_1: - s->curves[trc] = cmsBuildParametricToneCurve(s->ctx, 4, (double[5]) { - /* γ = */ 2.4, - /* a = */ 1/1.055, - /* b = */ 1 - 1/1.055, - /* c = */ 1/12.92, - /* d = */ 12.92 * 0.0031308, - }); - break; - case AVCOL_TRC_SMPTE428: - s->curves[trc] = cmsBuildParametricToneCurve(s->ctx, 2, (double[3]) { - /* γ = */ 2.6, - /* a = */ pow(52.37/48.0, 1/2.6), - /* b = */ 0.0 - }); - break; - - /* Can't be represented using the existing parametric tone curves. - * FIXME: use cmsBuildTabulatedToneCurveFloat instead */ - case AVCOL_TRC_IEC61966_2_4: - case AVCOL_TRC_BT1361_ECG: - case AVCOL_TRC_SMPTE2084: - case AVCOL_TRC_ARIB_STD_B67: - return AVERROR_PATCHWELCOME; - - default: - return AVERROR_INVALIDDATA; - } - - if (!s->curves[trc]) - return AVERROR(ENOMEM); - -done: - *out_curve = s->curves[trc]; - return 0; -} - -int ff_icc_profile_generate(FFIccContext *s, - enum AVColorPrimaries color_prim, - enum AVColorTransferCharacteristic color_trc, - cmsHPROFILE *out_profile) -{ - cmsToneCurve *tonecurve; - const AVColorPrimariesDesc *prim; - int ret; - - if (!(prim = av_csp_primaries_desc_from_id(color_prim))) - return AVERROR_INVALIDDATA; - if ((ret = get_curve(s, color_trc, &tonecurve)) < 0) - return ret; - - *out_profile = cmsCreateRGBProfileTHR(s->ctx, - &(cmsCIExyY) { av_q2d(prim->wp.x), av_q2d(prim->wp.y), 1.0 }, - &(cmsCIExyYTRIPLE) { - .Red = { av_q2d(prim->prim.r.x), av_q2d(prim->prim.r.y), 1.0 }, - .Green = { av_q2d(prim->prim.g.x), av_q2d(prim->prim.g.y), 1.0 }, - .Blue = { av_q2d(prim->prim.b.x), av_q2d(prim->prim.b.y), 1.0 }, - }, - (cmsToneCurve *[3]) { tonecurve, tonecurve, tonecurve } - ); - - return *out_profile == NULL ? AVERROR(ENOMEM) : 0; -} - -int ff_icc_profile_attach(FFIccContext *s, cmsHPROFILE profile, AVFrame *frame) -{ - cmsUInt32Number size; - AVBufferRef *buf; - - if (!cmsSaveProfileToMem(profile, NULL, &size)) - return AVERROR_EXTERNAL; - - buf = av_buffer_alloc(size); - if (!buf) - return AVERROR(ENOMEM); - - if (!cmsSaveProfileToMem(profile, buf->data, &size) || size != buf->size) { - av_buffer_unref(&buf); - return AVERROR_EXTERNAL; - } - - if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_ICC_PROFILE, buf)) { - av_buffer_unref(&buf); - return AVERROR(ENOMEM); - } - - return 0; -} - -static av_always_inline void XYZ_xy(cmsCIEXYZ XYZ, AVCIExy *xy) -{ - double k = 1.0 / (XYZ.X + XYZ.Y + XYZ.Z); - xy->x = av_d2q(k * XYZ.X, 100000); - xy->y = av_d2q(k * XYZ.Y, 100000); -} - -int ff_icc_profile_read_primaries(FFIccContext *s, cmsHPROFILE profile, - AVColorPrimariesDesc *out_primaries) -{ - static const uint8_t testprimaries[4][3] = { - { 0xFF, 0, 0 }, /* red */ - { 0, 0xFF, 0 }, /* green */ - { 0, 0, 0xFF }, /* blue */ - { 0xFF, 0xFF, 0xFF }, /* white */ - }; - - AVWhitepointCoefficients *wp = &out_primaries->wp; - AVPrimaryCoefficients *prim = &out_primaries->prim; - cmsFloat64Number prev_adapt; - cmsHPROFILE xyz; - cmsHTRANSFORM tf; - cmsCIEXYZ dst[4]; - - xyz = cmsCreateXYZProfileTHR(s->ctx); - if (!xyz) - return AVERROR(ENOMEM); - - /* We need to use an unadapted observer to get the raw values */ - prev_adapt = cmsSetAdaptationStateTHR(s->ctx, 0.0); - tf = cmsCreateTransformTHR(s->ctx, profile, TYPE_RGB_8, xyz, TYPE_XYZ_DBL, - INTENT_ABSOLUTE_COLORIMETRIC, - /* Note: These flags mostly don't do anything - * anyway, but specify them regardless */ - cmsFLAGS_NOCACHE | - cmsFLAGS_NOOPTIMIZE | - cmsFLAGS_LOWRESPRECALC | - cmsFLAGS_GRIDPOINTS(2)); - cmsSetAdaptationStateTHR(s->ctx, prev_adapt); - cmsCloseProfile(xyz); - if (!tf) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid ICC profile (e.g. CMYK)\n"); - return AVERROR_INVALIDDATA; - } - - cmsDoTransform(tf, testprimaries, dst, 4); - cmsDeleteTransform(tf); - XYZ_xy(dst[0], &prim->r); - XYZ_xy(dst[1], &prim->g); - XYZ_xy(dst[2], &prim->b); - XYZ_xy(dst[3], wp); - return 0; -} - -int ff_icc_profile_detect_transfer(FFIccContext *s, cmsHPROFILE profile, - enum AVColorTransferCharacteristic *out_trc) -{ - /* 8-bit linear grayscale ramp */ - static const uint8_t testramp[16][3] = { - { 1, 1, 1}, /* avoid exact zero due to log100 etc. */ - { 17, 17, 17}, - { 34, 34, 34}, - { 51, 51, 51}, - { 68, 68, 68}, - { 85, 85, 85}, - { 02, 02, 02}, - {119, 119, 119}, - {136, 136, 136}, - {153, 153, 153}, - {170, 170, 170}, - {187, 187, 187}, - {204, 204, 204}, - {221, 221, 221}, - {238, 238, 238}, - {255, 255, 255}, - }; - - double dst[FF_ARRAY_ELEMS(testramp)]; - - for (enum AVColorTransferCharacteristic trc = 0; trc < AVCOL_TRC_NB; trc++) { - cmsToneCurve *tonecurve; - cmsHPROFILE ref; - cmsHTRANSFORM tf; - double delta = 0.0; - if (get_curve(s, trc, &tonecurve) < 0) - continue; - - ref = cmsCreateGrayProfileTHR(s->ctx, cmsD50_xyY(), tonecurve); - if (!ref) - return AVERROR(ENOMEM); - - tf = cmsCreateTransformTHR(s->ctx, profile, TYPE_RGB_8, ref, TYPE_GRAY_DBL, - INTENT_RELATIVE_COLORIMETRIC, - cmsFLAGS_NOCACHE | cmsFLAGS_NOOPTIMIZE); - cmsCloseProfile(ref); - if (!tf) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid ICC profile (e.g. CMYK)\n"); - return AVERROR_INVALIDDATA; - } - - cmsDoTransform(tf, testramp, dst, FF_ARRAY_ELEMS(dst)); - cmsDeleteTransform(tf); - - for (int i = 0; i < FF_ARRAY_ELEMS(dst); i++) - delta += fabs(testramp[i][0] / 255.0 - dst[i]); - if (delta < 0.01) { - *out_trc = trc; - return 0; - } - } - - *out_trc = AVCOL_TRC_UNSPECIFIED; - return 0; -} +#include "libavcodec/fflcms2.c" diff --git a/libavfilter/fflcms2.h b/libavfilter/fflcms2.h index 0d238c679f..1ac29e357b 100644 --- a/libavfilter/fflcms2.h +++ b/libavfilter/fflcms2.h @@ -1,5 +1,4 @@ /* - * Copyright (c) 2022 Niklas Haas * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -17,71 +16,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/** - * @file - * Various functions for dealing with ICC profiles - */ - #ifndef AVFILTER_FFLCMS2_H #define AVFILTER_FFLCMS2_H -#include "libavutil/csp.h" -#include "libavutil/frame.h" -#include "libavutil/pixfmt.h" - -#include - -typedef struct FFIccContext { - void *avctx; - cmsContext ctx; - cmsToneCurve *curves[AVCOL_TRC_NB]; /* tone curve cache */ -} FFIccContext; - -/** - * Initializes an FFIccContext. This must be done prior to using it. - * - * Returns 0 on success, or a negative error code. - */ -int ff_icc_context_init(FFIccContext *s, void *avctx); -void ff_icc_context_uninit(FFIccContext *s); - -/** - * Generate an ICC profile for a given combination of color primaries and - * transfer function. Both values must be set to valid entries (not - * "undefined") for this function to work. - * - * Returns 0 on success, or a negative error code. - */ -int ff_icc_profile_generate(FFIccContext *s, - enum AVColorPrimaries color_prim, - enum AVColorTransferCharacteristic color_trc, - cmsHPROFILE *out_profile); - -/** - * Attach an ICC profile to a frame. Helper wrapper around cmsSaveProfileToMem - * and av_frame_new_side_data_from_buf. - * - * Returns 0 on success, or a negative error code. - */ -int ff_icc_profile_attach(FFIccContext *s, cmsHPROFILE profile, AVFrame *frame); - -/** - * Read the color primaries and white point coefficients encoded by an ICC - * profile, and return the raw values in `out_primaries`. - * - * Returns 0 on success, or a negative error code. - */ -int ff_icc_profile_read_primaries(FFIccContext *s, cmsHPROFILE profile, - AVColorPrimariesDesc *out_primaries); - -/** - * Attempt detecting the transfer characteristic that best approximates the - * transfer function encoded by an ICC profile. Sets `out_trc` to - * AVCOL_TRC_UNSPECIFIED if no clear match can be identified. - * - * Returns 0 on success (including no match), or a negative error code. - */ -int ff_icc_profile_detect_transfer(FFIccContext *s, cmsHPROFILE profile, - enum AVColorTransferCharacteristic *out_trc); +#include "libavcodec/fflcms2.h" #endif /* AVFILTER_FFLCMS2_H */ From patchwork Thu Jul 28 14:49:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 37020 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:1649:b0:8b:613a:194d with SMTP id no9csp326380pzb; Thu, 28 Jul 2022 07:50:35 -0700 (PDT) X-Google-Smtp-Source: AGRyM1sv/yVjDfmkE9BBBJJ1xBX1iCTNJ/dF+y15p9qNoQs10wrGs1Y6CQJ+1N9p56bzzQwrWofu X-Received: by 2002:a05:6402:5388:b0:435:71b:5d44 with SMTP id ew8-20020a056402538800b00435071b5d44mr27329799edb.364.1659019835792; Thu, 28 Jul 2022 07:50:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1659019835; cv=none; d=google.com; s=arc-20160816; b=t2cZL98KPEcab7TjuJMBN+51JIEaVx/4g8JNA1sxNXczGnm1NqqWV4BZNUBFKa+KYN WpjYIq6fElenTgvbPsA17sm06kZvD9/xp4dR6fqj/SWoDnbvyVv7fA1u2AYgXRWW0y2W eDQBphh9gU8WM4BG4KkfPWgbF/AfRlPu3d+pUVJvlMgFTG/WidF18TygC0qCz+uI8vfO P1tYggoHwXSGBVQcKubEBRzg8HfG9i26fDgo+1zrrikAjywXj+36o7mhK7KRPAJr1cEA OoM/EjoyOlPi4bPK4X+mZJhRjLawrSoKsfzjUyT1SoFRn3tOWLeRfspwrXN3Tu8stkz2 l9qw== 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=dj43DrNhgKrbXHesMHC/+zhWT74sVDuPpLdMZl27+FA=; b=gdm0WVjv8Pd2/8/fQyGy/Tl3uCpDJDVE4HKkwxKmSZAm4CnK7WNk3FcwkpK+y5cO8E QzVyaxqFzzCLK+yBQGGhKhogkwksXrB+34e1qD7glhbF8Si1eCgvEcKkcv3g5Owx7C+k pLvGw7LemS2htI7I9PuCxpVXji5f/7a1Pm0OQj0HRHmpAupCTMpSl6obvtZAjAtxmxIp 6yrtGKPx8BHkAsX/AKgh6tQ2VKzXhnTxdh/aIMMvTRwaOiIr0A8ZSF4bDioL4lblIxOe XvMFSuZ33FLnfSFi/fyA+Qy3LlV1VcEmkStIq/af090RsuTjUWcuYpYRxnYhmO/KXa0Y xZrg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=AfeVYVTC; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id m19-20020a056402431300b0043be8ea3363si1022467edc.263.2022.07.28.07.50.35; Thu, 28 Jul 2022 07:50:35 -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=@haasn.xyz header.s=mail header.b=AfeVYVTC; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id E474268B931; Thu, 28 Jul 2022 17:50:15 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id DE14368B99A for ; Thu, 28 Jul 2022 17:50:06 +0300 (EEST) Received: from haasn.dev (unknown [10.30.0.2]) by haasn.dev (Postfix) with ESMTP id A776A4AA64; Thu, 28 Jul 2022 16:50:06 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=haasn.xyz; s=mail; t=1659019806; bh=NAHj5o3/wflP1IMqeh6upyoQY+NIzhynCqcyZ+OziQU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AfeVYVTCzsQWFZnwpky5TS7GDkAp8kBBUiyS/HHlmkBvgXyJCc5Dtspaxo1aJ10UM 4frmSJzuOvt7Mtgh/6sbQYkn4iI83I+3fOinJcpGYY+7Z7ENNauwh5LhYuezx36aZW +x7HIBvVV4jxshpf0fq1CO1bqPwW1K5Szat/m1VE= From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Thu, 28 Jul 2022 16:49:57 +0200 Message-Id: <20220728145002.102600-3-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.37.1 In-Reply-To: <20220728145002.102600-1-ffmpeg@haasn.xyz> References: <20220728145002.102600-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v4 2/7] avcodec/codec_internal: add cap for ICC profile support 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: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: /ojrZtZxaPci From: Niklas Haas Codecs that can read/write ICC profiles deserve a special capability so the common logic in encode.c/decode.c can decide whether or not there needs to be any special handling for ICC profiles. The motivation here is to be able to use it to decide whether or not an ICC profile needs to be generated in the encode path, but it might as well get added to decoders as well for purely informative reasons. It's not entirely clear to me whether the "thp" and "smvjpeg" variants of "mjpeg" should have this capability set or not, given that the code technically supports it but I somehow doubt these files may contain them. In either case, this cap is purely informative for decoders so it doesn't matter too much either way. It's also not entirely clear whether the "amv" encoder should signal ICC profile support, but again erring on the side of caution, we probably *shouldn't* be generating (and encoding!) ICC profiles for this type of media file. Signed-off-by: Niklas Haas --- libavcodec/codec_internal.h | 4 ++++ libavcodec/libjxldec.c | 3 ++- libavcodec/libjxlenc.c | 3 ++- libavcodec/mjpegdec.c | 4 +++- libavcodec/mjpegenc.c | 2 +- libavcodec/pngdec.c | 6 ++++-- libavcodec/pngenc.c | 2 ++ libavcodec/tiff.c | 2 +- libavcodec/webp.c | 1 + 9 files changed, 20 insertions(+), 7 deletions(-) diff --git a/libavcodec/codec_internal.h b/libavcodec/codec_internal.h index 3619d04090..62ea91cf4d 100644 --- a/libavcodec/codec_internal.h +++ b/libavcodec/codec_internal.h @@ -75,6 +75,10 @@ * internal logic derive them from AVCodecInternal.last_pkt_props. */ #define FF_CODEC_CAP_SETS_FRAME_PROPS (1 << 8) +/** + * Codec supports embedded ICC profiles (AV_FRAME_DATA_ICC_PROFILE). + */ +#define FF_CODEC_CAP_ICC_PROFILES (1 << 9) /** * FFCodec.codec_tags termination value diff --git a/libavcodec/libjxldec.c b/libavcodec/libjxldec.c index b9322b082a..f54701596b 100644 --- a/libavcodec/libjxldec.c +++ b/libavcodec/libjxldec.c @@ -456,6 +456,7 @@ const FFCodec ff_libjxl_decoder = { .close = libjxl_decode_close, .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_OTHER_THREADS, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | - FF_CODEC_CAP_AUTO_THREADS | FF_CODEC_CAP_INIT_CLEANUP, + FF_CODEC_CAP_AUTO_THREADS | FF_CODEC_CAP_INIT_CLEANUP | + FF_CODEC_CAP_ICC_PROFILES, .p.wrapper_name = "libjxl", }; diff --git a/libavcodec/libjxlenc.c b/libavcodec/libjxlenc.c index dd85fcbc8e..7e97237cd1 100644 --- a/libavcodec/libjxlenc.c +++ b/libavcodec/libjxlenc.c @@ -469,7 +469,8 @@ const FFCodec ff_libjxl_encoder = { .close = libjxl_encode_close, .p.capabilities = AV_CODEC_CAP_OTHER_THREADS, .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | - FF_CODEC_CAP_AUTO_THREADS | FF_CODEC_CAP_INIT_CLEANUP, + FF_CODEC_CAP_AUTO_THREADS | FF_CODEC_CAP_INIT_CLEANUP | + FF_CODEC_CAP_ICC_PROFILES, .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB48, AV_PIX_FMT_RGBA64, diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 816eb1ce5d..5f058d026f 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -3027,7 +3027,9 @@ const FFCodec ff_mjpeg_decoder = { .p.priv_class = &mjpegdec_class, .p.profiles = NULL_IF_CONFIG_SMALL(ff_mjpeg_profiles), .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | - FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_SETS_PKT_DTS, + FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | + FF_CODEC_CAP_SETS_PKT_DTS | + FF_CODEC_CAP_ICC_PROFILES, .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_MJPEG_NVDEC_HWACCEL HWACCEL_NVDEC(mjpeg), diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index 63862a5043..3df0b51bb4 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -652,7 +652,7 @@ const FFCodec ff_mjpeg_encoder = { FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), .close = mjpeg_encode_close, .p.capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_ICC_PROFILES, .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 6e1214401d..3b888199d4 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -1727,7 +1727,8 @@ const FFCodec ff_apng_decoder = { .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context), .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | - FF_CODEC_CAP_ALLOCATE_PROGRESS, + FF_CODEC_CAP_ALLOCATE_PROGRESS | + FF_CODEC_CAP_ICC_PROFILES, }; #endif @@ -1744,6 +1745,7 @@ const FFCodec ff_png_decoder = { .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context), .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/, .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | - FF_CODEC_CAP_ALLOCATE_PROGRESS | FF_CODEC_CAP_INIT_CLEANUP, + FF_CODEC_CAP_ALLOCATE_PROGRESS | FF_CODEC_CAP_INIT_CLEANUP | + FF_CODEC_CAP_ICC_PROFILES, }; #endif diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c index 25cf769931..8ef863a6c1 100644 --- a/libavcodec/pngenc.c +++ b/libavcodec/pngenc.c @@ -1210,6 +1210,7 @@ const FFCodec ff_png_encoder = { AV_PIX_FMT_MONOBLACK, AV_PIX_FMT_NONE }, .p.priv_class = &pngenc_class, + .caps_internal = FF_CODEC_CAP_ICC_PROFILES, }; const FFCodec ff_apng_encoder = { @@ -1231,4 +1232,5 @@ const FFCodec ff_apng_encoder = { AV_PIX_FMT_NONE }, .p.priv_class = &pngenc_class, + .caps_internal = FF_CODEC_CAP_ICC_PROFILES, }; diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 329eafe494..043ff79e0a 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -2193,6 +2193,6 @@ const FFCodec ff_tiff_decoder = { .close = tiff_end, FF_CODEC_DECODE_CB(decode_frame), .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_ICC_PROFILES, .p.priv_class = &tiff_decoder_class, }; diff --git a/libavcodec/webp.c b/libavcodec/webp.c index bbc10ba2df..fb5688fc95 100644 --- a/libavcodec/webp.c +++ b/libavcodec/webp.c @@ -1565,4 +1565,5 @@ const FFCodec ff_webp_decoder = { FF_CODEC_DECODE_CB(webp_decode_frame), .close = webp_decode_close, .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .caps_internal = FF_CODEC_CAP_ICC_PROFILES, }; From patchwork Thu Jul 28 14:49:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 37024 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:1649:b0:8b:613a:194d with SMTP id no9csp326668pzb; Thu, 28 Jul 2022 07:51:11 -0700 (PDT) X-Google-Smtp-Source: AGRyM1vpBOai+/ap/NPzMehOW9QFtfpdWhASwww6UIBPrMJotsW91FyqpHzu4GZBdF0zNNeQNG4x X-Received: by 2002:a17:907:7e87:b0:72f:18d7:6094 with SMTP id qb7-20020a1709077e8700b0072f18d76094mr21603470ejc.77.1659019871140; Thu, 28 Jul 2022 07:51:11 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1659019871; cv=none; d=google.com; s=arc-20160816; b=pW+ZAA9wJAyjTilBSup9ls4x1gkGuWrLhABrs3wKahOkYt8obcOKD1XeZHHtbGSHKx AM5E71keYOm6+nliOblPJ4BbkhMyzjJlcqZduF8pwyLHmArJrr5q2hjuMEhM5qEC/LtQ E3YKaHc92gN/zdfN5GjJO+U3x6RSVdpxXjOf7yjLWxO9hiYA+IY3cSXnnsqgiIoCJ9Qt IyCXzW0BP663K7rpH54ZMlfux4OoOS+yNI+fKrIleBXY3KVDKvn+9b2o5EZAkZZXtlUA jo8M1628VNYkKKlQqs9DD9J8kAewPMBkXtepCLsGmP/pDpkQS8vu8zI2VfZ9bbUMaZQM af9A== 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=87eQAf2plHOVVQMGDVQVy9J8NQSmpvGullwRf7kSbFE=; b=Cl8hofOSP1XkeOYrwR0TjjO/uzBkgDTBlji509TTVuHK5luUJBEtHQFgJhu+a3AG9Z FsQSMw1c9FKCq1aNiKG9tSFHaQYTi9xbOum5awwbMK7ElJnH2u9LMu8QJKEC8tpbiBSk bs9wpnYXcw4SE+2okCX3H975JM2OJnGSnak762tKslcwokDkYqSzxRNSBDh6i1Sfgzfj KIr1K5zRBgJzu8MO1Plwq4UHt3cZuKg1nGByGDQ+WWqWINsxmF9MhRHiO9hTyIpTgvmk ojLQXZUUoVmx7rbKj3eQKbi9NOnyF9cqQluxU75Ug5ko1NyHfGh89Pzu2hB7/RfqmZaK XqhA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b="nR9RoFs/"; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id q22-20020a50aa96000000b0043574c5a72fsi904800edc.360.2022.07.28.07.51.10; Thu, 28 Jul 2022 07:51:11 -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=@haasn.xyz header.s=mail header.b="nR9RoFs/"; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 5444D68B9A6; Thu, 28 Jul 2022 17:50:19 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 2C4CE68B9A9 for ; Thu, 28 Jul 2022 17:50:07 +0300 (EEST) Received: from haasn.dev (unknown [10.30.0.2]) by haasn.dev (Postfix) with ESMTP id DB4E64AA72; Thu, 28 Jul 2022 16:50:06 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=haasn.xyz; s=mail; t=1659019806; bh=N8/nkCWDJiPfcQkHlFDOoJ6UB8mbcFVQn9ELubRIfLg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nR9RoFs/ZqJgLAnOaqbVb0xV30fvO8ycDTzxdUC7dKWXSYyeN66qYNcTCph5vzV9x Ud4aEet76Dxn/dmdiVBO/wMqjmnuw5DOoaM1qPr8cziO9nYEdZzdhhpLUf+kUQ2mOm LWp53BvkfxgBLFJ7opg0hJ1gxWDD2ztU5ec6uO04= From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Thu, 28 Jul 2022 16:49:58 +0200 Message-Id: <20220728145002.102600-4-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.37.1 In-Reply-To: <20220728145002.102600-1-ffmpeg@haasn.xyz> References: <20220728145002.102600-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v4 3/7] avcodec: add API for automatic handling of icc profiles 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: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: zSge7o08JwNa From: Niklas Haas This functionally already exists, but as pointed out in #9672 and #9673, requiring users to manually include filters is clumsy, error-prone and hard to use together with tools like ffplay. To streamline ICC profile support, add a new AVCodecContext flag to globally enable reading and writing ICC profiles, automatically, for all appropriate media types. Note that this commit only includes the new API. The implementation is split off to separate commits for readability. Signed-off-by: Niklas Haas --- doc/APIchanges | 5 +++++ doc/codecs.texi | 2 ++ libavcodec/avcodec.h | 6 ++++++ libavcodec/options_table.h | 1 + libavcodec/version.h | 2 +- 5 files changed, 15 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index b3563cd528..e374f3ca81 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,11 @@ libavutil: 2021-04-27 API changes, most recent first: +2022-07-xx - xxxxxxxxx - lavc 59.40.100 - avcodec.h + Add the AV_CODEC_FLAG2_ICC_PROFILES flag to AVCodecContext, to enable + automatic reading and writing of embedded ICC profiles in image files. + The "flags2" option now supports the corresponding flag "icc_profiles". + 2022-07-xx - xxxxxxxxxx - lavu 57.30.100 - frame.h Add AVFrame.duration, deprecate AVFrame.pkt_duration. diff --git a/doc/codecs.texi b/doc/codecs.texi index 5e10020900..1adacd2b59 100644 --- a/doc/codecs.texi +++ b/doc/codecs.texi @@ -644,6 +644,8 @@ for codecs that support it. See also @file{doc/examples/export_mvs.c}. Do not skip samples and export skip information as frame side data. @item ass_ro_flush_noop Do not reset ASS ReadOrder field on flush. +@item icc_profiles +Generate/parse embedded ICC profiles from/to colorimetry tags. @end table @item export_side_data @var{flags} (@emph{decoding/encoding,audio,video,subtitles}) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index cb5c25bf63..60b215d2e9 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -331,6 +331,12 @@ typedef struct RcOverride{ * Do not reset ASS ReadOrder field on flush (subtitles decoding) */ #define AV_CODEC_FLAG2_RO_FLUSH_NOOP (1 << 30) +/** + * Generate/parse ICC profiles on encode/decode, as appropriate for the type of + * file. No effect on codecs which cannot contain embedded ICC profiles, or + * when compiled without support for lcms2. + */ +#define AV_CODEC_FLAG2_ICC_PROFILES (1U << 31) /* Unsupported options : * Syntax Arithmetic coding (SAC) diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index e72b4d12b6..a72085ac90 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -83,6 +83,7 @@ static const AVOption avcodec_options[] = { {"export_mvs", "export motion vectors through frame side data", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_EXPORT_MVS}, INT_MIN, INT_MAX, V|D, "flags2"}, {"skip_manual", "do not skip samples and export skip information as frame side data", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_SKIP_MANUAL}, INT_MIN, INT_MAX, A|D, "flags2"}, {"ass_ro_flush_noop", "do not reset ASS ReadOrder field on flush", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_RO_FLUSH_NOOP}, INT_MIN, INT_MAX, S|D, "flags2"}, +{"icc_profiles", "generate/parse embedded ICC profiles from/to colorimetry tags", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_ICC_PROFILES}, INT_MIN, INT_MAX, S|D, "flags2"}, {"export_side_data", "Export metadata as side data", OFFSET(export_side_data), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT}, 0, UINT_MAX, A|V|S|D|E, "export_side_data"}, {"mvs", "export motion vectors through frame side data", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_EXPORT_DATA_MVS}, INT_MIN, INT_MAX, V|D, "export_side_data"}, {"prft", "export Producer Reference Time through packet side data", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_EXPORT_DATA_PRFT}, INT_MIN, INT_MAX, A|V|S|E, "export_side_data"}, diff --git a/libavcodec/version.h b/libavcodec/version.h index f2f14eaed1..19f3f4a272 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "version_major.h" -#define LIBAVCODEC_VERSION_MINOR 39 +#define LIBAVCODEC_VERSION_MINOR 40 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From patchwork Thu Jul 28 14:49:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 37025 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:1649:b0:8b:613a:194d with SMTP id no9csp326738pzb; Thu, 28 Jul 2022 07:51:20 -0700 (PDT) X-Google-Smtp-Source: AGRyM1tjklQMyIVNp3UqNDjuuuBr5aA223kNKuQJQwwkq7LNSXyCq+KYq/zce3gkA7WvwTchQLSN X-Received: by 2002:a17:907:980d:b0:72f:2cf2:9aff with SMTP id ji13-20020a170907980d00b0072f2cf29affmr21138483ejc.165.1659019880533; Thu, 28 Jul 2022 07:51:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1659019880; cv=none; d=google.com; s=arc-20160816; b=xEhYGZ3yP4I649arrOpJj9MNsmbtXR2tOelok00RhXRvehsKWe4ylGzUOFjshaetLU pjv3/lHP3mw2/h/oSNHuMUgxMcSVbUcgeoM/CIE7TaqnJwQIVvm1v35k3cN8IU8iKA/l ukANXAzUfHOv9xEXpSfAhTxXfjccUcKaLvnSacShCgmuYZJJLJIi4glTsoor+VDgMtgr lEad31T1c3OmWvGB5pb/MBw4uj9bfZz9xQfd5y9W2Pe+iBF9AZrmrkGsdFBv8wNdWN0+ gSxF8+BMnXLbrv6k+E9eNvunVue/LA20U8eGsMf5pmX6LS4wMVvg49ZaHa19NeflI2Iw joKw== 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=SzS5H8MVSIWbk7cGjJ11ywZOrjUBBjL72L5ShkClZ3M=; b=j1cmZmQgKs15PGQN0eBW8pmEOVkYOZKPdoCYyWddWSQ2IHUrS/SVyyJ8LzyRi1sZIk QkVpgRwAHWPpp6qrxazHLU7x1niRHhk20525hOB+P7QhKvbzTsw6ign3K0k6B3sdhF4O qZgNablL9wNJFuW5kAlUpIY+oFsiv9SMTt/RRbo9jklZXRH8viDH+sh/ywoQ6uuDqP/m X2fdqOK/jtz4K7kX6A24B8n89t1m4HhMMOTHB9LnEdZu/XyvkjnsF89jZWdv1Rho0X6x /kdwPJ2VCKDS85jZ/ADC4febFBZgJ5Q7nbLa42eyUpEMIUWCVssrRm3oulilK66c3KTT FuuQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b="l/MAFzll"; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id dp16-20020a170906c15000b0071576eb9e6bsi856181ejc.211.2022.07.28.07.51.20; Thu, 28 Jul 2022 07:51:20 -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=@haasn.xyz header.s=mail header.b="l/MAFzll"; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 276F868B9E7; Thu, 28 Jul 2022 17:50:20 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 55C8368B9A9 for ; Thu, 28 Jul 2022 17:50:07 +0300 (EEST) Received: from haasn.dev (unknown [10.30.0.2]) by haasn.dev (Postfix) with ESMTP id 198B34AAF5; Thu, 28 Jul 2022 16:50:07 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=haasn.xyz; s=mail; t=1659019807; bh=8tTeODSyhejhlEJANTAr9trY6FG3qVCLHl+JwXrTPxA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=l/MAFzllpuhf1R7LPg/8dTmLLA4jWZDiNsFCKyFb/F9dxaCB2KZ6THQhw8FbpvDXl IPRojCBJp03zOfYBmAU8RCa4CS/k1vkZeVt+MoscIiEplh0kuOl9WkXWGFNYMzcl4s rb1e7yQTDo/3EnGRn612DsWDOUO52VQYIQ+AqdZ8= From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Thu, 28 Jul 2022 16:49:59 +0200 Message-Id: <20220728145002.102600-5-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.37.1 In-Reply-To: <20220728145002.102600-1-ffmpeg@haasn.xyz> References: <20220728145002.102600-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v4 4/7] avcodec: add common fflcms2 boilerplate 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: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: /2Tf9VwKMcs4 From: Niklas Haas Handling this in general code makes more sense than handling it in individual codec files, because it would be a lot of unnecessary code duplication for the plenty of formats that support exporting ICC profiles (jpg, png, tiff, webp, jxl, ...). encode.c and decode.c will be in charge of initializing this state as needed, so we merely need to make sure to uninit it afterwards from the common destructor path. Signed-off-by: Niklas Haas --- configure | 2 +- libavcodec/Makefile | 1 + libavcodec/avcodec.c | 4 ++++ libavcodec/decode.c | 4 ++++ libavcodec/internal.h | 8 ++++++++ 5 files changed, 18 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 6629d14099..8c7e8c9d1d 100755 --- a/configure +++ b/configure @@ -3814,7 +3814,7 @@ swresample_suggest="libm libsoxr stdatomic" swscale_deps="avutil" swscale_suggest="libm stdatomic" -avcodec_extralibs="pthreads_extralibs iconv_extralibs dxva2_extralibs" +avcodec_extralibs="pthreads_extralibs iconv_extralibs dxva2_extralibs lcms2_extralibs" avfilter_extralibs="pthreads_extralibs" avutil_extralibs="d3d11va_extralibs nanosleep_extralibs pthreads_extralibs vaapi_drm_extralibs vaapi_x11_extralibs vdpau_x11_extralibs" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 6751b6b591..aff7752856 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -114,6 +114,7 @@ OBJS-$(CONFIG_INTRAX8) += intrax8.o intrax8dsp.o msmpeg4data.o OBJS-$(CONFIG_IVIDSP) += ivi_dsp.o OBJS-$(CONFIG_JNI) += ffjni.o jni.o OBJS-$(CONFIG_JPEGTABLES) += jpegtables.o +OBJS-$(CONFIG_LCMS2) += fflcms2.o OBJS-$(CONFIG_LLAUDDSP) += lossless_audiodsp.o OBJS-$(CONFIG_LLVIDDSP) += lossless_videodsp.o OBJS-$(CONFIG_LLVIDENCDSP) += lossless_videoencdsp.o diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c index 4bc18183a9..c9105c5df2 100644 --- a/libavcodec/avcodec.c +++ b/libavcodec/avcodec.c @@ -479,6 +479,10 @@ av_cold int avcodec_close(AVCodecContext *avctx) av_channel_layout_uninit(&avci->initial_ch_layout); +#if CONFIG_LCMS2 + ff_icc_context_uninit(&avci->icc); +#endif + av_freep(&avctx->internal); } diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 0613681f89..8922222271 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -49,6 +49,10 @@ #include "internal.h" #include "thread.h" +#if CONFIG_LCMS2 +# include "fflcms2.h" +#endif + static int apply_param_change(AVCodecContext *avctx, const AVPacket *avpkt) { int ret; diff --git a/libavcodec/internal.h b/libavcodec/internal.h index 6fb4e1b9af..8809a7079a 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -33,6 +33,10 @@ #include "avcodec.h" #include "config.h" +#if CONFIG_LCMS2 +# include "fflcms2.h" +#endif + #define FF_SANE_NB_CHANNELS 512U #if HAVE_SIMD_ALIGN_64 @@ -146,6 +150,10 @@ typedef struct AVCodecInternal { uint64_t initial_channel_layout; #endif AVChannelLayout initial_ch_layout; + +#if CONFIG_LCMS2 + FFIccContext icc; /* used to read and write embedded ICC profiles */ +#endif } AVCodecInternal; /** From patchwork Thu Jul 28 14:50:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 37023 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:1649:b0:8b:613a:194d with SMTP id no9csp326604pzb; Thu, 28 Jul 2022 07:51:02 -0700 (PDT) X-Google-Smtp-Source: AGRyM1vitypBh7BfvCc+rAHIIr7+yDiEqOj/4Ih4ob/9tRCHaUYudK4XCN/0Zn5QKZQeaKZDbnrN X-Received: by 2002:a17:907:94d1:b0:72f:10c:bb3c with SMTP id dn17-20020a17090794d100b0072f010cbb3cmr21102940ejc.532.1659019862350; Thu, 28 Jul 2022 07:51:02 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1659019862; cv=none; d=google.com; s=arc-20160816; b=ijxFI7NVihrss/zfURVcSHRfhD5Gmr6IqnmMf+eOUCHuoBZKS4K+iFzxl0yClRSn3c EZQLwjg94wsa0vtL+kS6oz6I3PoUT5DnYe4elSHYOISm2FhaFu0J6hWup/fiOrUW5sZE GP8Ewdm48cOJ1vLz3jzrQh+UlFvajCpxdT517LGZ88D35wNUiISTnaE57SBdw0yk3lYf zsRtPV9LKzuiLOxU5fBX8PadJEciO2XU0aj+hVZ/ubWnJ+2dXUhnxBwiRX9Psv8FA4wz FYvdIVOLEv4Vh+DhzKperGs6oSNK/REVNJRIIamGFrVq/AsKd2pRsqwU3qXBe3uXbYp/ IFKA== 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=cIpTxC6Th/EfcRPrZImAwn9Lwdx6vG9jNipyHD5wbdM=; b=XI5TDXqzJUyMpNDbPq7BA9C5u9eIT9tL6lszjGmjA4XZaB8jJxCN7jjcZI3W3OPBLe iesp5rVhq+SfvW6jNZorOIA81R+tR4FAKQNfhGbW8c9UzZ+kCoSmIhIfWdQhgLCIwxTb zn69cVWOdkkjQ0Gn3u+MC0QgnDiTjVUlfgRfyDhyXIygwvuX85TOcnarUmX+KarcTLFA LDW9RKdeB501fT5eIbd+mtB2o+gLKLhq0luauByoDRO1BsVrsEw3mkPESYjMEr0R+wUM j6f72EV8q+03E973wMD9qdQp6vXXk1U2ydCCbhfVLD2JUCbDSiwvqQmYCCPoqYIckkDE QIqg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=bUYRjT3Y; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id dn20-20020a17090794d400b00704dc5420adsi954339ejc.38.2022.07.28.07.51.02; Thu, 28 Jul 2022 07:51:02 -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=@haasn.xyz header.s=mail header.b=bUYRjT3Y; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 7B05C68B9DC; Thu, 28 Jul 2022 17:50:18 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 2907F68B9A6 for ; Thu, 28 Jul 2022 17:50:12 +0300 (EEST) Received: from haasn.dev (unknown [10.30.0.2]) by haasn.dev (Postfix) with ESMTP id 4BF834AAF8; Thu, 28 Jul 2022 16:50:07 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=haasn.xyz; s=mail; t=1659019807; bh=hMLzAeafXOLsxjCxKHs6OfrRPBp3s6Tt3Q9/28blPfI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bUYRjT3Y7IsTaV4WdE68phM8AZvIZh9j3s/IE20iwMEW8699YEFX5TmcffFaFuqQF P9IXWIPjrEmO0kST3uUtgfBoVRF2FiGzaw03dhBCit1ZA7zICV9bqbVsNgsVftCCye SRjkHJfZL31Kd3yFfeSmBK3ryWZPyWWE78IKCEIM= From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Thu, 28 Jul 2022 16:50:00 +0200 Message-Id: <20220728145002.102600-6-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.37.1 In-Reply-To: <20220728145002.102600-1-ffmpeg@haasn.xyz> References: <20220728145002.102600-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v4 5/7] avcodec/decode: parse ICC profiles 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: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: i30rZhVLLYfM From: Niklas Haas Implementation for the decode side of the ICC profile API, roughly matching the behavior of the existing vf_iccdetect filter. Closes: #9673 Signed-off-by: Niklas Haas --- libavcodec/decode.c | 61 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 8922222271..92958745df 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -49,10 +49,6 @@ #include "internal.h" #include "thread.h" -#if CONFIG_LCMS2 -# include "fflcms2.h" -#endif - static int apply_param_change(AVCodecContext *avctx, const AVPacket *avpkt) { int ret; @@ -508,6 +504,54 @@ FF_ENABLE_DEPRECATION_WARNINGS return ret < 0 ? ret : 0; } +#if CONFIG_LCMS2 +static int detect_colorspace(AVCodecContext *avctx, AVFrame *frame) +{ + AVCodecInternal *avci = avctx->internal; + enum AVColorTransferCharacteristic trc; + AVColorPrimariesDesc coeffs; + enum AVColorPrimaries prim; + cmsHPROFILE profile; + AVFrameSideData *sd; + int ret; + if (!(avctx->flags2 & AV_CODEC_FLAG2_ICC_PROFILES)) + return 0; + + sd = av_frame_get_side_data(frame, AV_FRAME_DATA_ICC_PROFILE); + if (!sd || !sd->size) + return 0; + + if (!avci->icc.avctx) { + ret = ff_icc_context_init(&avci->icc, avctx); + if (ret < 0) + return ret; + } + + profile = cmsOpenProfileFromMemTHR(avci->icc.ctx, sd->data, sd->size); + if (!profile) + return AVERROR_INVALIDDATA; + + ret = ff_icc_profile_read_primaries(&avci->icc, profile, &coeffs); + if (!ret) + ret = ff_icc_profile_detect_transfer(&avci->icc, profile, &trc); + cmsCloseProfile(profile); + if (ret < 0) + return ret; + + prim = av_csp_primaries_id_from_desc(&coeffs); + if (prim != AVCOL_PRI_UNSPECIFIED) + frame->color_primaries = prim; + if (trc != AVCOL_TRC_UNSPECIFIED) + frame->color_trc = trc; + return 0; +} +#else /* !CONFIG_LCMS2 */ +static int detect_colorspace(av_unused AVCodecContext *c, av_unused AVFrame *f) +{ + return 0; +} +#endif + static int decode_simple_receive_frame(AVCodecContext *avctx, AVFrame *frame) { int ret; @@ -528,7 +572,7 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame) { AVCodecInternal *avci = avctx->internal; const FFCodec *const codec = ffcodec(avctx->codec); - int ret; + int ret, ok; av_assert0(!frame->buf[0]); @@ -542,6 +586,13 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame) if (ret == AVERROR_EOF) avci->draining_done = 1; + /* preserve ret */ + ok = detect_colorspace(avctx, frame); + if (ok < 0) { + av_frame_unref(frame); + return ok; + } + if (!(codec->caps_internal & FF_CODEC_CAP_SETS_FRAME_PROPS) && IS_EMPTY(avci->last_pkt_props)) { // May fail if the FIFO is empty. From patchwork Thu Jul 28 14:50:01 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 37021 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:1649:b0:8b:613a:194d with SMTP id no9csp326468pzb; Thu, 28 Jul 2022 07:50:45 -0700 (PDT) X-Google-Smtp-Source: AGRyM1ukGdQYgnilNKgrqguvhxEqGp8DX8FaojR5OCD9pBGeQxs9L0h3udhTeLURDWi/dihikFhe X-Received: by 2002:a17:906:cc45:b0:72b:313b:f3ee with SMTP id mm5-20020a170906cc4500b0072b313bf3eemr20546577ejb.362.1659019844723; Thu, 28 Jul 2022 07:50:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1659019844; cv=none; d=google.com; s=arc-20160816; b=Zg0T2ggXFrOK567HkAM/KAb18g59rePFm8sXsc1382JeY90TJ9am8t9MGKSEIx4v9D 5d48Gq1KtXFG/tST3PLeoo36Nlmf06dg+fYNT2+atD/ZuVkx7WM99N/xsucM2q2DVgc8 0XlcUOfdSa4DJOkLDI+4seWLck8mD9Xyb1nOev+FcI5EtyMTOyy8Ic1DD4Jd+t59mCoq s01nGR8Ug46GGzaalOiPt8t7XbD4bcIpIVZgTKQXykNgm9iFRtVrDckHOQGd8pY8jLTH LbnYzBj3lgh4xb5SUbAzTfRNukKQVj/j9hZ66NaAiqLzCLg9hLPFt6K2UEicbzpMbjNe 3HNQ== 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=5zuMXp9W21+feCk617YcssrMLHB0/WV4H0TcFJDoHtM=; b=Us2rMuQbC22kx+W8GVvYA9YsIuf1k1H1dySe6VNeJhkx1l+aDvbYOPtWLOLB4vwGEr Tt3lLMc5b+tVkOsuw69I0qDPVKTxZzGwuRiHObh7wq274cWK7yZaW9opO5F89KVskKW4 GCf16TK8iimf5Lw79WpxwC6zJ+5NXOO9zmL1wImwhXox5spuEACbMiWrb5Fll3uTciiS WomAKNPb07GtFlMzLbQ3GdCgTMB/lFiKzdJXCd6u14XisE7+2f12w00IdG97f0HGl+H9 tvuKcYlPmU6WBB7DZwQ5PHU7SzRsiSnwEdDZ2aIlNqofVmPUiI5Prq5iRMYhniAQTdsM x59w== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=cO7cT3Ym; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id wu8-20020a170906eec800b0072ab4b5ffdcsi1008106ejb.96.2022.07.28.07.50.44; Thu, 28 Jul 2022 07:50:44 -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=@haasn.xyz header.s=mail header.b=cO7cT3Ym; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id E00AD68B9AC; Thu, 28 Jul 2022 17:50:16 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 21D9F68B8E9 for ; Thu, 28 Jul 2022 17:50:12 +0300 (EEST) Received: from haasn.dev (unknown [10.30.0.2]) by haasn.dev (Postfix) with ESMTP id 7E5564AAF9; Thu, 28 Jul 2022 16:50:07 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=haasn.xyz; s=mail; t=1659019807; bh=iFqvF3U3BuDklpCMX6gZa/dYI+aDcl6UfpXve6uOnSY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cO7cT3YmYagI0UuBKHll8t1cUnMg/a9rgcCoYiC1JPt3pDOkrpWimymKAXtE5eP10 DCotCZ854eZ47Lzn2LLoi/xIg4mqks4D6DjVRTPQ7xI371AQC2gIYVwnXnD5jDue/C TTjRq746OaUBd78oIeqNO+5iOQ9uvBH6X+ornzgY= From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Thu, 28 Jul 2022 16:50:01 +0200 Message-Id: <20220728145002.102600-7-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.37.1 In-Reply-To: <20220728145002.102600-1-ffmpeg@haasn.xyz> References: <20220728145002.102600-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v4 6/7] avcodec/encode:: generate ICC profiles 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: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 6r640A3/5aD3 From: Niklas Haas Only if requested, and only if the codec signals support for ICC profiles. Implementation roughly matches the functionality of the existing vf_iccgen filter, albeit with some reduced flexibility and no caching. Ideally, we'd also only do this on the first frame (e.g. mjpeg, apng), but there's no meaningful way for us to distinguish between this case and e.g. somebody using the image2 muxer, in which case we'd want to attach ICC profiles to every frame in the stream. Closes: #9672 Signed-off-by: Niklas Haas --- libavcodec/encode.c | 53 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 310fe20777..7cf13bf6d6 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -308,6 +308,53 @@ static int encode_receive_packet_internal(AVCodecContext *avctx, AVPacket *avpkt return ret; } +#if CONFIG_LCMS2 +static int encode_generate_icc_profile(AVCodecContext *avctx, AVFrame *frame) +{ + enum AVColorTransferCharacteristic trc = frame->color_trc; + enum AVColorPrimaries prim = frame->color_primaries; + const FFCodec *const codec = ffcodec(avctx->codec); + AVCodecInternal *avci = avctx->internal; + cmsHPROFILE profile; + int ret; + + /* don't generate ICC profiles if disabled or unsupported */ + if (!(avctx->flags2 & AV_CODEC_FLAG2_ICC_PROFILES)) + return 0; + if (!(codec->caps_internal & FF_CODEC_CAP_ICC_PROFILES)) + return 0; + + if (trc == AVCOL_TRC_UNSPECIFIED) + trc = avctx->color_trc; + if (prim == AVCOL_PRI_UNSPECIFIED) + prim = avctx->color_primaries; + if (trc == AVCOL_TRC_UNSPECIFIED || prim == AVCOL_PRI_UNSPECIFIED) + return 0; /* can't generate ICC profile with missing csp tags */ + + if (av_frame_get_side_data(frame, AV_FRAME_DATA_ICC_PROFILE)) + return 0; /* don't overwrite existing ICC profile */ + + if (!avci->icc.avctx) { + ret = ff_icc_context_init(&avci->icc, avctx); + if (ret < 0) + return ret; + } + + ret = ff_icc_profile_generate(&avci->icc, prim, trc, &profile); + if (ret < 0) + return ret; + + ret = ff_icc_profile_attach(&avci->icc, profile, frame); + cmsCloseProfile(profile); + return ret; +} +#else /* !CONFIG_LCMS2 */ +static int encode_generate_icc_profile(av_unused AVCodecContext *c, av_unused AVFrame *f) +{ + return 0; +} +#endif + static int encode_send_frame_internal(AVCodecContext *avctx, const AVFrame *src) { AVCodecInternal *avci = avctx->internal; @@ -360,6 +407,12 @@ FF_DISABLE_DEPRECATION_WARNINGS FF_ENABLE_DEPRECATION_WARNINGS #endif + if (avctx->codec->type == AVMEDIA_TYPE_VIDEO) { + ret = encode_generate_icc_profile(avctx, dst); + if (ret < 0) + return ret; + } + return 0; } From patchwork Thu Jul 28 14:50:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 37022 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:1649:b0:8b:613a:194d with SMTP id no9csp326534pzb; Thu, 28 Jul 2022 07:50:53 -0700 (PDT) X-Google-Smtp-Source: AGRyM1v7mxVHnJ0TyLCeV1LTOerni2sV7mkYaGpLnXQXOTWJtqSSLnJtnju7BVmpR6T4Ig619Qvs X-Received: by 2002:a05:6402:c47:b0:437:ce2d:c30d with SMTP id cs7-20020a0564020c4700b00437ce2dc30dmr27667543edb.395.1659019853035; Thu, 28 Jul 2022 07:50:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1659019853; cv=none; d=google.com; s=arc-20160816; b=XwR8JwvdlX+Z+3e40zRZnRewL0L9N7in/cObgrFIxa4rFVzD+4tFmV+6Mj7LfYXBrO sNNXtaNgmLqgdnuvj+ONHBG9r3Zj4hCFlsIaRhfLWI5DVqGNMJl6XeSFc6RCW6uL0x56 Nqv9GkLujmmGd0CIrFf6rGmc5vL3N5agjOndYXukOR1A23UtzTdfGPx/SlqwaeHxj3tl 0wS6/1Sw5U3MRp7bdrOkIaHSFee3IHVc07iWQezK8pY2vZlmstjt7YKj3JvzHxIOtpRm +I3CIJGTmHJA7ytS8YbabfJqNBAamE8cxGfrw3fC4/jW4Gz9BTJBFRc2vg+ff2/UuzZx Bzfw== 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=2hEzOM8jQEdWOmCPa46KXYDuemArAXbHTEyhcetMPM4=; b=tqqoKZKSaMzbLcvHbdfdf6op3rUcAplYGkTZP5bLZsi2sO6iOP53LGB941lWeKPmjo 9wjl1fOljuRD9bK8Fovmuy2IJwavEC3vjpwNsXlKqUtVpesZt/lETtufyjbplRAymTCi qxveuYrl7cqJ17Hlm1y0n+vizaiE0P//tKs58ssk8MB3kT58ucpl2l8xB8+t6ZdmPT3D 3vjFB3SwuiNrxGlPhUjmeFDcHlUvy7Nk5azofacN11adf+fo9Eku+IBBFxoInGGeVGTF SZKBWGH8q11ZvzeTKyE386q330KgDyh2vwinRXXPQLsvcaG2Bs1v+9dIdgkKaLPFsmce YnuQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=gt+IP5Oa; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id n4-20020a17090695c400b0072f72e5c0b8si686565ejy.836.2022.07.28.07.50.52; Thu, 28 Jul 2022 07:50:53 -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=@haasn.xyz header.s=mail header.b=gt+IP5Oa; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id A25F668B9AA; Thu, 28 Jul 2022 17:50:17 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 226C768B99A for ; Thu, 28 Jul 2022 17:50:12 +0300 (EEST) Received: from haasn.dev (unknown [10.30.0.2]) by haasn.dev (Postfix) with ESMTP id AF9234AAFB; Thu, 28 Jul 2022 16:50:07 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=haasn.xyz; s=mail; t=1659019807; bh=fDPY8qfcQSoK1Mtjmcso2wzyAEb3w84mnEYITtgwr0w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gt+IP5OaHM5T6v3KRYhTWLROek5jCMZmTLXZ2ianISCWrOHUwW7Khl/dIuYgK3kvA LTW3DkgUtxh0S7PtkgxTJmi/TFp54pTWC6sKByIHCehGkq1q8psjaRGsUORng93lZe 7wuKe8nHSdYegvTfAQgCkwlrLo7p6ZoSiV7+JeHc= From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Thu, 28 Jul 2022 16:50:02 +0200 Message-Id: <20220728145002.102600-8-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.37.1 In-Reply-To: <20220728145002.102600-1-ffmpeg@haasn.xyz> References: <20220728145002.102600-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v4 7/7] fate/png: add test for ICC profile parsing 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: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: SkihrO8/kDeZ From: Niklas Haas This tests the new "-flags2 icc_profiles" option by making sure the embedded ICC profile gets correctly detected as sRGB. Signed-off-by: Niklas Haas --- tests/fate/image.mak | 4 +++ tests/ref/fate/png-icc-parse | 48 ++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 tests/ref/fate/png-icc-parse diff --git a/tests/fate/image.mak b/tests/fate/image.mak index fca4eaf60a..03e794dc48 100644 --- a/tests/fate/image.mak +++ b/tests/fate/image.mak @@ -392,6 +392,10 @@ fate-png-side-data: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_frames \ FATE_PNG_TRANSCODE-$(call TRANSCODE, PNG, IMAGE2 IMAGE_PNG_PIPE) += fate-png-icc fate-png-icc: CMD = transcode png_pipe $(TARGET_SAMPLES)/png1/lena-int_rgb24.png image2 "-c png" "" "-show_frames" +FATE_PNG_PROBE-$(call ALLYES, LCMS2) += fate-png-icc-parse +fate-png-icc-parse: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_frames \ + -flags2 icc_profiles $(TARGET_SAMPLES)/png1/lena-int_rgb24.png + FATE_PNG-$(call DEMDEC, IMAGE2, PNG) += $(FATE_PNG) FATE_PNG_PROBE-$(call DEMDEC, IMAGE2, PNG) += $(FATE_PNG_PROBE) FATE_IMAGE_FRAMECRC += $(FATE_PNG-yes) diff --git a/tests/ref/fate/png-icc-parse b/tests/ref/fate/png-icc-parse new file mode 100644 index 0000000000..18bb18a804 --- /dev/null +++ b/tests/ref/fate/png-icc-parse @@ -0,0 +1,48 @@ +[FRAME] +media_type=video +stream_index=0 +key_frame=1 +pts=0 +pts_time=0.000000 +pkt_dts=0 +pkt_dts_time=0.000000 +best_effort_timestamp=0 +best_effort_timestamp_time=0.000000 +pkt_duration=1 +pkt_duration_time=0.040000 +duration=1 +duration_time=0.040000 +pkt_pos=0 +pkt_size=40194 +width=128 +height=128 +pix_fmt=rgb24 +sample_aspect_ratio=1:1 +pict_type=I +coded_picture_number=0 +display_picture_number=0 +interlaced_frame=1 +top_field_first=0 +repeat_pict=0 +color_range=pc +color_space=unknown +color_primaries=bt709 +color_transfer=iec61966-2-1 +chroma_location=unspecified +[SIDE_DATA] +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]