FFmpeg
libjxldec.c
Go to the documentation of this file.
1 /*
2  * JPEG XL decoding support via libjxl
3  * Copyright (c) 2021 Leo Izen <leo.izen@gmail.com>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file
24  * JPEG XL decoder using libjxl
25  */
26 
27 #include "libavutil/avassert.h"
28 #include "libavutil/buffer.h"
29 #include "libavutil/common.h"
30 #include "libavutil/csp.h"
31 #include "libavutil/error.h"
32 #include "libavutil/mem.h"
33 #include "libavutil/pixdesc.h"
34 #include "libavutil/pixfmt.h"
35 #include "libavutil/frame.h"
36 
37 #include "avcodec.h"
38 #include "codec_internal.h"
39 #include "decode.h"
40 #include "internal.h"
41 
42 #include <jxl/decode.h>
43 #include <jxl/thread_parallel_runner.h>
44 #include "libjxl.h"
45 
46 typedef struct LibJxlDecodeContext {
47  void *runner;
48  JxlDecoder *decoder;
49  JxlBasicInfo basic_info;
50  JxlPixelFormat jxl_pixfmt;
51 #if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0)
52  JxlBitDepth jxl_bit_depth;
53 #endif
54  JxlDecoderStatus events;
57  int64_t accumulated_pts;
58  int64_t frame_duration;
63 
65 {
67 
68  ctx->events = JXL_DEC_BASIC_INFO | JXL_DEC_FULL_IMAGE
69  | JXL_DEC_COLOR_ENCODING | JXL_DEC_FRAME;
70  if (JxlDecoderSubscribeEvents(ctx->decoder, ctx->events) != JXL_DEC_SUCCESS) {
71  av_log(avctx, AV_LOG_ERROR, "Error subscribing to JXL events\n");
72  return AVERROR_EXTERNAL;
73  }
74 
75  if (JxlDecoderSetParallelRunner(ctx->decoder, JxlThreadParallelRunner, ctx->runner) != JXL_DEC_SUCCESS) {
76  av_log(avctx, AV_LOG_ERROR, "Failed to set JxlThreadParallelRunner\n");
77  return AVERROR_EXTERNAL;
78  }
79 
80  memset(&ctx->basic_info, 0, sizeof(JxlBasicInfo));
81  memset(&ctx->jxl_pixfmt, 0, sizeof(JxlPixelFormat));
82  ctx->prev_is_last = 1;
83 
84  return 0;
85 }
86 
88 {
90  JxlMemoryManager manager;
91 
93  ctx->decoder = JxlDecoderCreate(&manager);
94  if (!ctx->decoder) {
95  av_log(avctx, AV_LOG_ERROR, "Failed to create JxlDecoder\n");
96  return AVERROR_EXTERNAL;
97  }
98 
99  ctx->runner = JxlThreadParallelRunnerCreate(&manager, ff_libjxl_get_threadcount(avctx->thread_count));
100  if (!ctx->runner) {
101  av_log(avctx, AV_LOG_ERROR, "Failed to create JxlThreadParallelRunner\n");
102  return AVERROR_EXTERNAL;
103  }
104 
105  ctx->avpkt = avctx->internal->in_pkt;
106  ctx->frame = av_frame_alloc();
107  if (!ctx->frame)
108  return AVERROR(ENOMEM);
109 
110  return libjxl_init_jxl_decoder(avctx);
111 }
112 
114 {
115  const JxlBasicInfo *basic_info = &ctx->basic_info;
116  JxlPixelFormat *format = &ctx->jxl_pixfmt;
117  format->endianness = JXL_NATIVE_ENDIAN;
118  format->num_channels = basic_info->num_color_channels + (basic_info->alpha_bits > 0);
119 #if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0)
120  ctx->jxl_bit_depth.bits_per_sample = avctx->bits_per_raw_sample = basic_info->bits_per_sample;
121  ctx->jxl_bit_depth.type = JXL_BIT_DEPTH_FROM_PIXEL_FORMAT;
122  ctx->jxl_bit_depth.exponent_bits_per_sample = basic_info->exponent_bits_per_sample;
123 #endif
124  /* Gray */
125  if (basic_info->num_color_channels == 1) {
126  if (basic_info->bits_per_sample <= 8) {
127  format->data_type = JXL_TYPE_UINT8;
128  return basic_info->alpha_bits ? AV_PIX_FMT_YA8 : AV_PIX_FMT_GRAY8;
129  }
130  if (basic_info->exponent_bits_per_sample || basic_info->bits_per_sample > 16) {
131  if (!basic_info->alpha_bits) {
132  format->data_type = JXL_TYPE_FLOAT;
133  return AV_PIX_FMT_GRAYF32;
134  }
135  av_log(avctx, AV_LOG_WARNING, "Downsampling gray+alpha float to 16-bit integer via libjxl\n");
136  }
137  format->data_type = JXL_TYPE_UINT16;
138  return basic_info->alpha_bits ? AV_PIX_FMT_YA16 : AV_PIX_FMT_GRAY16;
139  }
140  /* rgb only */
141  /* libjxl only supports packed RGB and gray output at the moment */
142  if (basic_info->num_color_channels == 3) {
143  if (basic_info->bits_per_sample <= 8) {
144  format->data_type = JXL_TYPE_UINT8;
145  return basic_info->alpha_bits ? AV_PIX_FMT_RGBA : AV_PIX_FMT_RGB24;
146  }
147  if (basic_info->exponent_bits_per_sample || basic_info->bits_per_sample > 16) {
148  format->data_type = JXL_TYPE_FLOAT;
149  return basic_info->alpha_bits ? AV_PIX_FMT_RGBAF32 : AV_PIX_FMT_RGBF32;
150  }
151  format->data_type = JXL_TYPE_UINT16;
152  return basic_info->alpha_bits ? AV_PIX_FMT_RGBA64 : AV_PIX_FMT_RGB48;
153  }
154 
155  return AV_PIX_FMT_NONE;
156 }
157 
158 static enum AVColorPrimaries libjxl_get_primaries(void *avctx, const JxlColorEncoding *jxl_color)
159 {
161  enum AVColorPrimaries prim;
162 
163  /* libjxl populates these double values even if it uses an enum space */
164  desc.prim.r.x = av_d2q(jxl_color->primaries_red_xy[0], 300000);
165  desc.prim.r.y = av_d2q(jxl_color->primaries_red_xy[1], 300000);
166  desc.prim.g.x = av_d2q(jxl_color->primaries_green_xy[0], 300000);
167  desc.prim.g.y = av_d2q(jxl_color->primaries_green_xy[1], 300000);
168  desc.prim.b.x = av_d2q(jxl_color->primaries_blue_xy[0], 300000);
169  desc.prim.b.y = av_d2q(jxl_color->primaries_blue_xy[1], 300000);
170  desc.wp.x = av_d2q(jxl_color->white_point_xy[0], 300000);
171  desc.wp.y = av_d2q(jxl_color->white_point_xy[1], 300000);
172 
174  if (prim == AVCOL_PRI_UNSPECIFIED) {
175  /* try D65 with the same primaries */
176  /* BT.709 uses D65 white point */
178  av_log(avctx, AV_LOG_WARNING, "Changing unknown white point to D65\n");
180  }
181 
182  return prim;
183 }
184 
185 static enum AVColorTransferCharacteristic libjxl_get_trc(void *avctx, const JxlColorEncoding *jxl_color)
186 {
187  switch (jxl_color->transfer_function) {
188  case JXL_TRANSFER_FUNCTION_709: return AVCOL_TRC_BT709;
189  case JXL_TRANSFER_FUNCTION_LINEAR: return AVCOL_TRC_LINEAR;
190  case JXL_TRANSFER_FUNCTION_SRGB: return AVCOL_TRC_IEC61966_2_1;
191  case JXL_TRANSFER_FUNCTION_PQ: return AVCOL_TRC_SMPTE2084;
192  case JXL_TRANSFER_FUNCTION_DCI: return AVCOL_TRC_SMPTE428;
193  case JXL_TRANSFER_FUNCTION_HLG: return AVCOL_TRC_ARIB_STD_B67;
194  case JXL_TRANSFER_FUNCTION_GAMMA:
195  if (jxl_color->gamma > 0.45355 && jxl_color->gamma < 0.45555)
196  return AVCOL_TRC_GAMMA22;
197  else if (jxl_color->gamma > 0.35614 && jxl_color->gamma < 0.35814)
198  return AVCOL_TRC_GAMMA28;
199  else
200  av_log(avctx, AV_LOG_WARNING, "Unsupported gamma transfer: %f\n", jxl_color->gamma);
201  break;
202  default:
203  av_log(avctx, AV_LOG_WARNING, "Unknown transfer function: %d\n", jxl_color->transfer_function);
204  }
205 
206  return AVCOL_TRC_UNSPECIFIED;
207 }
208 
209 static int libjxl_get_icc(AVCodecContext *avctx)
210 {
212  size_t icc_len;
213  JxlDecoderStatus jret;
214  /* an ICC profile is present, and we can meaningfully get it,
215  * because the pixel data is not XYB-encoded */
216 #if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0, 9, 0)
217  jret = JxlDecoderGetICCProfileSize(ctx->decoder, &ctx->jxl_pixfmt, JXL_COLOR_PROFILE_TARGET_DATA, &icc_len);
218 #else
219  jret = JxlDecoderGetICCProfileSize(ctx->decoder, JXL_COLOR_PROFILE_TARGET_DATA, &icc_len);
220 #endif
221  if (jret == JXL_DEC_SUCCESS && icc_len > 0) {
222  av_buffer_unref(&ctx->iccp);
223  ctx->iccp = av_buffer_alloc(icc_len);
224  if (!ctx->iccp)
225  return AVERROR(ENOMEM);
226 #if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0, 9, 0)
227  jret = JxlDecoderGetColorAsICCProfile(ctx->decoder, &ctx->jxl_pixfmt, JXL_COLOR_PROFILE_TARGET_DATA,
228  ctx->iccp->data, icc_len);
229 #else
230  jret = JxlDecoderGetColorAsICCProfile(ctx->decoder, JXL_COLOR_PROFILE_TARGET_DATA, ctx->iccp->data, icc_len);
231 #endif
232  if (jret != JXL_DEC_SUCCESS) {
233  av_log(avctx, AV_LOG_WARNING, "Unable to obtain ICC Profile\n");
234  av_buffer_unref(&ctx->iccp);
235  }
236  }
237 
238  return 0;
239 }
240 
241 /*
242  * There's generally four cases when it comes to decoding a libjxl image
243  * with regard to color encoding:
244  * (a) There is an embedded ICC profile in the image, and the image is XYB-encoded.
245  * (b) There is an embedded ICC profile in the image, and the image is not XYB-encoded.
246  * (c) There is no embedded ICC profile, and FFmpeg supports the tagged colorspace.
247  * (d) There is no embedded ICC profile, and FFmpeg does not support the tagged colorspace.
248  *
249  * In case (b), we forward the pixel data as is and forward the ICC Profile as-is.
250  * In case (c), we request the pixel data in the space it's tagged as,
251  * and tag the space accordingly.
252  * In case (a), libjxl does not support getting the pixel data in the space described by the ICC
253  * profile, so instead we request the pixel data in BT.2020/PQ as it is the widest
254  * space that FFmpeg supports.
255  * In case (d), we also request wide-gamut pixel data as a fallback since FFmpeg doesn't support
256  * the custom primaries tagged in the space.
257  */
259 {
261  JxlDecoderStatus jret;
262  int ret;
263  JxlColorEncoding jxl_color;
264  /* set this flag if we need to fall back on wide gamut */
265  int fallback = 0;
266 
267 #if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0, 9, 0)
268  jret = JxlDecoderGetColorAsEncodedProfile(ctx->decoder, NULL, JXL_COLOR_PROFILE_TARGET_ORIGINAL, &jxl_color);
269 #else
270  jret = JxlDecoderGetColorAsEncodedProfile(ctx->decoder, JXL_COLOR_PROFILE_TARGET_ORIGINAL, &jxl_color);
271 #endif
272  if (jret == JXL_DEC_SUCCESS) {
273  /* enum values describe the colors of this image */
274  jret = JxlDecoderSetPreferredColorProfile(ctx->decoder, &jxl_color);
275  if (jret == JXL_DEC_SUCCESS)
276 #if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0, 9, 0)
277  jret = JxlDecoderGetColorAsEncodedProfile(ctx->decoder, &ctx->jxl_pixfmt,
278  JXL_COLOR_PROFILE_TARGET_DATA, &jxl_color);
279 #else
280  jret = JxlDecoderGetColorAsEncodedProfile(ctx->decoder, JXL_COLOR_PROFILE_TARGET_DATA, &jxl_color);
281 #endif
282  /* if we couldn't successfully request the pixel data space, we fall back on wide gamut */
283  /* this code path is very unlikely to happen in practice */
284  if (jret != JXL_DEC_SUCCESS)
285  fallback = 1;
286  } else {
287  /* an ICC Profile is present in the stream */
288  if (ctx->basic_info.uses_original_profile) {
289  /* uses_original_profile is the same as !xyb_encoded */
290  av_log(avctx, AV_LOG_VERBOSE, "Using embedded ICC Profile\n");
291  if ((ret = libjxl_get_icc(avctx)) < 0)
292  return ret;
293  } else {
294  /*
295  * an XYB-encoded image with an embedded ICC profile can't always have the
296  * pixel data requested in the original space, so libjxl has no feature
297  * to allow this to happen, so we fall back on wide gamut
298  */
299  fallback = 1;
300  }
301  }
302 
303  avctx->color_range = frame->color_range = AVCOL_RANGE_JPEG;
304  if (ctx->basic_info.num_color_channels > 1)
305  avctx->colorspace = AVCOL_SPC_RGB;
308 
309  if (!ctx->iccp) {
310  /* checking enum values */
311  if (!fallback) {
312  if (avctx->colorspace == AVCOL_SPC_RGB)
313  avctx->color_primaries = libjxl_get_primaries(avctx, &jxl_color);
314  avctx->color_trc = libjxl_get_trc(avctx, &jxl_color);
315  }
316  /* fall back on wide gamut if enum values fail */
317  if (avctx->color_primaries == AVCOL_PRI_UNSPECIFIED) {
318  if (avctx->colorspace == AVCOL_SPC_RGB) {
319  av_log(avctx, AV_LOG_WARNING, "Falling back on wide gamut output\n");
320  jxl_color.primaries = JXL_PRIMARIES_2100;
322  }
323  /* libjxl requires this set even for grayscale */
324  jxl_color.white_point = JXL_WHITE_POINT_D65;
325  }
326  if (avctx->color_trc == AVCOL_TRC_UNSPECIFIED) {
327  if (ctx->jxl_pixfmt.data_type == JXL_TYPE_FLOAT
328  || ctx->jxl_pixfmt.data_type == JXL_TYPE_FLOAT16) {
329  av_log(avctx, AV_LOG_WARNING, "Falling back on Linear Light transfer\n");
330  jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_LINEAR;
331  avctx->color_trc = AVCOL_TRC_LINEAR;
332  } else {
333  av_log(avctx, AV_LOG_WARNING, "Falling back on iec61966-2-1/sRGB transfer\n");
334  jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_SRGB;
336  }
337  }
338  /* all colors will be in-gamut so we want accurate colors */
339  jxl_color.rendering_intent = JXL_RENDERING_INTENT_RELATIVE;
340  jxl_color.color_space = ctx->basic_info.num_color_channels > 1 ? JXL_COLOR_SPACE_RGB : JXL_COLOR_SPACE_GRAY;
341  jret = JxlDecoderSetPreferredColorProfile(ctx->decoder, &jxl_color);
342  if (jret != JXL_DEC_SUCCESS) {
343  av_log(avctx, AV_LOG_WARNING, "Unable to set fallback color encoding\n");
344  /*
345  * This should only happen if there's a non-XYB encoded image with custom primaries
346  * embedded as enums and no embedded ICC Profile.
347  * In this case, libjxl will synthesize an ICC Profile for us.
348  */
351  if ((ret = libjxl_get_icc(avctx)) < 0)
352  return ret;
353  }
354  }
355 
356  frame->color_trc = avctx->color_trc;
357  frame->color_primaries = avctx->color_primaries;
358  frame->colorspace = avctx->colorspace;
359 
360  return 0;
361 }
362 
364 {
366  JxlDecoderStatus jret = JXL_DEC_SUCCESS;
367  int ret;
368  AVPacket *pkt = ctx->avpkt;
369 
370  while (1) {
371  size_t remaining;
372  JxlFrameHeader header;
373 
374  if (!pkt->size) {
376  ret = ff_decode_get_packet(avctx, pkt);
377  if (ret < 0 && ret != AVERROR_EOF)
378  return ret;
379  ctx->accumulated_pts = 0;
380  ctx->frame_duration = 0;
381  if (!pkt->size) {
382  /* jret set by the last iteration of the loop */
383  if (jret == JXL_DEC_NEED_MORE_INPUT) {
384  av_log(avctx, AV_LOG_ERROR, "Unexpected end of JXL codestream\n");
385  return AVERROR_INVALIDDATA;
386  } else {
387  return AVERROR_EOF;
388  }
389  }
390  }
391 
392  jret = JxlDecoderSetInput(ctx->decoder, pkt->data, pkt->size);
393  if (jret == JXL_DEC_ERROR) {
394  /* this should never happen here unless there's a bug in libjxl */
395  av_log(avctx, AV_LOG_ERROR, "Unknown libjxl decode error\n");
396  return AVERROR_EXTERNAL;
397  }
398 
399  jret = JxlDecoderProcessInput(ctx->decoder);
400  /*
401  * JxlDecoderReleaseInput returns the number
402  * of bytes remaining to be read, rather than
403  * the number of bytes that it did read
404  */
405  remaining = JxlDecoderReleaseInput(ctx->decoder);
406  pkt->data += pkt->size - remaining;
407  pkt->size = remaining;
408 
409  switch(jret) {
410  case JXL_DEC_ERROR:
411  av_log(avctx, AV_LOG_ERROR, "Unknown libjxl decode error\n");
412  return AVERROR_INVALIDDATA;
413  case JXL_DEC_NEED_MORE_INPUT:
414  av_log(avctx, AV_LOG_DEBUG, "NEED_MORE_INPUT event emitted\n");
415  continue;
416  case JXL_DEC_BASIC_INFO:
417  av_log(avctx, AV_LOG_DEBUG, "BASIC_INFO event emitted\n");
418  if (JxlDecoderGetBasicInfo(ctx->decoder, &ctx->basic_info) != JXL_DEC_SUCCESS) {
419  /*
420  * this should never happen
421  * if it does it is likely a libjxl decoder bug
422  */
423  av_log(avctx, AV_LOG_ERROR, "Bad libjxl basic info event\n");
424  return AVERROR_EXTERNAL;
425  }
426  avctx->pix_fmt = libjxl_get_pix_fmt(avctx, ctx);
427  if (avctx->pix_fmt == AV_PIX_FMT_NONE) {
428  av_log(avctx, AV_LOG_ERROR, "Bad libjxl pixel format\n");
429  return AVERROR_EXTERNAL;
430  }
431  if ((ret = ff_set_dimensions(avctx, ctx->basic_info.xsize, ctx->basic_info.ysize)) < 0)
432  return ret;
433  if (ctx->basic_info.have_animation)
434  ctx->anim_timebase = av_make_q(ctx->basic_info.animation.tps_denominator,
435  ctx->basic_info.animation.tps_numerator);
436  continue;
437  case JXL_DEC_COLOR_ENCODING:
438  av_log(avctx, AV_LOG_DEBUG, "COLOR_ENCODING event emitted\n");
439  ret = libjxl_color_encoding_event(avctx, ctx->frame);
440  if (ret < 0)
441  return ret;
442  continue;
443  case JXL_DEC_NEED_IMAGE_OUT_BUFFER:
444  av_log(avctx, AV_LOG_DEBUG, "NEED_IMAGE_OUT_BUFFER event emitted\n");
445  ret = ff_get_buffer(avctx, ctx->frame, 0);
446  if (ret < 0)
447  return ret;
448  ctx->jxl_pixfmt.align = ctx->frame->linesize[0];
449  if (JxlDecoderSetImageOutBuffer(ctx->decoder, &ctx->jxl_pixfmt,
450  ctx->frame->data[0], ctx->frame->buf[0]->size)
451  != JXL_DEC_SUCCESS) {
452  av_log(avctx, AV_LOG_ERROR, "Bad libjxl dec need image out buffer event\n");
453  return AVERROR_EXTERNAL;
454  }
455 #if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0)
456  if (JxlDecoderSetImageOutBitDepth(ctx->decoder, &ctx->jxl_bit_depth) != JXL_DEC_SUCCESS) {
457  av_log(avctx, AV_LOG_ERROR, "Error setting output bit depth\n");
458  return AVERROR_EXTERNAL;
459  }
460 #endif
461  continue;
462  case JXL_DEC_FRAME:
463  /* Frame here refers to the Frame bundle, not a decoded picture */
464  av_log(avctx, AV_LOG_DEBUG, "FRAME event emitted\n");
465  if (ctx->prev_is_last) {
466  /*
467  * The last frame sent was tagged as "is_last" which
468  * means this is a new image file altogether.
469  */
470  ctx->frame->pict_type = AV_PICTURE_TYPE_I;
471  ctx->frame->flags |= AV_FRAME_FLAG_KEY;
472  }
473  if (JxlDecoderGetFrameHeader(ctx->decoder, &header) != JXL_DEC_SUCCESS) {
474  av_log(avctx, AV_LOG_ERROR, "Bad libjxl dec frame event\n");
475  return AVERROR_EXTERNAL;
476  }
477  ctx->prev_is_last = header.is_last;
478  /* zero duration for animation means the frame is not presented */
479  if (ctx->basic_info.have_animation && header.duration)
480  ctx->frame_duration = header.duration;
481  continue;
482  case JXL_DEC_FULL_IMAGE:
483  /* full image is one frame, even if animated */
484  av_log(avctx, AV_LOG_DEBUG, "FULL_IMAGE event emitted\n");
485  if (ctx->iccp) {
487  if (ret < 0)
488  return ret;
489  }
490  if (ctx->basic_info.have_animation) {
491  ctx->frame->pts = av_rescale_q(ctx->accumulated_pts, ctx->anim_timebase, avctx->pkt_timebase);
492  ctx->frame->duration = av_rescale_q(ctx->frame_duration, ctx->anim_timebase, avctx->pkt_timebase);
493  } else {
494  ctx->frame->pts = 0;
495  ctx->frame->duration = pkt->duration;
496  }
497  if (pkt->pts != AV_NOPTS_VALUE)
498  ctx->frame->pts += pkt->pts;
499  ctx->accumulated_pts += ctx->frame_duration;
500  ctx->frame->pkt_dts = pkt->dts;
501  av_frame_move_ref(frame, ctx->frame);
502  return 0;
503  case JXL_DEC_SUCCESS:
504  av_log(avctx, AV_LOG_DEBUG, "SUCCESS event emitted\n");
505  /*
506  * this event will be fired when the zero-length EOF
507  * packet is sent to the decoder by the client,
508  * but it will also be fired when the next image of
509  * an image2pipe sequence is loaded up
510  */
511  JxlDecoderReset(ctx->decoder);
513  continue;
514  default:
515  av_log(avctx, AV_LOG_ERROR, "Bad libjxl event: %d\n", jret);
516  return AVERROR_EXTERNAL;
517  }
518  }
519 }
520 
522 {
524 
525  if (ctx->runner)
526  JxlThreadParallelRunnerDestroy(ctx->runner);
527  ctx->runner = NULL;
528  if (ctx->decoder)
529  JxlDecoderDestroy(ctx->decoder);
530  ctx->decoder = NULL;
531  av_buffer_unref(&ctx->iccp);
532  av_frame_free(&ctx->frame);
533 
534  return 0;
535 }
536 
538  .p.name = "libjxl",
539  CODEC_LONG_NAME("libjxl JPEG XL"),
540  .p.type = AVMEDIA_TYPE_VIDEO,
541  .p.id = AV_CODEC_ID_JPEGXL,
542  .priv_data_size = sizeof(LibJxlDecodeContext),
545  .close = libjxl_decode_close,
546  .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_OTHER_THREADS,
547  .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
550  .p.wrapper_name = "libjxl",
551 };
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: packet.c:427
ff_decode_get_packet
int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt)
Called by decoders to get the next packet for decoding.
Definition: decode.c:237
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
libjxl_init_jxl_decoder
static int libjxl_init_jxl_decoder(AVCodecContext *avctx)
Definition: libjxldec.c:64
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
ff_libjxl_get_threadcount
size_t ff_libjxl_get_threadcount(int threads)
Transform threadcount in ffmpeg to one used by libjxl.
Definition: libjxl.c:33
FF_CODEC_CAP_INIT_CLEANUP
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
Definition: codec_internal.h:42
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
AV_PIX_FMT_YA8
@ AV_PIX_FMT_YA8
8 bits gray, 8 bits alpha
Definition: pixfmt.h:140
ff_frame_new_side_data_from_buf
int ff_frame_new_side_data_from_buf(const AVCodecContext *avctx, AVFrame *frame, enum AVFrameSideDataType type, AVBufferRef **buf, AVFrameSideData **psd)
Similar to ff_frame_new_side_data, but using an existing buffer ref.
Definition: decode.c:1997
AVCodecContext::colorspace
enum AVColorSpace colorspace
YUV colorspace type.
Definition: avcodec.h:685
AVColorTransferCharacteristic
AVColorTransferCharacteristic
Color Transfer Characteristic.
Definition: pixfmt.h:580
AVColorPrimariesDesc::wp
AVWhitepointCoefficients wp
Definition: csp.h:79
AVColorPrimariesDesc
Struct that contains both white point location and primaries location, providing the complete descrip...
Definition: csp.h:78
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
LibJxlDecodeContext::decoder
JxlDecoder * decoder
Definition: libjxldec.c:48
AVCOL_TRC_LINEAR
@ AVCOL_TRC_LINEAR
"Linear transfer characteristics"
Definition: pixfmt.h:589
LibJxlDecodeContext::avpkt
AVPacket * avpkt
Definition: libjxldec.c:56
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:160
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:374
pixdesc.h
AVCodecContext::color_trc
enum AVColorTransferCharacteristic color_trc
Color Transfer Characteristic.
Definition: avcodec.h:678
AVCOL_RANGE_JPEG
@ AVCOL_RANGE_JPEG
Full range content.
Definition: pixfmt.h:686
internal.h
AVPacket::data
uint8_t * data
Definition: packet.h:524
AVCOL_TRC_UNSPECIFIED
@ AVCOL_TRC_UNSPECIFIED
Definition: pixfmt.h:583
libjxl_decode_init
static av_cold int libjxl_decode_init(AVCodecContext *avctx)
Definition: libjxldec.c:87
FF_CODEC_CAP_NOT_INIT_THREADSAFE
#define FF_CODEC_CAP_NOT_INIT_THREADSAFE
The codec is not known to be init-threadsafe (i.e.
Definition: codec_internal.h:34
FFCodec
Definition: codec_internal.h:126
libjxl.h
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
AVCOL_SPC_RGB
@ AVCOL_SPC_RGB
order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB), YZX and ST 428-1
Definition: pixfmt.h:610
AVPacket::duration
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:542
LibJxlDecodeContext::accumulated_pts
int64_t accumulated_pts
Definition: libjxldec.c:57
AVColorPrimaries
AVColorPrimaries
Chromaticity coordinates of the source primaries.
Definition: pixfmt.h:555
ff_set_dimensions
int ff_set_dimensions(AVCodecContext *s, int width, int height)
Check that the provided frame dimensions are valid and set them on the codec context.
Definition: utils.c:94
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:130
AVCOL_TRC_IEC61966_2_1
@ AVCOL_TRC_IEC61966_2_1
IEC 61966-2-1 (sRGB or sYCC)
Definition: pixfmt.h:594
AVCodecContext::thread_count
int thread_count
thread count is used to decide how many independent tasks should be passed to execute()
Definition: avcodec.h:1583
AVCOL_TRC_GAMMA28
@ AVCOL_TRC_GAMMA28
also ITU-R BT470BG
Definition: pixfmt.h:586
libjxl_get_pix_fmt
static enum AVPixelFormat libjxl_get_pix_fmt(AVCodecContext *avctx, LibJxlDecodeContext *ctx)
Definition: libjxldec.c:113
AV_PIX_FMT_GRAY16
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:462
AVCOL_TRC_GAMMA22
@ AVCOL_TRC_GAMMA22
also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM
Definition: pixfmt.h:585
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:148
avassert.h
LibJxlDecodeContext::events
JxlDecoderStatus events
Definition: libjxldec.c:54
AVCodecContext::color_primaries
enum AVColorPrimaries color_primaries
Chromaticity coordinates of the source primaries.
Definition: avcodec.h:671
pkt
AVPacket * pkt
Definition: movenc.c:60
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
av_cold
#define av_cold
Definition: attributes.h:90
AV_FRAME_FLAG_KEY
#define AV_FRAME_FLAG_KEY
A flag to mark frames that are keyframes.
Definition: frame.h:625
av_csp_primaries_desc_from_id
const AVColorPrimariesDesc * av_csp_primaries_desc_from_id(enum AVColorPrimaries prm)
Retrieves a complete gamut description from an enum constant describing the color primaries.
Definition: csp.c:90
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1406
format
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample format(the sample packing is implied by the sample format) and sample rate. The lists are not just lists
LibJxlDecodeContext::jxl_bit_depth
JxlBitDepth jxl_bit_depth
Definition: libjxldec.c:52
AV_CODEC_CAP_OTHER_THREADS
#define AV_CODEC_CAP_OTHER_THREADS
Codec supports multithreading through a method other than slice- or frame-level multithreading.
Definition: codec.h:124
ff_libjxl_decoder
const FFCodec ff_libjxl_decoder
Definition: libjxldec.c:537
AVCodecContext::bits_per_raw_sample
int bits_per_raw_sample
Bits per sample/pixel of internal libavcodec pixel/sample format.
Definition: avcodec.h:1575
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
ctx
AVFormatContext * ctx
Definition: movenc.c:49
decode.h
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
av_csp_primaries_id_from_desc
enum AVColorPrimaries av_csp_primaries_id_from_desc(const AVColorPrimariesDesc *prm)
Detects which enum AVColorPrimaries constant corresponds to the given complete gamut description.
Definition: csp.c:110
libjxl_get_icc
static int libjxl_get_icc(AVCodecContext *avctx)
Definition: libjxldec.c:209
AV_PIX_FMT_RGBF32
#define AV_PIX_FMT_RGBF32
Definition: pixfmt.h:548
LibJxlDecodeContext::jxl_pixfmt
JxlPixelFormat jxl_pixfmt
Definition: libjxldec.c:50
AV_PIX_FMT_GRAYF32
#define AV_PIX_FMT_GRAYF32
Definition: pixfmt.h:511
AVCOL_PRI_UNSPECIFIED
@ AVCOL_PRI_UNSPECIFIED
Definition: pixfmt.h:558
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:271
AV_PIX_FMT_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:100
AV_PIX_FMT_RGBA64
#define AV_PIX_FMT_RGBA64
Definition: pixfmt.h:468
NULL
#define NULL
Definition: coverity.c:32
AVCodecContext::color_range
enum AVColorRange color_range
MPEG vs JPEG YUV range.
Definition: avcodec.h:695
av_buffer_unref
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition: buffer.c:139
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
AVCodecContext::internal
struct AVCodecInternal * internal
Private context used for internal data.
Definition: avcodec.h:480
AVCOL_PRI_BT709
@ AVCOL_PRI_BT709
also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP 177 Annex B
Definition: pixfmt.h:557
AV_PICTURE_TYPE_I
@ AV_PICTURE_TYPE_I
Intra.
Definition: avutil.h:279
AV_FRAME_DATA_ICC_PROFILE
@ AV_FRAME_DATA_ICC_PROFILE
The data contains an ICC profile as an opaque octet buffer following the format described by ISO 1507...
Definition: frame.h:144
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:81
error.h
AVCOL_PRI_BT2020
@ AVCOL_PRI_BT2020
ITU-R BT2020.
Definition: pixfmt.h:566
AVCOL_TRC_SMPTE2084
@ AVCOL_TRC_SMPTE2084
SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems.
Definition: pixfmt.h:597
ff_get_buffer
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1575
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:366
AV_PIX_FMT_RGB24
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:75
AV_CODEC_CAP_DR1
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:52
AVPacket::size
int size
Definition: packet.h:525
codec_internal.h
LibJxlDecodeContext::iccp
AVBufferRef * iccp
Definition: libjxldec.c:55
AVCodecContext::pkt_timebase
AVRational pkt_timebase
Timebase in which pkt_dts/pts and AVPacket.dts/pts are expressed.
Definition: avcodec.h:551
AV_PIX_FMT_RGB48
#define AV_PIX_FMT_RGB48
Definition: pixfmt.h:464
av_make_q
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition: rational.h:71
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
frame.h
header
static const uint8_t header[24]
Definition: sdr2.c:68
buffer.h
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:523
csp.h
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
LibJxlDecodeContext::frame_duration
int64_t frame_duration
Definition: libjxldec.c:58
av_buffer_alloc
AVBufferRef * av_buffer_alloc(size_t size)
Allocate an AVBuffer of the given size using av_malloc().
Definition: buffer.c:77
libjxl_get_primaries
static enum AVColorPrimaries libjxl_get_primaries(void *avctx, const JxlColorEncoding *jxl_color)
Definition: libjxldec.c:158
AVCOL_TRC_BT709
@ AVCOL_TRC_BT709
also ITU-R BT1361
Definition: pixfmt.h:582
AV_PIX_FMT_YA16
#define AV_PIX_FMT_YA16
Definition: pixfmt.h:463
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:517
common.h
AVCodecInternal::in_pkt
AVPacket * in_pkt
This packet is used to hold the packet given to decoders implementing the .decode API; it is unused b...
Definition: internal.h:76
LibJxlDecodeContext::anim_timebase
AVRational anim_timebase
Definition: libjxldec.c:60
AV_CODEC_ID_JPEGXL
@ AV_CODEC_ID_JPEGXL
Definition: codec_id.h:313
av_frame_move_ref
void av_frame_move_ref(AVFrame *dst, AVFrame *src)
Move everything contained in src to dst and reset src.
Definition: frame.c:633
av_d2q
AVRational av_d2q(double d, int max)
Convert a double precision floating point number to a rational.
Definition: rational.c:106
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:194
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:657
FF_CODEC_CAP_ICC_PROFILES
#define FF_CODEC_CAP_ICC_PROFILES
Codec supports embedded ICC profiles (AV_FRAME_DATA_ICC_PROFILE).
Definition: codec_internal.h:81
avcodec.h
ret
ret
Definition: filter_design.txt:187
pixfmt.h
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
libjxl_receive_frame
static int libjxl_receive_frame(AVCodecContext *avctx, AVFrame *frame)
Definition: libjxldec.c:363
AVCodecContext
main external API structure.
Definition: avcodec.h:445
AVCOL_TRC_ARIB_STD_B67
@ AVCOL_TRC_ARIB_STD_B67
ARIB STD-B67, known as "Hybrid log-gamma".
Definition: pixfmt.h:601
FF_CODEC_RECEIVE_FRAME_CB
#define FF_CODEC_RECEIVE_FRAME_CB(func)
Definition: codec_internal.h:292
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
AV_PIX_FMT_RGBAF32
#define AV_PIX_FMT_RGBAF32
Definition: pixfmt.h:549
AVFormatContext::duration
int64_t duration
Duration of the stream, in AV_TIME_BASE fractional seconds.
Definition: avformat.h:1390
desc
const char * desc
Definition: libsvtav1.c:79
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
mem.h
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
FF_CODEC_CAP_AUTO_THREADS
#define FF_CODEC_CAP_AUTO_THREADS
Codec handles avctx->thread_count == 0 (auto) internally.
Definition: codec_internal.h:72
LibJxlDecodeContext::frame
AVFrame * frame
Definition: libjxldec.c:61
LibJxlDecodeContext::runner
void * runner
Definition: libjxldec.c:47
libjxl_decode_close
static av_cold int libjxl_decode_close(AVCodecContext *avctx)
Definition: libjxldec.c:521
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:472
AVPacket
This structure stores compressed data.
Definition: packet.h:501
LibJxlDecodeContext
Definition: libjxldec.c:46
ff_libjxl_init_memory_manager
void ff_libjxl_init_memory_manager(JxlMemoryManager *manager)
Initialize and populate a JxlMemoryManager with av_malloc() and av_free() so libjxl will use these fu...
Definition: libjxl.c:65
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
AVCOL_TRC_SMPTE428
@ AVCOL_TRC_SMPTE428
SMPTE ST 428-1.
Definition: pixfmt.h:599
LibJxlDecodeContext::prev_is_last
int prev_is_last
Definition: libjxldec.c:59
LibJxlDecodeContext::basic_info
JxlBasicInfo basic_info
Definition: libjxldec.c:49
libjxl_get_trc
static enum AVColorTransferCharacteristic libjxl_get_trc(void *avctx, const JxlColorEncoding *jxl_color)
Definition: libjxldec.c:185
libjxl_color_encoding_event
static int libjxl_color_encoding_event(AVCodecContext *avctx, AVFrame *frame)
Definition: libjxldec.c:258