LCOV - code coverage report
Current view: top level - libavfilter - vsrc_mptestsrc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 152 0.0 %
Date: 2017-12-15 02:19:58 Functions: 0 16 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at>
       3             :  *
       4             :  * This file is part of FFmpeg.
       5             :  *
       6             :  * FFmpeg is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU General Public License as published by
       8             :  * the Free Software Foundation; either version 2 of the License, or
       9             :  * (at your option) any later version.
      10             :  *
      11             :  * FFmpeg is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
      18             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      19             :  */
      20             : 
      21             : /**
      22             :  * @file
      23             :  * MP test source, ported from MPlayer libmpcodecs/vf_test.c
      24             :  */
      25             : 
      26             : #include "libavutil/avstring.h"
      27             : #include "libavutil/opt.h"
      28             : #include "libavutil/parseutils.h"
      29             : #include "libavutil/pixdesc.h"
      30             : #include "avfilter.h"
      31             : #include "internal.h"
      32             : #include "formats.h"
      33             : #include "video.h"
      34             : 
      35             : #define WIDTH 512
      36             : #define HEIGHT 512
      37             : 
      38             : enum test_type {
      39             :     TEST_DC_LUMA,
      40             :     TEST_DC_CHROMA,
      41             :     TEST_FREQ_LUMA,
      42             :     TEST_FREQ_CHROMA,
      43             :     TEST_AMP_LUMA,
      44             :     TEST_AMP_CHROMA,
      45             :     TEST_CBP,
      46             :     TEST_MV,
      47             :     TEST_RING1,
      48             :     TEST_RING2,
      49             :     TEST_ALL,
      50             :     TEST_NB
      51             : };
      52             : 
      53             : typedef struct MPTestContext {
      54             :     const AVClass *class;
      55             :     AVRational frame_rate;
      56             :     int64_t pts, max_pts, duration;
      57             :     int hsub, vsub;
      58             :     int test;           ///< test_type
      59             : } MPTestContext;
      60             : 
      61             : #define OFFSET(x) offsetof(MPTestContext, x)
      62             : #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
      63             : static const AVOption mptestsrc_options[]= {
      64             :     { "rate",     "set video rate",     OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },
      65             :     { "r",        "set video rate",     OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },
      66             :     { "duration", "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = -1}, -1, INT64_MAX, FLAGS },
      67             :     { "d",        "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = -1}, -1, INT64_MAX, FLAGS },
      68             : 
      69             :     { "test", "set test to perform", OFFSET(test),  AV_OPT_TYPE_INT,   {.i64=TEST_ALL}, 0, INT_MAX, FLAGS, "test" },
      70             :     { "t",    "set test to perform", OFFSET(test),  AV_OPT_TYPE_INT,   {.i64=TEST_ALL}, 0, INT_MAX, FLAGS, "test" },
      71             :         { "dc_luma",     "", 0, AV_OPT_TYPE_CONST, {.i64=TEST_DC_LUMA},     INT_MIN, INT_MAX, FLAGS, "test" },
      72             :         { "dc_chroma",   "", 0, AV_OPT_TYPE_CONST, {.i64=TEST_DC_CHROMA},   INT_MIN, INT_MAX, FLAGS, "test" },
      73             :         { "freq_luma",   "", 0, AV_OPT_TYPE_CONST, {.i64=TEST_FREQ_LUMA},   INT_MIN, INT_MAX, FLAGS, "test" },
      74             :         { "freq_chroma", "", 0, AV_OPT_TYPE_CONST, {.i64=TEST_FREQ_CHROMA}, INT_MIN, INT_MAX, FLAGS, "test" },
      75             :         { "amp_luma",    "", 0, AV_OPT_TYPE_CONST, {.i64=TEST_AMP_LUMA},    INT_MIN, INT_MAX, FLAGS, "test" },
      76             :         { "amp_chroma",  "", 0, AV_OPT_TYPE_CONST, {.i64=TEST_AMP_CHROMA},  INT_MIN, INT_MAX, FLAGS, "test" },
      77             :         { "cbp",         "", 0, AV_OPT_TYPE_CONST, {.i64=TEST_CBP},         INT_MIN, INT_MAX, FLAGS, "test" },
      78             :         { "mv",          "", 0, AV_OPT_TYPE_CONST, {.i64=TEST_MV},          INT_MIN, INT_MAX, FLAGS, "test" },
      79             :         { "ring1",       "", 0, AV_OPT_TYPE_CONST, {.i64=TEST_RING1},       INT_MIN, INT_MAX, FLAGS, "test" },
      80             :         { "ring2",       "", 0, AV_OPT_TYPE_CONST, {.i64=TEST_RING2},       INT_MIN, INT_MAX, FLAGS, "test" },
      81             :         { "all",         "", 0, AV_OPT_TYPE_CONST, {.i64=TEST_ALL},         INT_MIN, INT_MAX, FLAGS, "test" },
      82             :     { NULL }
      83             : };
      84             : 
      85             : AVFILTER_DEFINE_CLASS(mptestsrc);
      86             : 
      87             : static double c[64];
      88             : 
      89           0 : static void init_idct(void)
      90             : {
      91             :     int i, j;
      92             : 
      93           0 :     for (i = 0; i < 8; i++) {
      94           0 :         double s = i == 0 ? sqrt(0.125) : 0.5;
      95             : 
      96           0 :         for (j = 0; j < 8; j++)
      97           0 :             c[i*8+j] = s*cos((M_PI/8.0)*i*(j+0.5));
      98             :     }
      99           0 : }
     100             : 
     101           0 : static void idct(uint8_t *dst, int dst_linesize, int src[64])
     102             : {
     103             :     int i, j, k;
     104             :     double tmp[64];
     105             : 
     106           0 :     for (i = 0; i < 8; i++) {
     107           0 :         for (j = 0; j < 8; j++) {
     108           0 :             double sum = 0.0;
     109             : 
     110           0 :             for (k = 0; k < 8; k++)
     111           0 :                 sum += c[k*8+j] * src[8*i+k];
     112             : 
     113           0 :             tmp[8*i+j] = sum;
     114             :         }
     115             :     }
     116             : 
     117           0 :     for (j = 0; j < 8; j++) {
     118           0 :         for (i = 0; i < 8; i++) {
     119           0 :             double sum = 0.0;
     120             : 
     121           0 :             for (k = 0; k < 8; k++)
     122           0 :                 sum += c[k*8+i]*tmp[8*k+j];
     123             : 
     124           0 :             dst[dst_linesize*i + j] = av_clip_uint8(lrint(sum));
     125             :         }
     126             :     }
     127           0 : }
     128             : 
     129           0 : static void draw_dc(uint8_t *dst, int dst_linesize, int color, int w, int h)
     130             : {
     131             :     int x, y;
     132             : 
     133           0 :     for (y = 0; y < h; y++)
     134           0 :         for (x = 0; x < w; x++)
     135           0 :             dst[x + y*dst_linesize] = color;
     136           0 : }
     137             : 
     138           0 : static void draw_basis(uint8_t *dst, int dst_linesize, int amp, int freq, int dc)
     139             : {
     140             :     int src[64];
     141             : 
     142           0 :     memset(src, 0, 64*sizeof(int));
     143           0 :     src[0] = dc;
     144           0 :     if (amp)
     145           0 :         src[freq] = amp;
     146           0 :     idct(dst, dst_linesize, src);
     147           0 : }
     148             : 
     149           0 : static void draw_cbp(uint8_t *dst[3], int dst_linesize[3], int cbp, int amp, int dc)
     150             : {
     151           0 :     if (cbp&1)  draw_basis(dst[0]                    , dst_linesize[0], amp, 1, dc);
     152           0 :     if (cbp&2)  draw_basis(dst[0]+8                  , dst_linesize[0], amp, 1, dc);
     153           0 :     if (cbp&4)  draw_basis(dst[0]+  8*dst_linesize[0], dst_linesize[0], amp, 1, dc);
     154           0 :     if (cbp&8)  draw_basis(dst[0]+8+8*dst_linesize[0], dst_linesize[0], amp, 1, dc);
     155           0 :     if (cbp&16) draw_basis(dst[1]                    , dst_linesize[1], amp, 1, dc);
     156           0 :     if (cbp&32) draw_basis(dst[2]                    , dst_linesize[2], amp, 1, dc);
     157           0 : }
     158             : 
     159           0 : static void dc_test(uint8_t *dst, int dst_linesize, int w, int h, int off)
     160             : {
     161           0 :     const int step = FFMAX(256/(w*h/256), 1);
     162           0 :     int x, y, color = off;
     163             : 
     164           0 :     for (y = 0; y < h; y += 16) {
     165           0 :         for (x = 0; x < w; x += 16) {
     166           0 :             draw_dc(dst + x + y*dst_linesize, dst_linesize, color, 8, 8);
     167           0 :             color += step;
     168             :         }
     169             :     }
     170           0 : }
     171             : 
     172           0 : static void freq_test(uint8_t *dst, int dst_linesize, int off)
     173             : {
     174           0 :     int x, y, freq = 0;
     175             : 
     176           0 :     for (y = 0; y < 8*16; y += 16) {
     177           0 :         for (x = 0; x < 8*16; x += 16) {
     178           0 :             draw_basis(dst + x + y*dst_linesize, dst_linesize, 4*(96+off), freq, 128*8);
     179           0 :             freq++;
     180             :         }
     181             :     }
     182           0 : }
     183             : 
     184           0 : static void amp_test(uint8_t *dst, int dst_linesize, int off)
     185             : {
     186           0 :     int x, y, amp = off;
     187             : 
     188           0 :     for (y = 0; y < 16*16; y += 16) {
     189           0 :         for (x = 0; x < 16*16; x += 16) {
     190           0 :             draw_basis(dst + x + y*dst_linesize, dst_linesize, 4*amp, 1, 128*8);
     191           0 :             amp++;
     192             :         }
     193             :     }
     194           0 : }
     195             : 
     196           0 : static void cbp_test(uint8_t *dst[3], int dst_linesize[3], int off)
     197             : {
     198           0 :     int x, y, cbp = 0;
     199             : 
     200           0 :     for (y = 0; y < 16*8; y += 16) {
     201           0 :         for (x = 0; x < 16*8; x += 16) {
     202             :             uint8_t *dst1[3];
     203           0 :             dst1[0] = dst[0] + x*2 + y*2*dst_linesize[0];
     204           0 :             dst1[1] = dst[1] + x   + y*  dst_linesize[1];
     205           0 :             dst1[2] = dst[2] + x   + y*  dst_linesize[2];
     206             : 
     207           0 :             draw_cbp(dst1, dst_linesize, cbp, (64+off)*4, 128*8);
     208           0 :             cbp++;
     209             :         }
     210             :     }
     211           0 : }
     212             : 
     213           0 : static void mv_test(uint8_t *dst, int dst_linesize, int off)
     214             : {
     215             :     int x, y;
     216             : 
     217           0 :     for (y = 0; y < 16*16; y++) {
     218           0 :         if (y&16)
     219           0 :             continue;
     220           0 :         for (x = 0; x < 16*16; x++)
     221           0 :             dst[x + y*dst_linesize] = x + off*8/(y/32+1);
     222             :     }
     223           0 : }
     224             : 
     225           0 : static void ring1_test(uint8_t *dst, int dst_linesize, int off)
     226             : {
     227           0 :     int x, y, color = 0;
     228             : 
     229           0 :     for (y = off; y < 16*16; y += 16) {
     230           0 :         for (x = off; x < 16*16; x += 16) {
     231           0 :             draw_dc(dst + x + y*dst_linesize, dst_linesize, ((x+y)&16) ? color : -color, 16, 16);
     232           0 :             color++;
     233             :         }
     234             :     }
     235           0 : }
     236             : 
     237           0 : static void ring2_test(uint8_t *dst, int dst_linesize, int off)
     238             : {
     239             :     int x, y;
     240             : 
     241           0 :     for (y = 0; y < 16*16; y++) {
     242           0 :         for (x = 0; x < 16*16; x++) {
     243           0 :             double d = hypot(x-8*16, y-8*16);
     244           0 :             double r = d/20 - (int)(d/20);
     245           0 :             if (r < off/30.0) {
     246           0 :                 dst[x + y*dst_linesize]     = 255;
     247           0 :                 dst[x + y*dst_linesize+256] = 0;
     248             :             } else {
     249           0 :                 dst[x + y*dst_linesize]     = x;
     250           0 :                 dst[x + y*dst_linesize+256] = x;
     251             :             }
     252             :         }
     253             :     }
     254           0 : }
     255             : 
     256           0 : static av_cold int init(AVFilterContext *ctx)
     257             : {
     258           0 :     MPTestContext *test = ctx->priv;
     259             : 
     260           0 :     test->max_pts = test->duration >= 0 ?
     261           0 :         av_rescale_q(test->duration, AV_TIME_BASE_Q, av_inv_q(test->frame_rate)) : -1;
     262           0 :     test->pts = 0;
     263             : 
     264           0 :     av_log(ctx, AV_LOG_VERBOSE, "rate:%d/%d duration:%f\n",
     265             :            test->frame_rate.num, test->frame_rate.den,
     266           0 :            test->duration < 0 ? -1 : test->max_pts * av_q2d(av_inv_q(test->frame_rate)));
     267           0 :     init_idct();
     268             : 
     269           0 :     return 0;
     270             : }
     271             : 
     272           0 : static int config_props(AVFilterLink *outlink)
     273             : {
     274           0 :     AVFilterContext *ctx = outlink->src;
     275           0 :     MPTestContext *test = ctx->priv;
     276           0 :     const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(outlink->format);
     277             : 
     278           0 :     test->hsub = pix_desc->log2_chroma_w;
     279           0 :     test->vsub = pix_desc->log2_chroma_h;
     280             : 
     281           0 :     outlink->w = WIDTH;
     282           0 :     outlink->h = HEIGHT;
     283           0 :     outlink->time_base = av_inv_q(test->frame_rate);
     284             : 
     285           0 :     return 0;
     286             : }
     287             : 
     288           0 : static int query_formats(AVFilterContext *ctx)
     289             : {
     290             :     static const enum AVPixelFormat pix_fmts[] = {
     291             :         AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE
     292             :     };
     293             : 
     294           0 :     AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
     295           0 :     if (!fmts_list)
     296           0 :         return AVERROR(ENOMEM);
     297           0 :     return ff_set_common_formats(ctx, fmts_list);
     298             : }
     299             : 
     300           0 : static int request_frame(AVFilterLink *outlink)
     301             : {
     302           0 :     MPTestContext *test = outlink->src->priv;
     303             :     AVFrame *picref;
     304           0 :     int w = WIDTH, h = HEIGHT,
     305           0 :         cw = AV_CEIL_RSHIFT(w, test->hsub), ch = AV_CEIL_RSHIFT(h, test->vsub);
     306           0 :     unsigned int frame = outlink->frame_count_in;
     307           0 :     enum test_type tt = test->test;
     308             :     int i;
     309             : 
     310           0 :     if (test->max_pts >= 0 && test->pts > test->max_pts)
     311           0 :         return AVERROR_EOF;
     312           0 :     picref = ff_get_video_buffer(outlink, w, h);
     313           0 :     if (!picref)
     314           0 :         return AVERROR(ENOMEM);
     315           0 :     picref->pts = test->pts++;
     316             : 
     317             :     // clean image
     318           0 :     for (i = 0; i < h; i++)
     319           0 :         memset(picref->data[0] + i*picref->linesize[0], 0, w);
     320           0 :     for (i = 0; i < ch; i++) {
     321           0 :         memset(picref->data[1] + i*picref->linesize[1], 128, cw);
     322           0 :         memset(picref->data[2] + i*picref->linesize[2], 128, cw);
     323             :     }
     324             : 
     325           0 :     if (tt == TEST_ALL && frame%30) /* draw a black frame at the beginning of each test */
     326           0 :         tt = (frame/30)%(TEST_NB-1);
     327             : 
     328           0 :     switch (tt) {
     329           0 :     case TEST_DC_LUMA:       dc_test(picref->data[0], picref->linesize[0], 256, 256, frame%30); break;
     330           0 :     case TEST_DC_CHROMA:     dc_test(picref->data[1], picref->linesize[1], 256, 256, frame%30); break;
     331           0 :     case TEST_FREQ_LUMA:   freq_test(picref->data[0], picref->linesize[0], frame%30); break;
     332           0 :     case TEST_FREQ_CHROMA: freq_test(picref->data[1], picref->linesize[1], frame%30); break;
     333           0 :     case TEST_AMP_LUMA:     amp_test(picref->data[0], picref->linesize[0], frame%30); break;
     334           0 :     case TEST_AMP_CHROMA:   amp_test(picref->data[1], picref->linesize[1], frame%30); break;
     335           0 :     case TEST_CBP:          cbp_test(picref->data   , picref->linesize   , frame%30); break;
     336           0 :     case TEST_MV:            mv_test(picref->data[0], picref->linesize[0], frame%30); break;
     337           0 :     case TEST_RING1:      ring1_test(picref->data[0], picref->linesize[0], frame%30); break;
     338           0 :     case TEST_RING2:      ring2_test(picref->data[0], picref->linesize[0], frame%30); break;
     339             :     }
     340             : 
     341           0 :     return ff_filter_frame(outlink, picref);
     342             : }
     343             : 
     344             : static const AVFilterPad mptestsrc_outputs[] = {
     345             :     {
     346             :         .name          = "default",
     347             :         .type          = AVMEDIA_TYPE_VIDEO,
     348             :         .request_frame = request_frame,
     349             :         .config_props  = config_props,
     350             :     },
     351             :     { NULL }
     352             : };
     353             : 
     354             : AVFilter ff_vsrc_mptestsrc = {
     355             :     .name          = "mptestsrc",
     356             :     .description   = NULL_IF_CONFIG_SMALL("Generate various test pattern."),
     357             :     .priv_size     = sizeof(MPTestContext),
     358             :     .priv_class    = &mptestsrc_class,
     359             :     .init          = init,
     360             :     .query_formats = query_formats,
     361             :     .inputs        = NULL,
     362             :     .outputs       = mptestsrc_outputs,
     363             : };

Generated by: LCOV version 1.13