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.
Unified · Split
| @@ -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 | |||
| 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 | |||
| 39 | static uint8_t uni_h261_rl_len [64*64*2*2]; | 47 | static 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 | |||
| 165 | static void h261_encode_block(H261EncContext *h, int16_t *block, int n) | 173 | static 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 | ||
| 370 | av_cold int ff_h261_encode_init(MpegEncContext *s) | 381 | av_cold int ff_h261_encode_init(MpegEncContext *s) |