[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