History

avcodec/h261enc: Avoid RLTable when writing macroblock

The RLTable API in rl.c is not well designed for codecs with an explicit end-of-block code. ff_h261_rl_tcoeff's vlc has the EOB code as first element (presumably so that the decoder can check for it via "if (level == 0)") and this implies that the indices returned by get_rl_index() are off by one for run == 0 which is therefore explicitly checked. This commit changes this by adding a simple LUT for the values not requiring escaping. It is easy to directly include the sign bit into this, so this has also been done.

Andreas Rheinhardt committed 2 years ago

Commit f3829cc1 parent 38744421 file · +31 −20Browse files

Showing the changes to libavcodec (1 of 1 file). Show all

Unified · Split

libavcodec/h261enc.c+31−20
@@ -36,6 +36,14 @@ · 35 unmodified lines
3636 #include "h261enc.h"
3737 #include "mpegvideoenc.h"
3838
39+#define H261_MAX_RUN 26
40+#define H261_MAX_LEVEL 15
41+
42+static struct VLCLUT {
43+ uint8_t len;
44+ uint16_t code;
45+} vlc_lut[H261_MAX_RUN + 1][32 /* 0..2 * H261_MAX_LEN are used */];
46+
3947 static uint8_t uni_h261_rl_len [64*64*2*2];
4048 #define UNI_ENC_INDEX(last,run,level) ((last)*128*64 + (run)*128 + (level))
4149
@@ -165,10 +173,8 @@ static inline int get_cbp(MpegEncContext *s, int16_t block[6][64]) · 123 unmodified lines
165173 static void h261_encode_block(H261EncContext *h, int16_t *block, int n)
166174 {
167175 MpegEncContext *const s = &h->s;
168− int level, run, i, j, last_index, last_non_zero, sign, slevel, code;
169− const RLTable *rl;
176+ int level, run, i, j, last_index, last_non_zero;
170177
171− rl = &ff_h261_rl_tcoeff;
172178 if (s->mb_intra) {
173179 /* DC coef */
174180 level = block[0];
@@ -204,24 +210,18 @@ static void h261_encode_block(H261EncContext *h, int16_t *block, int n) · 29 unmodified lines
204210 level = block[j];
205211 if (level) {
206212 run = i - last_non_zero - 1;
207− sign = 0;
208− slevel = level;
209− if (level < 0) {
210− sign = 1;
211− level = -level;
212− }
213− code = get_rl_index(rl, 0 /*no last in H.261, EOB is used*/,
214− run, level);
215− if (run == 0 && level < 16)
216− code += 1;
217− put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]);
218− if (code == rl->n) {
219− put_bits(&s->pb, 6, run);
220− av_assert1(slevel != 0);
221− av_assert1(level <= 127);
222− put_sbits(&s->pb, 8, slevel);
213+
214+ if (run <= H261_MAX_RUN &&
215+ (unsigned)(level + H261_MAX_LEVEL) <= 2 * H261_MAX_LEVEL &&
216+ vlc_lut[run][level + H261_MAX_LEVEL].len) {
217+ put_bits(&s->pb, vlc_lut[run][level + H261_MAX_LEVEL].len,
218+ vlc_lut[run][level + H261_MAX_LEVEL].code);
223219 } else {
224− put_bits(&s->pb, 1, sign);
220+ /* Escape */
221+ put_bits(&s->pb, 6 + 6, (1 << 6) | run);
222+ av_assert1(level != 0);
223+ av_assert1(FFABS(level) <= 127);
224+ put_sbits(&s->pb, 8, level);
225225 }
226226 last_non_zero = i;
227227 }
@@ -365,6 +365,17 @@ static av_cold void h261_encode_init_static(void) · 137 unmodified lines
365365
366366 ff_rl_init(&ff_h261_rl_tcoeff, h261_rl_table_store);
367367 init_uni_h261_rl_tab(&ff_h261_rl_tcoeff, uni_h261_rl_len);
368+
369+ // The following loop is over the ordinary elements, not EOB or escape.
370+ for (size_t i = 1; i < FF_ARRAY_ELEMS(ff_h261_tcoeff_vlc) - 1; i++) {
371+ unsigned run = ff_h261_tcoeff_run[i];
372+ unsigned level = ff_h261_tcoeff_level[i];
373+ unsigned len = ff_h261_tcoeff_vlc[i][1] + 1 /* sign */;
374+ unsigned code = ff_h261_tcoeff_vlc[i][0];
375+
376+ vlc_lut[run][H261_MAX_LEVEL + level] = (struct VLCLUT){ len, code << 1 };
377+ vlc_lut[run][H261_MAX_LEVEL - level] = (struct VLCLUT){ len, (code << 1) | 1 };
378+ }
368379 }
369380
370381 av_cold int ff_h261_encode_init(MpegEncContext *s)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t