From 9e5cb700b232e6a813cbeca39a7635f13664991b Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Tue, 17 Feb 2026 16:02:21 +0100 Subject: [PATCH] vcomp/lavc: support JXS --- src/libavcodec/lavc_common.c | 4 ++- src/libavcodec/lavc_common.h | 5 +++- src/video_compress/libavcodec.cpp | 44 ++++++++++++++++++++++++++++++- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/libavcodec/lavc_common.c b/src/libavcodec/lavc_common.c index 60aaaaf6b..9800db903 100644 --- a/src/libavcodec/lavc_common.c +++ b/src/libavcodec/lavc_common.c @@ -4,7 +4,7 @@ * @author Martin Piatka <445597@mail.muni.cz> */ /* - * Copyright (c) 2013-2025 CESNET, zájmové sdružení právnických osob + * Copyright (c) 2013-2026 CESNET, zájmové sdružení právnických osob * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -52,6 +52,7 @@ #include "host.h" #include "libavcodec/lavc_common.h" #include +#include "types.h" #include "utils/macros.h" #include "video.h" @@ -81,6 +82,7 @@ static const struct { { AV_CODEC_ID_PRORES, PRORES_422_PROXY }, { AV_CODEC_ID_PRORES, PRORES_422_LT }, { AV_CODEC_ID_APV, APV }, + { AV_CODEC_ID_JPEGXS, JPEG_XS }, }; codec_t get_av_to_ug_codec(enum AVCodecID av_codec) diff --git a/src/libavcodec/lavc_common.h b/src/libavcodec/lavc_common.h index 9a350f043..c0fb82451 100644 --- a/src/libavcodec/lavc_common.h +++ b/src/libavcodec/lavc_common.h @@ -3,7 +3,7 @@ * @author Martin Pulec */ /* - * Copyright (c) 2013-2025 CESNET, zájmové sdružení právnických osob + * Copyright (c) 2013-2026 CESNET, zájmové sdružení právnických osob * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -82,6 +82,9 @@ enum { #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(62, 3, 100) #define AV_CODEC_ID_APV AV_CODEC_ID_NONE #endif +#if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(62, 22, 101) +#define AV_CODEC_ID_JPEGXS AV_CODEC_ID_NONE +#endif #define Y210_PRESENT LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(56, 42, 100) // FFMPEG commit 1c37cad0 #define X2RGB10LE_PRESENT LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(56, 55, 100) // FFMPEG commit b09fb030 diff --git a/src/video_compress/libavcodec.cpp b/src/video_compress/libavcodec.cpp index 5acd196ef..40996dd5a 100644 --- a/src/video_compress/libavcodec.cpp +++ b/src/video_compress/libavcodec.cpp @@ -70,7 +70,7 @@ #include "utils/color_out.h" #include "utils/debug.h" // for debug_file_dump #include "utils/macros.h" -#include "utils/misc.h" +#include "utils/misc.h" // for get_framerate_[dn] #include "utils/string.h" // replace_all #include "utils/text.h" #include "video.h" @@ -185,6 +185,8 @@ static void libavcodec_compress_done(void *state); static void setparam_default(AVCodecContext *, struct setparam_param *); static void setparam_h264_h265_av1(AVCodecContext *, struct setparam_param *); static void setparam_jpeg(AVCodecContext *, struct setparam_param *); +static void setparam_jxs(AVCodecContext *codec_ctx, + struct setparam_param *param); static void setparam_oapv(AVCodecContext *, struct setparam_param *); static void setparam_vp8_vp9(AVCodecContext *, struct setparam_param *); static void set_codec_thread_mode(AVCodecContext *codec_ctx, struct setparam_param *param); @@ -235,6 +237,8 @@ get_codec_params(codec_t ug_codec) }; case APV: return { nullptr, 0, setparam_oapv, gui_dfl_prio }; + case JPEG_XS: + return { nullptr, 1, setparam_jxs, gui_dfl_prio }; default: break; } @@ -950,6 +954,8 @@ bool set_codec_ctx_params(struct state_video_compress_libav *s, AVPixelFormat pi s->codec_ctx->height = desc.height; /* frames per second */ s->codec_ctx->time_base = (AVRational){1,(int) desc.fps}; + s->codec_ctx->framerate = (AVRational) { get_framerate_n(desc.fps), + get_framerate_d(desc.fps) }; s->codec_ctx->gop_size = s->requested_gop; s->codec_ctx->max_b_frames = 0; @@ -962,6 +968,7 @@ bool set_codec_ctx_params(struct state_video_compress_libav *s, AVPixelFormat pi params.slices, s->codec_ctx->codec_id == AV_CODEC_ID_FFV1 ? 16 : DEFAULT_SLICE_COUNT); + MSG(VERBOSE, "Setting slices to %d\n", s->codec_ctx->slices); s->header_inserter = params.header_inserter_req == 1; // set user supplied parameters @@ -1806,6 +1813,41 @@ setparam_oapv(AVCodecContext */*codec_ctx*/, struct setparam_param *param) param->lavc_opts["oapv-params"] = oapv_params; } +static void +setparam_jxs(AVCodecContext * /* codec_ctx */, struct setparam_param *param) +{ + unsigned decomp_v = 0; + if (param->lavc_opts.find("decomp_v") == param->lavc_opts.end()) { + unsigned height = param->desc.height; + while (height % 2 == 0 && decomp_v < 2) { + decomp_v += 1; + height /= 2; + } + char num[2]; + snprintf_ch(num, "%u", decomp_v); + param->lavc_opts["decomp_v"] = num; + } else { + decomp_v = stoi(param->lavc_opts.at("decomp_v")); + } + + if (param->slices == -1) { + int slice_height = 1 << decomp_v; + param->slices = param->desc.height / slice_height; + } + + if (param->lavc_opts.find("decomp_h") == param->lavc_opts.end()) { + unsigned decomp_h = 0; + unsigned width = param->desc.width; + while (width % 2 == 0 && decomp_h < 5) { + decomp_h += 1; + width /= 2; + } + char num[2]; + snprintf_ch(num, "%u", decomp_h); + param->lavc_opts["decomp_h"] = num; + } +} + static void configure_amf([[maybe_unused]] AVCodecContext *codec_ctx, [[maybe_unused]] struct setparam_param *param) { check_av_opt_set(codec_ctx->priv_data, "rc", DEFAULT_AMF_RC); const char *const usage = codec_ctx->codec->id == AV_CODEC_ID_AV1