[Ffmpeg-devel] [RFC] ZMBV encoder

Michael Niedermayer michaelni
Mon Dec 4 16:59:35 CET 2006


Hi

On Mon, Dec 04, 2006 at 08:13:57AM +0200, Kostya wrote:
> Here is my ZMBV encoder for encoding palettized videos.

> Index: libavcodec/zmbvenc.c
> ===================================================================
> --- libavcodec/zmbvenc.c	(revision 0)
> +++ libavcodec/zmbvenc.c	(revision 0)
[...]
> +
> +#define ZMBV_KEYFRAME 1
> +#define ZMBV_DELTAPAL 2

duplicate from zmbv.c


[...]
> +/** Block comparing function
> + * XXX should be optimized and moved to DSPContext
> + * TODO handle out of edge ME
> + */
> +int block_cmp(uint8_t *src, int stride, uint8_t *src2, int stride2, int bw, int bh)
> +{
> +    int sum = 0;
> +    int i, j;
> +    for(j = 0; j < bh; j++){
> +        for(i = 0; i < bw; i++)
> +            sum += src[i] ^ src2[i];
> +        src += stride;
> +        src2 += stride2;
> +    }
> +    return sum;
> +}

i dont think sum += src[i] ^ src2[i]; is optimal compression wise ...
_maybe_

sum += score[src[i] ^ src2[i]];
and
for(i,j=0; i,j<256; i,j++){
    score[i^j] += ABS(i-j);
}

or even simply
sum += ABS(src[i] - src2[i])

might be better, and of course a 

for() 
    dst[i]= src[i] ^ src2[i]; 
sum= lzw_size(dst, len);

might be interresting ...


[...]
> +        uint8_t tpal[3];
> +        for(i = 0; i < 256; i++){
> +            tpal[0] = (palptr[i] >> 16) & 0xFF;
> +            tpal[1] = (palptr[i] >>  8) & 0xFF;
> +            tpal[2] = palptr[i] & 0xFF;

the &0xFF is unneeded


[...]
> +    }else{
> +        int x, y, bh2, bw2;
> +        uint8_t *tsrc, *tprev;
> +        uint8_t *mv;
> +        int bmvx, bmvy, bv, tx, ty, tv, dx, dy;
> +
> +        bw = (avctx->width + ZMBV_BLOCK - 1) / ZMBV_BLOCK;
> +        bh = (avctx->height + ZMBV_BLOCK - 1) / ZMBV_BLOCK;
> +        mv = c->work_buf + work_size;
> +        memset(c->work_buf + work_size, 0, (bw * bh * 2 + 3) & ~3);
> +        work_size += (bw * bh * 2 + 3) & ~3;
> +        /* for now just XOR'ing */
> +        for(y = 0; y < avctx->height; y += ZMBV_BLOCK) {
> +            bh2 = FFMIN(avctx->height - y, ZMBV_BLOCK);
> +            for(x = 0; x < avctx->width; x += ZMBV_BLOCK, mv += 2) {
> +                bw2 = FFMIN(avctx->width - x, ZMBV_BLOCK);
> +
> +                tsrc = src + x;
> +                tprev = prev + x;
> +
> +                bmvx = bmvy = 0;
> +                bv = block_cmp(tsrc, p->linesize[0], tprev, c->pstride, ZMBV_BLOCK, ZMBV_BLOCK);
> +                if(bv) for(ty = FFMAX(y - 16, 0); ty < FFMIN(y + 16, avctx->height - ZMBV_BLOCK); ty++){
> +                    for(tx = FFMAX(x - 16, 0); tx < FFMIN(x + 16, avctx->width - ZMBV_BLOCK); tx++){

use avctx->me_range


> +                        if(tx == x && ty == y) continue; // we already tested this block
> +                        dx = tx - x;
> +                        dy = ty - y;
> +                        tv = block_cmp(tsrc, p->linesize[0], tprev + dx + dy*c->pstride, c->pstride, ZMBV_BLOCK, ZMBV_BLOCK);
> +                        if(tv < bv){
> +                            bv = tv;
> +                            bmvx = dx;
> +                            bmvy = dy;
> +                            if(!bv) break;
> +                        }
> +                    }
> +                    if(!bv) break;
> +                }

hmmmmm
maybe try using the motion estimation code from lavc or at least implement
a optional more practical variant ...

practical:
take motion vector from left, top, top right, last frame and (0,0)
try cmp on all, take best
try (x,y+1), (x,y-1), (x+1,y) (x-1,y) where (x,y) is the best so far
continue this until the best is in the middle of this small set in
which case you are done

improvments:
try median(top,left,top right)
try right one from last frame and try bottom one from last frame


[...]
> +    c->width = avctx->width;
> +    c->height = avctx->height;
> +    c->curfrm = 0;
> +    c->keyint = avctx->keyint_min;

why is this copied from avctx? the copied variants dont seem to be used
much ...


[...]
> +/*
> + *
> + * Uninit zmbv decoder
> + *
> + */

not doxygen compatible

[...]

> +
> +AVCodec zmbv_encoder = {
> +    "zmbv",
> +    CODEC_TYPE_VIDEO,
> +    CODEC_ID_ZMBV,
> +    sizeof(ZmbvEncContext),
> +    encode_init,
> +    encode_frame,
> +    encode_end
> +};

supported pix_fmt entry is missing

[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

In the past you could go to a library and read, borrow or copy any book
Today you'd get arrested for mere telling someone where the library is




More information about the ffmpeg-devel mailing list