This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 3d90949d1e0b93a6435404e1b00c914ff6b65b21 Author: Ramiro Polla <[email protected]> AuthorDate: Tue Sep 23 17:40:10 2025 +0200 Commit: Ramiro Polla <[email protected]> CommitDate: Fri Feb 20 16:32:10 2026 +0100 avcodec/mjpegdec: split mjpeg_unescape_sos() out of ff_mjpeg_find_marker() Now only the image data is unescaped (and not the SOS header). As a side-effect, this also provides a proper fix for decoding CJPG files (issue #133). --- libavcodec/mjpegdec.c | 64 +++++++++++++++++++++++++++------------------------ libavcodec/mjpegdec.h | 4 +--- libavcodec/mxpegdec.c | 13 ++++------- 3 files changed, 40 insertions(+), 41 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index d79e4ecadc..88205ee5c7 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -55,6 +55,11 @@ #include "put_bits.h" +static int mjpeg_unescape_sos(MJpegDecodeContext *s, + const uint8_t *buf_ptr, const uint8_t *buf_end, + const uint8_t **unescaped_buf_ptr, + size_t *unescaped_buf_size); + static int init_default_huffman_tables(MJpegDecodeContext *s) { static const struct { @@ -1762,12 +1767,9 @@ int ff_mjpeg_decode_sos(MJpegDecodeContext *s, const uint8_t *mb_bitmask, predictor = bytestream2_get_byteu(&s->gB); /* JPEG Ss / lossless JPEG predictor / JPEG-LS NEAR */ ilv = bytestream2_get_byteu(&s->gB); /* JPEG Se / JPEG-LS ILV */ - if(s->avctx->codec_tag != AV_RL32("CJPG")){ uint8_t b = bytestream2_get_byteu(&s->gB); prev_shift = b >> 4; /* Ah */ point_transform = b & 0x0F; /* Al */ - }else - prev_shift = point_transform = 0; if (nb_components > 1) { /* interleaved stream */ @@ -1794,7 +1796,14 @@ int ff_mjpeg_decode_sos(MJpegDecodeContext *s, const uint8_t *mb_bitmask, if (s->mjpb_skiptosod) bytestream2_skip(&s->gB, s->mjpb_skiptosod); - ret = init_get_bits8(&s->gb, s->gB.buffer, bytestream2_get_bytes_left(&s->gB)); + const uint8_t *unescaped_buf_ptr; + size_t unescaped_buf_size; + ret = mjpeg_unescape_sos(s, s->gB.buffer, s->gB.buffer + bytestream2_get_bytes_left(&s->gB), + &unescaped_buf_ptr, &unescaped_buf_size); + if (ret < 0) + return ret; + + ret = init_get_bits8(&s->gb, unescaped_buf_ptr, unescaped_buf_size); if (ret < 0) return ret; @@ -2207,7 +2216,7 @@ static int mjpeg_decode_com(MJpegDecodeContext *s) /* return the 8 bit start code value and update the search state. Return -1 if no start code found */ -static int find_marker(const uint8_t **pbuf_ptr, const uint8_t *buf_end) +int ff_mjpeg_find_marker(const uint8_t **pbuf_ptr, const uint8_t *buf_end) { const uint8_t *buf_ptr; int val; @@ -2233,28 +2242,26 @@ found: return val; } -int ff_mjpeg_find_marker(MJpegDecodeContext *s, - const uint8_t **buf_ptr, const uint8_t *buf_end, - const uint8_t **unescaped_buf_ptr, - int *unescaped_buf_size) +static int mjpeg_unescape_sos(MJpegDecodeContext *s, + const uint8_t *buf_ptr, const uint8_t *buf_end, + const uint8_t **unescaped_buf_ptr, + size_t *unescaped_buf_size) { - int start_code; - start_code = find_marker(buf_ptr, buf_end); - - if (start_code != SOS || + if (s->avctx->codec_id == AV_CODEC_ID_MEDIA100 || + s->avctx->codec_id == AV_CODEC_ID_MJPEGB || s->avctx->codec_id == AV_CODEC_ID_THP) { - *unescaped_buf_ptr = *buf_ptr; - *unescaped_buf_size = buf_end - *buf_ptr; - return start_code; + *unescaped_buf_ptr = buf_ptr; + *unescaped_buf_size = buf_end - buf_ptr; + return 0; } - av_fast_padded_malloc(&s->buffer, &s->buffer_size, buf_end - *buf_ptr); + av_fast_padded_malloc(&s->buffer, &s->buffer_size, buf_end - buf_ptr); if (!s->buffer) return AVERROR(ENOMEM); /* unescape buffer of SOS, use special treatment for JPEG-LS */ if (!s->ls) { - const uint8_t *src = *buf_ptr; + const uint8_t *src = buf_ptr; const uint8_t *ptr = src; uint8_t *dst = s->buffer; @@ -2304,9 +2311,9 @@ int ff_mjpeg_find_marker(MJpegDecodeContext *s, AV_INPUT_BUFFER_PADDING_SIZE); av_log(s->avctx, AV_LOG_DEBUG, "escaping removed %td bytes\n", - (buf_end - *buf_ptr) - (dst - s->buffer)); + (buf_end - buf_ptr) - (dst - s->buffer)); } else { - const uint8_t *src = *buf_ptr; + const uint8_t *src = buf_ptr; uint8_t *dst = s->buffer; int bit_count = 0; int t = 0, b = 0; @@ -2349,7 +2356,7 @@ int ff_mjpeg_find_marker(MJpegDecodeContext *s, AV_INPUT_BUFFER_PADDING_SIZE); } - return start_code; + return 0; } static void reset_icc_profile(MJpegDecodeContext *s) @@ -2372,9 +2379,7 @@ int ff_mjpeg_decode_frame_from_buf(AVCodecContext *avctx, AVFrame *frame, { MJpegDecodeContext *s = avctx->priv_data; const uint8_t *buf_end, *buf_ptr; - const uint8_t *unescaped_buf_ptr; int hshift, vshift; - int unescaped_buf_size; int start_code; int index; int ret = 0; @@ -2396,23 +2401,22 @@ redo_for_pal8: buf_end = buf + buf_size; while (buf_ptr < buf_end) { /* find start next marker */ - start_code = ff_mjpeg_find_marker(s, &buf_ptr, buf_end, - &unescaped_buf_ptr, - &unescaped_buf_size); + start_code = ff_mjpeg_find_marker(&buf_ptr, buf_end); /* EOF */ if (start_code < 0) break; - if (unescaped_buf_size > INT_MAX / 8) { + ptrdiff_t bytes_left = buf_end - buf_ptr; + if (bytes_left > INT_MAX / 8) { av_log(avctx, AV_LOG_ERROR, - "MJPEG packet 0x%x too big (%d/%d), corrupt data?\n", - start_code, unescaped_buf_size, buf_size); + "MJPEG packet 0x%x too big (%td/%d), corrupt data?\n", + start_code, bytes_left, buf_size); return AVERROR_INVALIDDATA; } av_log(avctx, AV_LOG_DEBUG, "marker=%x avail_size_in_buf=%td\n", start_code, buf_end - buf_ptr); - bytestream2_init(&s->gB, unescaped_buf_ptr, unescaped_buf_size); + bytestream2_init(&s->gB, buf_ptr, bytes_left); if (avctx->debug & FF_DEBUG_STARTCODE) av_log(avctx, AV_LOG_DEBUG, "startcode: %X\n", start_code); diff --git a/libavcodec/mjpegdec.h b/libavcodec/mjpegdec.h index e8c6cca669..fdd1848d96 100644 --- a/libavcodec/mjpegdec.h +++ b/libavcodec/mjpegdec.h @@ -183,8 +183,6 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s); int ff_mjpeg_decode_sos(MJpegDecodeContext *s, const uint8_t *mb_bitmask,int mb_bitmask_size, const AVFrame *reference); -int ff_mjpeg_find_marker(MJpegDecodeContext *s, - const uint8_t **buf_ptr, const uint8_t *buf_end, - const uint8_t **unescaped_buf_ptr, int *unescaped_buf_size); +int ff_mjpeg_find_marker(const uint8_t **buf_ptr, const uint8_t *buf_end); #endif /* AVCODEC_MJPEGDEC_H */ diff --git a/libavcodec/mxpegdec.c b/libavcodec/mxpegdec.c index b66bff56c9..de374a8904 100644 --- a/libavcodec/mxpegdec.c +++ b/libavcodec/mxpegdec.c @@ -198,8 +198,6 @@ static int mxpeg_decode_frame(AVCodecContext *avctx, AVFrame *rframe, MXpegDecodeContext *s = avctx->priv_data; MJpegDecodeContext *jpg = &s->jpg; const uint8_t *buf_end, *buf_ptr; - const uint8_t *unescaped_buf_ptr; - int unescaped_buf_size; int start_code; int ret; @@ -212,15 +210,15 @@ static int mxpeg_decode_frame(AVCodecContext *avctx, AVFrame *rframe, s->got_mxm_bitmask = 0; s->got_sof_data = !!s->got_sof_data; while (buf_ptr < buf_end) { - start_code = ff_mjpeg_find_marker(jpg, &buf_ptr, buf_end, - &unescaped_buf_ptr, &unescaped_buf_size); + start_code = ff_mjpeg_find_marker(&buf_ptr, buf_end); if (start_code < 0) goto the_end; - bytestream2_init(&jpg->gB, unescaped_buf_ptr, unescaped_buf_size); + int bytes_left = buf_end - buf_ptr; + bytestream2_init(&jpg->gB, buf_ptr, bytes_left); if (start_code >= APP0 && start_code <= APP15) { - mxpeg_decode_app(s, unescaped_buf_ptr, unescaped_buf_size); + mxpeg_decode_app(s, buf_ptr, bytes_left); } switch (start_code) { @@ -247,8 +245,7 @@ static int mxpeg_decode_frame(AVCodecContext *avctx, AVFrame *rframe, } break; case COM: - ret = mxpeg_decode_com(s, unescaped_buf_ptr, - unescaped_buf_size); + ret = mxpeg_decode_com(s, buf_ptr, bytes_left); if (ret < 0) return ret; break; _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
