46#include <jxl/encode.h>
47#include <jxl/thread_parallel_runner.h>
89 return (100.0 -
quality) * 0.10;
91 return 0.1 + (100.0 -
quality) * 0.09;
110 JxlEncoderReset(
ctx->encoder);
113 if (JxlEncoderSetParallelRunner(
ctx->encoder, JxlThreadParallelRunner,
ctx->runner)
114 != JXL_ENC_SUCCESS) {
119 ctx->options = JxlEncoderFrameSettingsCreate(
ctx->encoder,
NULL);
135 JxlMemoryManager manager;
138 ctx->encoder = JxlEncoderCreate(&manager);
150 ctx->buffer_size = 4096;
159 if (
ctx->distance < 0.0) {
171 if (
ctx->distance > 0.0 &&
ctx->distance < 0.01)
172 ctx->distance = 0.01;
212 jxl_color->primaries = JXL_PRIMARIES_SRGB;
213 jxl_color->white_point = JXL_WHITE_POINT_D65;
216 jxl_color->primaries = JXL_PRIMARIES_2100;
217 jxl_color->white_point = JXL_WHITE_POINT_D65;
220 jxl_color->primaries = JXL_PRIMARIES_P3;
221 jxl_color->white_point = JXL_WHITE_POINT_DCI;
224 jxl_color->primaries = JXL_PRIMARIES_P3;
225 jxl_color->white_point = JXL_WHITE_POINT_D65;
228 av_log(avctx,
AV_LOG_WARNING,
"Unknown primaries, assuming BT.709/sRGB. Colors may be wrong.\n");
229 jxl_color->primaries = JXL_PRIMARIES_SRGB;
230 jxl_color->white_point = JXL_WHITE_POINT_D65;
238 jxl_color->primaries = JXL_PRIMARIES_CUSTOM;
239 jxl_color->white_point = JXL_WHITE_POINT_CUSTOM;
241 jxl_color->primaries_red_xy[0] =
av_q2d(
desc->prim.r.x);
242 jxl_color->primaries_red_xy[1] =
av_q2d(
desc->prim.r.y);
243 jxl_color->primaries_green_xy[0] =
av_q2d(
desc->prim.g.x);
244 jxl_color->primaries_green_xy[1] =
av_q2d(
desc->prim.g.y);
245 jxl_color->primaries_blue_xy[0] =
av_q2d(
desc->prim.b.x);
246 jxl_color->primaries_blue_xy[1] =
av_q2d(
desc->prim.b.y);
247 jxl_color->white_point_xy[0] =
av_q2d(
desc->wp.x);
248 jxl_color->white_point_xy[1] =
av_q2d(
desc->wp.y);
256 JxlColorEncoding jxl_color;
263 jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_709;
266 jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_LINEAR;
269 jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_SRGB;
272 jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_DCI;
275 jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_PQ;
278 jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_HLG;
281 jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_GAMMA;
282 jxl_color.gamma = 1/2.2f;
285 jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_GAMMA;
286 jxl_color.gamma = 1/2.8f;
291 "Unknown transfer function, assuming Linear Light. Colors may be wrong.\n");
292 jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_LINEAR;
295 "Unknown transfer function, assuming IEC61966-2-1/sRGB. Colors may be wrong.\n");
296 jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_SRGB;
300 jxl_color.rendering_intent = JXL_RENDERING_INTENT_RELATIVE;
301 if (info->num_color_channels == 1)
302 jxl_color.color_space = JXL_COLOR_SPACE_GRAY;
304 jxl_color.color_space = JXL_COLOR_SPACE_RGB;
312 if (JxlEncoderSetColorEncoding(
ctx->encoder, &jxl_color) != JXL_ENC_SUCCESS) {
323 JxlEncoderStatus jret = JXL_ENC_SUCCESS;
324 int ret = 0, opened = 0;
327 if (!
ctx->exif_buffer)
330 jret = JxlEncoderUseBoxes(
ctx->encoder);
331 if (jret != JXL_ENC_SUCCESS) {
338 jret = JxlEncoderAddBox(
ctx->encoder,
"Exif",
ctx->exif_buffer->data,
ctx->exif_buffer->size, JXL_TRUE);
339 if (jret != JXL_ENC_SUCCESS)
340 jret = JxlEncoderAddBox(
ctx->encoder,
"Exif",
ctx->exif_buffer->data,
ctx->exif_buffer->size, JXL_FALSE);
341 if (jret != JXL_ENC_SUCCESS) {
349 JxlEncoderCloseBoxes(
ctx->encoder);
363 int ret = 0, have_matrix = 0;
364 JxlEncoderStatus jret = JXL_ENC_SUCCESS;
367 JxlPixelFormat *jxl_fmt = &
ctx->jxl_fmt;
370#if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0)
371 JxlBitDepth jxl_bit_depth;
375 JxlEncoderInitBasicInfo(&info);
377 info.xsize =
frame->width;
378 info.ysize =
frame->height;
379 info.num_extra_channels = (jxl_fmt->num_channels + 1) & 0x1;
380 info.num_color_channels = jxl_fmt->num_channels - info.num_extra_channels;
384 info.alpha_bits = (info.num_extra_channels > 0) * info.bits_per_sample;
386 info.exponent_bits_per_sample = info.bits_per_sample > 16 ? 8 : 5;
387 info.alpha_exponent_bits = info.alpha_bits ? info.exponent_bits_per_sample : 0;
388 jxl_fmt->data_type = info.bits_per_sample > 16 ? JXL_TYPE_FLOAT : JXL_TYPE_FLOAT16;
390 info.exponent_bits_per_sample = 0;
391 info.alpha_exponent_bits = 0;
392 jxl_fmt->data_type = info.bits_per_sample <= 8 ? JXL_TYPE_UINT8 : JXL_TYPE_UINT16;
395 if (info.alpha_bits) {
398 info.alpha_premultiplied = 1;
404#if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0)
405 jxl_bit_depth.bits_per_sample = bits_per_sample;
406 jxl_bit_depth.type = JXL_BIT_DEPTH_FROM_PIXEL_FORMAT;
408 info.exponent_bits_per_sample : 0;
414 av_log(avctx,
AV_LOG_WARNING,
"This encoder does not support limited (tv) range, colors will be wrong!\n");
419 info.uses_original_profile =
ctx->distance == 0.0 || !
ctx->xyb;
436 if (ret >= 0 && orient) {
459 if (
frame->linesize[0] < 0)
465 info.orientation = orientation;
468 info.orientation =
frame->linesize[0] >= 0 ? JXL_ORIENT_IDENTITY : JXL_ORIENT_FLIP_VERTICAL;
472 if (
frame->linesize[0] < 0)
476 info.have_animation = 1;
477 info.animation.have_timecodes = 0;
478 info.animation.num_loops = 0;
484 jret = JxlEncoderSetBasicInfo(
ctx->encoder, &info);
485 if (jret != JXL_ENC_SUCCESS) {
491 if (info.alpha_bits) {
492 JxlExtraChannelInfo extra_info;
493 JxlEncoderInitExtraChannelInfo(JXL_CHANNEL_ALPHA, &extra_info);
494 extra_info.bits_per_sample = info.alpha_bits;
495 extra_info.exponent_bits_per_sample = info.alpha_exponent_bits;
496 extra_info.alpha_premultiplied = info.alpha_premultiplied;
497 jret = JxlEncoderSetExtraChannelInfo(
ctx->encoder, 0, &extra_info);
498 if (jret != JXL_ENC_SUCCESS) {
506 if (sd && sd->
size) {
507 jret = JxlEncoderSetICCProfile(
ctx->encoder, sd->
data, sd->
size);
508 if (jret != JXL_ENC_SUCCESS)
513 if (!sd || !sd->
size || jret != JXL_ENC_SUCCESS)
516#if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0)
517 jret = JxlEncoderSetFrameBitDepth(
ctx->options, &jxl_bit_depth);
518 if (jret != JXL_ENC_SUCCESS)
524 if (JxlEncoderGetRequiredCodestreamLevel(
ctx->encoder) > 5) {
525 jret = JxlEncoderSetCodestreamLevel(
ctx->encoder, 10);
526 if (jret != JXL_ENC_SUCCESS)
551 JxlPixelFormat *jxl_fmt = &
ctx->jxl_fmt;
554 if (JxlEncoderFrameSettingsSetOption(
ctx->options, JXL_ENC_FRAME_SETTING_EFFORT,
ctx->effort)
555 != JXL_ENC_SUCCESS) {
560 if (JxlEncoderSetFrameDistance(
ctx->options,
ctx->distance) != JXL_ENC_SUCCESS) {
570 if (JxlEncoderFrameSettingsSetOption(
ctx->options, JXL_ENC_FRAME_SETTING_MODULAR,
571 ctx->modular ||
ctx->distance <= 0.0 ? 1 : -1) != JXL_ENC_SUCCESS) {
576 jxl_fmt->endianness = JXL_NATIVE_ENDIAN;
577 if (
frame->linesize[0] >= 0) {
578 jxl_fmt->align =
frame->linesize[0];
581 jxl_fmt->align = -
frame->linesize[0];
595 JxlEncoderStatus jret;
596 size_t available =
ctx->buffer_size;
597 uint8_t *next_out =
ctx->buffer;
600 jret = JxlEncoderProcessOutput(
ctx->encoder, &next_out, &available);
601 if (jret == JXL_ENC_ERROR) {
605 *bytes_written =
ctx->buffer_size - available;
607 if (jret == JXL_ENC_SUCCESS)
609 if (jret == JXL_ENC_NEED_MORE_OUTPUT) {
616 size_t new_size =
ctx->buffer_size * 2;
621 ctx->buffer_size = new_size;
622 next_out =
ctx->buffer + *bytes_written;
623 available = new_size - *bytes_written;
642 size_t bytes_written = 0;
659 if (JxlEncoderAddImageFrame(
ctx->options, &
ctx->jxl_fmt,
data,
ctx->jxl_fmt.align *
frame->height)
660 != JXL_ENC_SUCCESS) {
668 JxlEncoderCloseInput(
ctx->encoder);
678 memcpy(
pkt->data,
ctx->buffer, bytes_written);
699 size_t bytes_written = 0;
724 ctx->duration =
ctx->prev->duration ?
ctx->prev->duration :
725 ctx->frame ?
ctx->frame->pts -
ctx->prev->pts :
726 ctx->duration ?
ctx->duration :
730 pkt->duration =
ctx->duration;
731 pkt->pts =
ctx->prev->pts;
734 if (JxlEncoderSetFrameHeader(
ctx->options, &
frame_header) != JXL_ENC_SUCCESS) {
743 if (JxlEncoderAddImageFrame(
ctx->options, &
ctx->jxl_fmt,
data,
ctx->jxl_fmt.align *
ctx->prev->height)
744 != JXL_ENC_SUCCESS) {
750 JxlEncoderCloseInput(
ctx->encoder);
760 memcpy(
pkt->data,
ctx->buffer, bytes_written);
777 JxlThreadParallelRunnerDestroy(
ctx->runner);
785 JxlEncoderDestroy(
ctx->encoder);
795#define OFFSET(x) offsetof(LibJxlEncodeContext, x)
796#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
800 {
"distance",
"Maximum Butteraugli distance (quality setting, "
803 {
"xyb",
"Use XYB-encoding for lossy images",
OFFSET(xyb),
809 .class_name =
"libjxl",
843 .p.wrapper_name =
"libjxl",
847 .p.name =
"libjxl_anim",
864 .p.wrapper_name =
"libjxl",
const FFCodec ff_libjxl_encoder
const FFCodec ff_libjxl_anim_encoder
static AVFormatContext * ctx
Libavcodec external API header.
Convenience header that includes libavutil's core.
#define CODEC_PIXFMTS_ARRAY(array)
#define FF_CODEC_CAP_NOT_INIT_THREADSAFE
The codec is not known to be init-threadsafe (i.e.
#define FF_CODEC_RECEIVE_PACKET_CB(func)
#define FF_CODEC_CAP_ICC_PROFILES
Codec supports embedded ICC profiles (AV_FRAME_DATA_ICC_PROFILE).
#define FF_CODEC_ENCODE_CB(func)
#define CODEC_LONG_NAME(str)
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
#define FF_CODEC_CAP_AUTO_THREADS
Codec handles avctx->thread_count == 0 (auto) internally.
Colorspace value utility functions for libavutil.
int(* init)(AVBSFContext *ctx)
int ff_get_encode_buffer(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int flags)
Get a buffer for a packet.
int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame)
Called by encoders to get the next frame for encoding.
int av_exif_get_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, int flags, AVExifEntry **value)
Get an entry with the tagged ID from the EXIF metadata struct.
int av_exif_parse_buffer(void *logctx, const uint8_t *buf, size_t size, AVExifMetadata *ifd, enum AVExifHeaderMode header_mode)
Decodes the EXIF data provided in the buffer and writes it into the struct *ifd.
void av_exif_free(AVExifMetadata *ifd)
Frees all resources associated with the given EXIF metadata struct.
int av_exif_matrix_to_orientation(const int32_t *matrix)
Convert a display matrix used by AV_FRAME_DATA_DISPLAYMATRIX into an orientation constant used by EXI...
int av_exif_orientation_to_matrix(int32_t *matrix, int orientation)
Convert an orientation constant used by EXIF's orientation tag into a display matrix used by AV_FRAME...
int ff_exif_sanitize_ifd(void *logctx, const AVFrame *frame, AVExifMetadata *ifd)
Compares values in the IFD with data in the provided AVFrame and sets the values in that IFD to match...
int av_exif_write(void *logctx, const AVExifMetadata *ifd, AVBufferRef **buffer, enum AVExifHeaderMode header_mode)
Allocates a buffer using av_malloc of an appropriate size and writes the EXIF data represented by ifd...
int32_t av_exif_get_tag_id(const char *name)
Retrieves the tag ID associated with the provided tag string name.
int av_exif_remove_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, int flags)
Remove an entry from the provided EXIF metadata struct.
@ AV_EXIF_TIFF_HEADER
The TIFF header starts with 0x49492a00, or 0x4d4d002a.
@ AV_EXIF_T_OFF
The first four bytes point to the actual start, then it's AV_EXIF_TIFF_HEADER.
EXIF metadata parser - internal functions.
reference-counted frame API
@ AV_OPT_TYPE_INT
Underlying C type is int.
@ AV_OPT_TYPE_FLOAT
Underlying C type is float.
#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
This encoder can reorder user opaque values from input AVFrames and return them with corresponding ou...
#define AV_CODEC_CAP_OTHER_THREADS
Codec supports multithreading through a method other than slice- or frame-level multithreading.
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
#define AV_CODEC_FLAG_QSCALE
Use fixed qscale.
@ AV_CODEC_ID_JPEGXL_ANIM
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
#define FF_QP2LAMBDA
factor to convert from H.263 QP to lambda
#define AVERROR_EXTERNAL
Generic error in an external library.
#define AVERROR_EOF
End of file.
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
AVFrameSideData * av_frame_get_side_data(const AVFrame *frame, enum AVFrameSideDataType type)
void av_frame_move_ref(AVFrame *dst, AVFrame *src)
Move everything contained in src to dst and reset src.
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
@ AV_FRAME_DATA_EXIF
Exchangeable image file format metadata.
@ AV_FRAME_DATA_DISPLAYMATRIX
This side data contains a 3x3 transformation matrix describing an affine transformation that needs to...
@ AV_FRAME_DATA_ICC_PROFILE
The data contains an ICC profile as an opaque octet buffer following the format described by ISO 1507...
#define AV_LOG_WARNING
Something somehow does not look correct.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
const char * av_default_item_name(void *ptr)
Return the context name.
const AVColorPrimariesDesc * av_csp_primaries_desc_from_id(enum AVColorPrimaries prm)
Retrieves a complete gamut description from an enum constant describing the color primaries.
static double av_q2d(AVRational a)
Convert an AVRational to a double.
#define LIBAVUTIL_VERSION_INT
void av_display_matrix_flip(int32_t matrix[9], int hflip, int vflip)
Flip the input matrix horizontally and/or vertically.
Libavutil version macros.
size_t ff_libjxl_get_threadcount(int threads)
Transform threadcount in ffmpeg to one used by libjxl.
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...
JPEG XL via libjxl common support header.
static const AVClass libjxl_encode_class
static int libjxl_preprocess_stream(AVCodecContext *avctx, const AVFrame *frame, int animated)
Sends metadata to libjxl based on the first frame of the stream, such as pixel format,...
static int libjxl_populate_colorspace(AVCodecContext *avctx, const AVFrame *frame, const AVPixFmtDescriptor *pix_desc, const JxlBasicInfo *info)
static int libjxl_anim_encode_frame(AVCodecContext *avctx, AVPacket *pkt)
Encode one frame of the animation.
static int libjxl_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet)
Encode an entire frame.
static enum AVPixelFormat libjxl_supported_pixfmts[]
static int libjxl_populate_primaries(void *avctx, JxlColorEncoding *jxl_color, enum AVColorPrimaries prm)
Populate a JxlColorEncoding with the given enum AVColorPrimaries.
static const AVOption libjxl_encode_options[]
static int libjxl_preprocess_frame(AVCodecContext *avctx, const AVFrame *frame, const uint8_t **data)
Sends frame information to libjxl on a per-frame basis.
static int libjxl_process_output(AVCodecContext *avctx, size_t *bytes_written)
Run libjxl's output processing loop, reallocating the packet as necessary if libjxl needs more space ...
static av_cold int libjxl_anim_encode_init(AVCodecContext *avctx)
Initializer for the animation encoder.
static av_cold int libjxl_encode_close(AVCodecContext *avctx)
static int libjxl_add_boxes(AVCodecContext *avctx)
static float quality_to_distance(float quality)
Map a quality setting for -qscale roughly from libjpeg quality numbers to libjxl's butteraugli distan...
static int libjxl_init_jxl_encoder(AVCodecContext *avctx)
Initialize the encoder on a per-file basis.
static av_cold int libjxl_encode_init(AVCodecContext *avctx)
Global encoder initialization.
Replacements for frequently missing libm functions.
Memory handling functions.
static float distance(float x, float y, int band)
int av_get_bits_per_pixel(const AVPixFmtDescriptor *pixdesc)
Return the number of bits per pixel used by the pixel format described by pixdesc.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
#define AV_PIX_FMT_FLAG_FLOAT
The pixel format contains IEEE-754 floating point values.
#define AV_PIX_FMT_RGBF32
#define AV_PIX_FMT_RGBAF32
@ AVCOL_RANGE_MPEG
Narrow or limited range content.
@ AVCOL_RANGE_UNSPECIFIED
@ AVCOL_RANGE_JPEG
Full range content.
@ AVALPHA_MODE_STRAIGHT
Alpha channel is independent of color values.
@ AVALPHA_MODE_UNSPECIFIED
Unknown alpha handling, or no alpha channel.
@ AVALPHA_MODE_PREMULTIPLIED
Alpha channel is multiplied into color values.
#define AV_PIX_FMT_RGBA64
#define AV_PIX_FMT_GRAYF32
AVPixelFormat
Pixel format.
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
@ AV_PIX_FMT_YA8
8 bits gray, 8 bits alpha
#define AV_PIX_FMT_GRAY16
AVColorPrimaries
Chromaticity coordinates of the source primaries.
@ AVCOL_PRI_SMPTE432
SMPTE ST 432-1 (2010) / P3 D65 / Display P3.
@ AVCOL_PRI_BT709
also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP 177 Annex B
@ AVCOL_PRI_SMPTE431
SMPTE ST 431-2 (2011) / DCI P3.
@ AVCOL_PRI_BT2020
ITU-R BT2020.
@ AVCOL_TRC_SMPTE2084
SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems.
@ AVCOL_TRC_GAMMA22
also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM
@ AVCOL_TRC_LINEAR
"Linear transfer characteristics"
@ AVCOL_TRC_GAMMA28
also ITU-R BT470BG
@ AVCOL_TRC_ARIB_STD_B67
ARIB STD-B67, known as "Hybrid log-gamma".
@ AVCOL_TRC_SMPTE428
SMPTE ST 428-1.
@ AVCOL_TRC_IEC61966_2_1
IEC 61966-2-1 (sRGB or sYCC)
@ AVCOL_TRC_BT709
also ITU-R BT1361
A reference to a data buffer.
Describe the class of an AVClass context structure.
main external API structure.
int global_quality
Global quality for codecs which cannot change it per frame.
enum AVColorRange color_range
MPEG vs JPEG YUV range.
enum AVColorPrimaries color_primaries
Chromaticity coordinates of the source primaries.
int bits_per_raw_sample
Bits per sample/pixel of internal libavcodec pixel/sample format.
int thread_count
thread count is used to decide how many independent tasks should be passed to execute()
enum AVColorTransferCharacteristic color_trc
Color Transfer Characteristic.
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
int flags
AV_CODEC_FLAG_*.
enum AVAlphaMode alpha_mode
Indicates how the alpha channel of the video is represented.
Struct that contains both white point location and primaries location, providing the complete descrip...
union AVExifEntry::@325220332140161067313112036135003363017341144014 value
Structure to hold side data for an AVFrame.
This structure describes decoded (raw) audio or video data.
This structure stores compressed data.
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
uint64_t flags
Combination of AV_PIX_FMT_FLAG_... flags.
uint8_t nb_components
The number of components each pixel has, (1-4)
AVBufferRef * exif_buffer
JxlEncoderFrameSettings * options
static const uint8_t quality[]