PR #21197 opened by James Almer (jamrial) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21197 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21197.patch
>From c54fef825bbb006f01735d6e53316f1f4412e819 Mon Sep 17 00:00:00 2001 From: James Almer <[email protected]> Date: Sun, 14 Dec 2025 13:42:22 -0300 Subject: [PATCH 1/6] avcodec/libsvtjpegxsdec: remove chunk decoding code That's the job of the parser. Signed-off-by: James Almer <[email protected]> --- libavcodec/libsvtjpegxsdec.c | 52 +++++------------------------------- 1 file changed, 6 insertions(+), 46 deletions(-) diff --git a/libavcodec/libsvtjpegxsdec.c b/libavcodec/libsvtjpegxsdec.c index 45d9134cd4..6c7b2be917 100644 --- a/libavcodec/libsvtjpegxsdec.c +++ b/libavcodec/libsvtjpegxsdec.c @@ -43,11 +43,7 @@ typedef struct SvtJpegXsDecodeContext { uint32_t decoder_initialized; /*0- AVPacket* avpkt have full frame*/ - /*1- AVPacket* avpkt have chunk of frame, need another buffer to merge packets*/ - uint32_t chunk_decoding; uint32_t frame_size; - uint32_t buffer_filled_len; - uint8_t* bitstream_buffer; int proxy_mode; } SvtJpegXsDecodeContext; @@ -112,17 +108,12 @@ static int svt_jpegxs_dec_decode(AVCodecContext* avctx, AVFrame* picture, int* g return err; } if (avpkt->size < svt_dec->frame_size) { - svt_dec->chunk_decoding = 1; - svt_dec->bitstream_buffer = av_malloc(svt_dec->frame_size); - if (!svt_dec->bitstream_buffer) { - av_log(avctx, AV_LOG_ERROR, "Failed to allocate svt_dec->bitstream_buffer.\n"); - return AVERROR(ENOMEM); - } - av_log(avctx, AV_LOG_DEBUG, "svt_jpegxs_dec_decode, bitstream_size=%d, chunk = %d\n", svt_dec->frame_size, avpkt->size); + av_log(avctx, AV_LOG_ERROR, "Not enough data in a packet.\n"); + return AVERROR(EINVAL); } if (avpkt->size > svt_dec->frame_size) { av_log(avctx, AV_LOG_ERROR, "Single packet have data for more than one frame.\n"); - return AVERROR_EXTERNAL; + return AVERROR(EINVAL); } err = svt_jpeg_xs_decoder_init(SVT_JPEGXS_API_VER_MAJOR, SVT_JPEGXS_API_VER_MINOR, @@ -150,29 +141,9 @@ static int svt_jpegxs_dec_decode(AVCodecContext* avctx, AVFrame* picture, int* g if (avctx->skip_frame == AVDISCARD_ALL) return 0; - if (svt_dec->chunk_decoding) { - uint8_t* bitstrream_addr = svt_dec->bitstream_buffer + svt_dec->buffer_filled_len; - int bytes_to_copy = avpkt->size; - //Do not copy more data than allocation - if ((bytes_to_copy + svt_dec->buffer_filled_len) > svt_dec->frame_size) { - bytes_to_copy = svt_dec->frame_size - svt_dec->buffer_filled_len; - } - - memcpy(bitstrream_addr, avpkt->data, bytes_to_copy); - svt_dec->buffer_filled_len += avpkt->size; - if (svt_dec->buffer_filled_len >= svt_dec->frame_size) { - dec_input.bitstream.buffer = svt_dec->bitstream_buffer; - dec_input.bitstream.allocation_size = svt_dec->frame_size; - dec_input.bitstream.used_size = svt_dec->frame_size; - } else { - *got_frame = 0; - return avpkt->size; - } - } else { - dec_input.bitstream.buffer = avpkt->data; - dec_input.bitstream.allocation_size = avpkt->size; - dec_input.bitstream.used_size = avpkt->size; - } + dec_input.bitstream.buffer = avpkt->data; + dec_input.bitstream.allocation_size = avpkt->size; + dec_input.bitstream.used_size = avpkt->size; dec_input.user_prv_ctx_ptr = avpkt; ret = ff_get_buffer(avctx, picture, 0); @@ -208,16 +179,6 @@ static int svt_jpegxs_dec_decode(AVCodecContext* avctx, AVFrame* picture, int* g return AVERROR_EXTERNAL; } - //Copy leftover from AVPacket if it contain data from two frames - if (svt_dec->chunk_decoding) { - int bytes_to_copy = svt_dec->buffer_filled_len % svt_dec->frame_size; - int packet_offset = avpkt->size - bytes_to_copy; - uint8_t* packet_addr = avpkt->data + packet_offset; - - memcpy(svt_dec->bitstream_buffer, packet_addr, bytes_to_copy); - svt_dec->buffer_filled_len = bytes_to_copy; - } - *got_frame = 1; return avpkt->size; @@ -228,7 +189,6 @@ static av_cold int svt_jpegxs_dec_free(AVCodecContext* avctx) SvtJpegXsDecodeContext* svt_dec = avctx->priv_data; svt_jpeg_xs_decoder_close(&svt_dec->decoder); - av_freep(&svt_dec->bitstream_buffer); return 0; } -- 2.49.1 >From e7abdd0c7a5bf22d36117b4a7ec926bdeba91e4f Mon Sep 17 00:00:00 2001 From: James Almer <[email protected]> Date: Sun, 14 Dec 2025 13:55:49 -0300 Subject: [PATCH 2/6] avcodec/libsvtjpegxsdec: support parameter changes Signed-off-by: James Almer <[email protected]> --- libavcodec/libsvtjpegxsdec.c | 51 ++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/libavcodec/libsvtjpegxsdec.c b/libavcodec/libsvtjpegxsdec.c index 6c7b2be917..274d7b5790 100644 --- a/libavcodec/libsvtjpegxsdec.c +++ b/libavcodec/libsvtjpegxsdec.c @@ -47,43 +47,43 @@ typedef struct SvtJpegXsDecodeContext { int proxy_mode; } SvtJpegXsDecodeContext; -static int set_pix_fmt(AVCodecContext* avctx, const svt_jpeg_xs_image_config_t *config) +static int set_pix_fmt(void *logctx, const svt_jpeg_xs_image_config_t *config) { - int ret = 0; + int ret = AVERROR_BUG; switch (config->format) { case COLOUR_FORMAT_PLANAR_YUV420: if (config->bit_depth == 8) - avctx->pix_fmt = AV_PIX_FMT_YUV420P; + return AV_PIX_FMT_YUV420P; else if (config->bit_depth == 10) - avctx->pix_fmt = AV_PIX_FMT_YUV420P10LE; + return AV_PIX_FMT_YUV420P10LE; else if (config->bit_depth == 12) - avctx->pix_fmt = AV_PIX_FMT_YUV420P12LE; + return AV_PIX_FMT_YUV420P12LE; else - avctx->pix_fmt = AV_PIX_FMT_YUV420P14LE; + return AV_PIX_FMT_YUV420P14LE; break; case COLOUR_FORMAT_PLANAR_YUV422: if (config->bit_depth == 8) - avctx->pix_fmt = AV_PIX_FMT_YUV422P; + return AV_PIX_FMT_YUV422P; else if (config->bit_depth == 10) - avctx->pix_fmt = AV_PIX_FMT_YUV422P10LE; + return AV_PIX_FMT_YUV422P10LE; else if (config->bit_depth == 12) - avctx->pix_fmt = AV_PIX_FMT_YUV422P12LE; + return AV_PIX_FMT_YUV422P12LE; else - avctx->pix_fmt = AV_PIX_FMT_YUV422P14LE; + return AV_PIX_FMT_YUV422P14LE; break; case COLOUR_FORMAT_PLANAR_YUV444_OR_RGB: if (config->bit_depth == 8) - avctx->pix_fmt = AV_PIX_FMT_YUV444P; + return AV_PIX_FMT_YUV444P; else if (config->bit_depth == 10) - avctx->pix_fmt = AV_PIX_FMT_YUV444P10LE; + return AV_PIX_FMT_YUV444P10LE; else if (config->bit_depth == 12) - avctx->pix_fmt = AV_PIX_FMT_YUV444P12LE; + return AV_PIX_FMT_YUV444P12LE; else - avctx->pix_fmt = AV_PIX_FMT_YUV444P14LE; + return AV_PIX_FMT_YUV444P14LE; break; default: - av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format.\n"); + av_log(logctx, AV_LOG_ERROR, "Unsupported pixel format.\n"); ret = AVERROR_INVALIDDATA; break; } @@ -100,9 +100,8 @@ static int svt_jpegxs_dec_decode(AVCodecContext* avctx, AVFrame* picture, int* g svt_jpeg_xs_frame_t dec_output; uint32_t pixel_size; - if (!svt_dec->decoder_initialized) { err = svt_jpeg_xs_decoder_get_single_frame_size_with_proxy( - avpkt->data, avpkt->size, NULL, &svt_dec->frame_size, 1 /*quick search*/, svt_dec->decoder.proxy_mode); + avpkt->data, avpkt->size, &svt_dec->config, &svt_dec->frame_size, 1 /*quick search*/, svt_dec->decoder.proxy_mode); if (err) { av_log(avctx, AV_LOG_ERROR, "svt_jpeg_xs_decoder_get_single_frame_size_with_proxy failed, err=%d\n", err); return err; @@ -116,6 +115,14 @@ static int svt_jpegxs_dec_decode(AVCodecContext* avctx, AVFrame* picture, int* g return AVERROR(EINVAL); } + ret = set_pix_fmt(avctx, &svt_dec->config); + if (ret < 0) + return ret; + + if (!svt_dec->decoder_initialized || ret != avctx->pix_fmt || + avctx->width != svt_dec->config.width || avctx->height != svt_dec->config.height) { + if (svt_dec->decoder_initialized) + svt_jpeg_xs_decoder_close(&svt_dec->decoder); err = svt_jpeg_xs_decoder_init(SVT_JPEGXS_API_VER_MAJOR, SVT_JPEGXS_API_VER_MINOR, &svt_dec->decoder, avpkt->data, avpkt->size, &svt_dec->config); if (err) { @@ -123,11 +130,7 @@ static int svt_jpegxs_dec_decode(AVCodecContext* avctx, AVFrame* picture, int* g return err; } - ret = set_pix_fmt(avctx, &svt_dec->config); - if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "set_pix_fmt failed, err=%d\n", ret); - return ret; - } + avctx->pix_fmt = ret; ret = ff_set_dimensions(avctx, svt_dec->config.width, svt_dec->config.height); if (ret < 0) { @@ -165,10 +168,6 @@ static int svt_jpegxs_dec_decode(AVCodecContext* avctx, AVFrame* picture, int* g } err = svt_jpeg_xs_decoder_get_frame(&svt_dec->decoder, &dec_output, 1 /*blocking*/); - if (err == SvtJxsErrorDecoderConfigChange) { - av_log(avctx, AV_LOG_ERROR, "svt_jpeg_xs_decoder_get_frame return SvtJxsErrorDecoderConfigChange\n"); - return AVERROR_INPUT_CHANGED; - } if (err) { av_log(avctx, AV_LOG_ERROR, "svt_jpeg_xs_decoder_get_frame failed, err=%d\n", err); return err; -- 2.49.1 >From 4bf8d1aa6100ea820b384e005e4a3d578a343221 Mon Sep 17 00:00:00 2001 From: James Almer <[email protected]> Date: Sun, 14 Dec 2025 14:27:15 -0300 Subject: [PATCH 3/6] avcodec/libsvtjpegxsdec: reindent after the previous changes Signed-off-by: James Almer <[email protected]> --- libavcodec/libsvtjpegxsdec.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/libavcodec/libsvtjpegxsdec.c b/libavcodec/libsvtjpegxsdec.c index 274d7b5790..e7e44b2896 100644 --- a/libavcodec/libsvtjpegxsdec.c +++ b/libavcodec/libsvtjpegxsdec.c @@ -100,20 +100,20 @@ static int svt_jpegxs_dec_decode(AVCodecContext* avctx, AVFrame* picture, int* g svt_jpeg_xs_frame_t dec_output; uint32_t pixel_size; - err = svt_jpeg_xs_decoder_get_single_frame_size_with_proxy( - avpkt->data, avpkt->size, &svt_dec->config, &svt_dec->frame_size, 1 /*quick search*/, svt_dec->decoder.proxy_mode); - if (err) { - av_log(avctx, AV_LOG_ERROR, "svt_jpeg_xs_decoder_get_single_frame_size_with_proxy failed, err=%d\n", err); - return err; - } - if (avpkt->size < svt_dec->frame_size) { - av_log(avctx, AV_LOG_ERROR, "Not enough data in a packet.\n"); - return AVERROR(EINVAL); - } - if (avpkt->size > svt_dec->frame_size) { - av_log(avctx, AV_LOG_ERROR, "Single packet have data for more than one frame.\n"); - return AVERROR(EINVAL); - } + err = svt_jpeg_xs_decoder_get_single_frame_size_with_proxy( + avpkt->data, avpkt->size, &svt_dec->config, &svt_dec->frame_size, 1 /*quick search*/, svt_dec->decoder.proxy_mode); + if (err) { + av_log(avctx, AV_LOG_ERROR, "svt_jpeg_xs_decoder_get_single_frame_size_with_proxy failed, err=%d\n", err); + return err; + } + if (avpkt->size < svt_dec->frame_size) { + av_log(avctx, AV_LOG_ERROR, "Not enough data in a packet.\n"); + return AVERROR(EINVAL); + } + if (avpkt->size > svt_dec->frame_size) { + av_log(avctx, AV_LOG_ERROR, "Single packet have data for more than one frame.\n"); + return AVERROR(EINVAL); + } ret = set_pix_fmt(avctx, &svt_dec->config); if (ret < 0) -- 2.49.1 >From 0bd4676f0894acb058c9d63781306bf30cc0529a Mon Sep 17 00:00:00 2001 From: James Almer <[email protected]> Date: Sun, 14 Dec 2025 14:00:31 -0300 Subject: [PATCH 4/6] avcodec/libsvtjpegxsdec: move some stack structs to the private decoder context Signed-off-by: James Almer <[email protected]> --- libavcodec/libsvtjpegxsdec.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libavcodec/libsvtjpegxsdec.c b/libavcodec/libsvtjpegxsdec.c index e7e44b2896..755c9a5387 100644 --- a/libavcodec/libsvtjpegxsdec.c +++ b/libavcodec/libsvtjpegxsdec.c @@ -40,6 +40,8 @@ typedef struct SvtJpegXsDecodeContext { AVClass* class; svt_jpeg_xs_image_config_t config; svt_jpeg_xs_decoder_api_t decoder; + svt_jpeg_xs_frame_t input; + svt_jpeg_xs_frame_t output; uint32_t decoder_initialized; /*0- AVPacket* avpkt have full frame*/ @@ -96,8 +98,6 @@ static int svt_jpegxs_dec_decode(AVCodecContext* avctx, AVFrame* picture, int* g SvtJpegXsDecodeContext* svt_dec = avctx->priv_data; SvtJxsErrorType_t err = SvtJxsErrorNone; int ret; - svt_jpeg_xs_frame_t dec_input; - svt_jpeg_xs_frame_t dec_output; uint32_t pixel_size; err = svt_jpeg_xs_decoder_get_single_frame_size_with_proxy( @@ -144,10 +144,10 @@ static int svt_jpegxs_dec_decode(AVCodecContext* avctx, AVFrame* picture, int* g if (avctx->skip_frame == AVDISCARD_ALL) return 0; - dec_input.bitstream.buffer = avpkt->data; - dec_input.bitstream.allocation_size = avpkt->size; - dec_input.bitstream.used_size = avpkt->size; - dec_input.user_prv_ctx_ptr = avpkt; + svt_dec->input.bitstream.buffer = avpkt->data; + svt_dec->input.bitstream.allocation_size = avpkt->size; + svt_dec->input.bitstream.used_size = avpkt->size; + svt_dec->input.user_prv_ctx_ptr = avpkt; ret = ff_get_buffer(avctx, picture, 0); if (ret < 0) @@ -156,24 +156,24 @@ static int svt_jpegxs_dec_decode(AVCodecContext* avctx, AVFrame* picture, int* g pixel_size = svt_dec->config.bit_depth <= 8 ? 1 : 2; for (int comp = 0; comp < svt_dec->config.components_num; comp++) { - dec_input.image.data_yuv[comp] = picture->data[comp]; - dec_input.image.stride[comp] = picture->linesize[comp]/pixel_size; - dec_input.image.alloc_size[comp] = picture->linesize[comp] * svt_dec->config.components[comp].height; + svt_dec->input.image.data_yuv[comp] = picture->data[comp]; + svt_dec->input.image.stride[comp] = picture->linesize[comp]/pixel_size; + svt_dec->input.image.alloc_size[comp] = picture->linesize[comp] * svt_dec->config.components[comp].height; } - err = svt_jpeg_xs_decoder_send_frame(&svt_dec->decoder, &dec_input, 1 /*blocking*/); + err = svt_jpeg_xs_decoder_send_frame(&svt_dec->decoder, &svt_dec->input, 1 /*blocking*/); if (err) { av_log(avctx, AV_LOG_ERROR, "svt_jpeg_xs_decoder_send_frame failed, err=%d\n", err); return err; } - err = svt_jpeg_xs_decoder_get_frame(&svt_dec->decoder, &dec_output, 1 /*blocking*/); + err = svt_jpeg_xs_decoder_get_frame(&svt_dec->decoder, &svt_dec->output, 1 /*blocking*/); if (err) { av_log(avctx, AV_LOG_ERROR, "svt_jpeg_xs_decoder_get_frame failed, err=%d\n", err); return err; } - if (dec_output.user_prv_ctx_ptr != avpkt) { + if (svt_dec->output.user_prv_ctx_ptr != avpkt) { av_log(avctx, AV_LOG_ERROR, "Returned different user_prv_ctx_ptr than expected\n"); return AVERROR_EXTERNAL; } -- 2.49.1 >From 8b468f7ccba6259baa5b2b8a215867648de7d7c9 Mon Sep 17 00:00:00 2001 From: James Almer <[email protected]> Date: Sun, 14 Dec 2025 14:10:36 -0300 Subject: [PATCH 5/6] avcodec/libsvtjpegxsdec: use AVCodecContext.lowres instead of a private option It was evidently an oversight. Found-by: Andreas Rheinhardt. Signed-off-by: James Almer <[email protected]> --- libavcodec/libsvtjpegxsdec.c | 15 ++------------- libavcodec/version.h | 2 +- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/libavcodec/libsvtjpegxsdec.c b/libavcodec/libsvtjpegxsdec.c index 755c9a5387..ca3ac22837 100644 --- a/libavcodec/libsvtjpegxsdec.c +++ b/libavcodec/libsvtjpegxsdec.c @@ -203,9 +203,9 @@ static av_cold int svt_jpegxs_dec_init(AVCodecContext* avctx) else svt_dec->decoder.verbose = VERBOSE_WARNINGS; - if (svt_dec->proxy_mode == 1) + if (avctx->lowres == 1) svt_dec->decoder.proxy_mode = proxy_mode_half; - else if (svt_dec->proxy_mode == 2) + else if (avctx->lowres == 2) svt_dec->decoder.proxy_mode = proxy_mode_quarter; else svt_dec->decoder.proxy_mode = proxy_mode_full; @@ -216,20 +216,9 @@ static av_cold int svt_jpegxs_dec_init(AVCodecContext* avctx) return 0; } -#define OFFSET(x) offsetof(SvtJpegXsDecodeContext, x) -#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM -static const AVOption svtjpegxs_dec_options[] = { - { "proxy_mode", "Resolution scaling mode", OFFSET(proxy_mode), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 2, VE, .unit = "proxy_mode" }, - { "full", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0}, INT_MIN, INT_MAX, VE, .unit = "proxy_mode" }, - { "half", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1}, INT_MIN, INT_MAX, VE, .unit = "proxy_mode" }, - { "quarter", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2}, INT_MIN, INT_MAX, VE, .unit = "proxy_mode" }, - {NULL}, -}; - static const AVClass svtjpegxs_dec_class = { .class_name = "libsvtjpegxsdec", .item_name = av_default_item_name, - .option = svtjpegxs_dec_options, .version = LIBAVUTIL_VERSION_INT, }; diff --git a/libavcodec/version.h b/libavcodec/version.h index 728ab8839d..3af30cdc3b 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -30,7 +30,7 @@ #include "version_major.h" #define LIBAVCODEC_VERSION_MINOR 23 -#define LIBAVCODEC_VERSION_MICRO 100 +#define LIBAVCODEC_VERSION_MICRO 101 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ -- 2.49.1 >From 02b46e645d0293c9dde38f7383d793e55140064b Mon Sep 17 00:00:00 2001 From: James Almer <[email protected]> Date: Sun, 14 Dec 2025 14:30:35 -0300 Subject: [PATCH 6/6] avcodec/libsvtjpegxsdec: only return AVERROR codes Signed-off-by: James Almer <[email protected]> --- libavcodec/libsvtjpegxsdec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/libsvtjpegxsdec.c b/libavcodec/libsvtjpegxsdec.c index ca3ac22837..8b13b2b7b5 100644 --- a/libavcodec/libsvtjpegxsdec.c +++ b/libavcodec/libsvtjpegxsdec.c @@ -104,7 +104,7 @@ static int svt_jpegxs_dec_decode(AVCodecContext* avctx, AVFrame* picture, int* g avpkt->data, avpkt->size, &svt_dec->config, &svt_dec->frame_size, 1 /*quick search*/, svt_dec->decoder.proxy_mode); if (err) { av_log(avctx, AV_LOG_ERROR, "svt_jpeg_xs_decoder_get_single_frame_size_with_proxy failed, err=%d\n", err); - return err; + return AVERROR_EXTERNAL; } if (avpkt->size < svt_dec->frame_size) { av_log(avctx, AV_LOG_ERROR, "Not enough data in a packet.\n"); @@ -127,7 +127,7 @@ static int svt_jpegxs_dec_decode(AVCodecContext* avctx, AVFrame* picture, int* g &svt_dec->decoder, avpkt->data, avpkt->size, &svt_dec->config); if (err) { av_log(avctx, AV_LOG_ERROR, "svt_jpeg_xs_decoder_init failed, err=%d\n", err); - return err; + return AVERROR_EXTERNAL; } avctx->pix_fmt = ret; @@ -164,13 +164,13 @@ static int svt_jpegxs_dec_decode(AVCodecContext* avctx, AVFrame* picture, int* g err = svt_jpeg_xs_decoder_send_frame(&svt_dec->decoder, &svt_dec->input, 1 /*blocking*/); if (err) { av_log(avctx, AV_LOG_ERROR, "svt_jpeg_xs_decoder_send_frame failed, err=%d\n", err); - return err; + return AVERROR_EXTERNAL; } err = svt_jpeg_xs_decoder_get_frame(&svt_dec->decoder, &svt_dec->output, 1 /*blocking*/); if (err) { av_log(avctx, AV_LOG_ERROR, "svt_jpeg_xs_decoder_get_frame failed, err=%d\n", err); - return err; + return AVERROR_EXTERNAL; } if (svt_dec->output.user_prv_ctx_ptr != avpkt) { -- 2.49.1 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
