From patchwork Mon May 9 13:43:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leo Izen X-Patchwork-Id: 35700 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:a885:b0:7f:4be2:bd17 with SMTP id ca5csp2942876pzb; Mon, 9 May 2022 06:44:36 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwEiI3MxziEJyrVgUAHTCXNQAfYi+yaBeP54kz27+lTLE2AIi1siLSLbyD84jA4uFrohovh X-Received: by 2002:a17:906:6546:b0:6f5:fc1:e8c0 with SMTP id u6-20020a170906654600b006f50fc1e8c0mr15490685ejn.554.1652103876191; Mon, 09 May 2022 06:44:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1652103876; cv=none; d=google.com; s=arc-20160816; b=wmvXiqIPmzVM6/KJ8eglqPEM5kNhV/Zc9oAE2d3qMFCa5IVAHFddJD2MZtSPGQOGjz DAEKUz3r4YDXoGp+H/wbXEOgSJWKLgj6Z2MithN6JG7yjXQdhll0nj6XboX6rJ8yKqDc 3YrkUxhgv4bsC9UJtAjzzCLs5Uy8WaQeQzelZz6vJB5poh5ha2ChYfZA7Kt7v7XrPNGX fZIEvQ8UDIuNIc5M85rT5CpQ9MVbihi9bMh2ix4QYrTEmaaWK8MNzstd7O3zANadiivK c/0sAkdcGj/MW5h8JsGA+ZeU/jQuQ3Oi19NHwfmbkRHXoKLf2gDwXn1XDzGsXiFJpW8B zLJg== 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=O/j8MTPkYw3ixUPQL4gUpcSr1oF0oo9i0J+D431OfsM=; b=y9xEAiTOSVcOIqP1hVxu08kPdNksra/Ns/quNTLds1XaAcrouOHeHigj8QcHITydq4 8v6dTq2UHMBcUWo5Nb8keR2Twv3wJUnIQ/Gr9atKDYnbmWyZ7xTYCnYxgegBey7Wydbi A566YmUTu+Mx78oEAO0dgYpugjjHSdmbMyH/BqAB3SMIWajaoOu+WxU8Kw55Fr5Dt6iH G5sMimy7Oe+bxO1YXCVygih5BX+zynu3p7v80tyKoLvoj3l3zFupxH0Ca+ugi4ABYZH6 15L2UIjQD4d03NGjEvQ0Ft9uSBfQkec+3n7f2WdNLOzu2/eyI4MpOEx+3fl2cj5RzJRL ZBbA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=XM+2oksC; 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 h10-20020a05640250ca00b00425d8c74949si14985057edb.417.2022.05.09.06.44.35; Mon, 09 May 2022 06:44:36 -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=XM+2oksC; 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 7EB9C68B3CA; Mon, 9 May 2022 16:44:21 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-io1-f52.google.com (mail-io1-f52.google.com [209.85.166.52]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 6B7CA68B3B5 for ; Mon, 9 May 2022 16:44:15 +0300 (EEST) Received: by mail-io1-f52.google.com with SMTP id r27so15329833iot.1 for ; Mon, 09 May 2022 06:44:15 -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=F99bcs+s+87OLo73egEeJGe3P2JILSiIbS8yphrR53g=; b=XM+2oksC8zt12XZCcQyOmdln2BCpIg58dDX/+MEAXz/20nGSrwbq2BJ8LslvEIoz4a XWrI3TyQcA3bLVZKw7HFu3qgOOoLLJCyvsk72teLYnEzjFSBYO3e6yB5aKbOj1P3RjAV hb7uyODNuIRVCre/skIwAKVXTANkbNq3HK/EC5Q2+Q0W/wKeA9QqhRwK0zQEgmsZvR4k VAhqwfruTxjzzC4pmJtldHUg+0NKmHms+7vrdEJrFSJbDbIqh5cKCtDZdN75qehnfOuH b0JijB/crSkydBlVxg7gPmNxhatJdIeq4/LhfYFleh75TiXNqwqQfBrLPkvVzrMs919l ov4g== 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=F99bcs+s+87OLo73egEeJGe3P2JILSiIbS8yphrR53g=; b=JwcRoB1hlmMyG+vWhCd0TJFsvwofODsmVRzYrN3q8s+QwbJzQPG5pPB1h4gu0cgwiD rvRzHpd5xl+FgoJoA6QcFVlNSRusGcWihsucjzUPRiPgW7dZQUPCdi50dWgjNWVZ88NE uqDA6r20MTyGOLa5WT3GSfKkU3g0w3apKB346qsqkmhrcs1uqjh/iwtPQAaz7E8LF+Gn 5MHAeyc/oEBxuAjhdy9lffiidpr+LMaHQYJNwUJ85GJceBK1F7BPYdelKRy0ZJBARv0c 3oi9FRgDOmqmxxYhLLOBXu1dI0DWS1d9WF6FGcQ3Mk5R/x6zgLMC+yMdSM8+r/sBFRor N9JQ== X-Gm-Message-State: AOAM532T7KIFJcuNtrqzu1/WqtBcKT8FEzeDFFw1+gFplNNb0UJqZULP P0uz04OXyLS8MGTZo5Y1n5rfdopC/mk= X-Received: by 2002:a05:6638:24cf:b0:32b:6bd0:7f82 with SMTP id y15-20020a05663824cf00b0032b6bd07f82mr7879785jat.80.1652103853788; Mon, 09 May 2022 06:44:13 -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 r8-20020a92ce88000000b002cde6e35300sm3098448ilo.74.2022.05.09.06.44.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 May 2022 06:44:13 -0700 (PDT) From: Leo Izen To: ffmpeg-devel@ffmpeg.org Date: Mon, 9 May 2022 09:43:54 -0400 Message-Id: <20220509134355.83745-2-leo.izen@gmail.com> X-Mailer: git-send-email 2.36.0 In-Reply-To: <20220509134355.83745-1-leo.izen@gmail.com> References: <20220509134355.83745-1-leo.izen@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v6 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: uMOU2BBuk7Lb 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 | 113 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 105 insertions(+), 8 deletions(-) diff --git a/libavcodec/libjxldec.c b/libavcodec/libjxldec.c index cd4bca3343..813ee279fe 100644 --- a/libavcodec/libjxldec.c +++ b/libavcodec/libjxldec.c @@ -135,6 +135,7 @@ static int libjxl_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_f uint8_t *buf = avpkt->data; size_t remaining = avpkt->size, iccp_len; JxlDecoderStatus jret; + JxlColorEncoding jxl_encoding; int ret; *got_frame = 0; @@ -189,16 +190,112 @@ 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); - 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 = JxlDecoderGetColorAsEncodedProfile(ctx->decoder, NULL, JXL_COLOR_PROFILE_TARGET_ORIGINAL, &jxl_encoding); + if (jret == JXL_DEC_SUCCESS) + jret = JxlDecoderSetPreferredColorProfile(ctx->decoder, &jxl_encoding); + if (jret == JXL_DEC_SUCCESS) + jret = JxlDecoderGetColorAsEncodedProfile(ctx->decoder, &ctx->jxl_pixfmt, JXL_COLOR_PROFILE_TARGET_DATA, &jxl_encoding); + + avctx->color_range = frame->color_range = AVCOL_RANGE_JPEG; + + if (jret == JXL_DEC_SUCCESS) { + 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_encoding.white_point == JXL_WHITE_POINT_DCI) { + avctx->color_primaries = AVCOL_PRI_SMPTE431; + } else if (jxl_encoding.white_point == JXL_WHITE_POINT_D65) { + avctx->color_primaries = AVCOL_PRI_SMPTE432; + } else { + av_log(avctx, AV_LOG_WARNING, "Unsupported JXL white point: %d\n", jxl_encoding.white_point); + jret = JXL_DEC_ERROR; + } + break; + case JXL_PRIMARIES_CUSTOM: + av_log(avctx, AV_LOG_WARNING, "Custom primaries are unsupported without an ICC profile\n"); + jret = JXL_DEC_ERROR; + break; + default: + av_log(avctx, AV_LOG_WARNING, "Unknown JXL color primaries: %d\n", jxl_encoding.primaries); + jret = JXL_DEC_ERROR; + } + } + + 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); + jret = JXL_DEC_ERROR; + } + break; + default: + av_log(avctx, AV_LOG_WARNING, "Unknown transfer function: %d\n", jxl_encoding.transfer_function); + jret = JXL_DEC_ERROR; + } + } + + /* fall back on ICCP if enum values fail */ + if (jret != JXL_DEC_SUCCESS) { + 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_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); + } + } } + + 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; + } + + 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 Mon May 9 13:43:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leo Izen X-Patchwork-Id: 35701 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:a885:b0:7f:4be2:bd17 with SMTP id ca5csp2942949pzb; Mon, 9 May 2022 06:44:44 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzBBkSXQNo2PtruPd25D8kW5vgs/o7kD6Jiw4rqS+n0tI2Uag2eVbRrYe9GzaTaeqy4bHOp X-Received: by 2002:a17:907:1c87:b0:6f0:29ea:cc01 with SMTP id nb7-20020a1709071c8700b006f029eacc01mr14591342ejc.671.1652103884625; Mon, 09 May 2022 06:44:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1652103884; cv=none; d=google.com; s=arc-20160816; b=ODKKS+SXAdORAmX/SiaDIRDbt3hO3xx3Yaaaj0aBjBV0gb4t8mxFie82axEfKvqnD1 Qtoqjz24WJJroa4K6CX25Fv632HRNumtkljpCHBFZ4vykpkBh8a/FqBr+1RjaKDF3Rah dIY/fDfO+amYHfDg8oRFBTclaWCl8gUM5e6Dn1HHyQIQLRR6Ootze8iNQoVOtmCjXjJR QEnpzF/ZsfGPDG1k641YO0f0apUcz1Glby00B8x5GR+BgkqyeIV2IRVR5rYrPeN2j8j2 Bh12LAGCnN6J7/VwAbBe96XOiXXosCl8aRo1+fP1tklAD2yTOuCUs8R0YdoBbBhpCoNd /8Qg== 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=ANDhXya3BklTeGT8y4lWC6JC6+7zbbpHy+KYIkniJfg=; b=umwrEAR6g6x9MBRAqV3B7aQqfXV6P/Vee77XCamVoM5CIHqgMIA2DnCobT7fW4Xqjp /HrP/GVzbvf6aJYCbXWjlqhwrppfLeJtkFxaEiabZpHLO/Y07u2QH2i2ElSKqyxPNEm6 caLkY5w3LzbucWpEpqiCX9fduJ4eSUuz0OdhvY5b9xJpwlMn1ot4OfQ2dwOyff50p9x4 fW4jtphMj+i30Z/uwqw1ynq7Brxxn1k7QuCNSkjQrAiTFLRPGVuHj/aemSuFQl+G1daO zwLsOzVDMkz0KwTAdb66ecrMJxxjuVHHXqFtG9xlLf/YKZpSI7ZBmzf/+bdwCokjB8of NJlw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=ntTjp130; 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 g1-20020a170906198100b006f3fd7b244fsi12221495ejd.102.2022.05.09.06.44.44; Mon, 09 May 2022 06:44: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=@gmail.com header.s=20210112 header.b=ntTjp130; 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 7EC5068B3A7; Mon, 9 May 2022 16:44:22 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-il1-f174.google.com (mail-il1-f174.google.com [209.85.166.174]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 9B75E68B3B5 for ; Mon, 9 May 2022 16:44:15 +0300 (EEST) Received: by mail-il1-f174.google.com with SMTP id f5so9293872ilj.13 for ; Mon, 09 May 2022 06:44:15 -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=MtMuKzoadrPIV8Brv1IgW+EwCA+yHPI3qMQoQ+Dj1S4=; b=ntTjp130Jx/Yt+zn21OSY71camCGQ8l4BoRWpUcej7hLpQ25gAKsm8OGEsxFBO6gPb 5Ziv6Lh57JQRZaLkgOrWEqc+841B4DgKr0v4FVKNFUctief65pRfziRPFDTiIIQpApSg MJ1xJqXSNFEhJ3ErEcbxjw8CPSSbyEF7s+87Zo3iX1Yj1ph+RA3dpDRD8PnoFihbiJBO 60AFSd5O2U7s1Yd4rC2EUsPPds2PFob5AzSswWHWlIhBZuB4B3qMC4H7WLM0fWml7rhl khkSuD6ponzl0264HvN5X4NvIK9j7kWMs4WjrujumCdu2R87JWVCH6y3+0COKHRJihyX LElw== 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=MtMuKzoadrPIV8Brv1IgW+EwCA+yHPI3qMQoQ+Dj1S4=; b=HWYVbNlNznkZskInTbbJpQQ+y1ZokggR+A1TwF9kYfoGwkeh4RZfL89r1+jVDcf7SR s8zTcNpF63YPur1PkmugSkeVtrJDTHmCF5tvg4lYXNa1wP3S+o4h3VLmDtpwbdBIiO8s UfUj9YFMkIHVOO3GbL7ahzJU6he+c33zvdcxkxrU8jhLaMs4klFmGsKoGgUlGNH1qUGg 6kwny2OrhpihHmiTd9UAS/WvfQzukXcJROZX6o0C7hadlzliUbHcbZEwL0SrlxEceCar eLdfeVW855iJe5UWQ1Qp7SAZNVgCki9tNjFGwsT5nmMZZgXCVDltWsjBy0gcTJ5La9+0 l7aQ== X-Gm-Message-State: AOAM530bJjVl1SilyEOBpD0CskT/MQ6YqaFj7yKi8ARXRRdomTWXiv30 CxyIDF5s6NYb0ndmwz1bKOUOAbxZLUQ= X-Received: by 2002:a05:6e02:18cf:b0:2cf:51d1:f694 with SMTP id s15-20020a056e0218cf00b002cf51d1f694mr6885411ilu.310.1652103854347; Mon, 09 May 2022 06:44:14 -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 r8-20020a92ce88000000b002cde6e35300sm3098448ilo.74.2022.05.09.06.44.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 May 2022 06:44:14 -0700 (PDT) From: Leo Izen To: ffmpeg-devel@ffmpeg.org Date: Mon, 9 May 2022 09:43:55 -0400 Message-Id: <20220509134355.83745-3-leo.izen@gmail.com> X-Mailer: git-send-email 2.36.0 In-Reply-To: <20220509134355.83745-1-leo.izen@gmail.com> References: <20220509134355.83745-1-leo.izen@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v6 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: r8vMuswqzn3J 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, 94 insertions(+), 30 deletions(-) diff --git a/libavcodec/libjxlenc.c b/libavcodec/libjxlenc.c index 8bebec6aeb..4c7c838018 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,7 @@ 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; } @@ -223,49 +223,113 @@ static int libjxl_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFra 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 || + avctx->color_range == AVCOL_RANGE_UNSPECIFIED && frame->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 && frame->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 */ 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 && avctx->color_trc != AVCOL_TRC_UNSPECIFIED + ? avctx->color_trc : frame->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 && avctx->color_primaries != AVCOL_PRI_UNSPECIFIED + ? avctx->color_primaries : frame->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];