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

Unified · Split

libavcodec/h261enc.c+31−20
@@ -36,6 +36,14 @@ · 35 unmodified lines
36#include "h261enc.h"36#include "h261enc.h"
37#include "mpegvideoenc.h"37#include "mpegvideoenc.h"
38 38
39#define H261_MAX_RUN 26
40#define H261_MAX_LEVEL 15
41
42static 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
39static uint8_t uni_h261_rl_len [64*64*2*2];47static uint8_t uni_h261_rl_len [64*64*2*2];
40#define UNI_ENC_INDEX(last,run,level) ((last)*128*64 + (run)*128 + (level))48#define UNI_ENC_INDEX(last,run,level) ((last)*128*64 + (run)*128 + (level))
41 49
@@ -165,10 +173,8 @@ static inline int get_cbp(MpegEncContext *s, int16_t block[6][64]) · 123 unmodified lines
165static void h261_encode_block(H261EncContext *h, int16_t *block, int n)173static void h261_encode_block(H261EncContext *h, int16_t *block, int n)
166{174{
167 MpegEncContext *const s = &h->s;175 MpegEncContext *const s = &h->s;
168 int level, run, i, j, last_index, last_non_zero, sign, slevel, code;176 int level, run, i, j, last_index, last_non_zero;
169 const RLTable *rl;
170 177
171 rl = &ff_h261_rl_tcoeff;
172 if (s->mb_intra) {178 if (s->mb_intra) {
173 /* DC coef */179 /* DC coef */
174 level = block[0];180 level = block[0];
@@ -204,24 +210,18 @@ static void h261_encode_block(H261EncContext *h, int16_t *block, int n) · 29 unmodified lines
204 level = block[j];210 level = block[j];
205 if (level) {211 if (level) {
206 run = i - last_non_zero - 1;212 run = i - last_non_zero - 1;
207 sign = 0;213
208 slevel = level;214 if (run <= H261_MAX_RUN &&
209 if (level < 0) {215 (unsigned)(level + H261_MAX_LEVEL) <= 2 * H261_MAX_LEVEL &&
210 sign = 1;216 vlc_lut[run][level + H261_MAX_LEVEL].len) {
211 level = -level;217 put_bits(&s->pb, vlc_lut[run][level + H261_MAX_LEVEL].len,
212 }218 vlc_lut[run][level + H261_MAX_LEVEL].code);
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);
223 } else {219 } 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);
225 }225 }
226 last_non_zero = i;226 last_non_zero = i;
227 }227 }
@@ -365,6 +365,17 @@ static av_cold void h261_encode_init_static(void) · 137 unmodified lines
365 365
366 ff_rl_init(&ff_h261_rl_tcoeff, h261_rl_table_store);366 ff_rl_init(&ff_h261_rl_tcoeff, h261_rl_table_store);
367 init_uni_h261_rl_tab(&ff_h261_rl_tcoeff, uni_h261_rl_len);367 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 }
368}379}
369 380
370av_cold int ff_h261_encode_init(MpegEncContext *s)381av_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