This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 6287ad1f9bd168e2a417b91df0a705c8d62925f3 Author: Lynne <[email protected]> AuthorDate: Sun Jul 26 13:55:17 2026 +0800 Commit: Lynne <[email protected]> CommitDate: Tue Oct 6 15:11:26 2026 +0900 jpeg2000dec: convert the decoder to the receive_frame API Convert the decoder to the receive_frame API (one codestream per packet; skipped frames pull the next packet instead of returning empty-handed), finish threading setup before the tile decode, and do not leave a partially initialized frame on the output on error. Move the tag-tree size, exp2fi and band stepsize helpers into the shared header as ff_-prefixed inlines so code outside jpeg2000.c can derive the same geometry and quantization parameters. --- libavcodec/jpeg2000.c | 89 +++++++++++++++++++++--------------------------- libavcodec/jpeg2000.h | 36 ++++++++++++++++++++ libavcodec/jpeg2000dec.c | 40 ++++++++++++++++++---- 3 files changed, 108 insertions(+), 57 deletions(-) diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c index 6433e13892..a21f9c2a82 100644 --- a/libavcodec/jpeg2000.c +++ b/libavcodec/jpeg2000.c @@ -39,18 +39,6 @@ /* tag tree routines */ -static int32_t tag_tree_size(int w, int h) -{ - int64_t res = 0; - while (w > 1 || h > 1) { - res += w * (int64_t)h; - av_assert0(res + 1 < INT32_MAX); - w = (w + 1) >> 1; - h = (h + 1) >> 1; - } - return (int32_t)(res + 1); -} - /* allocate the memory for tag tree */ static Jpeg2000TgtNode *ff_jpeg2000_tag_tree_init(int w, int h) { @@ -58,7 +46,7 @@ static Jpeg2000TgtNode *ff_jpeg2000_tag_tree_init(int w, int h) Jpeg2000TgtNode *res, *t, *t2; int32_t tt_size; - tt_size = tag_tree_size(w, h); + tt_size = ff_jpeg2000_tag_tree_size(w, h); t = res = av_calloc(tt_size, sizeof(*t)); if (!res) @@ -85,7 +73,7 @@ static Jpeg2000TgtNode *ff_jpeg2000_tag_tree_init(int w, int h) void ff_tag_tree_zero(Jpeg2000TgtNode *t, int w, int h, int val) { - int i, siz = tag_tree_size(w, h); + int i, siz = ff_jpeg2000_tag_tree_size(w, h); for (i = 0; i < siz; i++) { t[i].val = val; @@ -199,33 +187,22 @@ void ff_jpeg2000_set_significance(Jpeg2000T1Context *t1, int x, int y, t1->flags[(y - 1) * t1->stride + x - 1] |= JPEG2000_T1_SIG_SE; } +/* TODO: Implementation of quantization step not finished, see + * ISO/IEC 15444-1:2002 E.1 and A.6.4. */ // static const uint8_t lut_gain[2][4] = { { 0, 0, 0, 0 }, { 0, 1, 1, 2 } }; (unused) - -/** - * 2^(x) for integer x in the range -126..128. - * @return correctly rounded float - */ -static av_always_inline float exp2fi(int x) +float ff_jpeg2000_band_stepsize(AVCodecContext *avctx, + Jpeg2000CodingStyle *codsty, + Jpeg2000QuantStyle *qntsty, + int bandno, int gbandno, + int reslevelno, int cbps) { - av_assert2(-126 <= x && x <= 128); - /* Normal range */ - return av_int2float((x+127) << 23); -} + float fss; -static void init_band_stepsize(AVCodecContext *avctx, - Jpeg2000Band *band, - Jpeg2000CodingStyle *codsty, - Jpeg2000QuantStyle *qntsty, - int bandno, int gbandno, int reslevelno, - int cbps) -{ - /* TODO: Implementation of quantization step not finished, - * see ISO/IEC 15444-1:2002 E.1 and A.6.4. */ switch (qntsty->quantsty) { uint8_t gain; case JPEG2000_QSTY_NONE: /* TODO: to verify. No quantization in this case */ - band->f_stepsize = 1; + fss = 1; break; case JPEG2000_QSTY_SI: /*TODO: Compute formula to implement. */ @@ -240,35 +217,47 @@ static void init_band_stepsize(AVCodecContext *avctx, * delta_b = 2 ^ (R_b - expn_b) * (1 + (mant_b / 2 ^ 11)) * R_b = R_I + log2 (gain_b ) * see ISO/IEC 15444-1:2002 E.1.1 eqn. E-3 and E-4 */ - gain = cbps; - band->f_stepsize = exp2fi(gain - qntsty->expn[gbandno]); - band->f_stepsize *= qntsty->mant[gbandno] / 2048.0 + 1.0; + gain = cbps; + fss = ff_jpeg2000_exp2fi(gain - qntsty->expn[gbandno]); + fss *= qntsty->mant[gbandno] / 2048.0 + 1.0; break; default: - band->f_stepsize = 0; av_log(avctx, AV_LOG_ERROR, "Unknown quantization format\n"); - break; + return 0; } if (codsty->transform != FF_DWT53) { int lband = 0; switch (bandno + (reslevelno > 0)) { - case 1: - case 2: - band->f_stepsize *= F_LFTG_X * 2; - lband = 1; - break; - case 3: - band->f_stepsize *= F_LFTG_X * F_LFTG_X * 4; - break; + case 1: + case 2: + fss *= F_LFTG_X * 2; + lband = 1; + break; + case 3: + fss *= F_LFTG_X * F_LFTG_X * 4; + break; } - band->f_stepsize *= pow(F_LFTG_K, 2*(codsty->nreslevels2decode - reslevelno) + lband - 2); + fss *= pow(F_LFTG_K, 2 * (codsty->nreslevels2decode - reslevelno) + + lband - 2); } - if (band->f_stepsize > (INT_MAX >> 15)) { - band->f_stepsize = 0; + if (fss > (INT_MAX >> 15)) { av_log(avctx, AV_LOG_ERROR, "stepsize out of range\n"); + return 0; } + return fss; +} +static void init_band_stepsize(AVCodecContext *avctx, + Jpeg2000Band *band, + Jpeg2000CodingStyle *codsty, + Jpeg2000QuantStyle *qntsty, + int bandno, int gbandno, int reslevelno, + int cbps) +{ + band->f_stepsize = ff_jpeg2000_band_stepsize(avctx, codsty, qntsty, + bandno, gbandno, reslevelno, + cbps); band->i_stepsize = (int)floorf(band->f_stepsize * (1 << 15)); } diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h index 93221d90ca..52c00f4268 100644 --- a/libavcodec/jpeg2000.h +++ b/libavcodec/jpeg2000.h @@ -31,6 +31,9 @@ #include <stdint.h> +#include "libavutil/avassert.h" +#include "libavutil/intfloat.h" + #include "avcodec.h" #include "mqc.h" #include "jpeg2000dwt.h" @@ -289,6 +292,39 @@ static inline int ff_jpeg2000_getsgnctxno(int flag, int *xorbit) return ff_jpeg2000_sgnctxno_lut[flag & 15][(flag >> 8) & 15]; } +/* Node count of the tag-tree pyramid over a (w, h) leaf grid. */ +static inline int32_t ff_jpeg2000_tag_tree_size(int w, int h) +{ + int64_t res = 0; + while (w > 1 || h > 1) { + res += w * (int64_t)h; + av_assert0(res + 1 < INT32_MAX); + w = (w + 1) >> 1; + h = (h + 1) >> 1; + } + return (int32_t)(res + 1); +} + +/** + * 2^(x) for integer x in the range -126..128. + * @return correctly rounded float + */ +static av_always_inline float ff_jpeg2000_exp2fi(int x) +{ + av_assert2(-126 <= x && x <= 128); + /* Normal range */ + return av_int2float((x + 127) << 23); +} + +/* Band dequantization step size (ISO/IEC 15444-1:2002 E.1), shared between + * the software decoder's band setup and the Vulkan hwaccel's inline + * geometry. */ +float ff_jpeg2000_band_stepsize(AVCodecContext *avctx, + Jpeg2000CodingStyle *codsty, + Jpeg2000QuantStyle *qntsty, + int bandno, int gbandno, + int reslevelno, int cbps); + int ff_jpeg2000_init_component(Jpeg2000Component *comp, Jpeg2000CodingStyle *codsty, Jpeg2000QuantStyle *qntsty, diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 369377e4fc..870678f0b0 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -39,6 +39,7 @@ #include "bytestream.h" #include "codec_internal.h" #include "decode.h" +#include "internal.h" #include "thread.h" #include "jpeg2000.h" #include "jpeg2000dsp.h" @@ -2855,7 +2856,7 @@ static av_cold int jpeg2000_decode_init(AVCodecContext *avctx) } static int jpeg2000_decode_frame(AVCodecContext *avctx, AVFrame *picture, - int *got_frame, AVPacket *avpkt) + const AVPacket *avpkt) { Jpeg2000DecoderContext *s = avctx->priv_data; int ret; @@ -2902,7 +2903,7 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, AVFrame *picture, if (avctx->skip_frame >= AVDISCARD_ALL) { jpeg2000_dec_cleanup(s); - return avpkt->size; + return 0; } /* get picture buffer */ @@ -2916,22 +2917,47 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, AVFrame *picture, if (++x == s->ncomponents) picture->flags |= AV_FRAME_FLAG_LOSSLESS; - avctx->execute2(avctx, jpeg2000_decode_tile, picture, NULL, s->numXtiles * s->numYtiles); + ff_thread_finish_setup(avctx); - jpeg2000_dec_cleanup(s); + avctx->execute2(avctx, jpeg2000_decode_tile, picture, NULL, + s->numXtiles * s->numYtiles); - *got_frame = 1; + jpeg2000_dec_cleanup(s); if (s->avctx->pix_fmt == AV_PIX_FMT_PAL8) memcpy(picture->data[1], s->palette, 256 * sizeof(uint32_t)); - return bytestream2_tell(&s->g); + return 0; end: + /* Do not leave a partially initialized frame on the output. */ + av_frame_unref(picture); jpeg2000_dec_cleanup(s); return ret; } +static int jpeg2000_receive_frame(AVCodecContext *avctx, AVFrame *frame) +{ + AVPacket *const avpkt = avctx->internal->in_pkt; + int ret; + + /* One codestream per packet. Loop so that skipped frames (produce no + * output) transparently pull the next packet instead of returning to the + * caller empty-handed. */ + do { + ret = ff_decode_get_packet(avctx, avpkt); + if (ret < 0) + return ret; + + ret = jpeg2000_decode_frame(avctx, frame, avpkt); + av_packet_unref(avpkt); + if (ret < 0) + return ret; + } while (!frame->buf[0]); + + return 0; +} + #define OFFSET(x) offsetof(Jpeg2000DecoderContext, x) #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM @@ -2956,7 +2982,7 @@ const FFCodec ff_jpeg2000_decoder = { .p.capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_DR1, .priv_data_size = sizeof(Jpeg2000DecoderContext), .init = jpeg2000_decode_init, - FF_CODEC_DECODE_CB(jpeg2000_decode_frame), + FF_CODEC_RECEIVE_FRAME_CB(jpeg2000_receive_frame), .p.priv_class = &jpeg2000_class, .p.max_lowres = 5, .p.profiles = NULL_IF_CONFIG_SMALL(ff_jpeg2000_profiles), -- To stop receiving notification emails like this one, please contact [email protected]. _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
