This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 52c097065cb59927c532a09cfbcfbfb7948e3092 Author: James Almer <[email protected]> AuthorDate: Mon Dec 1 22:59:01 2025 -0300 Commit: James Almer <[email protected]> CommitDate: Sat Dec 13 18:45:17 2025 -0300 avcodec: add a JPEG-XS parser Signed-off-by: James Almer <[email protected]> --- Changelog | 1 + libavcodec/Makefile | 1 + libavcodec/{ffv1enc.h => jpegxs.h} | 35 +++---- libavcodec/jpegxs_parser.c | 207 +++++++++++++++++++++++++++++++++++++ libavcodec/parsers.c | 1 + 5 files changed, 225 insertions(+), 20 deletions(-) diff --git a/Changelog b/Changelog index ef72af1e93..aa0aaaed72 100644 --- a/Changelog +++ b/Changelog @@ -15,6 +15,7 @@ version <next>: - DPX Vulkan hwaccel - Rockchip H.264/HEVC hardware encoder - Add vf_scale_d3d12 filter +- JPEG-XS parser version 8.0: diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 40e68116e8..5ed8a27b76 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1272,6 +1272,7 @@ OBJS-$(CONFIG_HDR_PARSER) += hdr_parser.o OBJS-$(CONFIG_IPU_PARSER) += ipu_parser.o OBJS-$(CONFIG_JPEG2000_PARSER) += jpeg2000_parser.o OBJS-$(CONFIG_JPEGXL_PARSER) += jpegxl_parser.o jpegxl_parse.o +OBJS-$(CONFIG_JPEGXS_PARSER) += jpegxs_parser.o OBJS-$(CONFIG_MISC4_PARSER) += misc4_parser.o OBJS-$(CONFIG_MJPEG_PARSER) += mjpeg_parser.o OBJS-$(CONFIG_MLP_PARSER) += mlp_parse.o mlp_parser.o mlp.o diff --git a/libavcodec/ffv1enc.h b/libavcodec/jpegxs.h similarity index 50% copy from libavcodec/ffv1enc.h copy to libavcodec/jpegxs.h index 42d521a747..951e2f0d69 100644 --- a/libavcodec/ffv1enc.h +++ b/libavcodec/jpegxs.h @@ -1,8 +1,4 @@ /* - * FFV1 encoder - * - * Copyright (c) 2003-2013 Michael Niedermayer <[email protected]> - * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -20,23 +16,22 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef AVCODEC_FFV1ENC_H -#define AVCODEC_FFV1ENC_H - -#include "avcodec.h" +#ifndef AVCODEC_JPEGXS_H +#define AVCODEC_JPEGXS_H enum { - QTABLE_DEFAULT = -1, - QTABLE_8BIT, - QTABLE_GT8BIT, + JPEGXS_MARKER_SOC = 0xff10, // Start of codestream + JPEGXS_MARKER_EOC = 0xff11, // End of codestream + JPEGXS_MARKER_PIH = 0xff12, // Picture header + JPEGXS_MARKER_CDT = 0xff13, // Component table + JPEGXS_MARKER_WGT = 0xff14, // Weights table + JPEGXS_MARKER_COM = 0xff15, // Extension marker + JPEGXS_MARKER_NLT = 0xff16, // Nonlinearity marker + JPEGXS_MARKER_CWD = 0xff17, // Component-dependent wavelet decomposition marker + JPEGXS_MARKER_CTS = 0xff18, // Colour transformation specification marker + JPEGXS_MARKER_CRG = 0xff19, // Component registration marker + JPEGXS_MARKER_SLH = 0xff20, // Slice header + JPEGXS_MARKER_CAP = 0xff50, // Capabilities Marker }; -av_cold int ff_ffv1_encode_init(AVCodecContext *avctx); -av_cold int ff_ffv1_encode_determine_slices(AVCodecContext *avctx); -av_cold int ff_ffv1_write_extradata(AVCodecContext *avctx); -av_cold int ff_ffv1_encode_setup_plane_info(AVCodecContext *avctx, - enum AVPixelFormat pix_fmt); - -size_t ff_ffv1_encode_buffer_size(AVCodecContext *avctx); - -#endif /* AVCODEC_FFV1ENC_H */ +#endif /* AVCODEC_JPEGXS_H */ diff --git a/libavcodec/jpegxs_parser.c b/libavcodec/jpegxs_parser.c new file mode 100644 index 0000000000..a6a3d1fcce --- /dev/null +++ b/libavcodec/jpegxs_parser.c @@ -0,0 +1,207 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "bytestream.h" +#include "get_bits.h" +#include "jpegxs.h" +#include "parser.h" +#include "parser_internal.h" + +/** + * Find the end of the current frame in the bitstream. + * @return the position of the first byte of the next frame, or -1 + */ +static int jpegxs_find_frame_end(ParseContext *pc, const uint8_t *buf, + int buf_size) +{ + int pic_found, i = 0; + uint32_t state; + + pic_found = pc->frame_start_found; + state = pc->state; + + if (!pic_found) { + for (i = 0; i < buf_size; i++) { + state = (state << 8) | buf[i]; + if ((uint16_t)state == JPEGXS_MARKER_SOC) { + i++; + pic_found = 1; + break; + } + } + } + + if (pic_found) { + if (buf_size == 0) + return 0; + for(; i < buf_size; i++) { + state = (state << 8) | buf[i]; + if ((uint16_t)state == JPEGXS_MARKER_EOC) { + pc->frame_start_found = 0; + pc->state = -1; + return i + 1; + } + } + } + + pc->frame_start_found = pic_found; + pc->state = state; + return END_NOT_FOUND; +} + +static int jpegxs_parse_frame(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + GetByteContext gbc; + GetBitContext gb; + int8_t bpc[3], log2_chroma_w[3], log2_chroma_h[3]; + int size, marker, components; + + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + + if (buf_size < 4) + return 0; + + bytestream2_init(&gbc, buf, buf_size); + marker = bytestream2_get_be16(&gbc); + if (marker != JPEGXS_MARKER_SOC) + return 0; + + marker = bytestream2_get_be16(&gbc); + if (marker != JPEGXS_MARKER_CAP) + return 0; + size = bytestream2_get_be16(&gbc); + bytestream2_skip(&gbc, FFMAX(size - 2, 0)); + + marker = bytestream2_get_be16(&gbc); + if (marker != JPEGXS_MARKER_PIH) + return 0; + size = bytestream2_get_be16(&gbc); + bytestream2_skip(&gbc, 4); // Lcod + bytestream2_skip(&gbc, 2); // Ppih + bytestream2_skip(&gbc, 2); // Plev + size -= 8; + + s->width = bytestream2_get_be16(&gbc); + s->height = bytestream2_get_be16(&gbc); + size -= 4; + + bytestream2_skip(&gbc, 2); // Cw + bytestream2_skip(&gbc, 2); // Hsl + size -= 4; + + components = bytestream2_get_byte(&gbc); + if (components != 1 && components != 3) + return 0; + size--; + + bytestream2_skip(&gbc, FFMAX(size - 2, 0)); + + while (bytestream2_get_bytes_left(&gbc) > 0) { + marker = bytestream2_get_be16(&gbc); + + switch(marker) { + case JPEGXS_MARKER_CDT: + size = bytestream2_get_be16(&gbc); + init_get_bits8(&gb, gbc.buffer, FFMIN(FFMAX(size - 2, 0), bytestream2_get_bytes_left(&gbc))); + + for (int i = 0; i < components; i++) { + bpc[i] = get_bits(&gb, 8); + if (i && bpc[i] != bpc[i-1]) + return 0; + + log2_chroma_w[i] = get_bits(&gb, 4); + log2_chroma_h[i] = get_bits(&gb, 4); + + if (log2_chroma_h[i] > log2_chroma_w[i]) + return 0; + if (i == 2 && (log2_chroma_h[2] != log2_chroma_h[1] || + log2_chroma_w[2] != log2_chroma_w[1])) + return 0; + } + + switch (bpc[0]) { + case 8: + if (components == 1) s->format = AV_PIX_FMT_GRAY8; + else if (log2_chroma_w[1] == 1 && log2_chroma_h[1] == 1) s->format = AV_PIX_FMT_YUV444P; + else if (log2_chroma_w[1] == 2 && log2_chroma_h[1] == 1) s->format = AV_PIX_FMT_YUV422P; + else s->format = AV_PIX_FMT_YUV420P; + break; + case 10: + if (components == 1) s->format = AV_PIX_FMT_GRAY10; + else if (log2_chroma_w[1] == 1 && log2_chroma_h[1] == 1) s->format = AV_PIX_FMT_YUV444P10; + else if (log2_chroma_w[1] == 2 && log2_chroma_h[1] == 1) s->format = AV_PIX_FMT_YUV422P10; + else s->format = AV_PIX_FMT_YUV420P10; + break; + case 12: + if (components == 1) s->format = AV_PIX_FMT_GRAY12; + else if (log2_chroma_w[1] == 1 && log2_chroma_h[1] == 1) s->format = AV_PIX_FMT_YUV444P12; + else if (log2_chroma_w[1] == 2 && log2_chroma_h[1] == 1) s->format = AV_PIX_FMT_YUV422P12; + else s->format = AV_PIX_FMT_YUV420P12; + break; + case 14: + if (components == 1) s->format = AV_PIX_FMT_GRAY14; + else if (log2_chroma_w[1] == 1 && log2_chroma_h[1] == 1) s->format = AV_PIX_FMT_YUV444P14; + else if (log2_chroma_w[1] == 2 && log2_chroma_h[1] == 1) s->format = AV_PIX_FMT_YUV422P14; + else s->format = AV_PIX_FMT_YUV420P14; + break; + default: + s->format = AV_PIX_FMT_NONE; + break; + } + return 0; + default: + size = bytestream2_get_be16(&gbc); + bytestream2_skip(&gbc, FFMAX(size - 2, 0)); + break; + } + } + + return 0; +} + +static int jpegxsvideo_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + int next; + + next = jpegxs_find_frame_end(pc, buf, buf_size); + + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + + jpegxs_parse_frame(s, avctx, buf, buf_size); + + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +const FFCodecParser ff_jpegxs_parser = { + PARSER_CODEC_LIST(AV_CODEC_ID_JPEGXS), + .priv_data_size = sizeof(ParseContext), + .parse = jpegxsvideo_parse, + .close = ff_parse_close, +}; diff --git a/libavcodec/parsers.c b/libavcodec/parsers.c index cae1f7213e..4561f6eb3d 100644 --- a/libavcodec/parsers.c +++ b/libavcodec/parsers.c @@ -77,6 +77,7 @@ extern const FFCodecParser ff_hdr_parser; extern const FFCodecParser ff_ipu_parser; extern const FFCodecParser ff_jpeg2000_parser; extern const FFCodecParser ff_jpegxl_parser; +extern const FFCodecParser ff_jpegxs_parser; extern const FFCodecParser ff_misc4_parser; extern const FFCodecParser ff_mjpeg_parser; extern const FFCodecParser ff_mlp_parser; _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
