ffmpeg | branch: master | Andreas Rheinhardt <andreas.rheinha...@outlook.com> | Sat Jun 15 17:26:14 2024 +0200| [f3829cc72d74f41e0eb82bf968315de2b119a8a3] | committer: Andreas Rheinhardt
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. Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> > http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=f3829cc72d74f41e0eb82bf968315de2b119a8a3 --- libavcodec/h261enc.c | 51 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/libavcodec/h261enc.c b/libavcodec/h261enc.c index 8e08c749d1..b19830d578 100644 --- a/libavcodec/h261enc.c +++ b/libavcodec/h261enc.c @@ -36,6 +36,14 @@ #include "h261enc.h" #include "mpegvideoenc.h" +#define H261_MAX_RUN 26 +#define H261_MAX_LEVEL 15 + +static struct VLCLUT { + uint8_t len; + uint16_t code; +} vlc_lut[H261_MAX_RUN + 1][32 /* 0..2 * H261_MAX_LEN are used */]; + static uint8_t uni_h261_rl_len [64*64*2*2]; #define UNI_ENC_INDEX(last,run,level) ((last)*128*64 + (run)*128 + (level)) @@ -165,10 +173,8 @@ static inline int get_cbp(MpegEncContext *s, int16_t block[6][64]) static void h261_encode_block(H261EncContext *h, int16_t *block, int n) { MpegEncContext *const s = &h->s; - int level, run, i, j, last_index, last_non_zero, sign, slevel, code; - const RLTable *rl; + int level, run, i, j, last_index, last_non_zero; - rl = &ff_h261_rl_tcoeff; if (s->mb_intra) { /* DC coef */ level = block[0]; @@ -204,24 +210,18 @@ static void h261_encode_block(H261EncContext *h, int16_t *block, int n) level = block[j]; if (level) { run = i - last_non_zero - 1; - sign = 0; - slevel = level; - if (level < 0) { - sign = 1; - level = -level; - } - code = get_rl_index(rl, 0 /*no last in H.261, EOB is used*/, - run, level); - if (run == 0 && level < 16) - code += 1; - put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]); - if (code == rl->n) { - put_bits(&s->pb, 6, run); - av_assert1(slevel != 0); - av_assert1(level <= 127); - put_sbits(&s->pb, 8, slevel); + + if (run <= H261_MAX_RUN && + (unsigned)(level + H261_MAX_LEVEL) <= 2 * H261_MAX_LEVEL && + vlc_lut[run][level + H261_MAX_LEVEL].len) { + put_bits(&s->pb, vlc_lut[run][level + H261_MAX_LEVEL].len, + vlc_lut[run][level + H261_MAX_LEVEL].code); } else { - put_bits(&s->pb, 1, sign); + /* Escape */ + put_bits(&s->pb, 6 + 6, (1 << 6) | run); + av_assert1(level != 0); + av_assert1(FFABS(level) <= 127); + put_sbits(&s->pb, 8, level); } last_non_zero = i; } @@ -365,6 +365,17 @@ static av_cold void h261_encode_init_static(void) ff_rl_init(&ff_h261_rl_tcoeff, h261_rl_table_store); init_uni_h261_rl_tab(&ff_h261_rl_tcoeff, uni_h261_rl_len); + + // The following loop is over the ordinary elements, not EOB or escape. + for (size_t i = 1; i < FF_ARRAY_ELEMS(ff_h261_tcoeff_vlc) - 1; i++) { + unsigned run = ff_h261_tcoeff_run[i]; + unsigned level = ff_h261_tcoeff_level[i]; + unsigned len = ff_h261_tcoeff_vlc[i][1] + 1 /* sign */; + unsigned code = ff_h261_tcoeff_vlc[i][0]; + + vlc_lut[run][H261_MAX_LEVEL + level] = (struct VLCLUT){ len, code << 1 }; + vlc_lut[run][H261_MAX_LEVEL - level] = (struct VLCLUT){ len, (code << 1) | 1 }; + } } av_cold int ff_h261_encode_init(MpegEncContext *s) _______________________________________________ ffmpeg-cvslog mailing list ffmpeg-cvslog@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-cvslog To unsubscribe, visit link above, or email ffmpeg-cvslog-requ...@ffmpeg.org with subject "unsubscribe".