This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 8aff7f9f875a247ef7f10bcf103c60807b5fdc96 Author: Rainbaby <[email protected]> AuthorDate: Fri Aug 28 16:18:09 2026 +0900 Commit: Peter Ross <[email protected]> CommitDate: Mon Nov 2 22:18:06 2026 +0000 avcodec/cavs_aec: add the AVS1-P16 arithmetic decoder The Broadcasting profile codes its macroblock layer with the arithmetic coder of clause 8.4. This is the decoder only; its renormalization loops end with the buffer, so truncated input terminates. Signed-off-by: Rainbaby <[email protected]> --- libavcodec/Makefile | 2 +- libavcodec/cavs_aec.c | 54 +++++++++++++ libavcodec/cavs_aec.h | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 269 insertions(+), 1 deletion(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 2ea4f9417e..b30c263fae 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -306,7 +306,7 @@ OBJS-$(CONFIG_BONK_DECODER) += bonk.o OBJS-$(CONFIG_BRENDER_PIX_DECODER) += brenderpix.o OBJS-$(CONFIG_C93_DECODER) += c93.o OBJS-$(CONFIG_CAVS_DECODER) += cavs.o cavsdec.o cavsdsp.o \ - cavsdata.o + cavsdata.o cavs_aec.o OBJS-$(CONFIG_CBD2_DPCM_DECODER) += dpcm.o OBJS-$(CONFIG_CCAPTION_DECODER) += ccaption_dec.o ass.o OBJS-$(CONFIG_CDGRAPHICS_DECODER) += cdgraphics.o diff --git a/libavcodec/cavs_aec.c b/libavcodec/cavs_aec.c new file mode 100644 index 0000000000..bada516f16 --- /dev/null +++ b/libavcodec/cavs_aec.c @@ -0,0 +1,54 @@ +/* + * Chinese AVS video (AVS1-P16, Broadcasting profile) AEC decoder. + * Copyright (c) 2026 Rainbaby <[email protected]> + * + * 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 + */ + +/** + * @file + * Chinese AVS video (AVS1-P16, Broadcasting profile) AEC decoder + * + * Clause numbers refer to GY/T 257.1-2012. The renormalization loops end + * with the buffer, so truncated input terminates. The caller must have + * removed the annex A pseudo start codes from the payload. + */ + +#include <stdint.h> + +#include "cavs_aec.h" +#include "get_bits.h" + +void ff_cavs_aec_init(CAVSAECContext *aec, GetBitContext *gb) +{ + for (int i = 0; i < CAVS_AEC_NUM_CTX; i++) { + aec->ctx[i].mps = 0; + aec->ctx[i].cycno = 0; + aec->ctx[i].lg_pmps = CAVS_AEC_LGPMPS_INIT; + } + + aec->gb = gb; + aec->rs1 = 0; + aec->rt1 = CAVS_AEC_RT1_INIT; + aec->vs = 0; + aec->vt = get_bits(gb, 9); + while (!((aec->vt >> 8) & 0x01) && get_bits_left(gb) > 0) { + aec->vt = (aec->vt << 1) | get_bits1(gb); + aec->vs++; + } + aec->vt &= 0xFF; +} diff --git a/libavcodec/cavs_aec.h b/libavcodec/cavs_aec.h new file mode 100644 index 0000000000..251cef9713 --- /dev/null +++ b/libavcodec/cavs_aec.h @@ -0,0 +1,214 @@ +/* + * Chinese AVS video (AVS1-P16, Broadcasting profile) AEC decoder. + * Copyright (c) 2026 Rainbaby <[email protected]> + * + * 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 + */ + +/** + * @file + * Chinese AVS video (AVS1-P16, Broadcasting profile) AEC decoder + */ + +#ifndef AVCODEC_CAVS_AEC_H +#define AVCODEC_CAVS_AEC_H + +#include <stdint.h> + +#include "libavutil/attributes.h" +#include "libavutil/avassert.h" +#include "libavutil/error.h" +#include "libavutil/macros.h" + +#include "get_bits.h" + +/* Table 51's largest start index is 322, weighting_prediction, one model. */ +#define CAVS_AEC_NUM_CTX 323 + +/** Table 51 start index + ctxIdxInc, or AVERROR_INVALIDDATA/AVERROR_BUG. */ +static inline int ff_cavs_aec_ctx_idx(int start, int span, int inc) +{ + if (span <= 0 || start < 0 || start > CAVS_AEC_NUM_CTX - span) + return AVERROR_BUG; + if ((unsigned)inc >= (unsigned)span) + return AVERROR_INVALIDDATA; + + return start + inc; +} + +typedef struct CAVSAECModel { + uint8_t mps; ///< mps: more probable symbol, 1 bit, init 0 + uint8_t cycno; ///< cycno: adaptation counter, 2 bits, init 0 + uint16_t lg_pmps; ///< lgPmps: log domain P(MPS), 11 bits, init 1023 +} CAVSAECModel; + +typedef struct CAVSAECContext { + GetBitContext *gb; ///< bitstream reader, shared with the slice parser + int rs1; ///< range exponent, init 0 (rS1) + int rt1; ///< range mantissa, init 0xFF (rT1) + int vs; ///< offset exponent (valueS) + int vt; ///< offset mantissa, 9 bits inside a call (valueT) + CAVSAECModel ctx[CAVS_AEC_NUM_CTX]; ///< context models, 8.4.2.1 +} CAVSAECContext; + +/* Constants of clauses 8.4.2 and 8.4.4.3. */ +#define CAVS_AEC_LGPMPS_INIT 1023 +#define CAVS_AEC_LGPMPS_MAX 1023 +#define CAVS_AEC_LGPMPS_REFLECT 2047 +#define CAVS_AEC_LGPMPS_BYPASS 1023 +#define CAVS_AEC_LGPMPS_STUFF 4 +#define CAVS_AEC_RT1_INIT 0xFF + +/** Adapt one context model after a bin has been decoded, 8.4.4.3.5. */ +static inline void cavs_aec_update_ctx(CAVSAECModel *m, int bin) +{ + static const uint8_t cwr_tab[4] = { 3, 3, 4, 5 }; + /* cwr is 3..5, the leading entries only pad the table so it indexes */ + static const uint16_t lps_inc_tab[6] = { 0, 0, 0, 197, 95, 46 }; + const int cwr = cwr_tab[m->cycno]; + + if (bin != m->mps) + m->cycno = FFMIN(m->cycno + 1, 3); + else if (m->cycno == 0) + m->cycno = 1; + + if (bin == m->mps) { + m->lg_pmps -= (m->lg_pmps >> cwr) + (m->lg_pmps >> (cwr + 2)); + } else { + m->lg_pmps += lps_inc_tab[cwr]; + if (m->lg_pmps > CAVS_AEC_LGPMPS_MAX) { + m->lg_pmps = CAVS_AEC_LGPMPS_REFLECT - m->lg_pmps; + m->mps ^= 1; + } + } +} + +/** Decode one bin (8.4.4.3.2); the caller supplies predMps and lgPmps. */ +static av_always_inline int cavs_aec_decode_bin(CAVSAECContext *aec, + int pred_mps, int lg_pmps) +{ + GetBitContext *gb = aec->gb; + const int lps_range = lg_pmps >> 2; + int rs2, rt2, s_flag, bin; + + av_assert2(lps_range > 0); + + if (aec->rt1 >= lps_range) { + rs2 = aec->rs1; + rt2 = aec->rt1 - lps_range; + s_flag = 0; + } else { + rs2 = aec->rs1 + 1; + rt2 = 256 + aec->rt1 - lps_range; + s_flag = 1; + } + + if (rs2 > aec->vs || (rs2 == aec->vs && aec->vt >= rt2)) { + int t_rlps = s_flag ? aec->rt1 + lps_range : lps_range; + + bin = !pred_mps; + if (rs2 == aec->vs) + aec->vt -= rt2; + else + aec->vt = 256 + ((aec->vt << 1) | get_bits1(gb)) - rt2; + while (t_rlps < 0x100) { + t_rlps = t_rlps << 1; + aec->vt = (aec->vt << 1) | get_bits1(gb); + } + aec->rt1 = t_rlps & 0xFF; + } else { + bin = pred_mps; + aec->rs1 = rs2; + aec->rt1 = rt2; + } + + if (bin != pred_mps) { + aec->rs1 = 0; + aec->vs = 0; + /* the loop ends with the buffer, so truncated input terminates */ + while (aec->vt < 0x100 && get_bits_left(gb) > 0) { + aec->vs++; + aec->vt = (aec->vt << 1) | get_bits1(gb); + } + aec->vt &= 0xFF; + } + + return bin; +} + +/** Reset all contexts and start the decoder on byte aligned @p gb (8.4.1). */ +void ff_cavs_aec_init(CAVSAECContext *aec, GetBitContext *gb); + +/** Decode a bin with one context model (8.4.4.3.2). */ +static inline int ff_cavs_aec_decode_decision(CAVSAECContext *aec, int ctx_idx) +{ + CAVSAECModel *m; + int bin; + + av_assert2(ctx_idx >= 0 && ctx_idx < CAVS_AEC_NUM_CTX); + + m = &aec->ctx[ctx_idx]; + bin = cavs_aec_decode_bin(aec, m->mps, m->lg_pmps); + cavs_aec_update_ctx(m, bin); + + return bin; +} + +/** Decode a bin with two weighted context models (8.4.4.3.2). */ +static inline int ff_cavs_aec_decode_decision_w(CAVSAECContext *aec, + int ctx_idx, int ctx_idx_w) +{ + CAVSAECModel *m1, *m2; + int pred_mps, lg_pmps, bin; + + av_assert2(ctx_idx >= 0 && ctx_idx < CAVS_AEC_NUM_CTX); + av_assert2(ctx_idx_w >= 0 && ctx_idx_w < CAVS_AEC_NUM_CTX); + + m1 = &aec->ctx[ctx_idx]; + m2 = &aec->ctx[ctx_idx_w]; + + if (m1->mps == m2->mps) { + pred_mps = m1->mps; + lg_pmps = (m1->lg_pmps + m2->lg_pmps) / 2; + } else if (m1->lg_pmps < m2->lg_pmps) { + pred_mps = m1->mps; + lg_pmps = CAVS_AEC_LGPMPS_MAX - ((m2->lg_pmps - m1->lg_pmps) >> 1); + } else { + pred_mps = m2->mps; + lg_pmps = CAVS_AEC_LGPMPS_MAX - ((m1->lg_pmps - m2->lg_pmps) >> 1); + } + + bin = cavs_aec_decode_bin(aec, pred_mps, lg_pmps); + cavs_aec_update_ctx(m1, bin); + cavs_aec_update_ctx(m2, bin); + + return bin; +} + +/** Decode a bypass bin, fixed lgPmps (8.4.4.3.3). */ +static inline int ff_cavs_aec_decode_bypass(CAVSAECContext *aec) +{ + return cavs_aec_decode_bin(aec, 0, CAVS_AEC_LGPMPS_BYPASS); +} + +/** Decode aec_mb_stuffing_bit, fixed lgPmps (8.4.4.3.4). */ +static inline int ff_cavs_aec_decode_stuffing_bit(CAVSAECContext *aec) +{ + return cavs_aec_decode_bin(aec, 0, CAVS_AEC_LGPMPS_STUFF); +} + +#endif /* AVCODEC_CAVS_AEC_H */ -- 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]
