annotate ffmpeg/libavfilter/vsrc_mptestsrc.c @ 13:844d341cf643 tip

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