From patchwork Wed May 4 12:36:11 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leo Izen X-Patchwork-Id: 35582 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:a885:b0:7f:4be2:bd17 with SMTP id ca5csp415389pzb; Wed, 4 May 2022 05:37:08 -0700 (PDT) X-Google-Smtp-Source: ABdhPJx+wrKNBjbGbcqRx3eFQQY9TI129BkQyWhqjSf++ZcGPydkLF1Q3B1cKwrekyDAkfKekVLz X-Received: by 2002:a17:906:1be1:b0:6ce:b0a8:17d with SMTP id t1-20020a1709061be100b006ceb0a8017dmr20174136ejg.413.1651667828537; Wed, 04 May 2022 05:37:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1651667828; cv=none; d=google.com; s=arc-20160816; b=DKQ0G9mpEYK07Q26NysPycGP4+UJ3KKA4EaiTxH5yE8iLXDOqJWmHqO57EQJrAfsBp JUq/+KuR+CY6P2MJ8A03cHr7VW0S0IB9sFIMa/7NEgvePeHKPntZhFOPJtrpI/Ep9c2R NCQ1YFB3fGCRsbP2Ypvw9V8juF+geOE02sunNQ8DXCP0JmrCyb5kJfGIdX/Fmc4pasau oF/8nTVo6UAWdmuWeSc12E+4HFV8cKsvC1JN7pdrWUM4REO0tCAuDl81f/Gvx30TL955 27AalRW7M9RhYYJOKwvMpzLxO4Cyjlj5u4i6RFw+KLyP8hV67Cz/tpikkMrBeoST5fBT 9TVA== 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=kVeQWEzcbzNgstgh/NOxsvrfYvkat+ndVRAifVbPzhE=; b=fWmp9tSn5n254Ol4lDilW6o83YezPihI4D0HLSM2+qP65RPSX4bSHtDdoNAyEwjvBe YXHwrBtJ3YdZXkWeP41p3j0beKOZUFDPO2Q0fHw/NH553kIWy4Jzq542RCzLUZu6M3uy JnV6bufyMDnnPUTTrfcoIxYVAEXjqh2VEcBGx0/jCqQu++fycAaN827YlXzbe71PtD9r 61TI5Q3C2k+xS3JkpZXUqI9yCuwV0PD8n6DyWDOluFtvfHrgL4JQGa6rgkqfySH8blMe RM+7yxBkf7mP17k53ZcBy/054ETM6ghoH7PAY/O8Me7IWVzMH7ZlnSA7Vad8Stz7B51r ZCSA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=iuMV0Vmo; 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 u12-20020a170906124c00b006e89c2d0609si15443514eja.68.2022.05.04.05.37.08; Wed, 04 May 2022 05:37:08 -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 header.s=20210112 header.b=iuMV0Vmo; 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 3E4FE68B2F7; Wed, 4 May 2022 15:36:56 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-il1-f180.google.com (mail-il1-f180.google.com [209.85.166.180]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 1521D68B2EF for ; Wed, 4 May 2022 15:36:49 +0300 (EEST) Received: by mail-il1-f180.google.com with SMTP id y16so763454ilc.7 for ; Wed, 04 May 2022 05:36:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=tMM71/vl1DOnrftQ8b3MtUn+JWB82eZfffQqOerpTvA=; b=iuMV0Vmo3Yq60PdTgASJiWb/ukIXmH230IejJGyXbIuG5Vi1BsfnG2gxXGB6Ge4CXs FcOW3EPmN2uyr48Kz0FLh488BCmWya4F58urxJnu7SaPieKLDP2m1NcPDYu5ys8FWa6A /dk/x1DgGRwN7mkWuUdlEwAheueqqnWw86TpujRTkV3a05zY0XzJ3EUOWRo+DpbqIeGx hJTghTP76zd4EshCCbLclrQx5dxq+O2DrUzawFZzSxDXLyBYaiZqZL6Hf+BsK+0PEwow ZK5LTxQDNfTCQrP0YaM6tg3ShwZULtXMJbpD4cYwGP5uS2MlOe9gaxfJHLtgYYVpkvGQ oMmg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=tMM71/vl1DOnrftQ8b3MtUn+JWB82eZfffQqOerpTvA=; b=dPmP24TSa1WknrhCIYUwwHjSX2WQzFAXpCSxcJyePXFU4LNYSSQP3a6P1qmbifX2// GPs2AhonimWdE1lfvqr/zSuxmd1UYyNcXckkcty6wmCsxiYjeZ3QWSCqqBuG03nVoUi0 KtnvYCTQBKcwbeIcWFcfH0zF8e/GLnd3H7MrV3uCrTDi0+3wUtLws8qd7nzdc0Clr29N U3XMi3EukZnekq6qF5f9qkv9nxwaoaCd8od4M0tIMIffyc/QDcZl4dmxscVLkVK9jcp7 0oy0fccssIdxNaIC4MhqfdZA7K42oyvPxxfA8HUyd7qeJ3YLY29rUwrbMipTN38aseuz x2+Q== X-Gm-Message-State: AOAM533pyDr+4huV2zkirjzJgesscSDmNYa3l0uCLMyb0ptmmT37N656 R8ULKFvBrssLFtllhgqmhkyl77JAHik= X-Received: by 2002:a92:ca0a:0:b0:2cf:4d8e:de17 with SMTP id j10-20020a92ca0a000000b002cf4d8ede17mr998762ils.146.1651667807518; Wed, 04 May 2022 05:36:47 -0700 (PDT) Received: from gauss.local (c-68-41-54-207.hsd1.mi.comcast.net. [68.41.54.207]) by smtp.gmail.com with ESMTPSA id x18-20020a056638027200b0032b3a781758sm4660371jaq.28.2022.05.04.05.36.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 May 2022 05:36:47 -0700 (PDT) From: Leo Izen To: ffmpeg-devel@ffmpeg.org Date: Wed, 4 May 2022 08:36:11 -0400 Message-Id: <20220504123612.174661-2-leo.izen@gmail.com> X-Mailer: git-send-email 2.36.0 In-Reply-To: <20220504123612.174661-1-leo.izen@gmail.com> References: <20220504123612.174661-1-leo.izen@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v3 1/2] avcodec/libjxldec: properly tag output colorspace 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: vqobiFbQJmRn Whether an ICC profile is present or not, the decoder should now properly tag the colorspace of pixel data received by the decoder. --- libavcodec/libjxldec.c | 91 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 3 deletions(-) diff --git a/libavcodec/libjxldec.c b/libavcodec/libjxldec.c index cd4bca3343..823d24648f 100644 --- a/libavcodec/libjxldec.c +++ b/libavcodec/libjxldec.c @@ -189,16 +189,101 @@ static int libjxl_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_f continue; case JXL_DEC_COLOR_ENCODING: av_log(avctx, AV_LOG_DEBUG, "COLOR_ENCODING event emitted\n"); - jret = JxlDecoderGetICCProfileSize(ctx->decoder, &ctx->jxl_pixfmt, JXL_COLOR_PROFILE_TARGET_ORIGINAL, &iccp_len); + jret = JxlDecoderGetICCProfileSize(ctx->decoder, &ctx->jxl_pixfmt, JXL_COLOR_PROFILE_TARGET_DATA, &iccp_len); if (jret == JXL_DEC_SUCCESS && iccp_len > 0) { av_buffer_unref(&ctx->iccp); ctx->iccp = av_buffer_alloc(iccp_len); if (!ctx->iccp) return AVERROR(ENOMEM); - jret = JxlDecoderGetColorAsICCProfile(ctx->decoder, &ctx->jxl_pixfmt, JXL_COLOR_PROFILE_TARGET_ORIGINAL, ctx->iccp->data, iccp_len); - if (jret != JXL_DEC_SUCCESS) + jret = JxlDecoderGetColorAsICCProfile(ctx->decoder, &ctx->jxl_pixfmt, JXL_COLOR_PROFILE_TARGET_DATA, ctx->iccp->data, iccp_len); + if (jret != JXL_DEC_SUCCESS) { + av_log(avctx, AV_LOG_WARNING, "Unable to obtain ICCP from header\n"); av_buffer_unref(&ctx->iccp); + } } + avctx->color_range = frame->color_range = AVCOL_RANGE_JPEG; + if (ctx->iccp) { + /* if the ICCP is present, libjxl outputs sRGB */ + if (ctx->jxl_pixfmt.num_channels >= 3) { + avctx->colorspace = AVCOL_SPC_RGB; + avctx->color_primaries = AVCOL_PRI_BT709; + } + /* linear sRGB if float values, standard sRGB if int values */ + avctx->color_trc = ctx->jxl_pixfmt.data_type == JXL_TYPE_FLOAT + || ctx->jxl_pixfmt.data_type == JXL_TYPE_FLOAT16 + ? AVCOL_TRC_LINEAR : AVCOL_TRC_IEC61966_2_1; + } else { + JxlColorEncoding jxl_encoding; + jret = JxlDecoderGetColorAsEncodedProfile(ctx->decoder, &ctx->jxl_pixfmt, JXL_COLOR_PROFILE_TARGET_DATA, &jxl_encoding); + if (jret != JXL_DEC_SUCCESS) { + av_log(avctx, AV_LOG_WARNING, "Unable to obtain color encoding from header\n"); + continue; + } + + if (ctx->jxl_pixfmt.num_channels >= 3) { + avctx->colorspace = AVCOL_SPC_RGB; + switch (jxl_encoding.primaries) { + case JXL_PRIMARIES_SRGB: + avctx->color_primaries = AVCOL_PRI_BT709; + break; + case JXL_PRIMARIES_2100: + /* BT2020 and BT2100 use the same primaries */ + avctx->color_primaries = AVCOL_PRI_BT2020; + break; + case JXL_PRIMARIES_P3: + /* DCI P3 uses DCI, Display P3 uses D65 */ + if (jxl_pixfmt.white_point == JXL_WHITE_POINT_DCI) + avctx->color_primaries = AVCOL_PRI_SMPTE431; + else + avctx->color_primaries = AVCOL_PRI_SMPTE432; + break; + case JXL_PRIMARIES_CUSTOM: + av_log(avctx, AV_LOG_WARNING, "Custom primaries are unsupported without an ICC profile\n"); + avctx->color_primaries = AVCOL_PRI_UNSPECIFIED; + break; + default: + av_log(avctx, AV_LOG_WARNING, "Unknown JXL color primaries: %d\n", jxl_encoding.primaries); + avctx->color_primaries = AVCOL_PRI_UNSPECIFIED; + } + } + + switch (jxl_encoding.transfer_function) { + case JXL_TRANSFER_FUNCTION_709: + avctx->color_trc = AVCOL_TRC_BT709; + break; + case JXL_TRANSFER_FUNCTION_LINEAR: + avctx->color_trc = AVCOL_TRC_LINEAR; + break; + case JXL_TRANSFER_FUNCTION_SRGB: + avctx->color_trc = AVCOL_TRC_IEC61966_2_1; + break; + case JXL_TRANSFER_FUNCTION_PQ: + avctx->color_trc = AVCOL_TRC_SMPTE2084; + break; + case JXL_TRANSFER_FUNCTION_DCI: + avctx->color_trc = AVCOL_TRC_SMPTE428; + break; + case JXL_TRANSFER_FUNCTION_HLG: + avctx->color_trc = AVCOL_TRC_ARIB_STD_B67; + break; + case JXL_TRANSFER_FUNCTION_GAMMA: + if (jxl_encoding.gamma == 2.2) { + avctx->color_trc = AVCOL_TRC_GAMMA22; + } else if (jxl_encoding.gamma == 2.8) { + avctx->color_trc = AVCOL_TRC_GAMMA28; + } else { + av_log(avctx, AV_LOG_WARNING, "Unsupported gamma transfer: %f\n", jxl_encoding.gamma); + avctx->color_trc = AVCOL_TRC_UNSPECIFIED; + } + break; + default: + av_log(avctx, AV_LOG_WARNING, "Unknown transfer function: %d\n", jxl_encoding.transfer_function); + avctx->color_trc = AVCOL_TRC_UNSPECIFIED; + } + } + frame->color_trc = avctx->color_trc; + frame->color_primaries = avctx->color_primaries; + frame->colorspace = avctx->colorspace; continue; case JXL_DEC_NEED_IMAGE_OUT_BUFFER: av_log(avctx, AV_LOG_DEBUG, "NEED_IMAGE_OUT_BUFFER event emitted\n"); From patchwork Wed May 4 12:36:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leo Izen X-Patchwork-Id: 35583 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:a885:b0:7f:4be2:bd17 with SMTP id ca5csp415449pzb; Wed, 4 May 2022 05:37:18 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzkl59LFyZ9iDxKaS/k3hYshL4xns7LJxo9zOdCQhL8UzpJhbJBygqQUu6j9H+TyqwODl7A X-Received: by 2002:a17:907:1c8a:b0:6e9:2a0d:d7b7 with SMTP id nb10-20020a1709071c8a00b006e92a0dd7b7mr19681160ejc.572.1651667838317; Wed, 04 May 2022 05:37:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1651667838; cv=none; d=google.com; s=arc-20160816; b=W3XwzUyjk/glmKPVFlQNAKw85sHb34Da/lx90g5R0KaotZ27AlRKheDzNQGl+L0Pa/ b4z6yqmx+42MeiW/kbLe5RrUdMGyzlucp/X9UbfP3netc7czpOlksUQx1RgPt2EF1ymR reaS1YPXezS3ays8EoSpSFBN7PEvKvkKeyitvixvw8k7K551v68Vy5DBmsmRKRISFmFP Cp4xHWUAME3bjCrAloLBWslM2zqMF2E1u8IVTNgbs9McswdHtqq7C+nG4jylyG2x7dvL vrvrR6y+JKd4u5h2kd6kwN4RSX5nv6ej0x1fScZxMfNqElolKdS3Be8+UI458wZngFqT UhRg== 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=6zvweKMHe5Rm90bEk80aC2wb0MY9XbAN6i7Ps9CIjvk=; b=f0WqWuTJ//2Sh0k/6XGHjRVOvxZDfqKMlz1ZqEObb9WYGcH1wSJEuZgkDEjiDKYyqA 2cMvVzSwt33SA4LxE3r2WMj/dEJfdPe1s7Wb6HE5EG0Th4K/PkAv7kic7YvnUf/dX/wV yZplUL6/CfC8JPaGQVvlAq3qc+pimEz0lmGmGssdDfjkpotac9ENJ5OchVF2yIKfKN6u +cl2dLwwpQv3QIBPoLnPppogE+wwByCKmpeZmNJapAtGxeYLSDRq8d3dNJxdNzEOctHU oqOfzhMPtptWaAhk0LUb5LNoPBfMG7+R0YMPfh/+sSRCguGUNX1aVq66sqlYS7+5ljrY ZKoQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=VIwnxjfr; 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 rh2-20020a17090720e200b006e8c13b56e5si15954166ejb.804.2022.05.04.05.37.18; Wed, 04 May 2022 05:37:18 -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 header.s=20210112 header.b=VIwnxjfr; 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 44B2168B365; Wed, 4 May 2022 15:36:57 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-il1-f173.google.com (mail-il1-f173.google.com [209.85.166.173]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id A41D568B109 for ; Wed, 4 May 2022 15:36:49 +0300 (EEST) Received: by mail-il1-f173.google.com with SMTP id t4so755267ilo.12 for ; Wed, 04 May 2022 05:36:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=8E33JMBU1eOkKb+Y42kj1ut0ZPQjTrKnjLG0Vtvf2HI=; b=VIwnxjfrSEDAEAUkn2d+HYOzAbi2AZ2qlyeaT7chiP5KMYfDH6SehxS+6BwnV7Zd4e jaKbkDjOjOU/s4sOoEwfsoIBv8k7dUTlnj6+dOW5w7LBNTK4itty1e9/ajk8DPbD5It4 TpOm2E0JsW7qvFR+pnA40lAXHBP+d2KExXMpAX4ACAlN81+m6bwkHEAUH+u6Jqj/FTIa p2MFHyR519GXzttl730kQTtnENBBU/mJN3fFfZyxXkucz4pg44kn8unBwf88Wztejkpv kRZnUqf3wpljoEFs/FoEwL0lLkag2RK8WoLjGNcesew1QKEy//MzpCO1IvyIfTWFxsj4 CW4A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=8E33JMBU1eOkKb+Y42kj1ut0ZPQjTrKnjLG0Vtvf2HI=; b=fvMkLEFWQUuMvqyXnniOWW7bxLXyEeAUy/GvKqNh1bH63/PCvYkZObVcK6sWyXNMwn jvHaORn3sxHB7MpzeDH4D9lW3p+t9in/KheEvon3Pg9nlpDmmWgWUc0pj3PAnO0Rbg3P Xq+vhyLRh/OKzkuJD/K0rz7klYjNVO69Iql/PY7rn/7aKNgpAg1XmeYJc/jFJipDrV91 ilIIHlGspMfs0IZguww//cGXZ29YIg8JyaEiNGBPZLsBnndpRHRdBDKwz0PasdmO49PL R4gv5gOfmvsjObklIGxfP4tqcNiBWqL8/k9SOTONBCY4Zwm8KZODt/Udx7OQtNKeB8Wx 453A== X-Gm-Message-State: AOAM5313gwWLejo+tja9ykFL7GTGUHtk/j2mkYQXHdCXYREH5qCvCD3p ptBMKskd/inFeOtaeFwEJEjGS5uWbus= X-Received: by 2002:a05:6e02:1e03:b0:2cf:1538:e9cf with SMTP id g3-20020a056e021e0300b002cf1538e9cfmr5879085ila.204.1651667808363; Wed, 04 May 2022 05:36:48 -0700 (PDT) Received: from gauss.local (c-68-41-54-207.hsd1.mi.comcast.net. [68.41.54.207]) by smtp.gmail.com with ESMTPSA id x18-20020a056638027200b0032b3a781758sm4660371jaq.28.2022.05.04.05.36.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 May 2022 05:36:47 -0700 (PDT) From: Leo Izen To: ffmpeg-devel@ffmpeg.org Date: Wed, 4 May 2022 08:36:12 -0400 Message-Id: <20220504123612.174661-3-leo.izen@gmail.com> X-Mailer: git-send-email 2.36.0 In-Reply-To: <20220504123612.174661-1-leo.izen@gmail.com> References: <20220504123612.174661-1-leo.izen@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v3 2/2] avcodec/libjxlenc: properly read input colorspace 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: SbCxPA3AByqh Whether an ICC profile is present or not, the libjxl encoder wrapper should now properly read colorspace tags and forward them to libjxl appropriately, rather than just assume sRGB as before. It will also print warnings when colorimetric assumptions are made about the input data. --- libavcodec/libjxlenc.c | 128 ++++++++++++++++++++++++++++++----------- 1 file changed, 96 insertions(+), 32 deletions(-) diff --git a/libavcodec/libjxlenc.c b/libavcodec/libjxlenc.c index 8bebec6aeb..43bb7299c6 100644 --- a/libavcodec/libjxlenc.c +++ b/libavcodec/libjxlenc.c @@ -117,7 +117,7 @@ static int libjxl_init_jxl_encoder(AVCodecContext *avctx) return AVERROR_EXTERNAL; } - /* check for negative zero, our default */ + /* check for negative, our default */ if (ctx->distance < 0.0) { /* use ffmpeg.c -q option if passed */ if (avctx->flags & AV_CODEC_FLAG_QSCALE) @@ -133,7 +133,8 @@ static int libjxl_init_jxl_encoder(AVCodecContext *avctx) */ if (ctx->distance > 0.0 && ctx->distance < 0.01) ctx->distance = 0.01; - if (JxlEncoderOptionsSetDistance(ctx->options, ctx->distance) != JXL_ENC_SUCCESS) { + + if (JxlEncoderSetFrameDistance(ctx->options, ctx->distance) != JXL_ENC_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to set distance: %f\n", ctx->distance); return AVERROR_EXTERNAL; } @@ -219,57 +220,120 @@ static int libjxl_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFra info.num_color_channels = jxl_fmt.num_channels - info.num_extra_channels; info.bits_per_sample = av_get_bits_per_pixel(pix_desc) / jxl_fmt.num_channels; info.alpha_bits = (info.num_extra_channels > 0) * info.bits_per_sample; + if (pix_desc->flags & AV_PIX_FMT_FLAG_FLOAT) { info.exponent_bits_per_sample = info.bits_per_sample > 16 ? 8 : 5; info.alpha_exponent_bits = info.alpha_bits ? info.exponent_bits_per_sample : 0; jxl_fmt.data_type = info.bits_per_sample > 16 ? JXL_TYPE_FLOAT : JXL_TYPE_FLOAT16; - JxlColorEncodingSetToLinearSRGB(&jxl_color, info.num_color_channels == 1); } else { info.exponent_bits_per_sample = 0; info.alpha_exponent_bits = 0; jxl_fmt.data_type = info.bits_per_sample <= 8 ? JXL_TYPE_UINT8 : JXL_TYPE_UINT16; - JxlColorEncodingSetToSRGB(&jxl_color, info.num_color_channels == 1); } - if (info.bits_per_sample > 16 - || info.xsize > (1 << 18) || info.ysize > (1 << 18) - || (info.xsize << 4) * (info.ysize << 4) > (1 << 20)) { - /* - * must upgrade codestream to level 10, from level 5 - * the encoder will not do this automatically - */ - if (JxlEncoderSetCodestreamLevel(ctx->encoder, 10) != JXL_ENC_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Could not upgrade JXL Codestream level.\n"); - return AVERROR_EXTERNAL; - } - } + /* JPEG XL format itself does not support partial range */ + if (avctx->color_range == AVCOL_RANGE_MPEG) + av_log(avctx, AV_LOG_ERROR, "This encoder does not support partial(tv) range, colors will be wrong!\n"); + else if (avctx->color_range != AVCOL_RANGE_JPEG) + av_log(avctx, AV_LOG_WARNING, "Unknown color range, assuming full\n"); - /* bitexact lossless requires there to be no XYB transform */ + /* bitexact lossless requires there to be no XYB transform */ info.uses_original_profile = ctx->distance == 0.0; - sd = av_frame_get_side_data(frame, AV_FRAME_DATA_ICC_PROFILE); - if (sd && sd->size && JxlEncoderSetICCProfile(ctx->encoder, sd->data, sd->size) != JXL_ENC_SUCCESS) { - av_log(avctx, AV_LOG_WARNING, "Could not set ICC Profile\n"); - } else if (info.uses_original_profile) { - /* - * the color encoding is not used if uses_original_profile is false - * this just works around a bug in libjxl 0.7.0 and lower - */ - if (JxlEncoderSetColorEncoding(ctx->encoder, &jxl_color) != JXL_ENC_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to set JxlColorEncoding\n"); - return AVERROR_EXTERNAL; - } - } - if (JxlEncoderSetBasicInfo(ctx->encoder, &info) != JXL_ENC_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to set JxlBasicInfo\n"); return AVERROR_EXTERNAL; } + /* rendering intent doesn't matter here + * but libjxl will whine if we don't set it */ + jxl_color.rendering_intent = JXL_RENDERING_INTENT_RELATIVE; + + switch (avctx->color_trc) { + case AVCOL_TRC_BT709: + jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_709; + break; + case AVCOL_TRC_LINEAR: + jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_LINEAR; + break; + case AVCOL_TRC_IEC61966_2_1: + jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_SRGB; + break; + case AVCOL_TRC_SMPTE428: + jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_DCI; + break; + case AVCOL_TRC_SMPTE2084: + jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_PQ; + break; + case AVCOL_TRC_ARIB_STD_B67: + jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_HLG; + break; + case AVCOL_TRC_GAMMA22: + jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_GAMMA; + jxl_color.gamma = 2.2; + break; + case AVCOL_TRC_GAMMA28: + jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_GAMMA; + jxl_color.gamma = 2.8; + break; + default: + if (pix_desc->flags & AV_PIX_FMT_FLAG_FLOAT) { + av_log(avctx, AV_LOG_WARNING, "Unknown transfer function, assuming Linear Light\n"); + jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_LINEAR; + } else { + av_log(avctx, AV_LOG_WARNING, "Unknown transfer function, assuming IEC61966-2-1/sRGB\n"); + jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_SRGB; + } + } + + /* This should be implied to be honest + * but a libjxl but makes it fail otherwise */ + if (info.num_color_channels == 1) + jxl_color.color_space = JXL_COLOR_SPACE_GRAY; + else + jxl_color.color_space = JXL_COLOR_SPACE_RGB; + + switch (avctx->color_primaries) { + case AVCOL_PRI_BT709: + jxl_color.primaries = JXL_PRIMARIES_SRGB; + jxl_color.white_point = JXL_WHITE_POINT_D65; + break; + case AVCOL_PRI_BT2020: + jxl_color.primaries = JXL_PRIMARIES_2100; + jxl_color.white_point = JXL_WHITE_POINT_D65; + break; + case AVCOL_PRI_SMPTE431: + jxl_color.primaries = JXL_PRIMARIES_P3; + jxl_color.primaries = JXL_WHITE_POINT_DCI; + break; + case AVCOL_PRI_SMPTE432: + jxl_color.primaries = JXL_PRIMARIES_P3; + jxl_color.primaries = JXL_WHITE_POINT_D65; + break; + default: + av_log(avctx, AV_LOG_WARNING, "Unknown color primaries, assuming BT.709/sRGB+D65\n"); + jxl_color.primaries = JXL_PRIMARIES_SRGB; + jxl_color.white_point = JXL_WHITE_POINT_D65; + } + + sd = av_frame_get_side_data(frame, AV_FRAME_DATA_ICC_PROFILE); + if (sd && sd->size && JxlEncoderSetICCProfile(ctx->encoder, sd->data, sd->size) != JXL_ENC_SUCCESS) + av_log(avctx, AV_LOG_WARNING, "Could not set ICC Profile\n"); + if (JxlEncoderSetColorEncoding(ctx->encoder, &jxl_color) != JXL_ENC_SUCCESS) + av_log(avctx, AV_LOG_WARNING, "Failed to set JxlColorEncoding\n"); + + /* depending on basic info, level 10 might + * be required instead of level 5 */ + if (JxlEncoderGetRequiredCodestreamLevel(ctx->encoder) > 5) { + if (JxlEncoderSetCodestreamLevel(ctx->encoder, 10) != JXL_ENC_SUCCESS) + av_log(avctx, AV_LOG_WARNING, "Could not increase codestream level\n"); + } + jxl_fmt.endianness = JXL_NATIVE_ENDIAN; jxl_fmt.align = frame->linesize[0]; - if (JxlEncoderAddImageFrame(ctx->options, &jxl_fmt, frame->data[0], jxl_fmt.align * info.ysize) != JXL_ENC_SUCCESS) { + if (JxlEncoderAddImageFrame(ctx->options, &jxl_fmt, frame->data[0], + jxl_fmt.align * info.ysize) != JXL_ENC_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to add Image Frame\n"); return AVERROR_EXTERNAL; }