From patchwork Wed May 4 12:40:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leo Izen X-Patchwork-Id: 35584 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:a885:b0:7f:4be2:bd17 with SMTP id ca5csp416960pzb; Wed, 4 May 2022 05:41:08 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxD3MOYtWeqGn+wgdfoY9p9BZK7xJLE3rtjb5+5uQ1jpGpWaIWtMCgp/soiIsjJE1XTRmYZ X-Received: by 2002:a05:6402:cb6:b0:425:f2e0:3644 with SMTP id cn22-20020a0564020cb600b00425f2e03644mr22571680edb.301.1651668068623; Wed, 04 May 2022 05:41:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1651668068; cv=none; d=google.com; s=arc-20160816; b=AixOvz2KZAGssWXFtyeJkrM9KuRWkuLmP4xnNGc8jklRnqovDmYaQRUMVMlTERZgeb 0szub8jWfR1KkYB5y36PXpKL/f6ZxpwasxAsFX+FV2pLlBPn+NDcnZS8dAMO9a7hCenz Wh5UwTLAAajZnSuG3QOHzxAw2IRCRosAxWPThUKX7vdzdySDZoSzWPzanW8TA8//+OnM tW22d5/RjXXjhVRAOSUSyC7hiCYyyoWLhcdhXYkYsSVwzGhc79JlGRWe3SlrmXeFCnIH eTByVoUCdkNrYJAtuMB2YDCyrhmu7dQprM38M89yl1EyI92VeNQVZTu0qjFnCCCxpsZN ocWA== 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=/Rcy7TXxcx+pOPZtakkmEcn9O3TvkoBX8N4lvu+a1bM=; b=NraoheCXOI0Rf3M8yU7wryfyyNhfx0EbFTQp8pWJTfTfmfkA9XjpvXtIbVm4V4BPBI QlXJDu3GVY8WadUT9xmMk4kGnKyLUUwozlfTYBxVybIZKBUUaVVxTGS02wxWlHr6f1kq GsOBjspiiR0nkTndkKd+F+k+aeJnYr80GigAYm3WvJ1LAvyya2Z7wXrmetVdkrWmtoW8 eZQoUB/+qJFvk/9zum98qvQeNsrCXSheVlyR2jbxflEVEIQQKxUQ2tEFPn86jbJkg825 aoRi4BcdDsTOPX2QdOPVs3BMbh2Ruad1pzw9KKmQMHr/5tr024uhSKVgmFfr1JvTbUrV Ke0A== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=Vs+gx3ff; 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 e5-20020a170906080500b006f37d187707si15086167ejd.41.2022.05.04.05.41.08; Wed, 04 May 2022 05:41: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=Vs+gx3ff; 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 4588668B31C; Wed, 4 May 2022 15:40:58 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-io1-f44.google.com (mail-io1-f44.google.com [209.85.166.44]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id E76BE68B28D for ; Wed, 4 May 2022 15:40:50 +0300 (EEST) Received: by mail-io1-f44.google.com with SMTP id z26so1321294iot.8 for ; Wed, 04 May 2022 05:40:50 -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=DBqbmLn64mQNef2pYFqKIeDUv/nRE5Ez4Y5xcoP1p+8=; b=Vs+gx3fffOYwfqqoY6CBisCXY1pCZ1MXgmkyyLH9QxUgHxQjHKuLA42sTTtitc1ZT8 nfdo/LV2z6KszBFKaoW69Y3WG7kv0iF+fDeDhX+sNhQbpcHZ4fDtUPLc3kx1t66qCDyl 75emDjSvFdq8Rpov0F5RBQNnLjXksQt7K2iIYmxG1G9TmeMVWEAr6Tl1aidcPyAa5qTx Rw97+5A81yaiXPaRgzNhVadjJoSTuef4boOZ461h4dtCMYruCFehYDlIcI2LUp2wwaYn DjqDzdJWOaduDO9TR/XpY5CRQ/n/Tq6AMny/aAN8iARb97WfyE/qnryCGBHgDcOdtVGu lZBg== 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=DBqbmLn64mQNef2pYFqKIeDUv/nRE5Ez4Y5xcoP1p+8=; b=rpxNnMy0LTeGr/NThEQ0tlnP9Rjeu6Zwny4jFlIYItOViooiJmxmEWgCnL7CQ2SspG +i31fNh7FGIa5iwEibepwgiutolakJ0+VDMYfgN6DZR+OZTU2vT0/2k6m465zLgFVXf7 +D/P9Jezqnvx069d1nHQJCoev9XcX83SR9EhAwV6B+dkb2TtIPvoI6M2Opse3lKEH4rT t9t+kK6LhWE7SHyy7/ut9f+o+e006k17rW62WKgou/r1hVbtJO6NOmo51TK2bjV3uBnH 9wwJM6glvKqwDmPV6hDxkSre+MF0h9D6vTzvyE3hgPyT1mP4JfP3YBFfzzs1C18Jr8Bb 3VIQ== X-Gm-Message-State: AOAM533lZ+qEdrnrZf5gmijjQkQKPx5AaO5mPMzVzJG9hb8A9sNbhueH TK2+os3TxUVLacvyECZG8HeSBaMybWk= X-Received: by 2002:a05:6638:144b:b0:321:589b:a8ea with SMTP id l11-20020a056638144b00b00321589ba8eamr9049182jad.296.1651668049596; Wed, 04 May 2022 05:40:49 -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 j15-20020a92c20f000000b002cde6e352cbsm4114456ilo.21.2022.05.04.05.40.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 May 2022 05:40:49 -0700 (PDT) From: Leo Izen To: ffmpeg-devel@ffmpeg.org Date: Wed, 4 May 2022 08:40:45 -0400 Message-Id: <20220504124046.175331-2-leo.izen@gmail.com> X-Mailer: git-send-email 2.36.0 In-Reply-To: <20220504124046.175331-1-leo.izen@gmail.com> References: <20220504124046.175331-1-leo.izen@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v4 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: 3wgctBORTZhg 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..381def8b25 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_encoding.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:40:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leo Izen X-Patchwork-Id: 35585 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:a885:b0:7f:4be2:bd17 with SMTP id ca5csp417026pzb; Wed, 4 May 2022 05:41:17 -0700 (PDT) X-Google-Smtp-Source: ABdhPJztmecJJ/bB0P+IGFb1vNQJ/u967xBeaZziTWzwnbgH6OfoeQNED5yIiXMxzpDPLy/1azxy X-Received: by 2002:a05:6402:5205:b0:427:b431:e0ed with SMTP id s5-20020a056402520500b00427b431e0edmr18988618edd.186.1651668077734; Wed, 04 May 2022 05:41:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1651668077; cv=none; d=google.com; s=arc-20160816; b=kCWGFRNgS8ql2I5gxjQGlJJzhZ8KQc2T3EHqb32U7v3Ijhzw1aLRUGIORf/wQHhpKp gfsOB0KHjJ3h1ThCh2C0bR+waeq/ICSzXcjOSrZ5wuUGbdEbD/mh3pdlNYgd0jfJ2agY DgR2zall07emcDrH4h485T9RyQwAylLMkRVZ8HnAr/L4V0+acDEZFvhqvGwt/jXN6LUP gE/LFedNvUffoW4UyYYysuX/baIWD5EUY5Aqa4YoD2SLDYwTMf5YWKBgGJZjVcr67g7u pNG7VOcEkzmEJOV84qNd34jT/xoxdGZ7b1yBbVQ/GMAsfPd8BNL2vXXaqLtW9hpuaPOg FsRQ== 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=A0j9TNOx4PJHHhvO/El+ra8M0InYWr2hlAYtp3BtOllv3Y+EN71lMV6qANOkvZK68J xUTjFnPnxW16EdWdf6mz+82W4raOKdQAEmEVHtR8aCk7uT5T8IX91PuT0X+Fwj5tYRwm TOHziHmN8B6ggOi5Dgqid/7sI4e47R7a3uHtItxBlgXpgxU5A5JjoIEdGVrKAVYRVIm7 k8KPsJZgL+HNwkucEzoHhnAmdc04V6M8ca1apzwQmDTfkm/z+zA557Uw8RCvZZfHbEPd INjtGn4zk9ZxX9iKtKYTKLwZr0fCpzwe5yaWjsJecbWx+ltT9gvxMpk1u7PLRHV9Y9M7 3bBQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=dlcBVe2k; 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 yz13-20020a170906dc4d00b006e89f35bd27si15764927ejb.874.2022.05.04.05.41.17; Wed, 04 May 2022 05:41: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=@gmail.com header.s=20210112 header.b=dlcBVe2k; 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 37FD368B36E; Wed, 4 May 2022 15:40:59 +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 C9B8C68B28D for ; Wed, 4 May 2022 15:40:51 +0300 (EEST) Received: by mail-io1-f52.google.com with SMTP id c125so1319195iof.9 for ; Wed, 04 May 2022 05:40:51 -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=dlcBVe2kB48o7Ll8Jz+dxSC6eQknDUeFfgE4zAbEnNS/Pn1N6rarc6nOdkwFDmE8vV kPLPmEAcQidyT6GcNo9igWsXiKvCoE4d/yhI5/1TPJmfuzD7+FMXTTHwgQpv7ZvjkFoA S0j5pKOcILG7EvczP7iFOa7GMf/d7bW97wJu+PMrsGhheQ4TMhO7/azUb6bdq2+BoLdI WcHXtEti0ol7oBbv24zhVPnuPanoSL55ZEVq16xMVJfszh1/RfliQcijFTU/dciZVZ+f iIpL56+YKahwGtz9mJyh3PTPC3BSH1WOS5ROFTETinEgkSwVjTgmXlOizP2yqKsDw88R KEZA== 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=6Yws5WLKEV5mdCXSQ4kG+LsSDdmyEIY7jI1ShHS787UYp8+YtOG+pL0Xhfei4auj5n t30OlzVQEbuuGFj9VkCW09pjoZ0QXR2FBp60NQTQFUZVlSDLUAy2PG8sjjOWWvv4BGS7 apvMLn6c9rKuxNq6lES1dF5LiYC5tCGon5V2tzxhsC5eAnVbNo2VZ9lIlOjfb+q3Xngo 2XauT31d/P9aGW3qhMI7URKXb7LMTzHVleAtd0lFfIZiuiMPY+w1QQXHi39CXhR7RN8S kM+WcUUZNWglHHmfQmtmfYfnKVlxRssboC+TkW731y+jy2BTMpVEwiCKUYcVPgQIsWM3 S9Pw== X-Gm-Message-State: AOAM533SOnsJVl98b39bZVYJQtXxhpPNjWCgNR6GRg7dPaCQOXCZITmd WylEQNQbayppJR/XzECUKAmUXhWrNR4= X-Received: by 2002:a5e:dc06:0:b0:657:b4c5:5fe7 with SMTP id b6-20020a5edc06000000b00657b4c55fe7mr8222337iok.162.1651668050433; Wed, 04 May 2022 05:40:50 -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 j15-20020a92c20f000000b002cde6e352cbsm4114456ilo.21.2022.05.04.05.40.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 May 2022 05:40:50 -0700 (PDT) From: Leo Izen To: ffmpeg-devel@ffmpeg.org Date: Wed, 4 May 2022 08:40:46 -0400 Message-Id: <20220504124046.175331-3-leo.izen@gmail.com> X-Mailer: git-send-email 2.36.0 In-Reply-To: <20220504124046.175331-1-leo.izen@gmail.com> References: <20220504124046.175331-1-leo.izen@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v4 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: xDl3nIr1I2Jt 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; }