diff --git a/libavcodec/libjxl.h b/libavcodec/libjxl.h index 5387c438fd..e305b6e758 100644 --- a/libavcodec/libjxl.h +++ b/libavcodec/libjxl.h @@ -27,8 +27,20 @@ #ifndef AVCODEC_LIBJXL_H #define AVCODEC_LIBJXL_H +#include #include +/* + * libjxl version 0.7.0 and earlier doesn't contain these macros at all + * so to detect version 0.7.0 versus 0.8.0 we need to define them ourselves + */ +#ifndef JPEGXL_COMPUTE_NUMERIC_VERSION + #define JPEGXL_COMPUTE_NUMERIC_VERSION(major,minor,patch) ((major<<24) | (minor<<16) | (patch<<8) | 0) +#endif +#ifndef JPEGXL_NUMERIC_VERSION + #define JPEGXL_NUMERIC_VERSION JPEGXL_COMPUTE_NUMERIC_VERSION(0, 7, 0) +#endif + /** * Transform threadcount in ffmpeg to one used by libjxl. * diff --git a/libavcodec/libjxldec.c b/libavcodec/libjxldec.c index abe08eb400..045a1535f9 100644 --- a/libavcodec/libjxldec.c +++ b/libavcodec/libjxldec.c @@ -47,7 +47,9 @@ typedef struct LibJxlDecodeContext { JxlDecoder *decoder; JxlBasicInfo basic_info; JxlPixelFormat jxl_pixfmt; +#if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0) JxlBitDepth jxl_bit_depth; +#endif JxlDecoderStatus events; AVBufferRef *iccp; } LibJxlDecodeContext; @@ -94,14 +96,17 @@ static av_cold int libjxl_decode_init(AVCodecContext *avctx) return libjxl_init_jxl_decoder(avctx); } -static enum AVPixelFormat libjxl_get_pix_fmt(AVCodecContext *avctx, const JxlBasicInfo *basic_info, - JxlPixelFormat *format, JxlBitDepth *depth) +static enum AVPixelFormat libjxl_get_pix_fmt(AVCodecContext *avctx, LibJxlDecodeContext *ctx) { + const JxlBasicInfo *basic_info = &ctx->basic_info; + JxlPixelFormat *format = &ctx->jxl_pixfmt; format->endianness = JXL_NATIVE_ENDIAN; format->num_channels = basic_info->num_color_channels + (basic_info->alpha_bits > 0); - depth->bits_per_sample = avctx->bits_per_raw_sample = basic_info->bits_per_sample; - depth->type = JXL_BIT_DEPTH_FROM_PIXEL_FORMAT; - depth->exponent_bits_per_sample = basic_info->exponent_bits_per_sample; +#if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0) + ctx->jxl_bit_depth.bits_per_sample = avctx->bits_per_raw_sample = basic_info->bits_per_sample; + ctx->jxl_bit_depth.type = JXL_BIT_DEPTH_FROM_PIXEL_FORMAT; + ctx->jxl_bit_depth.exponent_bits_per_sample = basic_info->exponent_bits_per_sample; +#endif /* Gray */ if (basic_info->num_color_channels == 1) { if (basic_info->bits_per_sample <= 8) { @@ -372,7 +377,7 @@ static int libjxl_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_f av_log(avctx, AV_LOG_ERROR, "Bad libjxl basic info event\n"); return AVERROR_EXTERNAL; } - avctx->pix_fmt = libjxl_get_pix_fmt(avctx, &ctx->basic_info, &ctx->jxl_pixfmt, &ctx->jxl_bit_depth); + avctx->pix_fmt = libjxl_get_pix_fmt(avctx, ctx); if (avctx->pix_fmt == AV_PIX_FMT_NONE) { av_log(avctx, AV_LOG_ERROR, "Bad libjxl pixel format\n"); return AVERROR_EXTERNAL; @@ -395,10 +400,12 @@ static int libjxl_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_f av_log(avctx, AV_LOG_ERROR, "Bad libjxl dec need image out buffer event\n"); return AVERROR_EXTERNAL; } +#if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0) if (JxlDecoderSetImageOutBitDepth(ctx->decoder, &ctx->jxl_bit_depth) != JXL_DEC_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Error setting output bit depth\n"); return AVERROR_EXTERNAL; } +#endif continue; case JXL_DEC_FULL_IMAGE: /* full image is one frame, even if animated */ diff --git a/libavcodec/libjxlenc.c b/libavcodec/libjxlenc.c index c51024f180..897452f575 100644 --- a/libavcodec/libjxlenc.c +++ b/libavcodec/libjxlenc.c @@ -250,7 +250,10 @@ static int libjxl_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFra JxlBasicInfo info; JxlColorEncoding jxl_color; JxlPixelFormat jxl_fmt; + int bits_per_sample; +#if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0) JxlBitDepth jxl_bit_depth; +#endif JxlEncoderStatus jret; int ret; size_t available = ctx->buffer_size; @@ -270,22 +273,26 @@ static int libjxl_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFra info.ysize = frame->height; info.num_extra_channels = (jxl_fmt.num_channels + 1) % 2; info.num_color_channels = jxl_fmt.num_channels - info.num_extra_channels; - jxl_bit_depth.bits_per_sample = av_get_bits_per_pixel(pix_desc) / jxl_fmt.num_channels; + bits_per_sample = av_get_bits_per_pixel(pix_desc) / jxl_fmt.num_channels; info.bits_per_sample = avctx->bits_per_raw_sample > 0 && !(pix_desc->flags & AV_PIX_FMT_FLAG_FLOAT) - ? avctx->bits_per_raw_sample : jxl_bit_depth.bits_per_sample; + ? avctx->bits_per_raw_sample : bits_per_sample; 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; - jxl_bit_depth.exponent_bits_per_sample = info.exponent_bits_per_sample; } 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; - jxl_bit_depth.exponent_bits_per_sample = 0; } + +#if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0) + jxl_bit_depth.bits_per_sample = bits_per_sample; jxl_bit_depth.type = JXL_BIT_DEPTH_FROM_PIXEL_FORMAT; + jxl_bit_depth.exponent_bits_per_sample = pix_desc->flags & AV_PIX_FMT_FLAG_FLOAT ? + info.exponent_bits_per_sample : 0; +#endif /* JPEG XL format itself does not support limited range */ if (avctx->color_range == AVCOL_RANGE_MPEG || @@ -362,8 +369,11 @@ static int libjxl_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFra 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"); + +#if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0) if (JxlEncoderSetFrameBitDepth(ctx->options, &jxl_bit_depth) != JXL_ENC_SUCCESS) av_log(avctx, AV_LOG_WARNING, "Failed to set JxlBitDepth\n"); +#endif /* depending on basic info, level 10 might * be required instead of level 5 */