1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-08-04 22:03:09 +02:00

avcodec/mpeg4videoenc: Simplify creating LUT

There four cases for the LUT entry: An ordinary entry
or one of three escaping methods. Three of these methods
are only rarely possible --they correspond to the 102
codes of the underlying VLC and so only 102 of 16384 entries
are possible.

The earlier code would nevertheless try them all for every
LUT entry and use the best one; the new code meanwhile only
uses one method (the fallback one (i.e. the worst)) for them all
and only processes the 102 valid entries afterwards.

The implementation used also means that index_run, max_level
and max_run of the RLTable are no longer needed; the earlier
code would initialize said static tables although they are only
used for a short time to initialize something else.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
Andreas Rheinhardt
2025-05-18 08:35:23 +02:00
parent 295abb1fdc
commit d75a398d00

View File

@ -1184,95 +1184,78 @@ static av_cold void init_uni_dc_tab(void)
static av_cold void init_uni_mpeg4_rl_tab(RLTable *rl, uint32_t *bits_tab, static av_cold void init_uni_mpeg4_rl_tab(RLTable *rl, uint32_t *bits_tab,
uint8_t *len_tab) uint8_t *len_tab)
{ {
int slevel, run, last; // Type 3 escape method. The escape code is the same for both VLCs
// (0x3, seven bits), so it is hardcoded.
memset(len_tab, 30, 2 * 2 * 64 * 64);
len_tab += 64;
bits_tab += 64;
for (int run = 0; run < 64; ++run) {
for (int level = 1;; ++level) {
// Escape code type 3 not last run (6 bits) marker marker
unsigned code = (3 << 23) | (3 << 21) | (0 << 20) | (run << 14) | (1 << 13) | 1;
// first the negative levels
bits_tab[UNI_MPEG4_ENC_INDEX(0, run, -level)] = code | (-level & 0xfff) << 1;
bits_tab[UNI_MPEG4_ENC_INDEX(1, run, -level)] =
bits_tab[UNI_MPEG4_ENC_INDEX(0, run, -level)] | (1 << 20) /* last */;
av_assert0(MAX_LEVEL >= 64); if (level == 64) // positive levels have a range of 1..63
av_assert0(MAX_RUN >= 63); break;
bits_tab[UNI_MPEG4_ENC_INDEX(0, run, level)] = code | level << 1;
bits_tab[UNI_MPEG4_ENC_INDEX(1, run, level)] =
bits_tab[UNI_MPEG4_ENC_INDEX(0, run, level)] | (1 << 20) /* last */;
}
// Is this needed at all?
len_tab[UNI_MPEG4_ENC_INDEX(0, run, 0)] =
len_tab[UNI_MPEG4_ENC_INDEX(1, run, 0)] = 0;
}
for (slevel = -64; slevel < 64; slevel++) { uint8_t max_run[2][32] = { 0 };
if (slevel == 0)
continue;
for (run = 0; run < 64; run++) {
for (last = 0; last <= 1; last++) {
const int index = UNI_MPEG4_ENC_INDEX(last, run, slevel + 64);
int level = slevel < 0 ? -slevel : slevel;
int sign = slevel < 0 ? 1 : 0;
int bits, len, code;
int level1, run1;
len_tab[index] = 100; #define VLC_NUM_CODES 102 // excluding the escape
av_assert2(rl->n == VLC_NUM_CODES);
for (int i = VLC_NUM_CODES - 1, max_level, cur_run = 0; i >= 0; --i) {
int run = rl->table_run[i], level = rl->table_level[i];
int last = i >= rl->last;
unsigned code = rl->table_vlc[i][0] << 1;
int len = rl->table_vlc[i][1] + 1;
/* ESC0 */ bits_tab[UNI_MPEG4_ENC_INDEX(last, run, level)] = code;
code = get_rl_index(rl, last, run, level); len_tab [UNI_MPEG4_ENC_INDEX(last, run, level)] = len;
bits = rl->table_vlc[code][0]; bits_tab[UNI_MPEG4_ENC_INDEX(last, run, -level)] = code | 1;
len = rl->table_vlc[code][1]; len_tab [UNI_MPEG4_ENC_INDEX(last, run, -level)] = len;
bits = bits * 2 + sign;
len++;
if (code != rl->n && len < len_tab[index]) { if (!max_run[last][level])
bits_tab[index] = bits; max_run[last][level] = run + 1;
len_tab[index] = len; av_assert2(run + 1 <= max_run[last][level]);
}
/* ESC1 */
bits = rl->table_vlc[rl->n][0];
len = rl->table_vlc[rl->n][1];
bits = bits * 2;
len++; // esc1
level1 = level - rl->max_level[last][run];
if (level1 > 0) {
code = get_rl_index(rl, last, run, level1);
bits <<= rl->table_vlc[code][1];
len += rl->table_vlc[code][1];
bits += rl->table_vlc[code][0];
bits = bits * 2 + sign;
len++;
if (code != rl->n && len < len_tab[index]) { int run3 = run + max_run[last][level];
bits_tab[index] = bits; int len3 = len + 7 + 2;
len_tab[index] = len;
}
}
/* ESC2 */
bits = rl->table_vlc[rl->n][0];
len = rl->table_vlc[rl->n][1];
bits = bits * 4 + 2;
len += 2; // esc2
run1 = run - rl->max_run[last][level] - 1;
if (run1 >= 0) {
code = get_rl_index(rl, last, run1, level);
bits <<= rl->table_vlc[code][1];
len += rl->table_vlc[code][1];
bits += rl->table_vlc[code][0];
bits = bits * 2 + sign;
len++;
if (code != rl->n && len < len_tab[index]) { if (run3 < 64 && len3 < len_tab[UNI_MPEG4_ENC_INDEX(last, run3, level)]) {
bits_tab[index] = bits; unsigned code3 = code | (0x3 << 2 | 0x2) << len;
len_tab[index] = len; bits_tab[UNI_MPEG4_ENC_INDEX(last, run3, level)] = code3;
len_tab [UNI_MPEG4_ENC_INDEX(last, run3, level)] = len3;
bits_tab[UNI_MPEG4_ENC_INDEX(last, run3, -level)] = code3 | 1;
len_tab [UNI_MPEG4_ENC_INDEX(last, run3, -level)] = len3;
} }
} // table_run and table_level are ordered so that all the entries
/* ESC3 */ // with the same last and run are consecutive and level is ascending
bits = rl->table_vlc[rl->n][0]; // among these entries. By traversing downwards we therefore automatically
len = rl->table_vlc[rl->n][1]; // encounter max_level of a given run first, needed for escape method 1.
bits = bits * 4 + 3; if (run != cur_run) {
len += 2; // esc3 max_level = level;
bits = bits * 2 + last; cur_run = run;
len++; } else
bits = bits * 64 + run; av_assert2(max_level > level);
len += 6;
bits = bits * 2 + 1;
len++; // marker
bits = bits * 4096 + (slevel & 0xfff);
len += 12;
bits = bits * 2 + 1;
len++; // marker
if (len < len_tab[index]) { code |= 0x3 << (len + 1);
bits_tab[index] = bits; len += 7 + 1;
len_tab[index] = len; level += max_level;
} av_assert2(len_tab [UNI_MPEG4_ENC_INDEX(last, run, level)] >= len);
} bits_tab[UNI_MPEG4_ENC_INDEX(last, run, level)] = code;
} len_tab [UNI_MPEG4_ENC_INDEX(last, run, level)] = len;
bits_tab[UNI_MPEG4_ENC_INDEX(last, run, -level)] = code | 1;
len_tab [UNI_MPEG4_ENC_INDEX(last, run, -level)] = len;
} }
} }
@ -1280,8 +1263,6 @@ static av_cold void mpeg4_encode_init_static(void)
{ {
init_uni_dc_tab(); init_uni_dc_tab();
ff_mpeg4_init_rl_intra();
init_uni_mpeg4_rl_tab(&ff_mpeg4_rl_intra, uni_mpeg4_intra_rl_bits, uni_mpeg4_intra_rl_len); init_uni_mpeg4_rl_tab(&ff_mpeg4_rl_intra, uni_mpeg4_intra_rl_bits, uni_mpeg4_intra_rl_len);
init_uni_mpeg4_rl_tab(&ff_h263_rl_inter, uni_mpeg4_inter_rl_bits, uni_mpeg4_inter_rl_len); init_uni_mpeg4_rl_tab(&ff_h263_rl_inter, uni_mpeg4_inter_rl_bits, uni_mpeg4_inter_rl_len);