FFmpeg
Loading...
Searching...
No Matches
cavs_aec.h
Go to the documentation of this file.
1/*
2 * Chinese AVS video (AVS1-P16, Broadcasting profile) AEC decoder.
3 * Copyright (c) 2026 Rainbaby <r@bgr.jp>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22/**
23 * @file
24 * Chinese AVS video (AVS1-P16, Broadcasting profile) AEC decoder
25 */
26
27#ifndef AVCODEC_CAVS_AEC_H
28#define AVCODEC_CAVS_AEC_H
29
30#include <stdint.h>
31
33#include "libavutil/avassert.h"
34#include "libavutil/error.h"
35#include "libavutil/macros.h"
36
37#include "get_bits.h"
38
39/* Table 51's largest start index is 322, weighting_prediction, one model. */
40#define CAVS_AEC_NUM_CTX 323
41
42/** Table 51 start index + ctxIdxInc, or AVERROR_INVALIDDATA/AVERROR_BUG. */
43static inline int ff_cavs_aec_ctx_idx(int start, int span, int inc)
44{
45 if (span <= 0 || start < 0 || start > CAVS_AEC_NUM_CTX - span)
46 return AVERROR_BUG;
47 if ((unsigned)inc >= (unsigned)span)
49
50 return start + inc;
51}
52
53typedef struct CAVSAECModel {
54 uint8_t mps; ///< mps: more probable symbol, 1 bit, init 0
55 uint8_t cycno; ///< cycno: adaptation counter, 2 bits, init 0
56 uint16_t lg_pmps; ///< lgPmps: log domain P(MPS), 11 bits, init 1023
58
59typedef struct CAVSAECContext {
60 GetBitContext *gb; ///< bitstream reader, shared with the slice parser
61 int rs1; ///< range exponent, init 0 (rS1)
62 int rt1; ///< range mantissa, init 0xFF (rT1)
63 int vs; ///< offset exponent (valueS)
64 int vt; ///< offset mantissa, 9 bits inside a call (valueT)
65 CAVSAECModel ctx[CAVS_AEC_NUM_CTX]; ///< context models, 8.4.2.1
67
68/* Constants of clauses 8.4.2 and 8.4.4.3. */
69#define CAVS_AEC_LGPMPS_INIT 1023
70#define CAVS_AEC_LGPMPS_MAX 1023
71#define CAVS_AEC_LGPMPS_REFLECT 2047
72#define CAVS_AEC_LGPMPS_BYPASS 1023
73#define CAVS_AEC_LGPMPS_STUFF 4
74#define CAVS_AEC_RT1_INIT 0xFF
75
76/** Adapt one context model after a bin has been decoded, 8.4.4.3.5. */
77static inline void cavs_aec_update_ctx(CAVSAECModel *m, int bin)
78{
79 static const uint8_t cwr_tab[4] = { 3, 3, 4, 5 };
80 /* cwr is 3..5, the leading entries only pad the table so it indexes */
81 static const uint16_t lps_inc_tab[6] = { 0, 0, 0, 197, 95, 46 };
82 const int cwr = cwr_tab[m->cycno];
83
84 if (bin != m->mps)
85 m->cycno = FFMIN(m->cycno + 1, 3);
86 else if (m->cycno == 0)
87 m->cycno = 1;
88
89 if (bin == m->mps) {
90 m->lg_pmps -= (m->lg_pmps >> cwr) + (m->lg_pmps >> (cwr + 2));
91 } else {
92 m->lg_pmps += lps_inc_tab[cwr];
95 m->mps ^= 1;
96 }
97 }
98}
99
100/** Decode one bin (8.4.4.3.2); the caller supplies predMps and lgPmps. */
102 int pred_mps, int lg_pmps)
103{
104 GetBitContext *gb = aec->gb;
105 const int lps_range = lg_pmps >> 2;
106 int rs2, rt2, s_flag, bin;
107
108 av_assert2(lps_range > 0);
109
110 if (aec->rt1 >= lps_range) {
111 rs2 = aec->rs1;
112 rt2 = aec->rt1 - lps_range;
113 s_flag = 0;
114 } else {
115 rs2 = aec->rs1 + 1;
116 rt2 = 256 + aec->rt1 - lps_range;
117 s_flag = 1;
118 }
119
120 if (rs2 > aec->vs || (rs2 == aec->vs && aec->vt >= rt2)) {
121 int t_rlps = s_flag ? aec->rt1 + lps_range : lps_range;
122
123 bin = !pred_mps;
124 if (rs2 == aec->vs)
125 aec->vt -= rt2;
126 else
127 aec->vt = 256 + ((aec->vt << 1) | get_bits1(gb)) - rt2;
128 while (t_rlps < 0x100) {
129 t_rlps = t_rlps << 1;
130 aec->vt = (aec->vt << 1) | get_bits1(gb);
131 }
132 aec->rt1 = t_rlps & 0xFF;
133 } else {
134 bin = pred_mps;
135 aec->rs1 = rs2;
136 aec->rt1 = rt2;
137 }
138
139 if (bin != pred_mps) {
140 aec->rs1 = 0;
141 aec->vs = 0;
142 /* the loop ends with the buffer, so truncated input terminates */
143 while (aec->vt < 0x100 && get_bits_left(gb) > 0) {
144 aec->vs++;
145 aec->vt = (aec->vt << 1) | get_bits1(gb);
146 }
147 aec->vt &= 0xFF;
148 }
149
150 return bin;
151}
152
153/** Reset all contexts and start the decoder on byte aligned @p gb (8.4.1). */
155
156/** Decode a bin with one context model (8.4.4.3.2). */
157static inline int ff_cavs_aec_decode_decision(CAVSAECContext *aec, int ctx_idx)
158{
159 CAVSAECModel *m;
160 int bin;
161
162 av_assert2(ctx_idx >= 0 && ctx_idx < CAVS_AEC_NUM_CTX);
163
164 m = &aec->ctx[ctx_idx];
165 bin = cavs_aec_decode_bin(aec, m->mps, m->lg_pmps);
166 cavs_aec_update_ctx(m, bin);
167
168 return bin;
169}
170
171/** Decode a bin with two weighted context models (8.4.4.3.2). */
173 int ctx_idx, int ctx_idx_w)
174{
175 CAVSAECModel *m1, *m2;
176 int pred_mps, lg_pmps, bin;
177
178 av_assert2(ctx_idx >= 0 && ctx_idx < CAVS_AEC_NUM_CTX);
179 av_assert2(ctx_idx_w >= 0 && ctx_idx_w < CAVS_AEC_NUM_CTX);
180
181 m1 = &aec->ctx[ctx_idx];
182 m2 = &aec->ctx[ctx_idx_w];
183
184 if (m1->mps == m2->mps) {
185 pred_mps = m1->mps;
186 lg_pmps = (m1->lg_pmps + m2->lg_pmps) / 2;
187 } else if (m1->lg_pmps < m2->lg_pmps) {
188 pred_mps = m1->mps;
189 lg_pmps = CAVS_AEC_LGPMPS_MAX - ((m2->lg_pmps - m1->lg_pmps) >> 1);
190 } else {
191 pred_mps = m2->mps;
192 lg_pmps = CAVS_AEC_LGPMPS_MAX - ((m1->lg_pmps - m2->lg_pmps) >> 1);
193 }
194
195 bin = cavs_aec_decode_bin(aec, pred_mps, lg_pmps);
196 cavs_aec_update_ctx(m1, bin);
197 cavs_aec_update_ctx(m2, bin);
198
199 return bin;
200}
201
202/** Decode a bypass bin, fixed lgPmps (8.4.4.3.3). */
204{
206}
207
208/** Decode aec_mb_stuffing_bit, fixed lgPmps (8.4.4.3.4). */
213
214#endif /* AVCODEC_CAVS_AEC_H */
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition avassert.h:68
#define CAVS_AEC_NUM_CTX
Definition cavs_aec.h:40
static int ff_cavs_aec_decode_decision_w(CAVSAECContext *aec, int ctx_idx, int ctx_idx_w)
Decode a bin with two weighted context models (8.4.4.3.2).
Definition cavs_aec.h:172
static int ff_cavs_aec_decode_decision(CAVSAECContext *aec, int ctx_idx)
Decode a bin with one context model (8.4.4.3.2).
Definition cavs_aec.h:157
static int ff_cavs_aec_ctx_idx(int start, int span, int inc)
Table 51 start index + ctxIdxInc, or AVERROR_INVALIDDATA/AVERROR_BUG.
Definition cavs_aec.h:43
void ff_cavs_aec_init(CAVSAECContext *aec, GetBitContext *gb)
Reset all contexts and start the decoder on byte aligned gb (8.4.1).
Definition cavs_aec.c:36
static int ff_cavs_aec_decode_stuffing_bit(CAVSAECContext *aec)
Decode aec_mb_stuffing_bit, fixed lgPmps (8.4.4.3.4).
Definition cavs_aec.h:209
#define CAVS_AEC_LGPMPS_REFLECT
Definition cavs_aec.h:71
#define CAVS_AEC_LGPMPS_BYPASS
Definition cavs_aec.h:72
#define CAVS_AEC_LGPMPS_STUFF
Definition cavs_aec.h:73
#define CAVS_AEC_LGPMPS_MAX
Definition cavs_aec.h:70
static av_always_inline int cavs_aec_decode_bin(CAVSAECContext *aec, int pred_mps, int lg_pmps)
Decode one bin (8.4.4.3.2); the caller supplies predMps and lgPmps.
Definition cavs_aec.h:101
static void cavs_aec_update_ctx(CAVSAECModel *m, int bin)
Adapt one context model after a bin has been decoded, 8.4.4.3.5.
Definition cavs_aec.h:77
static int ff_cavs_aec_decode_bypass(CAVSAECContext *aec)
Decode a bypass bin, fixed lgPmps (8.4.4.3.3).
Definition cavs_aec.h:203
error code definitions
bitstream reader API header.
static int get_bits_left(GetBitContext *gb)
Definition get_bits.h:688
static unsigned int get_bits1(GetBitContext *s)
Definition get_bits.h:391
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition error.h:52
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
Macro definitions for various function/variable attributes.
#define av_always_inline
Definition attributes.h:72
Utility Preprocessor macros.
#define FFMIN(a, b)
Definition macros.h:49
static int inc(int num, int period)
Definition perlin.c:34
int vs
offset exponent (valueS)
Definition cavs_aec.h:63
GetBitContext * gb
bitstream reader, shared with the slice parser
Definition cavs_aec.h:60
CAVSAECModel ctx[CAVS_AEC_NUM_CTX]
context models, 8.4.2.1
Definition cavs_aec.h:65
int rt1
range mantissa, init 0xFF (rT1)
Definition cavs_aec.h:62
int rs1
range exponent, init 0 (rS1)
Definition cavs_aec.h:61
int vt
offset mantissa, 9 bits inside a call (valueT)
Definition cavs_aec.h:64
uint8_t mps
mps: more probable symbol, 1 bit, init 0
Definition cavs_aec.h:54
uint8_t cycno
cycno: adaptation counter, 2 bits, init 0
Definition cavs_aec.h:55
uint16_t lg_pmps
lgPmps: log domain P(MPS), 11 bits, init 1023
Definition cavs_aec.h:56