[FFmpeg-devel] [PATCH 01/10] zlib decoder

Måns Rullgård mans
Mon Jul 16 01:25:14 CEST 2007


Michael Niedermayer <michaelni at gmx.at> writes:

> Hi
>
> On Sun, Jul 15, 2007 at 09:12:21PM +0100, Mans Rullgard wrote:
> [...]
>> +struct AVInflateContext {
[...]
>> +};
>
> what about adding some doxygen comments which describe what all these
> variables mean?

Good idea I guess.

>> +static const unsigned short len_tab[29][2] = {
>
> what about subtracting 3 from [1], that way this table would need 58 bytes
> less

True, didn't think of that.

>> +static const unsigned short dist_tab[32][2] = {
>
> dist_tab[x][1] could theoretically be replaced by
> (dist_tab[x][1]<<dist_tab[x][0])+1
> then the table would also fit in 8bit but maybe thats not worth it



>> +        if (clen[i] > max_bits)
>> +            max_bits = clen[i];
>
> max_bits= FFMAX(max_bits, clen[i]);

Indeed.

>> +#define check_bits(label, gb, n)                                        \
>> +    case AV_INFLATE_ ## label:                                          \
>> +        ctx->state = AV_INFLATE_ ## label;                              \
>> +        if ((n) > (gb)->size_in_bits - get_bits_count(gb) && insize) {  \
>> +            needbits = n;                                               \
>> +            goto outbits;                                               \
>> +        }
>
> maybe macros should be all uppercase
> and iam tempted to suggest that the case AV_INFLATE_* and 
> ctx->state = AV_INFLATE_* could be added directly into the code without
> any macros, this would be more readable i think though it would increase
> the number of lines of source significantly, so iam not sure if its a
> good idea ...

Well, I found it more readable to hide the buffer switching code away
from the main decoding.

> then i would suggest to rename this to something like GOTO_OUTBITS_IF_END()
> or another name which says what is actually done

What?  Have we turned into Java programmers needing entire essays for
variable names?

>> +#define decode_code_lens()                                              \
>> +do {                                                                    \
>> +    ctx->i = 0;                                                         \
>> +    while (ctx->i < ctx->hlit + 257 + ctx->hdist + 1) {                 \
>> +        read_vlc(CLV, ctx->clv, &ctx->gb, cl_vlc);                      \
>> +                                                                        \
>> +        if (ctx->clv < 16) {                                            \
>> +            ctx->ll_len[ctx->i++] = ctx->clv;                           \
>> +        } else if (ctx->clv < 19) {                                     \
>> +            ctx->clr = 0;                                               \
>> +                                                                        \
>> +            if (ctx->clv == 16) {                                       \
>> +                read_bits(CLR1, ctx->clr, &ctx->gb, 2);                 \
>> +                ctx->clr += 3;                                          \
>> +                ctx->clv = ctx->ll_len[ctx->i-1];                       \
>> +            } else if (ctx->clv == 17) {                                \
>> +                read_bits(CLR2, ctx->clr, &ctx->gb, 3);                 \
>> +                ctx->clr += 3;                                          \
>> +                ctx->clv = 0;                                           \
>> +            } else if (ctx->clv == 18) {                                \
>> +                read_bits(CLR3, ctx->clr, &ctx->gb, 7);                 \
>> +                ctx->clr += 11;                                         \
>> +                ctx->clv = 0;                                           \
>> +            }                                                           \
>
> the above code contains 4 checks, case labels and all the other related
> code, thats alot even if its not vissible due to the macros ...
> why not check if theres 16+7 or whatever the max is bits available at one
> spot?

Probably no reason at all.

> read_vlc() itself also checks blindly for 16bit and not the proper vlc len

Yes, I know.  Thanks for reminding me.

>> +#define build_vlc_dynamic()                                             \
>> +do {                                                                    \
>> +    read_bits(HLIT, ctx->hlit, &ctx->gb, 5);                            \
>> +    read_bits(HDIST, ctx->hdist, &ctx->gb, 5);                          \
>> +    read_bits(HCLEN, ctx->hclen, &ctx->gb, 4);                          \
>
> 1 check is enough, theres no sense IMHO in being able to break out and
> continue between these 3

I guess not.

>> +static void
>> +copy_bytes(uint8_t *dst, uint8_t *src, unsigned int len)
>> +{
>> +    while (len--)
>> +        *dst++ = *src++;
>> +}
>
> i think we have such a copy routine somewhere already, but i dont remember
> where

Reimar said it looked familiar too.  Wherever it is, it's not in a
central location.  Where would be the appropriate place for a function
like this?

>> +        if (bp > ctx->bufsize) {
>> +            av_log(NULL, AV_LOG_ERROR, "offset too large: %d > %d\n",
>> +                   offset, os + ctx->bufsize);
>
> please add the needed AVClass or whatever to AVInflateContext or another
> appropriate place and use it for av_log()

Will do.

>> +#define STATE_START switch (ctx->state) { case AV_INFLATE_INIT:
>> +#define STATE(n)    case AV_INFLATE_ ## n:
>> +#define STATE_END   }
>
> what sense do these macros have?
> why not replace them by the single line they represent?

IIRC I was thinking of putting more stuff there at some point but
never needed to.

>> +        read_bits(BFINAL, ctx->bfinal, &ctx->gb, 1);
>> +        read_bits(BTYPE, ctx->btype, &ctx->gb, 2);
>
> these dont need the full case state check goto logic twice
>
> [...]
>> +            read_bits(NCLEN, ctx->nclen, &ctx->gb, 16);
>> +            read_bits(NCNLEN, nlen, &ctx->gb, 16);
>
> same as above

Yes.

>> +        if (ctx->container == CONTAINER_GZIP) {
>> +            read_bits(GZCRC, tmp, &ctx->gb, 16);
>> +            read_bits(GZISIZE, tmp, &ctx->gb, 16);
>> +        } else if (ctx->container == CONTAINER_ZLIB) {
>> +            read_bits(ZLIB_ADLER32_1, tmp, &ctx->gb, 16);
>> +            read_bits(ZLIB_ADLER32_2, tmp, &ctx->gb, 16);
>> +        }
>
> a single if(ctx->container != CONTAINER_RAW) check(32)_set_state_goto_magic
> seems enough, no need to do it 4 times

Yes.  It would also be good to actually compute and verify the checksums.

Thanks for your comments.  I initially focused on getting correct
operation at all.  Now I can look at simplifying bits like these.

-- 
M?ns Rullg?rd
mans at mansr.com




More information about the ffmpeg-devel mailing list