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 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  ctx->frame_duration = 1;
84 
85  return 0;
86 }
87 
89 {
91  JxlMemoryManager manager;
92 
94  ctx->decoder = JxlDecoderCreate(&manager);
95  if (!ctx->decoder) {
96  av_log(avctx, AV_LOG_ERROR, "Failed to create JxlDecoder\n");
97  return AVERROR_EXTERNAL;
98  }
99 
100  ctx->runner = JxlThreadParallelRunnerCreate(&manager, ff_libjxl_get_threadcount(avctx->thread_count));
101  if (!ctx->runner) {
102  av_log(avctx, AV_LOG_ERROR, "Failed to create JxlThreadParallelRunner\n");
103  return AVERROR_EXTERNAL;
104  }
105 
106  ctx->avpkt = avctx->internal->in_pkt;
107  ctx->pts = 0;
108  ctx->frame = av_frame_alloc();
109  if (!ctx->frame)
110  return AVERROR(ENOMEM);
111 
112  return libjxl_init_jxl_decoder(avctx);
113 }
114 
116 {
117  const JxlBasicInfo *basic_info = &ctx->basic_info;
118  JxlPixelFormat *format = &ctx->jxl_pixfmt;
119  format->endianness = JXL_NATIVE_ENDIAN;
120  format->num_channels = basic_info->num_color_channels + (basic_info->alpha_bits > 0);
121 #if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0)
122  ctx->jxl_bit_depth.bits_per_sample = avctx->bits_per_raw_sample = basic_info->bits_per_sample;
123  ctx->jxl_bit_depth.type = JXL_BIT_DEPTH_FROM_PIXEL_FORMAT;
124  ctx->jxl_bit_depth.exponent_bits_per_sample = basic_info->exponent_bits_per_sample;
125 #endif
126  /* Gray */
127  if (basic_info->num_color_channels == 1) {
128  if (basic_info->bits_per_sample <= 8) {
129  format->data_type = JXL_TYPE_UINT8;
130  return basic_info->alpha_bits ? AV_PIX_FMT_YA8 : AV_PIX_FMT_GRAY8;
131  }
132  if (basic_info->exponent_bits_per_sample || basic_info->bits_per_sample > 16) {
133  if (basic_info->alpha_bits)
134  return AV_PIX_FMT_NONE;
135  format->data_type = JXL_TYPE_FLOAT;
136  return AV_PIX_FMT_GRAYF32;
137  }
138  format->data_type = JXL_TYPE_UINT16;
139  return basic_info->alpha_bits ? AV_PIX_FMT_YA16 : AV_PIX_FMT_GRAY16;
140  }
141  /* rgb only */
142  /* libjxl only supports packed RGB and gray output at the moment */
143  if (basic_info->num_color_channels == 3) {
144  if (basic_info->bits_per_sample <= 8) {
145  format->data_type = JXL_TYPE_UINT8;
146  return basic_info->alpha_bits ? AV_PIX_FMT_RGBA : AV_PIX_FMT_RGB24;
147  }
148  if (basic_info->exponent_bits_per_sample)
149  av_log(avctx, AV_LOG_WARNING, "Downsampling float to 16-bit integer via libjxl\n");
150  else if (basic_info->bits_per_sample > 16)
151  av_log(avctx, AV_LOG_WARNING, "Downsampling larger integer to 16-bit via libjxl\n");
152  format->data_type = JXL_TYPE_UINT16;
153  return basic_info->alpha_bits ? AV_PIX_FMT_RGBA64 : AV_PIX_FMT_RGB48;
154  }
155 
156  return AV_PIX_FMT_NONE;
157 }
158 
159 static enum AVColorPrimaries libjxl_get_primaries(void *avctx, const JxlColorEncoding *jxl_color)
160 {
162  enum AVColorPrimaries prim;
163 
164  /* libjxl populates these double values even if it uses an enum space */
165  desc.prim.r.x = av_d2q(jxl_color->primaries_red_xy[0], 300000);
166  desc.prim.r.y = av_d2q(jxl_color->primaries_red_xy[1], 300000);
167  desc.prim.g.x = av_d2q(jxl_color->primaries_green_xy[0], 300000);
168  desc.prim.g.y = av_d2q(jxl_color->primaries_green_xy[1], 300000);
169  desc.prim.b.x = av_d2q(jxl_color->primaries_blue_xy[0], 300000);
170  desc.prim.b.y = av_d2q(jxl_color->primaries_blue_xy[1], 300000);
171  desc.wp.x = av_d2q(jxl_color->white_point_xy[0], 300000);
172  desc.wp.y = av_d2q(jxl_color->white_point_xy[1], 300000);
173 
175  if (prim == AVCOL_PRI_UNSPECIFIED) {
176  /* try D65 with the same primaries */
177  /* BT.709 uses D65 white point */
179  av_log(avctx, AV_LOG_WARNING, "Changing unknown white point to D65\n");
181  }
182 
183  return prim;
184 }
185 
186 static enum AVColorTransferCharacteristic libjxl_get_trc(void *avctx, const JxlColorEncoding *jxl_color)
187 {
188  switch (jxl_color->transfer_function) {
189  case JXL_TRANSFER_FUNCTION_709: return AVCOL_TRC_BT709;
190  case JXL_TRANSFER_FUNCTION_LINEAR: return AVCOL_TRC_LINEAR;
191  case JXL_TRANSFER_FUNCTION_SRGB: return AVCOL_TRC_IEC61966_2_1;
192  case JXL_TRANSFER_FUNCTION_PQ: return AVCOL_TRC_SMPTE2084;
193  case JXL_TRANSFER_FUNCTION_DCI: return AVCOL_TRC_SMPTE428;
194  case JXL_TRANSFER_FUNCTION_HLG: return AVCOL_TRC_ARIB_STD_B67;
195  case JXL_TRANSFER_FUNCTION_GAMMA:
196  if (jxl_color->gamma > 0.45355 && jxl_color->gamma < 0.45555)
197  return AVCOL_TRC_GAMMA22;
198  else if (jxl_color->gamma > 0.35614 && jxl_color->gamma < 0.35814)
199  return AVCOL_TRC_GAMMA28;
200  else
201  av_log(avctx, AV_LOG_WARNING, "Unsupported gamma transfer: %f\n", jxl_color->gamma);
202  break;
203  default:
204  av_log(avctx, AV_LOG_WARNING, "Unknown transfer function: %d\n", jxl_color->transfer_function);
205  }
206 
207  return AVCOL_TRC_UNSPECIFIED;
208 }
209 
210 static int libjxl_get_icc(AVCodecContext *avctx)
211 {
213  size_t icc_len;
214  JxlDecoderStatus jret;
215  /* an ICC profile is present, and we can meaningfully get it,
216  * because the pixel data is not XYB-encoded */
217 #if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0, 9, 0)
218  jret = JxlDecoderGetICCProfileSize(ctx->decoder, &ctx->jxl_pixfmt, JXL_COLOR_PROFILE_TARGET_DATA, &icc_len);
219 #else
220  jret = JxlDecoderGetICCProfileSize(ctx->decoder, JXL_COLOR_PROFILE_TARGET_DATA, &icc_len);
221 #endif
222  if (jret == JXL_DEC_SUCCESS && icc_len > 0) {
223  av_buffer_unref(&ctx->iccp);
224  ctx->iccp = av_buffer_alloc(icc_len);
225  if (!ctx->iccp)
226  return AVERROR(ENOMEM);
227 #if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0, 9, 0)
228  jret = JxlDecoderGetColorAsICCProfile(ctx->decoder, &ctx->jxl_pixfmt, JXL_COLOR_PROFILE_TARGET_DATA,
229  ctx->iccp->data, icc_len);
230 #else
231  jret = JxlDecoderGetColorAsICCProfile(ctx->decoder, JXL_COLOR_PROFILE_TARGET_DATA, ctx->iccp->data, icc_len);
232 #endif
233  if (jret != JXL_DEC_SUCCESS) {
234  av_log(avctx, AV_LOG_WARNING, "Unable to obtain ICC Profile\n");
235  av_buffer_unref(&ctx->iccp);
236  }
237  }
238 
239  return 0;
240 }
241 
242 /*
243  * There's generally four cases when it comes to decoding a libjxl image
244  * with regard to color encoding:
245  * (a) There is an embedded ICC profile in the image, and the image is XYB-encoded.
246  * (b) There is an embedded ICC profile in the image, and the image is not XYB-encoded.
247  * (c) There is no embedded ICC profile, and FFmpeg supports the tagged colorspace.
248  * (d) There is no embedded ICC profile, and FFmpeg does not support the tagged colorspace.
249  *
250  * In case (b), we forward the pixel data as is and forward the ICC Profile as-is.
251  * In case (c), we request the pixel data in the space it's tagged as,
252  * and tag the space accordingly.
253  * In case (a), libjxl does not support getting the pixel data in the space described by the ICC
254  * profile, so instead we request the pixel data in BT.2020/PQ as it is the widest
255  * space that FFmpeg supports.
256  * In case (d), we also request wide-gamut pixel data as a fallback since FFmpeg doesn't support
257  * the custom primaries tagged in the space.
258  */
260 {
262  JxlDecoderStatus jret;
263  int ret;
264  JxlColorEncoding jxl_color;
265  /* set this flag if we need to fall back on wide gamut */
266  int fallback = 0;
267 
268 #if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0, 9, 0)
269  jret = JxlDecoderGetColorAsEncodedProfile(ctx->decoder, NULL, JXL_COLOR_PROFILE_TARGET_ORIGINAL, &jxl_color);
270 #else
271  jret = JxlDecoderGetColorAsEncodedProfile(ctx->decoder, JXL_COLOR_PROFILE_TARGET_ORIGINAL, &jxl_color);
272 #endif
273  if (jret == JXL_DEC_SUCCESS) {
274  /* enum values describe the colors of this image */
275  jret = JxlDecoderSetPreferredColorProfile(ctx->decoder, &jxl_color);
276  if (jret == JXL_DEC_SUCCESS)
277 #if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0, 9, 0)
278  jret = JxlDecoderGetColorAsEncodedProfile(ctx->decoder, &ctx->jxl_pixfmt,
279  JXL_COLOR_PROFILE_TARGET_DATA, &jxl_color);
280 #else
281  jret = JxlDecoderGetColorAsEncodedProfile(ctx->decoder, JXL_COLOR_PROFILE_TARGET_DATA, &jxl_color);
282 #endif
283  /* if we couldn't successfully request the pixel data space, we fall back on wide gamut */
284  /* this code path is very unlikely to happen in practice */
285  if (jret != JXL_DEC_SUCCESS)
286  fallback = 1;
287  } else {
288  /* an ICC Profile is present in the stream */
289  if (ctx->basic_info.uses_original_profile) {
290  /* uses_original_profile is the same as !xyb_encoded */
291  av_log(avctx, AV_LOG_VERBOSE, "Using embedded ICC Profile\n");
292  if ((ret = libjxl_get_icc(avctx)) < 0)
293  return ret;
294  } else {
295  /*
296  * an XYB-encoded image with an embedded ICC profile can't always have the
297  * pixel data requested in the original space, so libjxl has no feature
298  * to allow this to happen, so we fall back on wide gamut
299  */
300  fallback = 1;
301  }
302  }
303 
305  if (ctx->basic_info.num_color_channels > 1)
306  avctx->colorspace = AVCOL_SPC_RGB;
309 
310  if (!ctx->iccp) {
311  /* checking enum values */
312  if (!fallback) {
313  if (avctx->colorspace == AVCOL_SPC_RGB)
314  avctx->color_primaries = libjxl_get_primaries(avctx, &jxl_color);
315  avctx->color_trc = libjxl_get_trc(avctx, &jxl_color);
316  }
317  /* fall back on wide gamut if enum values fail */
318  if (avctx->color_primaries == AVCOL_PRI_UNSPECIFIED) {
319  if (avctx->colorspace == AVCOL_SPC_RGB) {
320  av_log(avctx, AV_LOG_WARNING, "Falling back on wide gamut output\n");
321  jxl_color.primaries = JXL_PRIMARIES_2100;
323  }
324  /* libjxl requires this set even for grayscale */
325  jxl_color.white_point = JXL_WHITE_POINT_D65;
326  }
327  if (avctx->color_trc == AVCOL_TRC_UNSPECIFIED) {
328  if (ctx->jxl_pixfmt.data_type == JXL_TYPE_FLOAT
329  || ctx->jxl_pixfmt.data_type == JXL_TYPE_FLOAT16) {
330  av_log(avctx, AV_LOG_WARNING, "Falling back on Linear Light transfer\n");
331  jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_LINEAR;
332  avctx->color_trc = AVCOL_TRC_LINEAR;
333  } else {
334  av_log(avctx, AV_LOG_WARNING, "Falling back on iec61966-2-1/sRGB transfer\n");
335  jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_SRGB;
337  }
338  }
339  /* all colors will be in-gamut so we want accurate colors */
340  jxl_color.rendering_intent = JXL_RENDERING_INTENT_RELATIVE;
341  jxl_color.color_space = ctx->basic_info.num_color_channels > 1 ? JXL_COLOR_SPACE_RGB : JXL_COLOR_SPACE_GRAY;
342  jret = JxlDecoderSetPreferredColorProfile(ctx->decoder, &jxl_color);
343  if (jret != JXL_DEC_SUCCESS) {
344  av_log(avctx, AV_LOG_WARNING, "Unable to set fallback color encoding\n");
345  /*
346  * This should only happen if there's a non-XYB encoded image with custom primaries
347  * embedded as enums and no embedded ICC Profile.
348  * In this case, libjxl will synthesize an ICC Profile for us.
349  */
352  if ((ret = libjxl_get_icc(avctx)) < 0)
353  return ret;
354  }
355  }
356 
357  frame->color_trc = avctx->color_trc;
359  frame->colorspace = avctx->colorspace;
360 
361  return 0;
362 }
363 
365 {
367  JxlDecoderStatus jret = JXL_DEC_SUCCESS;
368  int ret;
369  AVPacket *pkt = ctx->avpkt;
370 
371  while (1) {
372  size_t remaining;
373 
374  if (!pkt->size) {
376  ret = ff_decode_get_packet(avctx, pkt);
377  if (ret < 0 && ret != AVERROR_EOF)
378  return ret;
379  if (!pkt->size) {
380  /* jret set by the last iteration of the loop */
381  if (jret == JXL_DEC_NEED_MORE_INPUT) {
382  av_log(avctx, AV_LOG_ERROR, "Unexpected end of JXL codestream\n");
383  return AVERROR_INVALIDDATA;
384  } else {
385  return AVERROR_EOF;
386  }
387  }
388  }
389 
390  jret = JxlDecoderSetInput(ctx->decoder, pkt->data, pkt->size);
391  if (jret == JXL_DEC_ERROR) {
392  /* this should never happen here unless there's a bug in libjxl */
393  av_log(avctx, AV_LOG_ERROR, "Unknown libjxl decode error\n");
394  return AVERROR_EXTERNAL;
395  }
396 
397  jret = JxlDecoderProcessInput(ctx->decoder);
398  /*
399  * JxlDecoderReleaseInput returns the number
400  * of bytes remaining to be read, rather than
401  * the number of bytes that it did read
402  */
403  remaining = JxlDecoderReleaseInput(ctx->decoder);
404  pkt->data += pkt->size - remaining;
405  pkt->size = remaining;
406 
407  switch(jret) {
408  case JXL_DEC_ERROR:
409  av_log(avctx, AV_LOG_ERROR, "Unknown libjxl decode error\n");
410  return AVERROR_INVALIDDATA;
411  case JXL_DEC_NEED_MORE_INPUT:
412  av_log(avctx, AV_LOG_DEBUG, "NEED_MORE_INPUT event emitted\n");
413  continue;
414  case JXL_DEC_BASIC_INFO:
415  av_log(avctx, AV_LOG_DEBUG, "BASIC_INFO event emitted\n");
416  if (JxlDecoderGetBasicInfo(ctx->decoder, &ctx->basic_info) != JXL_DEC_SUCCESS) {
417  /*
418  * this should never happen
419  * if it does it is likely a libjxl decoder bug
420  */
421  av_log(avctx, AV_LOG_ERROR, "Bad libjxl basic info event\n");
422  return AVERROR_EXTERNAL;
423  }
424  avctx->pix_fmt = libjxl_get_pix_fmt(avctx, ctx);
425  if (avctx->pix_fmt == AV_PIX_FMT_NONE) {
426  av_log(avctx, AV_LOG_ERROR, "Bad libjxl pixel format\n");
427  return AVERROR_EXTERNAL;
428  }
429  if ((ret = ff_set_dimensions(avctx, ctx->basic_info.xsize, ctx->basic_info.ysize)) < 0)
430  return ret;
431  if (ctx->basic_info.have_animation)
432  ctx->timebase = av_make_q(ctx->basic_info.animation.tps_denominator,
433  ctx->basic_info.animation.tps_numerator);
434  else if (avctx->pkt_timebase.num)
435  ctx->timebase = avctx->pkt_timebase;
436  else
437  ctx->timebase = AV_TIME_BASE_Q;
438  continue;
439  case JXL_DEC_COLOR_ENCODING:
440  av_log(avctx, AV_LOG_DEBUG, "COLOR_ENCODING event emitted\n");
441  ret = libjxl_color_encoding_event(avctx, ctx->frame);
442  if (ret < 0)
443  return ret;
444  continue;
445  case JXL_DEC_NEED_IMAGE_OUT_BUFFER:
446  av_log(avctx, AV_LOG_DEBUG, "NEED_IMAGE_OUT_BUFFER event emitted\n");
447  ret = ff_get_buffer(avctx, ctx->frame, 0);
448  if (ret < 0)
449  return ret;
450  ctx->jxl_pixfmt.align = ctx->frame->linesize[0];
451  if (JxlDecoderSetImageOutBuffer(ctx->decoder, &ctx->jxl_pixfmt,
452  ctx->frame->data[0], ctx->frame->buf[0]->size)
453  != JXL_DEC_SUCCESS) {
454  av_log(avctx, AV_LOG_ERROR, "Bad libjxl dec need image out buffer event\n");
455  return AVERROR_EXTERNAL;
456  }
457 #if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0)
458  if (JxlDecoderSetImageOutBitDepth(ctx->decoder, &ctx->jxl_bit_depth) != JXL_DEC_SUCCESS) {
459  av_log(avctx, AV_LOG_ERROR, "Error setting output bit depth\n");
460  return AVERROR_EXTERNAL;
461  }
462 #endif
463  continue;
464  case JXL_DEC_FRAME:
465  av_log(avctx, AV_LOG_DEBUG, "FRAME event emitted\n");
466  if (!ctx->basic_info.have_animation || ctx->prev_is_last) {
467  ctx->frame->pict_type = AV_PICTURE_TYPE_I;
468  ctx->frame->flags |= AV_FRAME_FLAG_KEY;
469  }
470  if (ctx->basic_info.have_animation) {
471  JxlFrameHeader header;
472  if (JxlDecoderGetFrameHeader(ctx->decoder, &header) != JXL_DEC_SUCCESS) {
473  av_log(avctx, AV_LOG_ERROR, "Bad libjxl dec frame event\n");
474  return AVERROR_EXTERNAL;
475  }
476  ctx->prev_is_last = header.is_last;
477  ctx->frame_duration = header.duration;
478  } else {
479  ctx->prev_is_last = 1;
480  ctx->frame_duration = 1;
481  }
482  continue;
483  case JXL_DEC_FULL_IMAGE:
484  /* full image is one frame, even if animated */
485  av_log(avctx, AV_LOG_DEBUG, "FULL_IMAGE event emitted\n");
486  if (ctx->iccp) {
488  if (!sd)
489  return AVERROR(ENOMEM);
490  /* ownership is transfered, and it is not ref-ed */
491  ctx->iccp = NULL;
492  }
493  if (avctx->pkt_timebase.num) {
494  ctx->frame->pts = av_rescale_q(ctx->pts, ctx->timebase, avctx->pkt_timebase);
495  ctx->frame->duration = av_rescale_q(ctx->frame_duration, ctx->timebase, avctx->pkt_timebase);
496  } else {
497  ctx->frame->pts = ctx->pts;
498  ctx->frame->duration = ctx->frame_duration;
499  }
500  ctx->pts += ctx->frame_duration;
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 };
AVFrame::color_trc
enum AVColorTransferCharacteristic color_trc
Definition: frame.h:660
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:423
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:241
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
AVFrame::color_range
enum AVColorRange color_range
MPEG vs JPEG YUV range.
Definition: frame.h:656
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
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:133
AVCodecContext::colorspace
enum AVColorSpace colorspace
YUV colorspace type.
Definition: avcodec.h:1029
AVColorTransferCharacteristic
AVColorTransferCharacteristic
Color Transfer Characteristic.
Definition: pixfmt.h:570
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:579
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:264
LibJxlDecodeContext::avpkt
AVPacket * avpkt
Definition: libjxldec.c:56
AVFrame::color_primaries
enum AVColorPrimaries color_primaries
Definition: frame.h:658
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:100
AVFrame::colorspace
enum AVColorSpace colorspace
YUV colorspace type.
Definition: frame.h:667
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:340
pixdesc.h
AVCodecContext::color_trc
enum AVColorTransferCharacteristic color_trc
Color Transfer Characteristic.
Definition: avcodec.h:1022
AVCOL_RANGE_JPEG
@ AVCOL_RANGE_JPEG
Full range content.
Definition: pixfmt.h:673
internal.h
AVPacket::data
uint8_t * data
Definition: packet.h:491
AVCOL_TRC_UNSPECIFIED
@ AVCOL_TRC_UNSPECIFIED
Definition: pixfmt.h:573
libjxl_decode_init
static av_cold int libjxl_decode_init(AVCodecContext *avctx)
Definition: libjxldec.c:88
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:127
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:600
AVColorPrimaries
AVColorPrimaries
Chromaticity coordinates of the source primaries.
Definition: pixfmt.h:545
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:131
AVCOL_TRC_IEC61966_2_1
@ AVCOL_TRC_IEC61966_2_1
IEC 61966-2-1 (sRGB or sYCC)
Definition: pixfmt.h:584
AVCodecContext::thread_count
int thread_count
thread count is used to decide how many independent tasks should be passed to execute()
Definition: avcodec.h:1532
AVCOL_TRC_GAMMA28
@ AVCOL_TRC_GAMMA28
also ITU-R BT470BG
Definition: pixfmt.h:576
libjxl_get_pix_fmt
static enum AVPixelFormat libjxl_get_pix_fmt(AVCodecContext *avctx, LibJxlDecodeContext *ctx)
Definition: libjxldec.c:115
AV_PIX_FMT_GRAY16
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:452
AVRational::num
int num
Numerator.
Definition: rational.h:59
AVCOL_TRC_GAMMA22
@ AVCOL_TRC_GAMMA22
also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM
Definition: pixfmt.h:575
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:88
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:1015
pkt
AVPacket * pkt
Definition: movenc.c:59
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:628
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:1233
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
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
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts_bsf.c:365
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:1517
LibJxlDecodeContext::pts
int64_t pts
Definition: libjxldec.c:57
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:48
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:210
LibJxlDecodeContext::jxl_pixfmt
JxlPixelFormat jxl_pixfmt
Definition: libjxldec.c:50
AV_PIX_FMT_GRAYF32
#define AV_PIX_FMT_GRAYF32
Definition: pixfmt.h:501
AVCOL_PRI_UNSPECIFIED
@ AVCOL_PRI_UNSPECIFIED
Definition: pixfmt.h:548
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:272
AV_PIX_FMT_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:93
frame
static AVFrame * frame
Definition: demux_decode.c:54
AV_PIX_FMT_RGBA64
#define AV_PIX_FMT_RGBA64
Definition: pixfmt.h:458
NULL
#define NULL
Definition: coverity.c:32
AVCodecContext::color_range
enum AVColorRange color_range
MPEG vs JPEG YUV range.
Definition: avcodec.h:1039
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:476
AVCOL_PRI_BT709
@ AVCOL_PRI_BT709
also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP 177 Annex B
Definition: pixfmt.h:547
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_frame_new_side_data_from_buf
AVFrameSideData * av_frame_new_side_data_from_buf(AVFrame *frame, enum AVFrameSideDataType type, AVBufferRef *buf)
Add a new side data to a frame from an existing AVBufferRef.
Definition: frame.c:780
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:74
error.h
AVCOL_PRI_BT2020
@ AVCOL_PRI_BT2020
ITU-R BT2020.
Definition: pixfmt.h:556
LibJxlDecodeContext::timebase
AVRational timebase
Definition: libjxldec.c:60
AVCOL_TRC_SMPTE2084
@ AVCOL_TRC_SMPTE2084
SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems.
Definition: pixfmt.h:587
ff_get_buffer
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1617
AV_PIX_FMT_RGB24
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:68
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:492
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:1817
AV_PIX_FMT_RGB48
#define AV_PIX_FMT_RGB48
Definition: pixfmt.h:454
av_make_q
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition: rational.h:71
frame.h
header
static const uint8_t header[24]
Definition: sdr2.c:67
buffer.h
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:159
AVCOL_TRC_BT709
@ AVCOL_TRC_BT709
also ITU-R BT1361
Definition: pixfmt.h:572
AV_PIX_FMT_YA16
#define AV_PIX_FMT_YA16
Definition: pixfmt.h:453
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:77
AV_CODEC_ID_JPEGXL
@ AV_CODEC_ID_JPEGXL
Definition: codec_id.h:316
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:649
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:658
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:82
avcodec.h
ret
ret
Definition: filter_design.txt:187
pixfmt.h
libjxl_receive_frame
static int libjxl_receive_frame(AVCodecContext *avctx, AVFrame *frame)
Definition: libjxldec.c:364
AVCodecContext
main external API structure.
Definition: avcodec.h:441
AVCOL_TRC_ARIB_STD_B67
@ AVCOL_TRC_ARIB_STD_B67
ARIB STD-B67, known as "Hybrid log-gamma".
Definition: pixfmt.h:591
FF_CODEC_RECEIVE_FRAME_CB
#define FF_CODEC_RECEIVE_FRAME_CB(func)
Definition: codec_internal.h:312
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
AVFormatContext::duration
int64_t duration
Duration of the stream, in AV_TIME_BASE fractional seconds.
Definition: avformat.h:1217
desc
const char * desc
Definition: libsvtav1.c:83
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:73
LibJxlDecodeContext::frame
AVFrame * frame
Definition: libjxldec.c:61
AVFrameSideData
Structure to hold side data for an AVFrame.
Definition: frame.h:246
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:468
AVPacket
This structure stores compressed data.
Definition: packet.h:468
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:589
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:186
libjxl_color_encoding_event
static int libjxl_color_encoding_event(AVCodecContext *avctx, AVFrame *frame)
Definition: libjxldec.c:259