* [FFmpeg-devel] [PATCH v9 0/2] libjxl Colorspace fixes
@ 2022-06-24 16:50 Leo Izen
2022-06-24 16:50 ` [FFmpeg-devel] [PATCH v9 1/2] avcodec/libjxldec: properly tag output colorspace Leo Izen
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Leo Izen @ 2022-06-24 16:50 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Leo Izen
Changes in v9:
- Minor cosmetic changes, as requested by Anton K
- More liberally commented casework, a.r.b. Haasn
- Structured flow to be a bit more readable
Changes in v8:
- Use avutil/csp for both encoding and decoding
- Handle the non-XYB case with an attached ICC Profile on decoding
- clean up some code and segment it out to static functions
Leo Izen (2):
avcodec/libjxldec: properly tag output colorspace
avcodec/libjxlenc: properly read input colorspace
libavcodec/libjxldec.c | 214 +++++++++++++++++++++++++++++++++++++----
libavcodec/libjxlenc.c | 153 +++++++++++++++++++++++------
2 files changed, 320 insertions(+), 47 deletions(-)
--
2.36.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 5+ messages in thread
* [FFmpeg-devel] [PATCH v9 1/2] avcodec/libjxldec: properly tag output colorspace
2022-06-24 16:50 [FFmpeg-devel] [PATCH v9 0/2] libjxl Colorspace fixes Leo Izen
@ 2022-06-24 16:50 ` Leo Izen
2022-06-24 16:50 ` [FFmpeg-devel] [PATCH v9 2/2] avcodec/libjxlenc: properly read input colorspace Leo Izen
2022-06-24 17:33 ` [FFmpeg-devel] [PATCH v9 0/2] libjxl Colorspace fixes Niklas Haas
2 siblings, 0 replies; 5+ messages in thread
From: Leo Izen @ 2022-06-24 16:50 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Leo Izen
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 | 214 +++++++++++++++++++++++++++++++++++++----
1 file changed, 197 insertions(+), 17 deletions(-)
diff --git a/libavcodec/libjxldec.c b/libavcodec/libjxldec.c
index cd4bca3343..d516d3b0ac 100644
--- a/libavcodec/libjxldec.c
+++ b/libavcodec/libjxldec.c
@@ -27,6 +27,7 @@
#include "libavutil/avassert.h"
#include "libavutil/buffer.h"
#include "libavutil/common.h"
+#include "libavutil/csp.h"
#include "libavutil/error.h"
#include "libavutil/mem.h"
#include "libavutil/pixdesc.h"
@@ -92,7 +93,7 @@ static av_cold int libjxl_decode_init(AVCodecContext *avctx)
return libjxl_init_jxl_decoder(avctx);
}
-static enum AVPixelFormat libjxl_get_pix_fmt(AVCodecContext *avctx, JxlBasicInfo *basic_info, JxlPixelFormat *format)
+static enum AVPixelFormat libjxl_get_pix_fmt(void *avctx, const JxlBasicInfo *basic_info, JxlPixelFormat *format)
{
format->endianness = JXL_NATIVE_ENDIAN;
format->num_channels = basic_info->num_color_channels + (basic_info->alpha_bits > 0);
@@ -129,11 +130,199 @@ static enum AVPixelFormat libjxl_get_pix_fmt(AVCodecContext *avctx, JxlBasicInfo
return AV_PIX_FMT_NONE;
}
+static enum AVColorPrimaries libjxl_get_primaries(void *avctx, const JxlColorEncoding *jxl_color)
+{
+ AVColorPrimariesDesc desc;
+ enum AVColorPrimaries prim;
+
+ /* libjxl populates these double values even if it uses an enum space */
+ desc.prim.r.x = av_d2q(jxl_color->primaries_red_xy[0], 300000);
+ desc.prim.r.y = av_d2q(jxl_color->primaries_red_xy[1], 300000);
+ desc.prim.g.x = av_d2q(jxl_color->primaries_green_xy[0], 300000);
+ desc.prim.g.y = av_d2q(jxl_color->primaries_green_xy[1], 300000);
+ desc.prim.b.x = av_d2q(jxl_color->primaries_blue_xy[0], 300000);
+ desc.prim.b.y = av_d2q(jxl_color->primaries_blue_xy[1], 300000);
+ desc.wp.x = av_d2q(jxl_color->white_point_xy[0], 300000);
+ desc.wp.y = av_d2q(jxl_color->white_point_xy[1], 300000);
+
+ prim = av_csp_primaries_id_from_desc(&desc);
+ if (prim == AVCOL_PRI_UNSPECIFIED) {
+ /* try D65 with the same primaries */
+ /* BT.709 uses D65 white point */
+ desc.wp = av_csp_primaries_desc_from_id(AVCOL_PRI_BT709)->wp;
+ av_log(avctx, AV_LOG_WARNING, "Changing unknown white point to D65\n");
+ prim = av_csp_primaries_id_from_desc(&desc);
+ }
+
+ return prim;
+}
+
+static enum AVColorTransferCharacteristic libjxl_get_trc(void *avctx, const JxlColorEncoding *jxl_color)
+{
+ switch (jxl_color->transfer_function) {
+ case JXL_TRANSFER_FUNCTION_709: return AVCOL_TRC_BT709;
+ case JXL_TRANSFER_FUNCTION_LINEAR: return AVCOL_TRC_LINEAR;
+ case JXL_TRANSFER_FUNCTION_SRGB: return AVCOL_TRC_IEC61966_2_1;
+ case JXL_TRANSFER_FUNCTION_PQ: return AVCOL_TRC_SMPTE2084;
+ case JXL_TRANSFER_FUNCTION_DCI: return AVCOL_TRC_SMPTE428;
+ case JXL_TRANSFER_FUNCTION_HLG: return AVCOL_TRC_ARIB_STD_B67;
+ case JXL_TRANSFER_FUNCTION_GAMMA:
+ if (jxl_color->gamma > 2.199 && jxl_color->gamma < 2.201)
+ return AVCOL_TRC_GAMMA22;
+ else if (jxl_color->gamma > 2.799 && jxl_color->gamma < 2.801)
+ return AVCOL_TRC_GAMMA28;
+ else
+ av_log(avctx, AV_LOG_WARNING, "Unsupported gamma transfer: %f\n", jxl_color->gamma);
+ break;
+ default:
+ av_log(avctx, AV_LOG_WARNING, "Unknown transfer function: %d\n", jxl_color->transfer_function);
+ }
+
+ return AVCOL_TRC_UNSPECIFIED;
+}
+
+static int libjxl_get_icc(AVCodecContext *avctx)
+{
+ LibJxlDecodeContext *ctx = avctx->priv_data;
+ size_t icc_len;
+ JxlDecoderStatus jret;
+ /* an ICC profile is present, and we can meaningfully get it,
+ * because the pixel data is not XYB-encoded */
+ jret = JxlDecoderGetICCProfileSize(ctx->decoder, &ctx->jxl_pixfmt, JXL_COLOR_PROFILE_TARGET_DATA, &icc_len);
+ if (jret == JXL_DEC_SUCCESS && icc_len > 0) {
+ av_buffer_unref(&ctx->iccp);
+ ctx->iccp = av_buffer_alloc(icc_len);
+ if (!ctx->iccp)
+ return AVERROR(ENOMEM);
+ jret = JxlDecoderGetColorAsICCProfile(ctx->decoder, &ctx->jxl_pixfmt, JXL_COLOR_PROFILE_TARGET_DATA,
+ ctx->iccp->data, icc_len);
+ if (jret != JXL_DEC_SUCCESS) {
+ av_log(avctx, AV_LOG_WARNING, "Unable to obtain ICC Profile\n");
+ av_buffer_unref(&ctx->iccp);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * There's generally four cases when it comes to decoding a libjxl image
+ * with regard to color encoding:
+ * (a) There is an embedded ICC profile in the image, and the image is XYB-encoded.
+ * (b) There is an embedded ICC profile in the image, and the image is not XYB-encoded.
+ * (c) There is no embedded ICC profile, and FFmpeg supports the tagged colorspace.
+ * (d) There is no embedded ICC profile, and FFmpeg does not support the tagged colorspace.
+ *
+ * In case (b), we forward the pixel data as is and forward the ICC Profile as-is.
+ * In case (c), we request the pixel data in the space it's tagged as,
+ * and tag the space accordingly.
+ * In case (a), libjxl does not support getting the pixel data in the space described by the ICC
+ * profile, so instead we request the pixel data in BT.2020/PQ as it is the widest
+ * space that FFmpeg supports.
+ * In case (d), we also request wide-gamut pixel data as a fallback since FFmpeg doesn't support
+ * the custom primaries tagged in the space.
+ */
+static int libjxl_color_encoding_event(AVCodecContext *avctx, AVFrame *frame)
+{
+ LibJxlDecodeContext *ctx = avctx->priv_data;
+ JxlDecoderStatus jret;
+ int ret;
+ JxlColorEncoding jxl_color;
+ /* set this flag if we need to fall back on wide gamut */
+ int fallback = 0;
+
+ jret = JxlDecoderGetColorAsEncodedProfile(ctx->decoder, NULL, JXL_COLOR_PROFILE_TARGET_ORIGINAL, &jxl_color);
+ if (jret == JXL_DEC_SUCCESS) {
+ /* enum values describe the colors of this image */
+ jret = JxlDecoderSetPreferredColorProfile(ctx->decoder, &jxl_color);
+ if (jret == JXL_DEC_SUCCESS)
+ jret = JxlDecoderGetColorAsEncodedProfile(ctx->decoder, &ctx->jxl_pixfmt, JXL_COLOR_PROFILE_TARGET_DATA, &jxl_color);
+ /* if we couldn't successfully request the pixel data space, we fall back on wide gamut */
+ /* this code path is very unlikely to happen in practice */
+ if (jret != JXL_DEC_SUCCESS)
+ fallback = 1;
+ } else {
+ /* an ICC Profile is present in the stream */
+ if (ctx->basic_info.uses_original_profile) {
+ /* uses_original_profile is the same as !xyb_encoded */
+ av_log(avctx, AV_LOG_VERBOSE, "Using embedded ICC Profile\n");
+ if ((ret = libjxl_get_icc(avctx)) < 0)
+ return ret;
+ } else {
+ /*
+ * an XYB-encoded image with an embedded ICC profile can't always have the
+ * pixel data requested in the original space, so libjxl has no feature
+ * to allow this to happen, so we fall back on wide gamut
+ */
+ fallback = 1;
+ }
+ }
+
+ avctx->color_range = frame->color_range = AVCOL_RANGE_JPEG;
+ if (ctx->jxl_pixfmt.num_channels >= 3)
+ avctx->colorspace = AVCOL_SPC_RGB;
+ avctx->color_primaries = AVCOL_PRI_UNSPECIFIED;
+ avctx->color_trc = AVCOL_TRC_UNSPECIFIED;
+
+ if (!ctx->iccp) {
+ /* checking enum values */
+ if (!fallback) {
+ if (avctx->colorspace == AVCOL_SPC_RGB)
+ avctx->color_primaries = libjxl_get_primaries(avctx, &jxl_color);
+ avctx->color_trc = libjxl_get_trc(avctx, &jxl_color);
+ }
+ /* fall back on wide gamut if enum values fail */
+ if (avctx->color_primaries == AVCOL_PRI_UNSPECIFIED) {
+ if (avctx->colorspace == AVCOL_SPC_RGB) {
+ av_log(avctx, AV_LOG_WARNING, "Falling back on wide gamut output\n");
+ jxl_color.primaries = JXL_PRIMARIES_2100;
+ avctx->color_primaries = AVCOL_PRI_BT2020;
+ }
+ /* libjxl requires this set even for grayscale */
+ jxl_color.white_point = JXL_WHITE_POINT_D65;
+ }
+ if (avctx->color_trc == AVCOL_TRC_UNSPECIFIED) {
+ if (ctx->jxl_pixfmt.data_type == JXL_TYPE_FLOAT
+ || ctx->jxl_pixfmt.data_type == JXL_TYPE_FLOAT16) {
+ av_log(avctx, AV_LOG_WARNING, "Falling back on Linear Light transfer\n");
+ jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_LINEAR;
+ avctx->color_trc = AVCOL_TRC_LINEAR;
+ } else {
+ av_log(avctx, AV_LOG_WARNING, "Falling back on iec61966-2-1/sRGB transfer\n");
+ jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_SRGB;
+ avctx->color_trc = AVCOL_TRC_IEC61966_2_1;
+ }
+ }
+ /* all colors will be in-gamut so we want accurate colors */
+ jxl_color.rendering_intent = JXL_RENDERING_INTENT_RELATIVE;
+ jxl_color.color_space = avctx->colorspace == AVCOL_SPC_RGB ? JXL_COLOR_SPACE_RGB : JXL_COLOR_SPACE_GRAY;
+ jret = JxlDecoderSetPreferredColorProfile(ctx->decoder, &jxl_color);
+ if (jret != JXL_DEC_SUCCESS) {
+ av_log(avctx, AV_LOG_WARNING, "Unable to set fallback color encoding\n");
+ /*
+ * This should only happen if there's a non-XYB encoded image with custom primaries
+ * embedded as enums and no embedded ICC Profile.
+ * In this case, libjxl will synthesize an ICC Profile for us.
+ */
+ avctx->color_trc = AVCOL_TRC_UNSPECIFIED;
+ avctx->color_primaries = AVCOL_PRI_UNSPECIFIED;
+ if ((ret = libjxl_get_icc(avctx)) < 0)
+ return ret;
+ }
+ }
+
+ frame->color_trc = avctx->color_trc;
+ frame->color_primaries = avctx->color_primaries;
+ frame->colorspace = avctx->colorspace;
+
+ return 0;
+}
+
static int libjxl_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt)
{
LibJxlDecodeContext *ctx = avctx->priv_data;
uint8_t *buf = avpkt->data;
- size_t remaining = avpkt->size, iccp_len;
+ size_t remaining = avpkt->size;
JxlDecoderStatus jret;
int ret;
*got_frame = 0;
@@ -183,30 +372,21 @@ static int libjxl_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_f
av_log(avctx, AV_LOG_ERROR, "Bad libjxl pixel format\n");
return AVERROR_EXTERNAL;
}
- ret = ff_set_dimensions(avctx, ctx->basic_info.xsize, ctx->basic_info.ysize);
- if (ret < 0)
+ if ((ret = ff_set_dimensions(avctx, ctx->basic_info.xsize, ctx->basic_info.ysize)) < 0)
return ret;
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)
- av_buffer_unref(&ctx->iccp);
- }
+ if ((ret = libjxl_color_encoding_event(avctx, frame)) < 0)
+ return ret;
continue;
case JXL_DEC_NEED_IMAGE_OUT_BUFFER:
av_log(avctx, AV_LOG_DEBUG, "NEED_IMAGE_OUT_BUFFER event emitted\n");
- ret = ff_get_buffer(avctx, frame, 0);
- if (ret < 0)
+ if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
return ret;
ctx->jxl_pixfmt.align = frame->linesize[0];
- if (JxlDecoderSetImageOutBuffer(ctx->decoder, &ctx->jxl_pixfmt, frame->data[0], frame->buf[0]->size) != JXL_DEC_SUCCESS) {
+ if (JxlDecoderSetImageOutBuffer(ctx->decoder, &ctx->jxl_pixfmt, frame->data[0], frame->buf[0]->size)
+ != JXL_DEC_SUCCESS) {
av_log(avctx, AV_LOG_ERROR, "Bad libjxl dec need image out buffer event\n");
return AVERROR_EXTERNAL;
}
--
2.36.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 5+ messages in thread
* [FFmpeg-devel] [PATCH v9 2/2] avcodec/libjxlenc: properly read input colorspace
2022-06-24 16:50 [FFmpeg-devel] [PATCH v9 0/2] libjxl Colorspace fixes Leo Izen
2022-06-24 16:50 ` [FFmpeg-devel] [PATCH v9 1/2] avcodec/libjxldec: properly tag output colorspace Leo Izen
@ 2022-06-24 16:50 ` Leo Izen
2022-06-24 17:33 ` [FFmpeg-devel] [PATCH v9 0/2] libjxl Colorspace fixes Niklas Haas
2 siblings, 0 replies; 5+ messages in thread
From: Leo Izen @ 2022-06-24 16:50 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Leo Izen
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 | 153 +++++++++++++++++++++++++++++++++--------
1 file changed, 123 insertions(+), 30 deletions(-)
diff --git a/libavcodec/libjxlenc.c b/libavcodec/libjxlenc.c
index 8bebec6aeb..6a948cc3ae 100644
--- a/libavcodec/libjxlenc.c
+++ b/libavcodec/libjxlenc.c
@@ -27,6 +27,7 @@
#include <string.h>
#include "libavutil/avutil.h"
+#include "libavutil/csp.h"
#include "libavutil/error.h"
#include "libavutil/frame.h"
#include "libavutil/libm.h"
@@ -117,7 +118,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 +134,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;
}
@@ -185,6 +186,52 @@ static av_cold int libjxl_encode_init(AVCodecContext *avctx)
return 0;
}
+/**
+ * Populate a JxlColorEncoding with the given enum AVColorPrimaries.
+ * @return < 0 upon failure, >= 0 upon success
+ */
+static int libjxl_populate_primaries(JxlColorEncoding *jxl_color, enum AVColorPrimaries prm)
+{
+ const AVColorPrimariesDesc *desc;
+
+ switch (prm) {
+ case AVCOL_PRI_BT709:
+ jxl_color->primaries = JXL_PRIMARIES_SRGB;
+ jxl_color->white_point = JXL_WHITE_POINT_D65;
+ return 0;
+ case AVCOL_PRI_BT2020:
+ jxl_color->primaries = JXL_PRIMARIES_2100;
+ jxl_color->white_point = JXL_WHITE_POINT_D65;
+ return 0;
+ case AVCOL_PRI_SMPTE431:
+ jxl_color->primaries = JXL_PRIMARIES_P3;
+ jxl_color->white_point = JXL_WHITE_POINT_DCI;
+ return 0;
+ case AVCOL_PRI_SMPTE432:
+ jxl_color->primaries = JXL_PRIMARIES_P3;
+ jxl_color->white_point = JXL_WHITE_POINT_D65;
+ return 0;
+ }
+
+ desc = av_csp_primaries_desc_from_id(prm);
+ if (!desc)
+ return AVERROR(EINVAL);
+
+ jxl_color->primaries = JXL_PRIMARIES_CUSTOM;
+ jxl_color->white_point = JXL_WHITE_POINT_CUSTOM;
+
+ jxl_color->primaries_red_xy[0] = av_q2d(desc->prim.r.x);
+ jxl_color->primaries_red_xy[1] = av_q2d(desc->prim.r.y);
+ jxl_color->primaries_green_xy[0] = av_q2d(desc->prim.g.x);
+ jxl_color->primaries_green_xy[1] = av_q2d(desc->prim.g.y);
+ jxl_color->primaries_blue_xy[0] = av_q2d(desc->prim.b.x);
+ jxl_color->primaries_blue_xy[1] = av_q2d(desc->prim.b.y);
+ jxl_color->white_point_xy[0] = av_q2d(desc->wp.x);
+ jxl_color->white_point_xy[1] = av_q2d(desc->wp.y);
+
+ return 0;
+}
+
/**
* Encode an entire frame. Currently animation, is not supported by
* this encoder, so this will always reinitialize a new still image
@@ -223,49 +270,95 @@ 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 limited 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_WARNING, "This encoder does not support limited (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 (pc)\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 (frame->color_trc && frame->color_trc != AVCOL_TRC_UNSPECIFIED
+ ? frame->color_trc : 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. Colors may be wrong.\n");
+ jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_LINEAR;
+ } else {
+ av_log(avctx, AV_LOG_WARNING, "Unknown transfer function, assuming IEC61966-2-1/sRGB. Colors may be wrong.\n");
+ jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_SRGB;
+ }
+ }
+
+ /* This should be implied to be honest
+ * but a libjxl bug 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;
+
+ ret = libjxl_populate_primaries(&jxl_color,
+ frame->color_primaries && frame->color_primaries != AVCOL_PRI_UNSPECIFIED
+ ? frame->color_primaries : avctx->color_primaries);
+ if (ret < 0)
+ return ret;
+
+ 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];
--
2.36.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [FFmpeg-devel] [PATCH v9 0/2] libjxl Colorspace fixes
2022-06-24 16:50 [FFmpeg-devel] [PATCH v9 0/2] libjxl Colorspace fixes Leo Izen
2022-06-24 16:50 ` [FFmpeg-devel] [PATCH v9 1/2] avcodec/libjxldec: properly tag output colorspace Leo Izen
2022-06-24 16:50 ` [FFmpeg-devel] [PATCH v9 2/2] avcodec/libjxlenc: properly read input colorspace Leo Izen
@ 2022-06-24 17:33 ` Niklas Haas
2022-06-25 15:08 ` Niklas Haas
2 siblings, 1 reply; 5+ messages in thread
From: Niklas Haas @ 2022-06-24 17:33 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Leo Izen
LGTM
On Fri, 24 Jun 2022 12:50:54 -0400 Leo Izen <leo.izen@gmail.com> wrote:
> Changes in v9:
> - Minor cosmetic changes, as requested by Anton K
> - More liberally commented casework, a.r.b. Haasn
> - Structured flow to be a bit more readable
>
> Changes in v8:
> - Use avutil/csp for both encoding and decoding
> - Handle the non-XYB case with an attached ICC Profile on decoding
> - clean up some code and segment it out to static functions
>
> Leo Izen (2):
> avcodec/libjxldec: properly tag output colorspace
> avcodec/libjxlenc: properly read input colorspace
>
> libavcodec/libjxldec.c | 214 +++++++++++++++++++++++++++++++++++++----
> libavcodec/libjxlenc.c | 153 +++++++++++++++++++++++------
> 2 files changed, 320 insertions(+), 47 deletions(-)
>
> --
> 2.36.1
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [FFmpeg-devel] [PATCH v9 0/2] libjxl Colorspace fixes
2022-06-24 17:33 ` [FFmpeg-devel] [PATCH v9 0/2] libjxl Colorspace fixes Niklas Haas
@ 2022-06-25 15:08 ` Niklas Haas
0 siblings, 0 replies; 5+ messages in thread
From: Niklas Haas @ 2022-06-25 15:08 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Leo Izen
On Fri, 24 Jun 2022 19:33:52 +0200 Niklas Haas <ffmpeg@haasn.xyz> wrote:
> LGTM
>
> On Fri, 24 Jun 2022 12:50:54 -0400 Leo Izen <leo.izen@gmail.com> wrote:
> > Changes in v9:
> > - Minor cosmetic changes, as requested by Anton K
> > - More liberally commented casework, a.r.b. Haasn
> > - Structured flow to be a bit more readable
> >
> > Changes in v8:
> > - Use avutil/csp for both encoding and decoding
> > - Handle the non-XYB case with an attached ICC Profile on decoding
> > - clean up some code and segment it out to static functions
> >
> > Leo Izen (2):
> > avcodec/libjxldec: properly tag output colorspace
> > avcodec/libjxlenc: properly read input colorspace
> >
> > libavcodec/libjxldec.c | 214 +++++++++++++++++++++++++++++++++++++----
> > libavcodec/libjxlenc.c | 153 +++++++++++++++++++++++------
> > 2 files changed, 320 insertions(+), 47 deletions(-)
> >
> > --
> > 2.36.1
> >
> > _______________________________________________
> > ffmpeg-devel mailing list
> > ffmpeg-devel@ffmpeg.org
> > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> >
> > To unsubscribe, visit link above, or email
> > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Merged.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2022-06-25 15:08 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-24 16:50 [FFmpeg-devel] [PATCH v9 0/2] libjxl Colorspace fixes Leo Izen
2022-06-24 16:50 ` [FFmpeg-devel] [PATCH v9 1/2] avcodec/libjxldec: properly tag output colorspace Leo Izen
2022-06-24 16:50 ` [FFmpeg-devel] [PATCH v9 2/2] avcodec/libjxlenc: properly read input colorspace Leo Izen
2022-06-24 17:33 ` [FFmpeg-devel] [PATCH v9 0/2] libjxl Colorspace fixes Niklas Haas
2022-06-25 15:08 ` Niklas Haas
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git