[FFmpeg-devel] [PATCH 2/3] avcodec/libjxlenc: Move image initialization code into libjxl_encode_init_image
Zsolt Vadász
zsolt_vadasz at protonmail.com
Mon Dec 11 19:05:19 EET 2023
---
libavcodec/libjxlenc.c | 69 +++++++++++++++++++++++++++---------------
1 file changed, 45 insertions(+), 24 deletions(-)
diff --git a/libavcodec/libjxlenc.c b/libavcodec/libjxlenc.c
index 92a458d51a..6110c42a7c 100644
--- a/libavcodec/libjxlenc.c
+++ b/libavcodec/libjxlenc.c
@@ -50,6 +50,9 @@ typedef struct LibJxlEncodeContext {
JxlEncoder *encoder;
JxlEncoderFrameSettings *options;
JxlBasicInfo info;
+ JxlPixelFormat jxl_fmt;
+ int animated;
+ int first_frame;
int effort;
float distance;
int modular;
@@ -181,6 +184,9 @@ static av_cold int libjxl_encode_init(AVCodecContext *avctx)
return AVERROR(ENOMEM);
}
+ ctx->animated = 0;
+ ctx->first_frame = 1;
+
return 0;
}
@@ -235,28 +241,19 @@ static int libjxl_populate_primaries(void *avctx, JxlColorEncoding *jxl_color, e
return 0;
}
-/**
- * Encode an entire frame. Currently animation, is not supported by
- * this encoder, so this will always reinitialize a new still image
- * and encode a one-frame image (for image2 and image2pipe).
- */
-static int libjxl_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet)
+static int libjxl_encode_init_image(AVCodecContext *avctx, const AVFrame *frame)
{
LibJxlEncodeContext *ctx = avctx->priv_data;
- AVFrameSideData *sd;
- const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(frame->format);
+ int ret;
JxlBasicInfo *info = &ctx->info;
+ JxlPixelFormat *jxl_fmt = &ctx->jxl_fmt;
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;
- size_t bytes_written = 0;
- uint8_t *next_out = ctx->buffer;
+ const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(frame->format);
+ AVFrameSideData *sd;
/* reset the encoder every frame for image2 muxer */
JxlEncoderReset(ctx->encoder);
@@ -269,23 +266,23 @@ static int libjxl_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFra
/* populate the basic info settings */
JxlEncoderInitBasicInfo(info);
- jxl_fmt.num_channels = pix_desc->nb_components;
+ jxl_fmt->num_channels = pix_desc->nb_components;
info->xsize = frame->width;
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;
- bits_per_sample = av_get_bits_per_pixel(pix_desc) / jxl_fmt.num_channels;
+ info->num_extra_channels = (jxl_fmt->num_channels + 1) % 2;
+ info->num_color_channels = jxl_fmt->num_channels - info->num_extra_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 : 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_fmt->data_type = info->bits_per_sample > 16 ? JXL_TYPE_FLOAT : JXL_TYPE_FLOAT16;
} 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_fmt->data_type = info->bits_per_sample <= 8 ? JXL_TYPE_UINT8 : JXL_TYPE_UINT16;
}
#if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0)
@@ -383,17 +380,41 @@ static int libjxl_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFra
av_log(avctx, AV_LOG_WARNING, "Could not increase codestream level\n");
}
- jxl_fmt.endianness = JXL_NATIVE_ENDIAN;
- jxl_fmt.align = frame->linesize[0];
+ jxl_fmt->endianness = JXL_NATIVE_ENDIAN;
+ jxl_fmt->align = frame->linesize[0];
+
+ return 0;
+}
+
+/**
+ * Encode an entire frame. Currently animation, is not supported by
+ * this encoder, so this will always reinitialize a new still image
+ * and encode a one-frame image (for image2 and image2pipe).
+ */
+static int libjxl_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet)
+{
+ LibJxlEncodeContext *ctx = avctx->priv_data;
+ JxlEncoderStatus jret;
+ JxlBasicInfo *info = &ctx->info;
+ JxlPixelFormat *jxl_fmt = &ctx->jxl_fmt;
+ int ret;
+ size_t available = ctx->buffer_size;
+ size_t bytes_written = 0;
+ uint8_t *next_out = ctx->buffer;
+
+ if(!ctx->animated || ctx->first_frame) {
+ if((ret = libjxl_encode_init_image(avctx, frame)) < 0)
+ return ret;
+ ctx->first_frame = 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;
}
/*
* Run this after the last frame in the image has been passed.
- * TODO support animation
*/
JxlEncoderCloseInput(ctx->encoder);
--
2.43.0
More information about the ffmpeg-devel
mailing list