Browse code

lavfi: add rgbtestsrc source, ported from MPlayer libmpcodecs

The licence was changed from GPL to LGPL with explicit approval from
the original author.

See thread:
Subject: [FFmpeg-devel] [PATCH] lavfi: add rgbtestsrc source,
ported from MPlayer libmpcodecs
Date: Mon, 11 Jul 2011 16:32:41 +0200

Stefano Sabatini authored on 2011/07/11 23:27:09
Showing 5 changed files
... ...
@@ -2045,13 +2045,17 @@ Some examples follow:
2045 2045
 frei0r_src=200x200:10:partik0l=1234 [overlay]; [in][overlay] overlay
2046 2046
 @end example
2047 2047
 
2048
-@section testsrc
2048
+@section rgbtestsrc, testsrc
2049 2049
 
2050
-Generate a test video pattern, showing a color pattern, a scrolling
2051
-gradient and a timestamp. This is mainly intended for testing
2052
-purposes.
2050
+The @code{rgbtestsrc} source generates an RGB test pattern useful for
2051
+detecting RGB vs BGR issues. You should see a red, green and blue
2052
+stripe from top to bottom.
2053 2053
 
2054
-It accepts an optional sequence of @var{key}=@var{value} pairs,
2054
+The @code{testsrc} source generates a test video pattern, showing a
2055
+color pattern, a scrolling gradient and a timestamp. This is mainly
2056
+intended for testing purposes.
2057
+
2058
+Both sources accept an optional sequence of @var{key}=@var{value} pairs,
2055 2059
 separated by ":". The description of the accepted options follows.
2056 2060
 
2057 2061
 @table @option
... ...
@@ -69,6 +69,7 @@ OBJS-$(CONFIG_COLOR_FILTER)                  += vsrc_color.o
69 69
 OBJS-$(CONFIG_FREI0R_SRC_FILTER)             += vf_frei0r.o
70 70
 OBJS-$(CONFIG_MOVIE_FILTER)                  += vsrc_movie.o
71 71
 OBJS-$(CONFIG_NULLSRC_FILTER)                += vsrc_nullsrc.o
72
+OBJS-$(CONFIG_RGBTESTSRC_FILTER)             += vsrc_testsrc.o
72 73
 OBJS-$(CONFIG_TESTSRC_FILTER)                += vsrc_testsrc.o
73 74
 
74 75
 OBJS-$(CONFIG_BUFFERSINK_FILTER)             += vsink_buffer.o
... ...
@@ -85,6 +85,7 @@ void avfilter_register_all(void)
85 85
     REGISTER_FILTER (FREI0R,      frei0r_src,  vsrc);
86 86
     REGISTER_FILTER (MOVIE,       movie,       vsrc);
87 87
     REGISTER_FILTER (NULLSRC,     nullsrc,     vsrc);
88
+    REGISTER_FILTER (RGBTESTSRC,  rgbtestsrc,  vsrc);
88 89
     REGISTER_FILTER (TESTSRC,     testsrc,     vsrc);
89 90
 
90 91
     REGISTER_FILTER (BUFFER,      buffersink,  vsink);
... ...
@@ -29,8 +29,8 @@
29 29
 #include "libavutil/rational.h"
30 30
 
31 31
 #define LIBAVFILTER_VERSION_MAJOR  2
32
-#define LIBAVFILTER_VERSION_MINOR 25
33
-#define LIBAVFILTER_VERSION_MICRO  1
32
+#define LIBAVFILTER_VERSION_MINOR 26
33
+#define LIBAVFILTER_VERSION_MICRO  0
34 34
 
35 35
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
36 36
                                                LIBAVFILTER_VERSION_MINOR, \
... ...
@@ -21,13 +21,19 @@
21 21
 
22 22
 /**
23 23
  * @file
24
- * Based on the test pattern generator demuxer by Nicolas George:
24
+ * Misc test sources.
25
+ *
26
+ * testsrc is based on the test pattern generator demuxer by Nicolas George:
25 27
  * http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/2007-October/037845.html
28
+ *
29
+ * rgbtestsrc is ported from MPlayer libmpcodecs/vf_rgbtest.c by
30
+ * Michael Niedermayer.
26 31
  */
27 32
 
28 33
 #include <float.h>
29 34
 
30 35
 #include "libavutil/opt.h"
36
+#include "libavutil/intreadwrite.h"
31 37
 #include "libavutil/parseutils.h"
32 38
 #include "avfilter.h"
33 39
 
... ...
@@ -41,6 +47,9 @@ typedef struct {
41 41
     char *rate;                 ///< video frame rate
42 42
     char *duration;             ///< total duration of the generated video
43 43
     void (* fill_picture_fn)(AVFilterContext *ctx, AVFilterBufferRef *picref);
44
+
45
+    /* only used by rgbtest */
46
+    int rgba_map[4];
44 47
 } TestSourceContext;
45 48
 
46 49
 #define OFFSET(x) offsetof(TestSourceContext, x)
... ...
@@ -350,3 +359,130 @@ AVFilter avfilter_vsrc_testsrc = {
350 350
 };
351 351
 
352 352
 #endif /* CONFIG_TESTSRC_FILTER */
353
+
354
+#if CONFIG_RGBTESTSRC_FILTER
355
+
356
+static const char *rgbtestsrc_get_name(void *ctx)
357
+{
358
+    return "rgbtestsrc";
359
+}
360
+
361
+static const AVClass rgbtestsrc_class = {
362
+    "RGBTestSourceContext",
363
+    rgbtestsrc_get_name,
364
+    testsrc_options
365
+};
366
+
367
+#define R 0
368
+#define G 1
369
+#define B 2
370
+#define A 3
371
+
372
+static void rgbtest_put_pixel(uint8_t *dst, int dst_linesize,
373
+                              int x, int y, int r, int g, int b, enum PixelFormat fmt,
374
+                              int rgba_map[4])
375
+{
376
+    int32_t v;
377
+    uint8_t *p;
378
+
379
+    switch (fmt) {
380
+    case PIX_FMT_BGR444: ((uint16_t*)(dst + y*dst_linesize))[x] = ((r >> 4) << 8) | ((g >> 4) << 4) | (b >> 4); break;
381
+    case PIX_FMT_RGB444: ((uint16_t*)(dst + y*dst_linesize))[x] = ((b >> 4) << 8) | ((g >> 4) << 4) | (r >> 4); break;
382
+    case PIX_FMT_BGR555: ((uint16_t*)(dst + y*dst_linesize))[x] = ((r>>3)<<10) | ((g>>3)<<5) | (b>>3); break;
383
+    case PIX_FMT_RGB555: ((uint16_t*)(dst + y*dst_linesize))[x] = ((b>>3)<<10) | ((g>>3)<<5) | (r>>3); break;
384
+    case PIX_FMT_BGR565: ((uint16_t*)(dst + y*dst_linesize))[x] = ((r>>3)<<11) | ((g>>2)<<5) | (b>>3); break;
385
+    case PIX_FMT_RGB565: ((uint16_t*)(dst + y*dst_linesize))[x] = ((b>>3)<<11) | ((g>>2)<<5) | (r>>3); break;
386
+    case PIX_FMT_RGB24:
387
+    case PIX_FMT_BGR24:
388
+        v = (r << (rgba_map[R]*8)) + (g << (rgba_map[G]*8)) + (b << (rgba_map[B]*8));
389
+        p = dst + 3*x + y*dst_linesize;
390
+        AV_WL24(p, v);
391
+        break;
392
+    case PIX_FMT_RGBA:
393
+    case PIX_FMT_BGRA:
394
+    case PIX_FMT_ARGB:
395
+    case PIX_FMT_ABGR:
396
+        v = (r << (rgba_map[R]*8)) + (g << (rgba_map[G]*8)) + (b << (rgba_map[B]*8));
397
+        p = dst + 4*x + y*dst_linesize;
398
+        AV_WL32(p, v);
399
+        break;
400
+    }
401
+}
402
+
403
+static void rgbtest_fill_picture(AVFilterContext *ctx, AVFilterBufferRef *picref)
404
+{
405
+    TestSourceContext *test = ctx->priv;
406
+    int x, y, w = picref->video->w, h = picref->video->h;
407
+
408
+    for (y = 0; y < h; y++) {
409
+         for (x = 0; x < picref->video->w; x++) {
410
+             int c = 256*x/w;
411
+             int r = 0, g = 0, b = 0;
412
+
413
+             if      (3*y < h  ) r = c;
414
+             else if (3*y < 2*h) g = c;
415
+             else                b = c;
416
+
417
+             rgbtest_put_pixel(picref->data[0], picref->linesize[0], x, y, r, g, b,
418
+                               ctx->outputs[0]->format, test->rgba_map);
419
+         }
420
+     }
421
+}
422
+
423
+static av_cold int rgbtest_init(AVFilterContext *ctx, const char *args, void *opaque)
424
+{
425
+    TestSourceContext *test = ctx->priv;
426
+
427
+    test->class = &rgbtestsrc_class;
428
+    test->fill_picture_fn = rgbtest_fill_picture;
429
+    return init(ctx, args, opaque);
430
+}
431
+
432
+static int rgbtest_query_formats(AVFilterContext *ctx)
433
+{
434
+    static const enum PixelFormat pix_fmts[] = {
435
+        PIX_FMT_RGBA, PIX_FMT_ARGB, PIX_FMT_BGRA, PIX_FMT_ABGR,
436
+        PIX_FMT_BGR24, PIX_FMT_RGB24,
437
+        PIX_FMT_RGB444, PIX_FMT_BGR444,
438
+        PIX_FMT_RGB565, PIX_FMT_BGR565,
439
+        PIX_FMT_RGB555, PIX_FMT_BGR555,
440
+        PIX_FMT_NONE
441
+    };
442
+    avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts));
443
+    return 0;
444
+}
445
+
446
+static int rgbtest_config_props(AVFilterLink *outlink)
447
+{
448
+    TestSourceContext *test = outlink->src->priv;
449
+
450
+    switch (outlink->format) {
451
+    case PIX_FMT_ARGB:  test->rgba_map[A] = 0; test->rgba_map[R] = 1; test->rgba_map[G] = 2; test->rgba_map[B] = 3; break;
452
+    case PIX_FMT_ABGR:  test->rgba_map[A] = 0; test->rgba_map[B] = 1; test->rgba_map[G] = 2; test->rgba_map[R] = 3; break;
453
+    case PIX_FMT_RGBA:
454
+    case PIX_FMT_RGB24: test->rgba_map[R] = 0; test->rgba_map[G] = 1; test->rgba_map[B] = 2; test->rgba_map[A] = 3; break;
455
+    case PIX_FMT_BGRA:
456
+    case PIX_FMT_BGR24: test->rgba_map[B] = 0; test->rgba_map[G] = 1; test->rgba_map[R] = 2; test->rgba_map[A] = 3; break;
457
+    }
458
+
459
+    return config_props(outlink);
460
+}
461
+
462
+AVFilter avfilter_vsrc_rgbtestsrc = {
463
+    .name      = "rgbtestsrc",
464
+    .description = NULL_IF_CONFIG_SMALL("Generate RGB test pattern."),
465
+    .priv_size = sizeof(TestSourceContext),
466
+    .init      = rgbtest_init,
467
+
468
+    .query_formats   = rgbtest_query_formats,
469
+
470
+    .inputs    = (AVFilterPad[]) {{ .name = NULL}},
471
+
472
+    .outputs   = (AVFilterPad[]) {{ .name = "default",
473
+                                    .type = AVMEDIA_TYPE_VIDEO,
474
+                                    .request_frame = request_frame,
475
+                                    .config_props  = rgbtest_config_props, },
476
+                                  { .name = NULL }},
477
+};
478
+
479
+#endif /* CONFIG_RGBTESTSRC_FILTER */