[FFmpeg-devel] [WIP] life source

Clément Bœsch ubitux at gmail.com
Sun Nov 20 23:35:23 CET 2011


On Sun, Nov 20, 2011 at 08:11:05PM +0100, Clément Bœsch wrote:
> On Sat, Nov 19, 2011 at 11:14:46PM +0100, Stefano Sabatini wrote:
> > On date Sunday 2011-06-26 20:11:52 +0200, Stefano Sabatini encoded:
> > > From 680fc136c9f85e289b86195dc54e5b76bffe6b97 Mon Sep 17 00:00:00 2001
> > > From: Stefano Sabatini <stefano.sabatini-lala at poste.it>
> > > Date: Sun, 26 Jun 2011 19:47:18 +0200
> > > Subject: [PATCH] lavfi: add lifesrc source
> > > 
> > > ---
> > >  libavfilter/Makefile       |    1 +
> > >  libavfilter/allfilters.c   |    1 +
> > >  libavfilter/vsrc_lifesrc.c |  305 ++++++++++++++++++++++++++++++++++++++++++++
> > >  3 files changed, 307 insertions(+), 0 deletions(-)
> > >  create mode 100644 libavfilter/vsrc_lifesrc.c
> > 
> > Well since I'm in an all-play-no-work mood I worked to an updated
> > version.
> > 
> > I could also add support to "bricks" (cells which can't never be
> > filled) and provide an option for specifying connected topology, but
> > that can be done later.
> > 
> > Example:
> > ffplay -f lavfi "lifesrc=f=CREDITS:s=300x300:rule=21219, boxblur=2:2, negate"
> 
> fun :)
> 
> [...]
> > +
> > +    if (!life->filename) {
> > +        av_log(ctx, AV_LOG_ERROR, "No filename specified, aborting\n");
> > +        return AVERROR(EINVAL);
> > +    }
> > +
> > +    if ((ret = init_pattern_from_file(ctx) < 0))
> > +        return ret;
> 
> if ((ret = ...) < 0), or else it will crash with for instance an empty
> file.
> 
> BTW, I agree with both Michael and Nicolas about having it upstream (I
> want to do something on it :)) and the random init board in case of no
> file.
> 

The attached WIP patch add some progressive death support:
  state = 0 -> alive
  state = 1 -> dead
  state = 2 -> very dead
  state = 3 -> very very dead...
   [...]
  state = 255 -> definitely, dead.

...and set the color accordingly. The output now looks like an awesome
automato[1] fight.

[1]: http://en.wikipedia.org/wiki/Automaton + http://en.wikipedia.org/wiki/Tomato

-- 
Clément B.
-------------- next part --------------
From b692cf4dab9529a98d853ff41dc4e437af3917c3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= <ubitux at gmail.com>
Date: Sun, 20 Nov 2011 23:30:38 +0100
Subject: [PATCH] lifesrc/WIP: add progressive death.

---
 libavfilter/vsrc_lifesrc.c |   49 ++++++++++++++++++++++++-------------------
 1 files changed, 27 insertions(+), 22 deletions(-)

diff --git a/libavfilter/vsrc_lifesrc.c b/libavfilter/vsrc_lifesrc.c
index 76531db..99bf7bb 100644
--- a/libavfilter/vsrc_lifesrc.c
+++ b/libavfilter/vsrc_lifesrc.c
@@ -129,17 +129,18 @@ static int init_pattern_from_file(AVFilterContext *ctx)
         return AVERROR(ENOMEM);
     }
 
-    /* fill buf[0] */
     p = life->file_buf;
+    memset(life->buf[0], 0xff, life->w * life->h);
     for (i0 = 0, i = (life->h - h)/2; i0 < h; i0++, i++) {
         for (j = (life->w - max_w)/2;; j++) {
             av_log(ctx, AV_LOG_DEBUG, "%d:%d %c\n", i, j, *p == '\n' ? 'N' : *p);
             if (*p == '\n') {
                 p++; break;
             } else
-                life->buf[0][i*life->w + j] = !!isgraph(*(p++));
+                life->buf[0][i*life->w + j] = !isgraph(*(p++)) * 0xff;
         }
     }
+    memcpy(life->buf[1], life->buf[0], life->w * life->h);
     life->buf_idx = 0;
 
     return 0;
@@ -222,17 +223,18 @@ static void evolve(AVFilterContext *ctx)
         for (j = 0; j < life->w; j++) {
             /* compute the number of filled cells near the cell (i j) */
             int n =
-                ((i-1)<0        || (j-1)<0        ? 0 : oldbuf[(i-1)*life->w +j-1]) +
-                ((i-1)<0                          ? 0 : oldbuf[(i-1)*life->w +j  ]) +
-                ((i-1)<0        || (j+1)==life->w ? 0 : oldbuf[(i-1)*life->w +j+1]) +
-                (                  (j-1)<0        ? 0 : oldbuf[ i   *life->w +j-1]) +
-                (                  (j+1)==life->w ? 0 : oldbuf[ i   *life->w +j+1]) +
-                ((i+1)==life->h || (j-1)<0        ? 0 : oldbuf[(i+1)*life->w +j-1]) +
-                ((i+1)==life->h                   ? 0 : oldbuf[(i+1)*life->w +j  ]) +
-                ((i+1)==life->h || (j+1)==life->w ? 0 : oldbuf[(i+1)*life->w +j+1]);
-            v = !!(1<<n & (oldbuf[i*life->w + j] ? life->life_rule : life->death_rule));
-            av_dlog(ctx, "i:%d j:%d live:%d n:%d v:%d\n", i, j, oldbuf[i*life->w + j], n, v);
-            newbuf[i*life->w+j] = v;
+                ((i-1)<0        || (j-1)<0        ? 0 : !oldbuf[(i-1)*life->w +j-1]) +
+                ((i-1)<0                          ? 0 : !oldbuf[(i-1)*life->w +j  ]) +
+                ((i-1)<0        || (j+1)==life->w ? 0 : !oldbuf[(i-1)*life->w +j+1]) +
+                (                  (j-1)<0        ? 0 : !oldbuf[ i   *life->w +j-1]) +
+                (                  (j+1)==life->w ? 0 : !oldbuf[ i   *life->w +j+1]) +
+                ((i+1)==life->h || (j-1)<0        ? 0 : !oldbuf[(i+1)*life->w +j-1]) +
+                ((i+1)==life->h                   ? 0 : !oldbuf[(i+1)*life->w +j  ]) +
+                ((i+1)==life->h || (j+1)==life->w ? 0 : !oldbuf[(i+1)*life->w +j+1]);
+            v = 1<<n & (!oldbuf[i*life->w + j] ? life->life_rule : life->death_rule);
+            av_dlog(ctx, "i:%d j:%d death_age:%d n:%d v:%d\n", i, j, oldbuf[i*life->w + j], n, v);
+            *newbuf = v ? 0 : *newbuf + (*newbuf<255);
+            newbuf++;
         }
     }
 
@@ -243,18 +245,21 @@ static void fill_picture(AVFilterContext *ctx, AVFilterBufferRef *picref)
 {
     LifeContext *life = ctx->priv;
     uint8_t *buf = life->buf[life->buf_idx];
-    int i, j, k;
+    int i, j;
 
     /* fill the output picture with the old grid buffer */
     for (i = 0; i < life->h; i++) {
-        uint8_t byte = 0;
         uint8_t *p = picref->data[0] + i * picref->linesize[0];
-        for (k = 0, j = 0; j < life->w; j++) {
-            byte |= buf[i*life->w+j]<<(7-k++);
-            if (k==8 || j == life->w-1) {
-                k = 0;
-                *p++ = byte;
-                byte = 0;
+        for (j = 0; j < life->w; j++) {
+            uint8_t death_age = buf[i*life->w + j];
+            if (death_age == 0) { // alive
+                *p++ = 0;
+                *p++ = 0xff;
+                *p++ = 0;
+            } else {
+                *p++ = FFMAX(0, 200 - death_age);
+                *p++ = FFMAX(0,  50 - death_age);
+                *p++ = FFMAX(0,  50 - death_age);
             }
         }
     }
@@ -282,7 +287,7 @@ static int request_frame(AVFilterLink *outlink)
 
 static int query_formats(AVFilterContext *ctx)
 {
-    static const enum PixelFormat pix_fmts[] = { PIX_FMT_MONOBLACK, PIX_FMT_NONE };
+    static const enum PixelFormat pix_fmts[] = { PIX_FMT_RGB24, PIX_FMT_NONE };
     avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts));
     return 0;
 }
-- 
1.7.7.3

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20111120/7cd380dc/attachment.asc>


More information about the ffmpeg-devel mailing list