aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2024-10-15 11:43:03 +0200
committerAnton Khirnov <anton@khirnov.net>2024-10-17 11:00:35 +0200
commit2094a7256cc02ee4431349d2aa48989c5ee76355 (patch)
tree578f9bd8f58726ef9d342f5fe69a73adc5c9d3a2
parentd08feb900348e448c0b8f3271b4719034da70dd2 (diff)
downloadffmpeg-2094a7256cc02ee4431349d2aa48989c5ee76355.tar.gz
lavfi/vsrc_life: avoid modifying the context in query_formats()
It is supposed to be free of side effects. Do it in init instead.
-rw-r--r--libavfilter/vsrc_life.c125
1 files changed, 63 insertions, 62 deletions
diff --git a/libavfilter/vsrc_life.c b/libavfilter/vsrc_life.c
index a624dbb63c..b5b4626e20 100644
--- a/libavfilter/vsrc_life.c
+++ b/libavfilter/vsrc_life.c
@@ -160,6 +160,58 @@ static void show_life_grid(AVFilterContext *ctx)
}
#endif
+static void fill_picture_monoblack(AVFilterContext *ctx, AVFrame *picref)
+{
+ LifeContext *life = ctx->priv;
+ uint8_t *buf = life->buf[life->buf_idx];
+ int i, j, k;
+
+ /* 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] == ALIVE_CELL)<<(7-k++);
+ if (k==8 || j == life->w-1) {
+ k = 0;
+ *p++ = byte;
+ byte = 0;
+ }
+ }
+ }
+}
+
+// divide by 255 and round to nearest
+// apply a fast variant: (X+127)/255 = ((X+127)*257+257)>>16 = ((X+128)*257)>>16
+#define FAST_DIV255(x) ((((x) + 128) * 257) >> 16)
+
+static void fill_picture_rgb(AVFilterContext *ctx, AVFrame *picref)
+{
+ LifeContext *life = ctx->priv;
+ uint8_t *buf = life->buf[life->buf_idx];
+ int i, j;
+
+ /* fill the output picture with the old grid buffer */
+ for (i = 0; i < life->h; i++) {
+ uint8_t *p = picref->data[0] + i * picref->linesize[0];
+ for (j = 0; j < life->w; j++) {
+ uint8_t v = buf[i*life->w + j];
+ if (life->mold && v != ALIVE_CELL) {
+ const uint8_t *c1 = life-> mold_color;
+ const uint8_t *c2 = life->death_color;
+ int death_age = FFMIN((0xff - v) * life->mold, 0xff);
+ *p++ = FAST_DIV255((c2[0] << 8) + ((int)c1[0] - (int)c2[0]) * death_age);
+ *p++ = FAST_DIV255((c2[1] << 8) + ((int)c1[1] - (int)c2[1]) * death_age);
+ *p++ = FAST_DIV255((c2[2] << 8) + ((int)c1[2] - (int)c2[2]) * death_age);
+ } else {
+ const uint8_t *c = v == ALIVE_CELL ? life->life_color : life->death_color;
+ AV_WB24(p, c[0]<<16 | c[1]<<8 | c[2]);
+ p += 3;
+ }
+ }
+ }
+}
+
static int init_pattern_from_file(AVFilterContext *ctx)
{
LifeContext *life = ctx->priv;
@@ -259,6 +311,13 @@ static av_cold int init(AVFilterContext *ctx)
return ret;
}
+ if (life->mold || memcmp(life-> life_color, "\xff\xff\xff", 3)
+ || memcmp(life->death_color, "\x00\x00\x00", 3)) {
+ life->draw = fill_picture_rgb;
+ } else {
+ life->draw = fill_picture_monoblack;
+ }
+
av_log(ctx, AV_LOG_VERBOSE,
"s:%dx%d r:%d/%d rule:%s stay_rule:%d born_rule:%d stitch:%d seed:%"PRId64"\n",
life->w, life->h, life->frame_rate.num, life->frame_rate.den,
@@ -345,58 +404,6 @@ static void evolve(AVFilterContext *ctx)
life->buf_idx = !life->buf_idx;
}
-static void fill_picture_monoblack(AVFilterContext *ctx, AVFrame *picref)
-{
- LifeContext *life = ctx->priv;
- uint8_t *buf = life->buf[life->buf_idx];
- int i, j, k;
-
- /* 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] == ALIVE_CELL)<<(7-k++);
- if (k==8 || j == life->w-1) {
- k = 0;
- *p++ = byte;
- byte = 0;
- }
- }
- }
-}
-
-// divide by 255 and round to nearest
-// apply a fast variant: (X+127)/255 = ((X+127)*257+257)>>16 = ((X+128)*257)>>16
-#define FAST_DIV255(x) ((((x) + 128) * 257) >> 16)
-
-static void fill_picture_rgb(AVFilterContext *ctx, AVFrame *picref)
-{
- LifeContext *life = ctx->priv;
- uint8_t *buf = life->buf[life->buf_idx];
- int i, j;
-
- /* fill the output picture with the old grid buffer */
- for (i = 0; i < life->h; i++) {
- uint8_t *p = picref->data[0] + i * picref->linesize[0];
- for (j = 0; j < life->w; j++) {
- uint8_t v = buf[i*life->w + j];
- if (life->mold && v != ALIVE_CELL) {
- const uint8_t *c1 = life-> mold_color;
- const uint8_t *c2 = life->death_color;
- int death_age = FFMIN((0xff - v) * life->mold, 0xff);
- *p++ = FAST_DIV255((c2[0] << 8) + ((int)c1[0] - (int)c2[0]) * death_age);
- *p++ = FAST_DIV255((c2[1] << 8) + ((int)c1[1] - (int)c2[1]) * death_age);
- *p++ = FAST_DIV255((c2[2] << 8) + ((int)c1[2] - (int)c2[2]) * death_age);
- } else {
- const uint8_t *c = v == ALIVE_CELL ? life->life_color : life->death_color;
- AV_WB24(p, c[0]<<16 | c[1]<<8 | c[2]);
- p += 3;
- }
- }
- }
-}
-
static int request_frame(AVFilterLink *outlink)
{
LifeContext *life = outlink->src->priv;
@@ -418,16 +425,10 @@ static int request_frame(AVFilterLink *outlink)
static int query_formats(AVFilterContext *ctx)
{
LifeContext *life = ctx->priv;
- enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_NONE, AV_PIX_FMT_NONE };
-
- if (life->mold || memcmp(life-> life_color, "\xff\xff\xff", 3)
- || memcmp(life->death_color, "\x00\x00\x00", 3)) {
- pix_fmts[0] = AV_PIX_FMT_RGB24;
- life->draw = fill_picture_rgb;
- } else {
- pix_fmts[0] = AV_PIX_FMT_MONOBLACK;
- life->draw = fill_picture_monoblack;
- }
+ const enum AVPixelFormat pix_fmts[] = {
+ life->draw == fill_picture_rgb ? AV_PIX_FMT_RGB24 : AV_PIX_FMT_MONOBLACK,
+ AV_PIX_FMT_NONE
+ };
return ff_set_common_formats_from_list(ctx, pix_fmts);
}