2724a8cc592e1edd3cf40b0bf64babd3cbc5fc44
[platform/upstream/gst-plugins-base.git] / gst / videotestsrc / videotestsrc.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 /* non-GST-specific stuff */
25
26 #include "gstvideotestsrc.h"
27 #include "videotestsrc.h"
28 #include "gstvideotestsrcorc.h"
29
30 #include <gst/math-compat.h>
31
32 #include <string.h>
33 #include <stdlib.h>
34
35 #define TO_16(x) (((x)<<8) | (x))
36
37 static unsigned char
38 random_char (guint * state)
39 {
40   *state *= 1103515245;
41   *state += 12345;
42   return (*state >> 16) & 0xff;
43 }
44
45 enum
46 {
47   COLOR_WHITE = 0,
48   COLOR_YELLOW,
49   COLOR_CYAN,
50   COLOR_GREEN,
51   COLOR_MAGENTA,
52   COLOR_RED,
53   COLOR_BLUE,
54   COLOR_BLACK,
55   COLOR_NEG_I,
56   COLOR_POS_Q,
57   COLOR_SUPER_BLACK,
58   COLOR_DARK_GREY
59 };
60
61 static const struct vts_color_struct vts_colors_bt709_ycbcr_100[] = {
62   {235, 128, 128, 255, 255, 255, 255, (235 << 8)},
63   {219, 16, 138, 255, 255, 255, 0, (219 << 8)},
64   {188, 154, 16, 255, 0, 255, 255, (188 << 8)},
65   {173, 42, 26, 255, 0, 255, 0, (173 << 8)},
66   {78, 214, 230, 255, 255, 0, 255, (78 << 8)},
67   {63, 102, 240, 255, 255, 0, 0, (64 << 8)},
68   {32, 240, 118, 255, 0, 0, 255, (32 << 8)},
69   {16, 128, 128, 255, 0, 0, 0, (16 << 8)},
70   {16, 198, 21, 255, 0, 0, 128, (16 << 8)},     /* -I ? */
71   {16, 235, 198, 255, 0, 128, 255, (16 << 8)},  /* +Q ? */
72   {0, 128, 128, 255, 0, 0, 0, 0},
73   {32, 128, 128, 255, 19, 19, 19, (32 << 8)},
74 };
75
76 static const struct vts_color_struct vts_colors_bt709_ycbcr_75[] = {
77   {180, 128, 128, 255, 191, 191, 191, (180 << 8)},
78   {168, 44, 136, 255, 191, 191, 0, (168 << 8)},
79   {145, 147, 44, 255, 0, 191, 191, (145 << 8)},
80   {133, 63, 52, 255, 0, 191, 0, (133 << 8)},
81   {63, 193, 204, 255, 191, 0, 191, (63 << 8)},
82   {51, 109, 212, 255, 191, 0, 0, (51 << 8)},
83   {28, 212, 120, 255, 0, 0, 191, (28 << 8)},
84   {16, 128, 128, 255, 0, 0, 0, (16 << 8)},
85   {16, 198, 21, 255, 0, 0, 128, (16 << 8)},     /* -I ? */
86   {16, 235, 198, 255, 0, 128, 255, (16 << 8)},  /* +Q ? */
87   {0, 128, 128, 255, 0, 0, 0, 0},
88   {32, 128, 128, 255, 19, 19, 19, (32 << 8)},
89 };
90
91 static const struct vts_color_struct vts_colors_bt601_ycbcr_100[] = {
92   {235, 128, 128, 255, 255, 255, 255, (235 << 8)},
93   {210, 16, 146, 255, 255, 255, 0, (219 << 8)},
94   {170, 166, 16, 255, 0, 255, 255, (188 << 8)},
95   {145, 54, 34, 255, 0, 255, 0, (173 << 8)},
96   {106, 202, 222, 255, 255, 0, 255, (78 << 8)},
97   {81, 90, 240, 255, 255, 0, 0, (64 << 8)},
98   {41, 240, 110, 255, 0, 0, 255, (32 << 8)},
99   {16, 128, 128, 255, 0, 0, 0, (16 << 8)},
100   {16, 198, 21, 255, 0, 0, 128, (16 << 8)},     /* -I ? */
101   {16, 235, 198, 255, 0, 128, 255, (16 << 8)},  /* +Q ? */
102   {-0, 128, 128, 255, 0, 0, 0, 0},
103   {32, 128, 128, 255, 19, 19, 19, (32 << 8)},
104 };
105
106 static const struct vts_color_struct vts_colors_bt601_ycbcr_75[] = {
107   {180, 128, 128, 255, 191, 191, 191, (180 << 8)},
108   {162, 44, 142, 255, 191, 191, 0, (168 << 8)},
109   {131, 156, 44, 255, 0, 191, 191, (145 << 8)},
110   {112, 72, 58, 255, 0, 191, 0, (133 << 8)},
111   {84, 184, 198, 255, 191, 0, 191, (63 << 8)},
112   {65, 100, 212, 255, 191, 0, 0, (51 << 8)},
113   {35, 212, 114, 255, 0, 0, 191, (28 << 8)},
114   {16, 128, 128, 255, 0, 0, 0, (16 << 8)},
115   {16, 198, 21, 255, 0, 0, 128, (16 << 8)},     /* -I ? */
116   {16, 235, 198, 255, 0, 128, 255, (16 << 8)},  /* +Q ? */
117   {-0, 128, 128, 255, 0, 0, 0, 0},
118   {32, 128, 128, 255, 19, 19, 19, (32 << 8)},
119 };
120
121
122 static void paint_tmpline_ARGB (paintinfo * p, int x, int w);
123 static void paint_tmpline_AYUV (paintinfo * p, int x, int w);
124
125 static void convert_hline_generic (paintinfo * p, GstVideoFrame * frame, int y);
126 static void convert_hline_bayer (paintinfo * p, GstVideoFrame * frame, int y);
127
128 #define SCALEBITS 10
129 #define ONE_HALF  (1 << (SCALEBITS - 1))
130 #define FIX(x)    ((int) ((x) * (1<<SCALEBITS) + 0.5))
131
132 #define RGB_TO_Y(r, g, b) \
133 ((FIX(0.29900) * (r) + FIX(0.58700) * (g) + \
134   FIX(0.11400) * (b) + ONE_HALF) >> SCALEBITS)
135
136 #define RGB_TO_U(r1, g1, b1, shift)\
137 (((- FIX(0.16874) * r1 - FIX(0.33126) * g1 +         \
138      FIX(0.50000) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
139
140 #define RGB_TO_V(r1, g1, b1, shift)\
141 (((FIX(0.50000) * r1 - FIX(0.41869) * g1 -           \
142    FIX(0.08131) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
143
144 #define RGB_TO_Y_CCIR(r, g, b) \
145 ((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \
146   FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
147
148 #define RGB_TO_U_CCIR(r1, g1, b1, shift)\
149 (((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 +         \
150      FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
151
152 #define RGB_TO_V_CCIR(r1, g1, b1, shift)\
153 (((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 -           \
154    FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
155
156 #define RGB_TO_Y_CCIR_709(r, g, b) \
157 ((FIX(0.212600*219.0/255.0) * (r) + FIX(0.715200*219.0/255.0) * (g) + \
158   FIX(0.072200*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
159
160 #define RGB_TO_U_CCIR_709(r1, g1, b1, shift)\
161 (((- FIX(0.114572*224.0/255.0) * r1 - FIX(0.385427*224.0/255.0) * g1 +         \
162      FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
163
164 #define RGB_TO_V_CCIR_709(r1, g1, b1, shift)\
165 (((FIX(0.50000*224.0/255.0) * r1 - FIX(0.454153*224.0/255.0) * g1 -           \
166    FIX(0.045847*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
167
168 static void
169 videotestsrc_setup_paintinfo (GstVideoTestSrc * v, paintinfo * p, int w, int h)
170 {
171   gint a, r, g, b;
172   gint width;
173   GstVideoInfo *info = &v->info;
174
175   width = GST_VIDEO_INFO_WIDTH (info);
176
177   if (info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT601) {
178     p->colors = vts_colors_bt601_ycbcr_100;
179   } else {
180     p->colors = vts_colors_bt709_ycbcr_100;
181   }
182
183   if (v->bayer) {
184     p->paint_tmpline = paint_tmpline_ARGB;
185     p->convert_tmpline = convert_hline_bayer;
186   } else {
187     p->convert_tmpline = convert_hline_generic;
188     if (GST_VIDEO_INFO_IS_RGB (info)) {
189       p->paint_tmpline = paint_tmpline_ARGB;
190     } else {
191       p->paint_tmpline = paint_tmpline_AYUV;
192     }
193   }
194   p->tmpline = v->tmpline;
195   p->tmpline2 = v->tmpline2;
196   p->tmpline_u8 = v->tmpline_u8;
197   p->tmpline_u16 = v->tmpline_u16;
198   p->n_lines = v->n_lines;
199   p->offset = v->offset;
200   p->lines = v->lines;
201   p->x_offset = (v->horizontal_speed * v->n_frames) % width;
202   if (p->x_offset < 0)
203     p->x_offset += width;
204   p->x_invert = v->x_invert;
205   p->y_invert = v->y_invert;
206
207   a = (v->foreground_color >> 24) & 0xff;
208   r = (v->foreground_color >> 16) & 0xff;
209   g = (v->foreground_color >> 8) & 0xff;
210   b = (v->foreground_color >> 0) & 0xff;
211   p->foreground_color.A = a;
212   p->foreground_color.R = r;
213   p->foreground_color.G = g;
214   p->foreground_color.B = b;
215
216   if (info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT601) {
217     p->foreground_color.Y = RGB_TO_Y_CCIR (r, g, b);
218     p->foreground_color.U = RGB_TO_U_CCIR (r, g, b, 0);
219     p->foreground_color.V = RGB_TO_V_CCIR (r, g, b, 0);
220   } else {
221     p->foreground_color.Y = RGB_TO_Y_CCIR_709 (r, g, b);
222     p->foreground_color.U = RGB_TO_U_CCIR_709 (r, g, b, 0);
223     p->foreground_color.V = RGB_TO_V_CCIR_709 (r, g, b, 0);
224   }
225   p->foreground_color.gray = RGB_TO_Y (r, g, b);
226
227   a = (v->background_color >> 24) & 0xff;
228   r = (v->background_color >> 16) & 0xff;
229   g = (v->background_color >> 8) & 0xff;
230   b = (v->background_color >> 0) & 0xff;
231   p->background_color.A = a;
232   p->background_color.R = r;
233   p->background_color.G = g;
234   p->background_color.B = b;
235
236   if (info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT601) {
237     p->background_color.Y = RGB_TO_Y_CCIR (r, g, b);
238     p->background_color.U = RGB_TO_U_CCIR (r, g, b, 0);
239     p->background_color.V = RGB_TO_V_CCIR (r, g, b, 0);
240   } else {
241     p->background_color.Y = RGB_TO_Y_CCIR_709 (r, g, b);
242     p->background_color.U = RGB_TO_U_CCIR_709 (r, g, b, 0);
243     p->background_color.V = RGB_TO_V_CCIR_709 (r, g, b, 0);
244   }
245   p->background_color.gray = RGB_TO_Y (r, g, b);
246
247   p->subsample = v->subsample;
248 }
249
250 static void
251 videotestsrc_convert_tmpline (paintinfo * p, GstVideoFrame * frame, int j)
252 {
253   int x = p->x_offset;
254   int i;
255   int width = frame->info.width;
256   int height = frame->info.height;
257   int n_lines = p->n_lines;
258   int offset = p->offset;
259   guint8 *tmpline = p->tmpline, *tmpline2 = p->tmpline2;
260
261   /* `tmpline2` is only used here and when the shift amount `x` is
262    * non-zero, which only applies when `horizontal-speed` is set.
263    *
264    * Instead of copying the rotated line back to `tmpline` for
265    * `p->convert_tmpline` to use, swap the pointers briefly. Besides
266    * being cheaper, this also lets us reuse the painted `tmpline` for
267    * subsequent lines.
268    */
269   if (x != 0) {
270     memcpy (tmpline2, tmpline + x * 4, (width - x) * 4);
271     memcpy (tmpline2 + (width - x) * 4, tmpline, x * 4);
272     p->tmpline = tmpline2;
273     p->tmpline2 = tmpline;
274   }
275
276   for (i = width; i < width + 5; i++) {
277     p->tmpline[4 * i + 0] = p->tmpline[4 * (width - 1) + 0];
278     p->tmpline[4 * i + 1] = p->tmpline[4 * (width - 1) + 1];
279     p->tmpline[4 * i + 2] = p->tmpline[4 * (width - 1) + 2];
280     p->tmpline[4 * i + 3] = p->tmpline[4 * (width - 1) + 3];
281   }
282
283   p->convert_tmpline (p, frame, j);
284
285   if (j == height - 1) {
286     while (j % n_lines - offset != n_lines - 1) {
287       j++;
288       p->convert_tmpline (p, frame, j);
289     }
290   }
291
292   if (x != 0) {
293     p->tmpline = tmpline;
294     p->tmpline2 = tmpline2;
295   }
296 }
297
298 #define BLEND1(a,b,x) ((a)*(x) + (b)*(255-(x)))
299 #define DIV255(x) (((x) + (((x)+128)>>8) + 128)>>8)
300 #define BLEND(a,b,x) DIV255(BLEND1(a,b,x))
301
302 #ifdef unused
303 static void
304 videotestsrc_blend_color (struct vts_color_struct *dest,
305     struct vts_color_struct *a, struct vts_color_struct *b, int x)
306 {
307   dest->Y = BLEND (a->Y, b->Y, x);
308   dest->U = BLEND (a->U, b->U, x);
309   dest->V = BLEND (a->V, b->V, x);
310   dest->R = BLEND (a->R, b->R, x);
311   dest->G = BLEND (a->G, b->G, x);
312   dest->B = BLEND (a->B, b->B, x);
313   dest->gray = BLEND (a->gray, b->gray, x);
314
315 }
316 #endif
317
318 static void
319 videotestsrc_blend_line (GstVideoTestSrc * v, guint8 * dest,
320     const guint8 * src, const struct vts_color_struct *a,
321     const struct vts_color_struct *b, int x1, int x2)
322 {
323   int i;
324   if (v->bayer || GST_VIDEO_INFO_IS_RGB (&v->info)) {
325     for (i = x1; i < x2; i++) {
326       dest[i * 4 + 0] = BLEND (a->A, b->A, src[i]);
327       dest[i * 4 + 1] = BLEND (a->R, b->R, src[i]);
328       dest[i * 4 + 2] = BLEND (a->G, b->G, src[i]);
329       dest[i * 4 + 3] = BLEND (a->B, b->B, src[i]);
330     }
331   } else {
332     for (i = x1; i < x2; i++) {
333       dest[i * 4 + 0] = BLEND (a->A, b->A, src[i]);
334       dest[i * 4 + 1] = BLEND (a->Y, b->Y, src[i]);
335       dest[i * 4 + 2] = BLEND (a->U, b->U, src[i]);
336       dest[i * 4 + 3] = BLEND (a->V, b->V, src[i]);
337     }
338   }
339 #undef BLEND
340 }
341
342 void
343 gst_video_test_src_smpte (GstVideoTestSrc * v, GstClockTime pts,
344     GstVideoFrame * frame)
345 {
346   int i;
347   int y1, y2;
348   int j;
349   paintinfo pi = PAINT_INFO_INIT;
350   paintinfo *p = &pi;
351   int w = frame->info.width, h = frame->info.height;
352
353   videotestsrc_setup_paintinfo (v, p, w, h);
354
355   y1 = 2 * h / 3;
356   y2 = 3 * h / 4;
357
358   /* color bars */
359   for (j = 0; j < y1; j++) {
360     for (i = 0; i < 7; i++) {
361       int x1 = i * w / 7;
362       int x2 = (i + 1) * w / 7;
363
364       p->color = p->colors + i;
365       p->paint_tmpline (p, x1, (x2 - x1));
366     }
367     videotestsrc_convert_tmpline (p, frame, j);
368   }
369
370   /* inverse blue bars */
371   for (j = y1; j < y2; j++) {
372     for (i = 0; i < 7; i++) {
373       int x1 = i * w / 7;
374       int x2 = (i + 1) * w / 7;
375       int k;
376
377       if (i & 1) {
378         k = 7;
379       } else {
380         k = 6 - i;
381       }
382       p->color = p->colors + k;
383       p->paint_tmpline (p, x1, (x2 - x1));
384     }
385     videotestsrc_convert_tmpline (p, frame, j);
386   }
387
388   for (j = y2; j < h; j++) {
389     /* -I, white, Q regions */
390     for (i = 0; i < 3; i++) {
391       int x1 = i * w / 6;
392       int x2 = (i + 1) * w / 6;
393       int k;
394
395       if (i == 0) {
396         k = 8;
397       } else if (i == 1) {
398         k = 0;
399       } else
400         k = 9;
401
402       p->color = p->colors + k;
403       p->paint_tmpline (p, x1, (x2 - x1));
404     }
405
406     /* superblack, black, dark grey */
407     for (i = 0; i < 3; i++) {
408       int x1 = w / 2 + i * w / 12;
409       int x2 = w / 2 + (i + 1) * w / 12;
410       int k;
411
412       if (i == 0) {
413         k = COLOR_SUPER_BLACK;
414       } else if (i == 1) {
415         k = COLOR_BLACK;
416       } else
417         k = COLOR_DARK_GREY;
418
419       p->color = p->colors + k;
420       p->paint_tmpline (p, x1, (x2 - x1));
421     }
422
423     {
424       int x1 = w * 3 / 4;
425       struct vts_color_struct color;
426
427       color = p->colors[COLOR_BLACK];
428       p->color = &color;
429
430       for (i = x1; i < w; i++) {
431         int y = random_char (&v->random_state);
432         p->tmpline_u8[i] = y;
433       }
434       videotestsrc_blend_line (v, p->tmpline, p->tmpline_u8,
435           &p->foreground_color, &p->background_color, x1, w);
436
437     }
438     videotestsrc_convert_tmpline (p, frame, j);
439
440   }
441 }
442
443 void
444 gst_video_test_src_smpte75 (GstVideoTestSrc * v, GstClockTime pts,
445     GstVideoFrame * frame)
446 {
447   int i;
448   int j;
449   paintinfo pi = PAINT_INFO_INIT;
450   paintinfo *p = &pi;
451   int w = frame->info.width, h = frame->info.height;
452
453   videotestsrc_setup_paintinfo (v, p, w, h);
454   if (v->info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT601) {
455     p->colors = vts_colors_bt601_ycbcr_75;
456   } else {
457     p->colors = vts_colors_bt709_ycbcr_75;
458   }
459
460   /* color bars */
461   for (j = 0; j < h; j++) {
462     for (i = 0; i < 7; i++) {
463       int x1 = i * w / 7;
464       int x2 = (i + 1) * w / 7;
465
466       p->color = p->colors + i;
467       p->paint_tmpline (p, x1, (x2 - x1));
468     }
469     videotestsrc_convert_tmpline (p, frame, j);
470   }
471 }
472
473 void
474 gst_video_test_src_smpte100 (GstVideoTestSrc * v, GstClockTime pts,
475     GstVideoFrame * frame)
476 {
477   int i;
478   int j;
479   paintinfo pi = PAINT_INFO_INIT;
480   paintinfo *p = &pi;
481   int w = frame->info.width, h = frame->info.height;
482
483   videotestsrc_setup_paintinfo (v, p, w, h);
484
485   /* color bars */
486   for (j = 0; j < h; j++) {
487     for (i = 0; i < 7; i++) {
488       int x1 = i * w / 7;
489       int x2 = (i + 1) * w / 7;
490
491       p->color = p->colors + i;
492       p->paint_tmpline (p, x1, (x2 - x1));
493     }
494     videotestsrc_convert_tmpline (p, frame, j);
495   }
496 }
497
498 void
499 gst_video_test_src_bar (GstVideoTestSrc * v, GstClockTime pts,
500     GstVideoFrame * frame)
501 {
502   int j;
503   paintinfo pi = PAINT_INFO_INIT;
504   paintinfo *p = &pi;
505   int w = frame->info.width, h = frame->info.height;
506
507   videotestsrc_setup_paintinfo (v, p, w, h);
508
509   for (j = 0; j < h; j++) {
510     /* use fixed size for now */
511     int x2 = w / 7;
512
513     p->color = &p->foreground_color;
514     p->paint_tmpline (p, 0, x2);
515     p->color = &p->background_color;
516     p->paint_tmpline (p, x2, (w - x2));
517     videotestsrc_convert_tmpline (p, frame, j);
518   }
519 }
520
521 void
522 gst_video_test_src_snow (GstVideoTestSrc * v, GstClockTime pts,
523     GstVideoFrame * frame)
524 {
525   int i;
526   int j;
527   paintinfo pi = PAINT_INFO_INIT;
528   paintinfo *p = &pi;
529   struct vts_color_struct color;
530   int w = frame->info.width, h = frame->info.height;
531
532   videotestsrc_setup_paintinfo (v, p, w, h);
533
534   color = p->colors[COLOR_BLACK];
535   p->color = &color;
536
537   for (j = 0; j < h; j++) {
538     for (i = 0; i < w; i++) {
539       int y = random_char (&v->random_state);
540       p->tmpline_u8[i] = y;
541     }
542     videotestsrc_blend_line (v, p->tmpline, p->tmpline_u8,
543         &p->foreground_color, &p->background_color, 0, w);
544     videotestsrc_convert_tmpline (p, frame, j);
545   }
546 }
547
548 static void
549 gst_video_test_src_unicolor (GstVideoTestSrc * v, GstVideoFrame * frame,
550     int color_index)
551 {
552   int i;
553   paintinfo pi = PAINT_INFO_INIT;
554   paintinfo *p = &pi;
555   int w = frame->info.width, h = frame->info.height;
556
557   videotestsrc_setup_paintinfo (v, p, w, h);
558
559   p->color = p->colors + color_index;
560   if (color_index == COLOR_BLACK) {
561     p->color = &p->background_color;
562   }
563   if (color_index == COLOR_WHITE) {
564     p->color = &p->foreground_color;
565   }
566
567   for (i = 0; i < h; i++) {
568     p->paint_tmpline (p, 0, w);
569     videotestsrc_convert_tmpline (p, frame, i);
570   }
571 }
572
573 void
574 gst_video_test_src_black (GstVideoTestSrc * v, GstClockTime pts,
575     GstVideoFrame * frame)
576 {
577   gst_video_test_src_unicolor (v, frame, COLOR_BLACK);
578 }
579
580 void
581 gst_video_test_src_white (GstVideoTestSrc * v, GstClockTime pts,
582     GstVideoFrame * frame)
583 {
584   gst_video_test_src_unicolor (v, frame, COLOR_WHITE);
585 }
586
587 void
588 gst_video_test_src_red (GstVideoTestSrc * v, GstClockTime pts,
589     GstVideoFrame * frame)
590 {
591   gst_video_test_src_unicolor (v, frame, COLOR_RED);
592 }
593
594 void
595 gst_video_test_src_green (GstVideoTestSrc * v, GstClockTime pts,
596     GstVideoFrame * frame)
597 {
598   gst_video_test_src_unicolor (v, frame, COLOR_GREEN);
599 }
600
601 void
602 gst_video_test_src_blue (GstVideoTestSrc * v, GstClockTime pts,
603     GstVideoFrame * frame)
604 {
605   gst_video_test_src_unicolor (v, frame, COLOR_BLUE);
606 }
607
608 void
609 gst_video_test_src_blink (GstVideoTestSrc * v, GstClockTime pts,
610     GstVideoFrame * frame)
611 {
612   int i;
613   paintinfo pi = PAINT_INFO_INIT;
614   paintinfo *p = &pi;
615   int w = frame->info.width, h = frame->info.height;
616
617   videotestsrc_setup_paintinfo (v, p, w, h);
618
619   if (v->n_frames & 1) {
620     p->color = &p->foreground_color;
621   } else {
622     p->color = &p->background_color;
623   }
624
625   for (i = 0; i < h; i++) {
626     p->paint_tmpline (p, 0, w);
627     videotestsrc_convert_tmpline (p, frame, i);
628   }
629 }
630
631 void
632 gst_video_test_src_solid (GstVideoTestSrc * v, GstClockTime pts,
633     GstVideoFrame * frame)
634 {
635   int i;
636   paintinfo pi = PAINT_INFO_INIT;
637   paintinfo *p = &pi;
638   int w = frame->info.width, h = frame->info.height;
639
640   videotestsrc_setup_paintinfo (v, p, w, h);
641
642   p->color = &p->foreground_color;
643
644   for (i = 0; i < h; i++) {
645     p->paint_tmpline (p, 0, w);
646     videotestsrc_convert_tmpline (p, frame, i);
647   }
648 }
649
650 void
651 gst_video_test_src_checkers1 (GstVideoTestSrc * v, GstClockTime pts,
652     GstVideoFrame * frame)
653 {
654   int x, y;
655   paintinfo pi = PAINT_INFO_INIT;
656   paintinfo *p = &pi;
657   int w = frame->info.width, h = frame->info.height;
658
659   videotestsrc_setup_paintinfo (v, p, w, h);
660
661   for (y = 0; y < h; y++) {
662     for (x = 0; x < w; x++) {
663       if ((x ^ y) & 1) {
664         p->color = p->colors + COLOR_GREEN;
665       } else {
666         p->color = p->colors + COLOR_RED;
667       }
668       p->paint_tmpline (p, x, 1);
669     }
670     videotestsrc_convert_tmpline (p, frame, y);
671   }
672 }
673
674 void
675 gst_video_test_src_checkers2 (GstVideoTestSrc * v, GstClockTime pts,
676     GstVideoFrame * frame)
677 {
678   int x, y;
679   paintinfo pi = PAINT_INFO_INIT;
680   paintinfo *p = &pi;
681   int w = frame->info.width, h = frame->info.height;
682
683   videotestsrc_setup_paintinfo (v, p, w, h);
684
685   for (y = 0; y < h; y++) {
686     for (x = 0; x < w; x += 2) {
687       guint len = MIN (2, w - x);
688
689       if ((x ^ y) & 2) {
690         p->color = p->colors + COLOR_GREEN;
691       } else {
692         p->color = p->colors + COLOR_RED;
693       }
694       p->paint_tmpline (p, x, len);
695     }
696     videotestsrc_convert_tmpline (p, frame, y);
697   }
698 }
699
700 void
701 gst_video_test_src_checkers4 (GstVideoTestSrc * v, GstClockTime pts,
702     GstVideoFrame * frame)
703 {
704   int x, y;
705   paintinfo pi = PAINT_INFO_INIT;
706   paintinfo *p = &pi;
707   int w = frame->info.width, h = frame->info.height;
708
709   videotestsrc_setup_paintinfo (v, p, w, h);
710
711   for (y = 0; y < h; y++) {
712     for (x = 0; x < w; x += 4) {
713       guint len = MIN (4, w - x);
714
715       if ((x ^ y) & 4) {
716         p->color = p->colors + COLOR_GREEN;
717       } else {
718         p->color = p->colors + COLOR_RED;
719       }
720       p->paint_tmpline (p, x, len);
721     }
722     videotestsrc_convert_tmpline (p, frame, y);
723   }
724 }
725
726 void
727 gst_video_test_src_checkers8 (GstVideoTestSrc * v, GstClockTime pts,
728     GstVideoFrame * frame)
729 {
730   int x, y;
731   paintinfo pi = PAINT_INFO_INIT;
732   paintinfo *p = &pi;
733   int w = frame->info.width, h = frame->info.height;
734
735   videotestsrc_setup_paintinfo (v, p, w, h);
736
737   for (y = 0; y < h; y++) {
738     for (x = 0; x < w; x += 8) {
739       guint len = MIN (8, w - x);
740
741       if ((x ^ y) & 8) {
742         p->color = p->colors + COLOR_GREEN;
743       } else {
744         p->color = p->colors + COLOR_RED;
745       }
746       p->paint_tmpline (p, x, len);
747     }
748     videotestsrc_convert_tmpline (p, frame, y);
749   }
750 }
751
752 static const guint8 sine_table[256] = {
753   128, 131, 134, 137, 140, 143, 146, 149,
754   152, 156, 159, 162, 165, 168, 171, 174,
755   176, 179, 182, 185, 188, 191, 193, 196,
756   199, 201, 204, 206, 209, 211, 213, 216,
757   218, 220, 222, 224, 226, 228, 230, 232,
758   234, 236, 237, 239, 240, 242, 243, 245,
759   246, 247, 248, 249, 250, 251, 252, 252,
760   253, 254, 254, 255, 255, 255, 255, 255,
761   255, 255, 255, 255, 255, 255, 254, 254,
762   253, 252, 252, 251, 250, 249, 248, 247,
763   246, 245, 243, 242, 240, 239, 237, 236,
764   234, 232, 230, 228, 226, 224, 222, 220,
765   218, 216, 213, 211, 209, 206, 204, 201,
766   199, 196, 193, 191, 188, 185, 182, 179,
767   176, 174, 171, 168, 165, 162, 159, 156,
768   152, 149, 146, 143, 140, 137, 134, 131,
769   128, 124, 121, 118, 115, 112, 109, 106,
770   103, 99, 96, 93, 90, 87, 84, 81,
771   79, 76, 73, 70, 67, 64, 62, 59,
772   56, 54, 51, 49, 46, 44, 42, 39,
773   37, 35, 33, 31, 29, 27, 25, 23,
774   21, 19, 18, 16, 15, 13, 12, 10,
775   9, 8, 7, 6, 5, 4, 3, 3,
776   2, 1, 1, 0, 0, 0, 0, 0,
777   0, 0, 0, 0, 0, 0, 1, 1,
778   2, 3, 3, 4, 5, 6, 7, 8,
779   9, 10, 12, 13, 15, 16, 18, 19,
780   21, 23, 25, 27, 29, 31, 33, 35,
781   37, 39, 42, 44, 46, 49, 51, 54,
782   56, 59, 62, 64, 67, 70, 73, 76,
783   79, 81, 84, 87, 90, 93, 96, 99,
784   103, 106, 109, 112, 115, 118, 121, 124
785 };
786
787
788 void
789 gst_video_test_src_zoneplate (GstVideoTestSrc * v, GstClockTime pts,
790     GstVideoFrame * frame)
791 {
792   int i;
793   int j;
794   paintinfo pi = PAINT_INFO_INIT;
795   paintinfo *p = &pi;
796   struct vts_color_struct color;
797   int t = v->n_frames;
798   int w = frame->info.width, h = frame->info.height;
799   int xreset = -(w / 2) - v->xoffset;   /* starting values for x^2 and y^2, centering the ellipse */
800   int yreset = -(h / 2) - v->yoffset;
801
802   int x, y;
803   int accum_kx;
804   int accum_kxt;
805   int accum_ky;
806   int accum_kyt;
807   int accum_kxy;
808   int kt;
809   int kt2;
810   int ky2;
811   int delta_kxt = v->kxt * t;
812   int delta_kxy;
813   int scale_kxy = 0xffff / (w / 2);
814   int scale_kx2 = 0xffff / w;
815
816   videotestsrc_setup_paintinfo (v, p, w, h);
817
818   color = p->colors[COLOR_BLACK];
819   p->color = &color;
820
821   /* Zoneplate equation:
822    *
823    * phase = k0 + kx*x + ky*y + kt*t
824    *       + kxt*x*t + kyt*y*t + kxy*x*y
825    *       + kx2*x*x + ky2*y*y + Kt2*t*t
826    */
827
828 #if 0
829   for (j = 0, y = yreset; j < h; j++, y++) {
830     for (i = 0, x = xreset; i < w; i++, x++) {
831
832       /* zero order */
833       int phase = v->k0;
834
835       /* first order */
836       phase = phase + (v->kx * i) + (v->ky * j) + (v->kt * t);
837
838       /* cross term */
839       /* phase = phase + (v->kxt * i * t) + (v->kyt * j * t); */
840       /* phase = phase + (v->kxy * x * y) / (w/2); */
841
842       /*second order */
843       /*normalise x/y terms to rate of change of phase at the picture edge */
844       phase =
845           phase + ((v->kx2 * x * x) / w) + ((v->ky2 * y * y) / h) +
846           ((v->kt2 * t * t) >> 1);
847
848       color.Y = sine_table[phase & 0xff];
849
850       color.R = color.Y;
851       color.G = color.Y;
852       color.B = color.Y;
853       p->paint_tmpline (p, i, 1);
854     }
855   }
856 #endif
857
858   /* optimised version, with original code shown in comments */
859   accum_ky = 0;
860   accum_kyt = 0;
861   kt = v->kt * t;
862   kt2 = v->kt2 * t * t;
863   for (j = 0, y = yreset; j < h; j++, y++) {
864     accum_kx = 0;
865     accum_kxt = 0;
866     accum_ky += v->ky;
867     accum_kyt += v->kyt * t;
868     delta_kxy = v->kxy * y * scale_kxy;
869     accum_kxy = delta_kxy * xreset;
870     ky2 = (v->ky2 * y * y) / h;
871     for (i = 0, x = xreset; i < w; i++, x++) {
872
873       /* zero order */
874       int phase = v->k0;
875
876       /* first order */
877       accum_kx += v->kx;
878       /* phase = phase + (v->kx * i) + (v->ky * j) + (v->kt * t); */
879       phase = phase + accum_kx + accum_ky + kt;
880
881       /* cross term */
882       accum_kxt += delta_kxt;
883       accum_kxy += delta_kxy;
884       /* phase = phase + (v->kxt * i * t) + (v->kyt * j * t); */
885       phase = phase + accum_kxt + accum_kyt;
886
887       /* phase = phase + (v->kxy * x * y) / (w/2); */
888       /* phase = phase + accum_kxy / (w/2); */
889       phase = phase + (accum_kxy >> 16);
890
891       /*second order */
892       /*normalise x/y terms to rate of change of phase at the picture edge */
893       /*phase = phase + ((v->kx2 * x * x)/w) + ((v->ky2 * y * y)/h) + ((v->kt2 * t * t)>>1); */
894       phase = phase + ((v->kx2 * x * x * scale_kx2) >> 16) + ky2 + (kt2 >> 1);
895
896       p->tmpline_u8[i] = sine_table[phase & 0xff];
897     }
898     videotestsrc_blend_line (v, p->tmpline, p->tmpline_u8,
899         &p->foreground_color, &p->background_color, 0, w);
900     videotestsrc_convert_tmpline (p, frame, j);
901   }
902 }
903
904 void
905 gst_video_test_src_chromazoneplate (GstVideoTestSrc * v, GstClockTime pts,
906     GstVideoFrame * frame)
907 {
908   int i;
909   int j;
910   paintinfo pi = PAINT_INFO_INIT;
911   paintinfo *p = &pi;
912   struct vts_color_struct color;
913   int t = v->n_frames;
914   int w = frame->info.width, h = frame->info.height;
915
916   int xreset = -(w / 2) - v->xoffset;   /* starting values for x^2 and y^2, centering the ellipse */
917   int yreset = -(h / 2) - v->yoffset;
918
919   int x, y;
920   int accum_kx;
921   int accum_kxt;
922   int accum_ky;
923   int accum_kyt;
924   int accum_kxy;
925   int kt;
926   int kt2;
927   int ky2;
928   int delta_kxt = v->kxt * t;
929   int delta_kxy;
930   int scale_kxy = 0xffff / (w / 2);
931   int scale_kx2 = 0xffff / w;
932
933   videotestsrc_setup_paintinfo (v, p, w, h);
934
935   color = p->colors[COLOR_BLACK];
936   p->color = &color;
937
938   /* Zoneplate equation:
939    *
940    * phase = k0 + kx*x + ky*y + kt*t
941    *       + kxt*x*t + kyt*y*t + kxy*x*y
942    *       + kx2*x*x + ky2*y*y + Kt2*t*t
943    */
944
945   /* optimised version, with original code shown in comments */
946   accum_ky = 0;
947   accum_kyt = 0;
948   kt = v->kt * t;
949   kt2 = v->kt2 * t * t;
950   for (j = 0, y = yreset; j < h; j++, y++) {
951     accum_kx = 0;
952     accum_kxt = 0;
953     accum_ky += v->ky;
954     accum_kyt += v->kyt * t;
955     delta_kxy = v->kxy * y * scale_kxy;
956     accum_kxy = delta_kxy * xreset;
957     ky2 = (v->ky2 * y * y) / h;
958     for (i = 0, x = xreset; i < w; i++, x++) {
959
960       /* zero order */
961       int phase = v->k0;
962
963       /* first order */
964       accum_kx += v->kx;
965       /* phase = phase + (v->kx * i) + (v->ky * j) + (v->kt * t); */
966       phase = phase + accum_kx + accum_ky + kt;
967
968       /* cross term */
969       accum_kxt += delta_kxt;
970       accum_kxy += delta_kxy;
971       /* phase = phase + (v->kxt * i * t) + (v->kyt * j * t); */
972       phase = phase + accum_kxt + accum_kyt;
973
974       /* phase = phase + (v->kxy * x * y) / (w/2); */
975       /* phase = phase + accum_kxy / (w/2); */
976       phase = phase + (accum_kxy >> 16);
977
978       /*second order */
979       /*normalise x/y terms to rate of change of phase at the picture edge */
980       /*phase = phase + ((v->kx2 * x * x)/w) + ((v->ky2 * y * y)/h) + ((v->kt2 * t * t)>>1); */
981       phase = phase + ((v->kx2 * x * x * scale_kx2) >> 16) + ky2 + (kt2 >> 1);
982
983       color.Y = 128;
984       color.U = sine_table[phase & 0xff];
985       color.V = sine_table[phase & 0xff];
986
987       color.R = 128;
988       color.G = 128;
989       color.B = color.V;
990
991       color.gray = color.Y << 8;
992       p->paint_tmpline (p, i, 1);
993     }
994     videotestsrc_convert_tmpline (p, frame, j);
995   }
996 }
997
998 #undef SCALE_AMPLITUDE
999 void
1000 gst_video_test_src_circular (GstVideoTestSrc * v, GstClockTime pts,
1001     GstVideoFrame * frame)
1002 {
1003   int i;
1004   int j;
1005   paintinfo pi = PAINT_INFO_INIT;
1006   paintinfo *p = &pi;
1007   double freq[8];
1008   int w = frame->info.width, h = frame->info.height;
1009
1010   int d;
1011
1012   videotestsrc_setup_paintinfo (v, p, w, h);
1013
1014   for (i = 1; i < 8; i++) {
1015     freq[i] = 200 * pow (2.0, -(i - 1) / 4.0);
1016   }
1017
1018   for (j = 0; j < h; j++) {
1019     for (i = 0; i < w; i++) {
1020       double dist;
1021       int seg;
1022
1023       dist =
1024           sqrt ((2 * i - w) * (2 * i - w) + (2 * j - h) * (2 * j -
1025               h)) / (2 * w);
1026       seg = floor (dist * 16);
1027       if (seg == 0 || seg >= 8) {
1028         p->tmpline_u8[i] = 0;
1029       } else {
1030         d = floor (256 * dist * freq[seg] + 0.5);
1031         p->tmpline_u8[i] = sine_table[d & 0xff];
1032       }
1033     }
1034     videotestsrc_blend_line (v, p->tmpline, p->tmpline_u8,
1035         &p->foreground_color, &p->background_color, 0, w);
1036     videotestsrc_convert_tmpline (p, frame, j);
1037   }
1038 }
1039
1040 void
1041 gst_video_test_src_gamut (GstVideoTestSrc * v, GstClockTime pts,
1042     GstVideoFrame * frame)
1043 {
1044   int x, y;
1045   paintinfo pi = PAINT_INFO_INIT;
1046   paintinfo *p = &pi;
1047   struct vts_color_struct yuv_primary;
1048   struct vts_color_struct yuv_secondary;
1049   int w = frame->info.width, h = frame->info.height;
1050
1051   videotestsrc_setup_paintinfo (v, p, w, h);
1052
1053   for (y = 0; y < h; y++) {
1054     int region = (y * 4) / h;
1055
1056     switch (region) {
1057       case 0:                  /* black */
1058         yuv_primary = p->colors[COLOR_BLACK];
1059         yuv_secondary = p->colors[COLOR_BLACK];
1060         yuv_secondary.Y = 0;
1061         break;
1062       case 1:
1063         yuv_primary = p->colors[COLOR_WHITE];
1064         yuv_secondary = p->colors[COLOR_WHITE];
1065         yuv_secondary.Y = 255;
1066         break;
1067       case 2:
1068         yuv_primary = p->colors[COLOR_RED];
1069         yuv_secondary = p->colors[COLOR_RED];
1070         yuv_secondary.V = 255;
1071         break;
1072       case 3:
1073         yuv_primary = p->colors[COLOR_BLUE];
1074         yuv_secondary = p->colors[COLOR_BLUE];
1075         yuv_secondary.U = 255;
1076         break;
1077     }
1078
1079     for (x = 0; x < w; x += 8) {
1080       int len = MIN (8, w - x);
1081
1082       if ((x ^ y) & (1 << 4)) {
1083         p->color = &yuv_primary;
1084       } else {
1085         p->color = &yuv_secondary;
1086       }
1087       p->paint_tmpline (p, x, len);
1088     }
1089     videotestsrc_convert_tmpline (p, frame, y);
1090   }
1091 }
1092
1093 void
1094 gst_video_test_src_ball (GstVideoTestSrc * v, GstClockTime pts,
1095     GstVideoFrame * frame)
1096 {
1097   int i;
1098   int radius = 20;
1099   int w = frame->info.width, h = frame->info.height;
1100   gint64 wall_time;
1101   gdouble rad = 0;
1102   double x, y;
1103   int flipit = 0;
1104
1105   paintinfo pi = PAINT_INFO_INIT;
1106   paintinfo *p = &pi;
1107
1108   struct vts_color_struct
1109       *foreground_color = &p->foreground_color,
1110       *background_color = &p->background_color;
1111
1112   switch (v->animation_mode) {
1113     case GST_VIDEO_TEST_SRC_FRAMES:
1114       rad = (gdouble) (v->n_frames) / 200;
1115       flipit = (v->n_frames / 50) % 2;
1116       break;
1117     case GST_VIDEO_TEST_SRC_WALL_TIME:
1118       wall_time = g_get_real_time ();
1119
1120       rad = (gdouble) wall_time / 1000000.0;
1121       flipit = (wall_time / 1000000) % 2;
1122       break;
1123     case GST_VIDEO_TEST_SRC_RUNNING_TIME:
1124       rad = (gdouble) (pts) / GST_SECOND;
1125       flipit = (pts / GST_SECOND) % 2;
1126       break;
1127   }
1128   if (v->motion_type == GST_VIDEO_TEST_SRC_HSWEEP) {
1129     /* Periodic reset for half sweep */
1130     rad /= 2;
1131     rad -= floor (2 * rad) / 2;
1132   }
1133
1134   /* Scale for the animation calcs */
1135   rad = 2 * G_PI * rad;
1136
1137   if (v->motion_type == GST_VIDEO_TEST_SRC_WAVY) {
1138     x = radius + (0.5 + 0.5 * sin (rad)) * (w - 2 * radius);
1139     y = radius + (0.5 + 0.5 * sin (rad * sqrt (2))) * (h - 2 * radius);
1140   } else {
1141     /* sweep and hsweep */
1142     /* x,y is center of circle,
1143      * radius is radius
1144      * rad = angle .. of sweep.
1145      */
1146
1147     radius = MIN (h, w) / 4 - 0;
1148
1149     /* 0 is the margin between edge of screen and top of ball */
1150     x = w / 2 + sin (rad) * radius;
1151     y = h / 2 - cos (rad) * radius;
1152   }
1153
1154   if (v->flip && flipit) {
1155     foreground_color = &p->background_color;
1156     background_color = &p->foreground_color;
1157   }
1158
1159   /* draw ball on frame */
1160   videotestsrc_setup_paintinfo (v, p, w, h);
1161   for (i = 0; i < h; i++) {
1162     if (i < y - radius || i > y + radius) {
1163       memset (p->tmpline_u8, 0, w);
1164     } else {
1165       double o = MAX (0, (radius * radius - (i - y) * (i - y)));
1166       int r = rint (sqrt (o));
1167       int x1, x2;
1168       int j;
1169
1170       x1 = 0;
1171       x2 = MAX (0, x - r);
1172       for (j = x1; j < x2; j++) {
1173         p->tmpline_u8[j] = 0;
1174       }
1175
1176       x1 = MAX (0, x - r);
1177       x2 = MIN (w, x + r + 1);
1178       for (j = x1; j < x2; j++) {
1179         double rr = radius - sqrt ((j - x) * (j - x) + (i - y) * (i - y));
1180
1181         rr *= 0.5;
1182         p->tmpline_u8[j] = CLAMP ((int) floor (256 * rr), 0, 255);
1183       }
1184
1185       x1 = MIN (w, x + r + 1);
1186       x2 = w;
1187       for (j = x1; j < x2; j++) {
1188         p->tmpline_u8[j] = 0;
1189       }
1190     }
1191
1192     if ((v->motion_type == GST_VIDEO_TEST_SRC_SWEEP) ||
1193         (v->motion_type == GST_VIDEO_TEST_SRC_HSWEEP)) {
1194       /* dot in the middle (to draw a line down the center) */
1195       p->tmpline_u8[w / 2] = 255;
1196       p->tmpline_u8[(int) x] = 255;
1197     }
1198
1199     videotestsrc_blend_line (v, p->tmpline, p->tmpline_u8,
1200         foreground_color, background_color, 0, w);
1201     videotestsrc_convert_tmpline (p, frame, i);
1202   }
1203
1204   if ((v->motion_type == GST_VIDEO_TEST_SRC_SWEEP) ||
1205       (v->motion_type == GST_VIDEO_TEST_SRC_HSWEEP)) {
1206     /* draw a line across the middle of frame and ball. */
1207     for (i = 0; i < w; i++) {
1208       p->tmpline_u8[i] = 255;
1209     }
1210     videotestsrc_blend_line (v, p->tmpline, p->tmpline_u8,
1211         foreground_color, background_color, 0, w);
1212     videotestsrc_convert_tmpline (p, frame, h / 2);
1213     videotestsrc_convert_tmpline (p, frame, y);
1214   }
1215 }
1216
1217 static void
1218 paint_tmpline_ARGB (paintinfo * p, int x, int w)
1219 {
1220   int offset;
1221   guint32 value;
1222
1223 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1224   value = (p->color->A << 0) | (p->color->R << 8) |
1225       (p->color->G << 16) | ((guint32) p->color->B << 24);
1226 #else
1227   value = ((guint32) p->color->A << 24) | (p->color->R << 16) |
1228       (p->color->G << 8) | (p->color->B << 0);
1229 #endif
1230
1231   offset = (x * 4);
1232   video_test_src_orc_splat_u32 (p->tmpline + offset, value, w);
1233 }
1234
1235 static void
1236 paint_tmpline_AYUV (paintinfo * p, int x, int w)
1237 {
1238   int offset;
1239   guint32 value;
1240
1241 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1242   value = (p->color->A << 0) | (p->color->Y << 8) |
1243       (p->color->U << 16) | ((guint32) p->color->V << 24);
1244 #else
1245   value = ((guint32) p->color->A << 24) | (p->color->Y << 16) |
1246       (p->color->U << 8) | (p->color->V << 0);
1247 #endif
1248
1249   offset = (x * 4);
1250   video_test_src_orc_splat_u32 (p->tmpline + offset, value, w);
1251 }
1252
1253 static void
1254 convert_hline_generic (paintinfo * p, GstVideoFrame * frame, int y)
1255 {
1256   const GstVideoFormatInfo *finfo, *uinfo;
1257   gint line, offset, i, width, height, bits;
1258   guint n_lines;
1259   gpointer dest;
1260
1261   finfo = frame->info.finfo;
1262   uinfo = gst_video_format_get_info (finfo->unpack_format);
1263
1264   width = GST_VIDEO_FRAME_WIDTH (frame);
1265   height = GST_VIDEO_FRAME_HEIGHT (frame);
1266
1267   bits = GST_VIDEO_FORMAT_INFO_DEPTH (uinfo, 0);
1268
1269   n_lines = p->n_lines;
1270   offset = p->offset;
1271   line = y % n_lines;
1272   dest = p->lines[line];
1273
1274   if (bits == 16) {
1275     /* 16 bits */
1276     for (i = 0; i < width; i++) {
1277       p->tmpline_u16[i * 4 + 0] = TO_16 (p->tmpline[i * 4 + 0]);
1278       p->tmpline_u16[i * 4 + 1] = TO_16 (p->tmpline[i * 4 + 1]);
1279       p->tmpline_u16[i * 4 + 2] = TO_16 (p->tmpline[i * 4 + 2]);
1280       p->tmpline_u16[i * 4 + 3] = TO_16 (p->tmpline[i * 4 + 3]);
1281     }
1282     memcpy (dest, p->tmpline_u16, width * 8);
1283   } else {
1284     memcpy (dest, p->tmpline, width * 4);
1285   }
1286
1287   if (line - offset == n_lines - 1) {
1288     gpointer lines[8];
1289     guint idx;
1290
1291     y -= n_lines - 1;
1292
1293     for (i = 0; i < n_lines; i++) {
1294       idx = CLAMP (y + i + offset, 0, height - 1);
1295       lines[i] = p->lines[idx % n_lines];
1296     }
1297
1298     if (p->subsample)
1299       gst_video_chroma_resample (p->subsample, lines, width);
1300
1301     for (i = 0; i < n_lines; i++) {
1302       idx = y + i + offset;
1303       if (idx > height - 1)
1304         break;
1305       finfo->pack_func (finfo, GST_VIDEO_PACK_FLAG_NONE,
1306           lines[i], 0, frame->data, frame->info.stride,
1307           frame->info.chroma_site, idx, width);
1308     }
1309   }
1310 }
1311
1312 static void
1313 convert_hline_bayer (paintinfo * p, GstVideoFrame * frame, int y)
1314 {
1315   int i;
1316   guint8 *data = GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
1317   guint8 *R = data + y * GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0);
1318   guint8 *argb = p->tmpline;
1319   gint width = GST_VIDEO_FRAME_WIDTH (frame);
1320   int x_inv = p->x_invert;
1321   int y_inv = p->y_invert;
1322
1323   if ((y ^ y_inv) & 1) {
1324     for (i = 0; i < width; i++) {
1325       if ((i ^ x_inv) & 1) {
1326         R[i] = argb[4 * i + 1];
1327       } else {
1328         R[i] = argb[4 * i + 2];
1329       }
1330     }
1331   } else {
1332     for (i = 0; i < width; i++) {
1333       if ((i ^ x_inv) & 1) {
1334         R[i] = argb[4 * i + 2];
1335       } else {
1336         R[i] = argb[4 * i + 3];
1337       }
1338     }
1339   }
1340 }
1341
1342 void
1343 gst_video_test_src_pinwheel (GstVideoTestSrc * v, GstClockTime pts,
1344     GstVideoFrame * frame)
1345 {
1346   int i;
1347   int j;
1348   int k;
1349   int t = v->n_frames;
1350   paintinfo pi = PAINT_INFO_INIT;
1351   paintinfo *p = &pi;
1352   struct vts_color_struct color;
1353   int w = frame->info.width, h = frame->info.height;
1354   double c[20];
1355   double s[20];
1356
1357   videotestsrc_setup_paintinfo (v, p, w, h);
1358
1359   color = p->colors[COLOR_BLACK];
1360   p->color = &color;
1361
1362   for (k = 0; k < 19; k++) {
1363     double theta = M_PI / 19 * k + 0.001 * v->kt * t;
1364     c[k] = cos (theta);
1365     s[k] = sin (theta);
1366   }
1367
1368   for (j = 0; j < h; j++) {
1369     for (i = 0; i < w; i++) {
1370       double v;
1371       v = 0;
1372       for (k = 0; k < 19; k++) {
1373         double x, y;
1374
1375         x = c[k] * (i - 0.5 * w) + s[k] * (j - 0.5 * h);
1376         x *= 1.0;
1377
1378         y = CLAMP (x, -1, 1);
1379         if (k & 1)
1380           y = -y;
1381
1382         v += y;
1383       }
1384
1385       p->tmpline_u8[i] = CLAMP (rint (v * 128 + 128), 0, 255);
1386     }
1387     videotestsrc_blend_line (v, p->tmpline, p->tmpline_u8,
1388         &p->foreground_color, &p->background_color, 0, w);
1389     videotestsrc_convert_tmpline (p, frame, j);
1390   }
1391 }
1392
1393 void
1394 gst_video_test_src_spokes (GstVideoTestSrc * v, GstClockTime pts,
1395     GstVideoFrame * frame)
1396 {
1397   int i;
1398   int j;
1399   int k;
1400   int t = v->n_frames;
1401   paintinfo pi = PAINT_INFO_INIT;
1402   paintinfo *p = &pi;
1403   struct vts_color_struct color;
1404   int w = frame->info.width, h = frame->info.height;
1405   double c[20];
1406   double s[20];
1407
1408   videotestsrc_setup_paintinfo (v, p, w, h);
1409
1410   color = p->colors[COLOR_BLACK];
1411   p->color = &color;
1412
1413   for (k = 0; k < 19; k++) {
1414     double theta = M_PI / 19 * k + 0.001 * v->kt * t;
1415     c[k] = cos (theta);
1416     s[k] = sin (theta);
1417   }
1418
1419   for (j = 0; j < h; j++) {
1420     for (i = 0; i < w; i++) {
1421       double v;
1422       v = 0;
1423       for (k = 0; k < 19; k++) {
1424         double x, y;
1425         double sharpness = 1.0;
1426         double linewidth = 2.0;
1427
1428         x = c[k] * (i - 0.5 * w) + s[k] * (j - 0.5 * h);
1429         x = linewidth * 0.5 - fabs (x);
1430         x *= sharpness;
1431
1432         y = CLAMP (x + 0.5, 0.0, 1.0);
1433
1434         v += y;
1435       }
1436
1437       p->tmpline_u8[i] = CLAMP (rint (v * 255), 0, 255);
1438     }
1439     videotestsrc_blend_line (v, p->tmpline, p->tmpline_u8,
1440         &p->foreground_color, &p->background_color, 0, w);
1441     videotestsrc_convert_tmpline (p, frame, j);
1442   }
1443 }
1444
1445 void
1446 gst_video_test_src_gradient (GstVideoTestSrc * v, GstClockTime pts,
1447     GstVideoFrame * frame)
1448 {
1449   int i;
1450   int j;
1451   paintinfo pi = PAINT_INFO_INIT;
1452   paintinfo *p = &pi;
1453   struct vts_color_struct color;
1454   int w = frame->info.width, h = frame->info.height;
1455
1456   videotestsrc_setup_paintinfo (v, p, w, h);
1457
1458   color = p->colors[COLOR_BLACK];
1459   p->color = &color;
1460
1461   for (j = 0; j < h; j++) {
1462     int y = j * 255.0 / h;
1463     for (i = 0; i < w; i++) {
1464       p->tmpline_u8[i] = y;
1465     }
1466     videotestsrc_blend_line (v, p->tmpline, p->tmpline_u8,
1467         &p->foreground_color, &p->background_color, 0, w);
1468     videotestsrc_convert_tmpline (p, frame, j);
1469   }
1470 }
1471
1472 void
1473 gst_video_test_src_colors (GstVideoTestSrc * v, GstClockTime pts,
1474     GstVideoFrame * frame)
1475 {
1476   int i;
1477   int j;
1478   paintinfo pi = PAINT_INFO_INIT;
1479   paintinfo *p = &pi;
1480   struct vts_color_struct color;
1481   int w = frame->info.width, h = frame->info.height;
1482
1483   videotestsrc_setup_paintinfo (v, p, w, h);
1484
1485   color = p->colors[COLOR_BLACK];
1486   p->color = &color;
1487
1488   for (j = 0; j < h; j++) {
1489     for (i = 0; i < w; i++) {
1490       p->tmpline[i * 4 + 0] = 0xff;
1491       p->tmpline[i * 4 + 1] = ((i * 4096) / w) % 256;
1492       p->tmpline[i * 4 + 2] = (((j * 16) / h) << 4) | ((i * 16) / w);
1493       p->tmpline[i * 4 + 3] = ((j * 4096) / h) % 256;
1494     }
1495     videotestsrc_convert_tmpline (p, frame, j);
1496   }
1497 }