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