[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