[FFmpeg-devel] [PATCH] MVI demuxer / Motion Pixels decoder

Michael Niedermayer michaelni
Mon Jul 7 19:30:09 CEST 2008


On Sat, Jul 05, 2008 at 01:10:15AM +0200, Gregory Montoir wrote:
> Michael Niedermayer wrote:
>> On Thu, Jul 03, 2008 at 11:40:16PM +0200, Gregory Montoir wrote:
[...]
> +static void mp_yuv_to_rgb(int y, int v, int u, int *r, int *g, int *b)
> +{
> +    *r = (1000 * y + 701 * v) / 1000;
> +    *g = (1000 * y - 357 * v - 172 * u) / 1000;
> +    *b = (1000 * y + 886 * u) / 1000;
> +}

unsigned int r,g,b;
r = (1000 * y + 701 * v) / 1000;
g = (1000 * y - 357 * v - 172 * u) / 1000;
b = (1000 * y + 886 * u) / 1000;

if(r<32 && g<32 && b<32) return (r << 10) | (g << 5) | b;
else                     return 1<<16;


> +
> +static void mp_set_zero_yuv(YuvPixel *d)
> +{
> +    int map[32], i, j, diff, count = 0;
> +
> +    for (i = 0; i < 32; ++i)
> +        if (d[i].u != 0 || d[i].v != 0 || d[i].y != 0)
> +            map[count++] = i;
> +    if (count != 0) {
> +        for (i = 0; i < map[0]; ++i)
> +            d[i] = d[map[0]];
> +        for (i = 0; i < count - 1; ++i) {
> +            diff = (map[i + 1] - map[i]) / 2;
> +            for (j = map[i] + 1; j < map[i + 1]; ++j) {
> +                d[j] = (diff > 0) ? d[map[i]] : d[map[i + 1]];
> +                --diff;
> +            }
> +        }
> +        for (i = map[count - 1] + 1; i < 32; ++i)
> +            d[i] = d[map[count - 1]];
> +    }

below is simpler though slower but i think speed doesnt matter for the
once run init code.

for(i=0; i<31; i++){
    for(j=0; j<31-i; j++)
        if(!(d[j].u | d[j].v | d[j].y))
            d[j]= d[j+1];
    for(j=31; j>i; j--)
        if(!(d[j].u | d[j].v | d[j].y))
            d[j]= d[j-1];
}



> +}
> +
> +static void mp_build_rgb_yuv_table(YuvPixel *p)
> +{
> +    int y, v, u, r, g, b, i;
> +
> +    for (y = 0; y <= 31; ++y)
> +        for (v = -31; v <= 31; ++v)
> +            for (u = -31; u <= 31; ++u) {

> +                mp_yuv_to_rgb(y, v, u, &r, &g, &b);
> +                if (r < 0 || r > 31 || g < 0 || g > 31 || b < 0 || b > 31)
> +                    continue;
> +                i = (r << 10) | (g << 5) | b;

i= mp_yuv_to_rgb15(y, v, u);
if(i > 0x7FFF)
    continue;


> +                if (p[i].u == 0 && p[i].v == 0 && p[i].y == 0) {
> +                    p[i].y = y;
> +                    p[i].v = v;
> +                    p[i].u = u;
> +                }
> +            }
> +    for (i = 0; i < 1024; ++i)
> +        mp_set_zero_yuv(p + i * 32);
> +}
> +
> +static av_cold int mp_decode_init(AVCodecContext *avctx)
> +{
> +    MotionPixelsContext *mp = avctx->priv_data;
> +
> +    if (!mp_rgb_yuv_table_init) {
> +        mp_rgb_yuv_table_init = 1;
> +        mp_build_rgb_yuv_table(mp_rgb_yuv_table);
> +    }

A value (like the last one) of the mp_rgb_yuv_table could be checked instead
of mp_rgb_yuv_table_init. 


[...]
> +static void mp_get_code(MotionPixelsContext *mp, GetBitContext *gb, int size, int code)
> +{
> +    while (get_bits1(gb)) {
> +        ++size;
> +        code <<= 1;
> +        mp_get_code(mp, gb, size, code + 1);
> +    }
> +    if (mp->current_codes_count < MAX_HUFF_CODES) {
> +        mp->codes[mp->current_codes_count  ].code = code;
> +        mp->codes[mp->current_codes_count++].size = size;
> +    }
> +}

this isnt enough, a string of 1 bits will still cause a stack overflow
through the recursive calls


[...]
> +static YuvPixel mp_get_yuv_from_rgb(MotionPixelsContext *mp, int x, int y)
> +{
> +    int color;
> +
> +    color = *(uint16_t *)&mp->frame.data[0][y * mp->frame.linesize[0] + x * 2];
> +    return mp_rgb_yuv_table[color];
> +}
> +

> +static void mp_set_rgb_from_yuv(MotionPixelsContext *mp, int x, int y, const YuvPixel *p)
> +{

> +    int r, g, b, color;
> +
> +    mp_yuv_to_rgb(p->y, p->v, p->u, &r, &g, &b);
> +    r = av_clip(r, 0, 31);
> +    g = av_clip(g, 0, 31);
> +    b = av_clip(b, 0, 31);
> +    color = (r << 10) | (g << 5) | b;

int color= mp_yuv_to_rgb(p->y, p->v, p->u);


> +    *(uint16_t *)&mp->frame.data[0][y * mp->frame.linesize[0] + x * 2] = color;
> +}
> +
> +static int mp_get_vlc(MotionPixelsContext *mp, GetBitContext *gb)
> +{
> +    int i;
> +
> +    i = (mp->codes_count == 1) ? 0 : get_vlc2(gb, mp->vlc.table, mp->max_codes_bits, 1);
> +    return mp->codes[i].delta;
> +}
> +
> +static void mp_decode_line(MotionPixelsContext *mp, GetBitContext *gb, int y)
> +{
> +    YuvPixel p;
> +    const int y0 = y * mp->avctx->width;
> +    int w, i, x = 0, xp = -1;
> +
> +    p = mp->vpt[y];
> +    if (mp->changes_map[y0 + x] == 0) {
> +        memset(mp->gradient_scale, 1, sizeof(mp->gradient_scale));
> +        ++x;
> +    }
> +    while (x < mp->avctx->width) {
> +        w = mp->changes_map[y0 + x];
> +        if (w != 0) {
> +            if ((y & 3) == 0) {
> +                if (mp->changes_map[y0 + x + mp->avctx->width] < w ||
> +                    mp->changes_map[y0 + x + mp->avctx->width * 2] < w ||
> +                    mp->changes_map[y0 + x + mp->avctx->width * 3] < w) {
> +                    for (i = (x + 3) & ~3; i < x + w; i += 4) {
> +                        mp->hpt[((y / 4) * mp->avctx->width + i) / 4] = mp_get_yuv_from_rgb(mp, i, y);
> +                    }
> +                }
> +            }
> +            x += w;
> +            xp = x - 1;
> +        } else {
> +            if (xp != -1) {
> +                memset(mp->gradient_scale, 1, sizeof(mp->gradient_scale));
> +                p = mp_get_yuv_from_rgb(mp, xp, y);
> +                xp = -1;
> +            }
> +            p.y += mp_gradient(mp, 0, mp_get_vlc(mp, gb));

> +            if ((y & 3) == 0) {
> +                if ((x & 3) == 0) {
> +                    p.v += mp_gradient(mp, 1, mp_get_vlc(mp, gb));
> +                    p.u += mp_gradient(mp, 2, mp_get_vlc(mp, gb));
> +                    mp->hpt[((y / 4) * mp->avctx->width + x) / 4] = p;
> +                }
> +            } else {
> +                if ((x & 3) == 0) {
> +                    p.v = mp->hpt[((y / 4) * mp->avctx->width + x) / 4].v;
> +                    p.u = mp->hpt[((y / 4) * mp->avctx->width + x) / 4].u;
> +                }
> +            }

if ((x & 3) == 0) {
    if ((y & 3) == 0) {
        p.v += mp_gradient(mp, 1, mp_get_vlc(mp, gb));
        p.u += mp_gradient(mp, 2, mp_get_vlc(mp, gb));
        mp->hpt[((y / 4) * mp->avctx->width + x) / 4] = p;
    } else {
        p.v = mp->hpt[((y / 4) * mp->avctx->width + x) / 4].v;
        p.u = mp->hpt[((y / 4) * mp->avctx->width + x) / 4].u;
    }
}


> +            mp_set_rgb_from_yuv(mp, x, y, &p);
> +            ++x;
> +        }
> +    }
> +}
> +

> +static void mp_decode_frame_helper(MotionPixelsContext *mp, GetBitContext *gb)
> +{
> +    YuvPixel p;
> +    int y, y0, yp = -1;
> +

> +    for (y = 0; y < mp->avctx->height; ++y) {
> +        if (mp->changes_map[y * mp->avctx->width] != 0) {
> +            yp = y;
> +        } else {
> +            if (yp != -1) {
> +                p = mp_get_yuv_from_rgb(mp, 0, yp);
> +                memset(mp->gradient_scale, 1, sizeof(mp->gradient_scale));
> +                yp = -1;
> +            }
> +            p.y += mp_gradient(mp, 0, mp_get_vlc(mp, gb));
> +            if ((y & 3) == 0) {
> +                p.v += mp_gradient(mp, 1, mp_get_vlc(mp, gb));
> +                p.u += mp_gradient(mp, 2, mp_get_vlc(mp, gb));
> +            }
> +            mp->vpt[y] = p;
> +            mp_set_rgb_from_yuv(mp, 0, y, &p);
> +        }
> +    }

for (y = 0; y < mp->avctx->height; ++y) {
    if (mp->changes_map[y * mp->avctx->width]) {
        p = mp_get_yuv_from_rgb(mp, 0, y);
        memset(mp->gradient_scale, 1, sizeof(mp->gradient_scale));
    } else {
        p.y += mp_gradient(mp, 0, mp_get_vlc(mp, gb));
        if ((y & 3) == 0) {
            p.v += mp_gradient(mp, 1, mp_get_vlc(mp, gb));
            p.u += mp_gradient(mp, 2, mp_get_vlc(mp, gb));
        }
        mp->vpt[y] = p;
        mp_set_rgb_from_yuv(mp, 0, y, &p);
    }
}

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

it is not once nor twice but times without number that the same ideas make
their appearance in the world. -- Aristotle
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20080707/a1dcc684/attachment.pgp>



More information about the ffmpeg-devel mailing list