From patchwork Tue May 3 16:56:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leo Izen X-Patchwork-Id: 35580 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:a885:b0:7f:4be2:bd17 with SMTP id ca5csp518641pzb; Tue, 3 May 2022 09:57:51 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzegCgj/TeKmli8EipR1K8RUasPO6RyMB12PD+7Jo5R4nzZhTkVkR5SzmZwFL0VwEvBQUwv X-Received: by 2002:a05:6402:2204:b0:426:34f1:1d2d with SMTP id cq4-20020a056402220400b0042634f11d2dmr18820369edb.335.1651597071375; Tue, 03 May 2022 09:57:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1651597071; cv=none; d=google.com; s=arc-20160816; b=bpWlIwqf2CxRqVgtha0MnWZ9XsHcnU85TnaGQ/6dOmtZ2D3QE/j9wjYvkSJ2FCcI7l fVpfUGvUYSNMsNmB2UMV0zDltzPaILripF/RYvIERmK6Dot84YF3XwFf/JaQP/XL8TP/ wiU0xSFjM22OI0iqph4xuuD/VC1+mNqexP4fPANhCnbSFqcNvpQCA7jWZQtpxcs0zhD+ G/4cJ1duR+xdFv39fBCVdm9cwlJH2TwI3WY7BRjx9PwRuPClhYmwEpLaP3uC34OlFR90 iEeuyt3cP1hEG4Yzze/L0dSKZgEDH9H+4PWKbiSxeJkcL14Iwh5DG/1NBSG0sCl7MilL auBA== 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=RO+Miow/RMzg8W906v+KcHQhNzlmuYV9PcUMuKzVC84=; b=EHbeiuXtJRGVGkGK7WpJUTlMk+NaP0yxMksyRk1vtRScwW8KvHDKVhweJgU9/u+uKJ yWEk//XCICWCEmalRvFO9OO+ujwFCXFmPPKLbMxMxdgplvNK/y7b8O1OXEuV5mPcsbLO ZaG/Z8c/eSMb/yMhzNF0GeXMX/ibNmYDKOPQTwDK/6tJyJUL40Rx6embvbNJrEeYozmT UHIcQGZPf7LWqBVeyjVXjqEc6jtDD3vU4MPgtsRHcm1VkDYfT5ULEHBRt18WBb3ioTP1 V7ap0th9nlAbwlGJPXSqZ9kz5mLjSFiv8d3gYG5WNjozmRM0Q5xNim54iJSyzaUjgg+R FIaQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=EgrsqE4N; 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 n19-20020a1709065e1300b006f39657d6c2si14210169eju.783.2022.05.03.09.57.31; Tue, 03 May 2022 09:57:51 -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=EgrsqE4N; 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 7577C68B322; Tue, 3 May 2022 19:57:09 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-il1-f176.google.com (mail-il1-f176.google.com [209.85.166.176]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 8EB4768AC91 for ; Tue, 3 May 2022 19:57:02 +0300 (EEST) Received: by mail-il1-f176.google.com with SMTP id t4so10120279ilo.12 for ; Tue, 03 May 2022 09:57:02 -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=lDo3pzAMhpJjTfOXbToFBi6t+9MTpKwoXdTsD9XieIs=; b=EgrsqE4NgPkkPCYtMPLvT04fzPlvEeX/7v3yG4pKMo1MsY0oEj4YbW4zzL5XrxgiIl hVx7b9ATSkHaGswsxOPUBZyfz0v/0QcAT3y5tNbDLuTM2nYOZ7p7AfnkG4TWyC/Jl/Rn 7nQ/5nKwEZPWfLmQVNBUnnnOh6kcKz0yMuHgRJDH64wLqB5oRckdiBujoM0NfpDLnlv7 vb1Kjok7ehxLnLS77agzBu/u7NcH75oAyjUR9fDUejtwlMgJpjnCu3KzDi3Qvd6bm90u VmGTj2xbOtNlrWSOiVAvtcohRmnD9aO7d1cUATNyc5ItTQyak0O4n14vz9eb/e77BpSt 8Vbw== 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=lDo3pzAMhpJjTfOXbToFBi6t+9MTpKwoXdTsD9XieIs=; b=HQ9fnDDhUsoG/Ayas1hDUf+Dr7kDIn3TjageTtJyr7JnduEqtJlwz2Dma+lbhd5MtY qvGSn+Ofx1eZquEk9gqDXad/Mm+LommcqTH146BFvsu9YGyY9r89T0bcx8qvH4HWSJSg 5/Z6yjnlP5tnG721Olhe8IWWCAeKzq26daCHVantrF5unfOc735srLIUlAX0yCEqGjZU QDcj0Czr1JPoEuwxmYglEJTFWN4lS5AdrtrlVDeZnZXr/mu5zi4GabO6MbBBxayZJAYX Tmx2OlwnUREZuRkW4Yv7e/1hI2W5Ymo7XjdAIyqzJ8cQhv82X5UoWTKPD/+RdYTIfN3/ hBHg== X-Gm-Message-State: AOAM5328dLowJRx4S6a6it20zC6Z6stuJ94SsF5afx5OnIujY/k3FPa2 hB+jstgvWZuqeah++B3UMLbX+c9VJLU= X-Received: by 2002:a05:6e02:1bef:b0:2cc:5948:f432 with SMTP id y15-20020a056e021bef00b002cc5948f432mr6863827ilv.183.1651597020759; Tue, 03 May 2022 09:57:00 -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 y16-20020a056e020f5000b002cde6e352d9sm3578815ilj.35.2022.05.03.09.57.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 03 May 2022 09:57:00 -0700 (PDT) From: Leo Izen To: ffmpeg-devel@ffmpeg.org Date: Tue, 3 May 2022 12:56:37 -0400 Message-Id: <20220503165638.138718-2-leo.izen@gmail.com> X-Mailer: git-send-email 2.36.0 In-Reply-To: <20220503165638.138718-1-leo.izen@gmail.com> References: <20220503165638.138718-1-leo.izen@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v2 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: UFhkMO+EJ0Ct 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 | 84 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 3 deletions(-) diff --git a/libavcodec/libjxldec.c b/libavcodec/libjxldec.c index cd4bca3343..e6a46288a6 100644 --- a/libavcodec/libjxldec.c +++ b/libavcodec/libjxldec.c @@ -189,16 +189,94 @@ 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: + avctx->color_primaries = AVCOL_PRI_BT2020; + break; + case JXL_PRIMARIES_P3: + avctx->color_primaries = AVCOL_PRI_SMPTE431; + break; + case JXL_PRIMARIES_CUSTOM: + av_log(avctx, AV_LOG_WARNING, "Custom primaries are unsupported\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: + 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 Tue May 3 16:56:38 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leo Izen X-Patchwork-Id: 35579 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:a885:b0:7f:4be2:bd17 with SMTP id ca5csp518589pzb; Tue, 3 May 2022 09:57:44 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwkcTk87nzjzIpg/bMhLbeWgwGDsmzDBk3Q4FNjPBhiMreTUg789tgxlVvZEeNOSYP0xuD8 X-Received: by 2002:a05:6402:1385:b0:413:2bc6:4400 with SMTP id b5-20020a056402138500b004132bc64400mr19285875edv.94.1651597063936; Tue, 03 May 2022 09:57:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1651597063; cv=none; d=google.com; s=arc-20160816; b=pZ9AuRGxCRz0d5h8QPIMIxk4zDxFpVRaqd0xpK1t0PixEsZq6r2mbdJubN5GjiF1qd 0D/WWaCqAl0XTTsyVehkzCg7QEdlWx59k4dGK9mZ8Zu2WWZpALXIQdlmDYRz1IhN8Vzi 4RQpFgtuiUjUcryM7nwQSKi7ydc1cuoLIRg+Roi/6WMTb5H+MxLcONeVpyEX0SqeLGf+ Mr4WutC5OXcahCd2owvAMht2URJI6+ky5bXKWFjxcJI8aw+S6zETFYTuVKYZ1kSQw7Xp kTZ2hD29VfsfrvM+MYaN4BUNtrFWHgBrxDX3s5K2NIankz90lqIj33ctoY5O1hQMuVBR LTKQ== 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=MRJuqO34QBzny50EHm439vu6PxAWApl1iy8BuMbxZow=; b=CJPlkC9/NbXAJRg4vebsQJLavFkFGiHcWgO+WE/RUIgsMbJbbWtosz++IAcUkCLaXL txnKDkPBmO39gazXx+iu0zC3yQr8hpI/cFqMVproiDBSNNCuchrw6fqjClxlkGz8dpso LrjD5BWPOQyIMtTkZLjPNEuANR6QhnbKARER5s3qjgGhoyoAII4FUFj5jGbHPcZ3VM5H MF/2CA5YuDa4q7IWfZ1jjTqf9j/jeaYrnqH2e3iYPVJfd9On2/WC13p5GSmH/vi369wl r9Mxxx/jM1SAO5gFCX2CL7eVrxpqUNmnEgvSgZbdYwdZL/63jq4qV4khiR7HQyjdO+Bk hRBw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=FrrlEYyj; 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 h22-20020a1709060f5600b006e8c21ffdc7si6056816ejj.221.2022.05.03.09.57.43; Tue, 03 May 2022 09:57:43 -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=FrrlEYyj; 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 767B168B3DD; Tue, 3 May 2022 19:57:10 +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 F1FF76806F5 for ; Tue, 3 May 2022 19:57:02 +0300 (EEST) Received: by mail-il1-f180.google.com with SMTP id t4so10120290ilo.12 for ; Tue, 03 May 2022 09:57:02 -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=SPLWGWL0AsNC2IptirQsLuN0pxnwbmfc7JEmPOgirko=; b=FrrlEYyjubctW/GGppOndDjaY4WHZBFBEB7ayYGIdGXD2yV52ZBCRebWy1zJTbfveZ EuLrqMN1TMDC+VKfE72NAp2X1PPCR4dd67tmmgPbT1IGa9l2v1c2Unsdi8AXY0x5UMK2 62r3egHUXFiXd+rMKh/HhtJsCBQqU5A3bG2c2FnygCqwTNvOUhq4a9NlxrZEq+gm/QOE qMfAyy/NW20IgzrL/G0H58nZrwDujuehBl7HlNIuTthBBpjtX/WbogxBaVkwGYnYe6f7 lqZ4ds3a4X7c1uom0ubYGStXZzuCYdfd1B0SDeHh1tUlApyuCmiORZ/rpwzsOoXevNwA zwYw== 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=SPLWGWL0AsNC2IptirQsLuN0pxnwbmfc7JEmPOgirko=; b=bVDQj/2dq6LfgcO2nVw7vs4mvexjWpTqSInkyM4KeZWFsMhKZLsAulGNfM8hsHfayL E7txFo513Fi9jYM2c9Qps/sAEsQRTX9DqMK7d+86IuaYJqi+KZeuqfKA2ukrshZwOdDQ /O7OdLuQS6JzOJqsJw6Pl/Plfz0sdLciKeFt6yBNM/SqqrkiHkbwRHVrtBha639EWkY9 KMRY90mB/xJMMYearD5bibopV4QNF3eTDzctN966Fx1Efb9gnPIp80DDFvjpN2t7MboM bF7IkVTMqCZTEUGT/O9FgzVtMcHAeoHWeoilR0kp662q+MlibBbKJ9/0eZuCI67i+aoM +8kw== X-Gm-Message-State: AOAM533SmhB27iiwnhJRKWbt3d1I0U2Ez6AECgqbQ0L4hwWMhTgNgtKv rpVLSTJj8nEcqo2bu9eM+9VQEQwu2FA= X-Received: by 2002:a05:6e02:1487:b0:2cd:82ae:5e13 with SMTP id n7-20020a056e02148700b002cd82ae5e13mr6517399ilk.29.1651597021340; Tue, 03 May 2022 09:57:01 -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 y16-20020a056e020f5000b002cde6e352d9sm3578815ilj.35.2022.05.03.09.57.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 03 May 2022 09:57:01 -0700 (PDT) From: Leo Izen To: ffmpeg-devel@ffmpeg.org Date: Tue, 3 May 2022 12:56:38 -0400 Message-Id: <20220503165638.138718-3-leo.izen@gmail.com> X-Mailer: git-send-email 2.36.0 In-Reply-To: <20220503165638.138718-1-leo.izen@gmail.com> References: <20220503165638.138718-1-leo.izen@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v2 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: Hw3n75OFBqZF 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 | 124 ++++++++++++++++++++++++++++++----------- 1 file changed, 93 insertions(+), 31 deletions(-) diff --git a/libavcodec/libjxlenc.c b/libavcodec/libjxlenc.c index 8bebec6aeb..e176435529 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,118 @@ 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_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; }