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

Gregory Montoir cyx
Mon Jul 7 23:30:14 CEST 2008


Michael Niedermayer wrote:
> 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;

changed (with optional clipping, necessary for yuv->rgb when decoding).


>> +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];
> }

changed (but swapped the 2 inner for loops to get the same table contents).


>> +}
>> +
>> +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;

changed.


>> +                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. 

done.


> [...]
>> +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

added max_codes_bits check.


> [...]
>> +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);

changed (with clipping).


>> [...]
>> +            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;
>     }
> }

changed.


> [...]
>> +    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);
>     }
> }
> 

haven't changed for the moment. the idea was avoid the calls to memset() 
and yuv_to_rgb() if there were not necessary (changes_map[y] can be != 0 
for several consecutives lines and only the previous line is used when 
applying the deltas).

-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: ffmpeg-mvi-6.diff
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20080707/cdfb31dd/attachment.asc>



More information about the ffmpeg-devel mailing list