4cec2b142c73290c35a4d5ce3116cafbc51d119e
[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., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, 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 (void)
39 {
40   static unsigned int state;
41
42   state *= 1103515245;
43   state += 12345;
44   return (state >> 16) & 0xff;
45 }
46
47 enum
48 {
49   COLOR_WHITE = 0,
50   COLOR_YELLOW,
51   COLOR_CYAN,
52   COLOR_GREEN,
53   COLOR_MAGENTA,
54   COLOR_RED,
55   COLOR_BLUE,
56   COLOR_BLACK,
57   COLOR_NEG_I,
58   COLOR_POS_Q,
59   COLOR_SUPER_BLACK,
60   COLOR_DARK_GREY
61 };
62
63 static const struct vts_color_struct vts_colors_bt709_ycbcr_100[] = {
64   {235, 128, 128, 255, 255, 255, 255, (235 << 8)},
65   {219, 16, 138, 255, 255, 255, 0, (219 << 8)},
66   {188, 154, 16, 255, 0, 255, 255, (188 < 8)},
67   {173, 42, 26, 255, 0, 255, 0, (173 << 8)},
68   {78, 214, 230, 255, 255, 0, 255, (78 << 8)},
69   {63, 102, 240, 255, 255, 0, 0, (64 << 8)},
70   {32, 240, 118, 255, 0, 0, 255, (32 << 8)},
71   {16, 128, 128, 255, 0, 0, 0, (16 << 8)},
72   {16, 198, 21, 255, 0, 0, 128, (16 << 8)},     /* -I ? */
73   {16, 235, 198, 255, 0, 128, 255, (16 << 8)},  /* +Q ? */
74   {0, 128, 128, 255, 0, 0, 0, 0},
75   {32, 128, 128, 255, 19, 19, 19, (32 << 8)},
76 };
77
78 static const struct vts_color_struct vts_colors_bt709_ycbcr_75[] = {
79   {180, 128, 128, 255, 191, 191, 191, (180 << 8)},
80   {168, 44, 136, 255, 191, 191, 0, (168 << 8)},
81   {145, 147, 44, 255, 0, 191, 191, (145 << 8)},
82   {133, 63, 52, 255, 0, 191, 0, (133 << 8)},
83   {63, 193, 204, 255, 191, 0, 191, (63 << 8)},
84   {51, 109, 212, 255, 191, 0, 0, (51 << 8)},
85   {28, 212, 120, 255, 0, 0, 191, (28 << 8)},
86   {16, 128, 128, 255, 0, 0, 0, (16 << 8)},
87   {16, 198, 21, 255, 0, 0, 128, (16 << 8)},     /* -I ? */
88   {16, 235, 198, 255, 0, 128, 255, (16 << 8)},  /* +Q ? */
89   {0, 128, 128, 255, 0, 0, 0, 0},
90   {32, 128, 128, 255, 19, 19, 19, (32 << 8)},
91 };
92
93 static const struct vts_color_struct vts_colors_bt601_ycbcr_100[] = {
94   {235, 128, 128, 255, 255, 255, 255, (235 << 8)},
95   {210, 16, 146, 255, 255, 255, 0, (219 << 8)},
96   {170, 166, 16, 255, 0, 255, 255, (188 < 8)},
97   {145, 54, 34, 255, 0, 255, 0, (173 << 8)},
98   {106, 202, 222, 255, 255, 0, 255, (78 << 8)},
99   {81, 90, 240, 255, 255, 0, 0, (64 << 8)},
100   {41, 240, 110, 255, 0, 0, 255, (32 << 8)},
101   {16, 128, 128, 255, 0, 0, 0, (16 << 8)},
102   {16, 198, 21, 255, 0, 0, 128, (16 << 8)},     /* -I ? */
103   {16, 235, 198, 255, 0, 128, 255, (16 << 8)},  /* +Q ? */
104   {-0, 128, 128, 255, 0, 0, 0, 0},
105   {32, 128, 128, 255, 19, 19, 19, (32 << 8)},
106 };
107
108 static const struct vts_color_struct vts_colors_bt601_ycbcr_75[] = {
109   {180, 128, 128, 255, 191, 191, 191, (180 << 8)},
110   {162, 44, 142, 255, 191, 191, 0, (168 << 8)},
111   {131, 156, 44, 255, 0, 191, 191, (145 << 8)},
112   {112, 72, 58, 255, 0, 191, 0, (133 << 8)},
113   {84, 184, 198, 255, 191, 0, 191, (63 << 8)},
114   {65, 100, 212, 255, 191, 0, 0, (51 << 8)},
115   {35, 212, 114, 255, 0, 0, 191, (28 << 8)},
116   {16, 128, 128, 255, 0, 0, 0, (16 << 8)},
117   {16, 198, 21, 255, 0, 0, 128, (16 << 8)},     /* -I ? */
118   {16, 235, 198, 255, 0, 128, 255, (16 << 8)},  /* +Q ? */
119   {-0, 128, 128, 255, 0, 0, 0, 0},
120   {32, 128, 128, 255, 19, 19, 19, (32 << 8)},
121 };
122
123
124 static void paint_tmpline_ARGB (paintinfo * p, int x, int w);
125 static void paint_tmpline_AYUV (paintinfo * p, int x, int w);
126
127 static void convert_hline_generic (paintinfo * p, GstVideoFrame * frame, int y);
128 static void convert_hline_bayer (paintinfo * p, GstVideoFrame * frame, int y);
129
130 #define SCALEBITS 10
131 #define ONE_HALF  (1 << (SCALEBITS - 1))
132 #define FIX(x)    ((int) ((x) * (1<<SCALEBITS) + 0.5))
133
134 #define RGB_TO_Y(r, g, b) \
135 ((FIX(0.29900) * (r) + FIX(0.58700) * (g) + \
136   FIX(0.11400) * (b) + ONE_HALF) >> SCALEBITS)
137
138 #define RGB_TO_U(r1, g1, b1, shift)\
139 (((- FIX(0.16874) * r1 - FIX(0.33126) * g1 +         \
140      FIX(0.50000) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
141
142 #define RGB_TO_V(r1, g1, b1, shift)\
143 (((FIX(0.50000) * r1 - FIX(0.41869) * g1 -           \
144    FIX(0.08131) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
145
146 #define RGB_TO_Y_CCIR(r, g, b) \
147 ((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \
148   FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
149
150 #define RGB_TO_U_CCIR(r1, g1, b1, shift)\
151 (((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 +         \
152      FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
153
154 #define RGB_TO_V_CCIR(r1, g1, b1, shift)\
155 (((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 -           \
156    FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
157
158 #define RGB_TO_Y_CCIR_709(r, g, b) \
159 ((FIX(0.212600*219.0/255.0) * (r) + FIX(0.715200*219.0/255.0) * (g) + \
160   FIX(0.072200*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
161
162 #define RGB_TO_U_CCIR_709(r1, g1, b1, shift)\
163 (((- FIX(0.114572*224.0/255.0) * r1 - FIX(0.385427*224.0/255.0) * g1 +         \
164      FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
165
166 #define RGB_TO_V_CCIR_709(r1, g1, b1, shift)\
167 (((FIX(0.50000*224.0/255.0) * r1 - FIX(0.454153*224.0/255.0) * g1 -           \
168    FIX(0.045847*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
169
170 static void
171 videotestsrc_setup_paintinfo (GstVideoTestSrc * v, paintinfo * p, int w, int h)
172 {
173   gint a, r, g, b;
174   gint width;
175   GstVideoInfo *info = &v->info;
176
177   width = GST_VIDEO_INFO_WIDTH (info);
178
179   if (info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT601) {
180     p->colors = vts_colors_bt601_ycbcr_100;
181   } else {
182     p->colors = vts_colors_bt709_ycbcr_100;
183   }
184
185   if (v->bayer) {
186     p->paint_tmpline = paint_tmpline_ARGB;
187     p->convert_tmpline = convert_hline_bayer;
188   } else {
189     p->convert_tmpline = convert_hline_generic;
190     if (GST_VIDEO_INFO_IS_RGB (info)) {
191       p->paint_tmpline = paint_tmpline_ARGB;
192     } else {
193       p->paint_tmpline = paint_tmpline_AYUV;
194     }
195   }
196   p->tmpline = v->tmpline;
197   p->tmpline2 = v->tmpline2;
198   p->tmpline_u8 = v->tmpline_u8;
199   p->tmpline_u16 = v->tmpline_u16;
200   p->x_offset = (v->horizontal_speed * v->n_frames) % width;
201   if (p->x_offset < 0)
202     p->x_offset += width;
203   p->x_invert = v->x_invert;
204   p->y_invert = v->y_invert;
205
206   a = (v->foreground_color >> 24) & 0xff;
207   r = (v->foreground_color >> 16) & 0xff;
208   g = (v->foreground_color >> 8) & 0xff;
209   b = (v->foreground_color >> 0) & 0xff;
210   p->foreground_color.A = a;
211   p->foreground_color.R = r;
212   p->foreground_color.G = g;
213   p->foreground_color.B = b;
214
215   if (info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT601) {
216     p->foreground_color.Y = RGB_TO_Y_CCIR (r, g, b);
217     p->foreground_color.U = RGB_TO_U_CCIR (r, g, b, 0);
218     p->foreground_color.V = RGB_TO_V_CCIR (r, g, b, 0);
219   } else {
220     p->foreground_color.Y = RGB_TO_Y_CCIR_709 (r, g, b);
221     p->foreground_color.U = RGB_TO_U_CCIR_709 (r, g, b, 0);
222     p->foreground_color.V = RGB_TO_V_CCIR_709 (r, g, b, 0);
223   }
224   p->foreground_color.gray = RGB_TO_Y (r, g, b);
225
226   a = (v->background_color >> 24) & 0xff;
227   r = (v->background_color >> 16) & 0xff;
228   g = (v->background_color >> 8) & 0xff;
229   b = (v->background_color >> 0) & 0xff;
230   p->background_color.A = a;
231   p->background_color.R = r;
232   p->background_color.G = g;
233   p->background_color.B = b;
234
235   if (info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT601) {
236     p->background_color.Y = RGB_TO_Y_CCIR (r, g, b);
237     p->background_color.U = RGB_TO_U_CCIR (r, g, b, 0);
238     p->background_color.V = RGB_TO_V_CCIR (r, g, b, 0);
239   } else {
240     p->background_color.Y = RGB_TO_Y_CCIR_709 (r, g, b);
241     p->background_color.U = RGB_TO_U_CCIR_709 (r, g, b, 0);
242     p->background_color.V = RGB_TO_V_CCIR_709 (r, g, b, 0);
243   }
244   p->background_color.gray = RGB_TO_Y (r, g, b);
245
246 }
247
248 static void
249 videotestsrc_convert_tmpline (paintinfo * p, GstVideoFrame * frame, int j)
250 {
251   int x = p->x_offset;
252   int i;
253   int width = frame->info.width;
254
255   if (x != 0) {
256     memcpy (p->tmpline2, p->tmpline, width * 4);
257     memcpy (p->tmpline, p->tmpline2 + x * 4, (width - x) * 4);
258     memcpy (p->tmpline + (width - x) * 4, p->tmpline2, x * 4);
259   }
260
261   for (i = width; i < width + 5; i++) {
262     p->tmpline[4 * i + 0] = p->tmpline[4 * (width - 1) + 0];
263     p->tmpline[4 * i + 1] = p->tmpline[4 * (width - 1) + 1];
264     p->tmpline[4 * i + 2] = p->tmpline[4 * (width - 1) + 2];
265     p->tmpline[4 * i + 3] = p->tmpline[4 * (width - 1) + 3];
266   }
267
268   p->convert_tmpline (p, frame, j);
269 }
270
271 #define BLEND1(a,b,x) ((a)*(x) + (b)*(255-(x)))
272 #define DIV255(x) (((x) + (((x)+128)>>8) + 128)>>8)
273 #define BLEND(a,b,x) DIV255(BLEND1(a,b,x))
274
275 #ifdef unused
276 static void
277 videotestsrc_blend_color (struct vts_color_struct *dest,
278     struct vts_color_struct *a, struct vts_color_struct *b, int x)
279 {
280   dest->Y = BLEND (a->Y, b->Y, x);
281   dest->U = BLEND (a->U, b->U, x);
282   dest->V = BLEND (a->V, b->V, x);
283   dest->R = BLEND (a->R, b->R, x);
284   dest->G = BLEND (a->G, b->G, x);
285   dest->B = BLEND (a->B, b->B, x);
286   dest->gray = BLEND (a->gray, b->gray, x);
287
288 }
289 #endif
290
291 static void
292 videotestsrc_blend_line (GstVideoTestSrc * v, guint8 * dest, guint8 * src,
293     struct vts_color_struct *a, struct vts_color_struct *b, int n)
294 {
295   int i;
296   if (v->bayer || GST_VIDEO_INFO_IS_RGB (&v->info)) {
297     for (i = 0; i < n; i++) {
298       dest[i * 4 + 0] = BLEND (a->A, b->A, src[i]);
299       dest[i * 4 + 1] = BLEND (a->R, b->R, src[i]);
300       dest[i * 4 + 2] = BLEND (a->G, b->G, src[i]);
301       dest[i * 4 + 3] = BLEND (a->B, b->B, src[i]);
302     }
303   } else {
304     for (i = 0; i < n; i++) {
305       dest[i * 4 + 0] = BLEND (a->A, b->A, src[i]);
306       dest[i * 4 + 1] = BLEND (a->Y, b->Y, src[i]);
307       dest[i * 4 + 2] = BLEND (a->U, b->U, src[i]);
308       dest[i * 4 + 3] = BLEND (a->V, b->V, src[i]);
309     }
310   }
311 #undef BLEND
312 }
313
314 void
315 gst_video_test_src_smpte (GstVideoTestSrc * v, GstVideoFrame * frame)
316 {
317   int i;
318   int y1, y2;
319   int j;
320   paintinfo pi = PAINT_INFO_INIT;
321   paintinfo *p = &pi;
322   int w = frame->info.width, h = frame->info.height;
323
324   videotestsrc_setup_paintinfo (v, p, w, h);
325
326   y1 = 2 * h / 3;
327   y2 = 3 * h / 4;
328
329   /* color bars */
330   for (j = 0; j < y1; j++) {
331     for (i = 0; i < 7; i++) {
332       int x1 = i * w / 7;
333       int x2 = (i + 1) * w / 7;
334
335       p->color = p->colors + i;
336       p->paint_tmpline (p, x1, (x2 - x1));
337     }
338     videotestsrc_convert_tmpline (p, frame, j);
339   }
340
341   /* inverse blue bars */
342   for (j = y1; j < y2; j++) {
343     for (i = 0; i < 7; i++) {
344       int x1 = i * w / 7;
345       int x2 = (i + 1) * w / 7;
346       int k;
347
348       if (i & 1) {
349         k = 7;
350       } else {
351         k = 6 - i;
352       }
353       p->color = p->colors + k;
354       p->paint_tmpline (p, x1, (x2 - x1));
355     }
356     videotestsrc_convert_tmpline (p, frame, j);
357   }
358
359   for (j = y2; j < h; j++) {
360     /* -I, white, Q regions */
361     for (i = 0; i < 3; i++) {
362       int x1 = i * w / 6;
363       int x2 = (i + 1) * w / 6;
364       int k;
365
366       if (i == 0) {
367         k = 8;
368       } else if (i == 1) {
369         k = 0;
370       } else
371         k = 9;
372
373       p->color = p->colors + k;
374       p->paint_tmpline (p, x1, (x2 - x1));
375     }
376
377     /* superblack, black, dark grey */
378     for (i = 0; i < 3; i++) {
379       int x1 = w / 2 + i * w / 12;
380       int x2 = w / 2 + (i + 1) * w / 12;
381       int k;
382
383       if (i == 0) {
384         k = COLOR_SUPER_BLACK;
385       } else if (i == 1) {
386         k = COLOR_BLACK;
387       } else
388         k = COLOR_DARK_GREY;
389
390       p->color = p->colors + k;
391       p->paint_tmpline (p, x1, (x2 - x1));
392     }
393
394     {
395       int x1 = w * 3 / 4;
396       struct vts_color_struct color;
397
398       color = p->colors[COLOR_BLACK];
399       p->color = &color;
400
401       for (i = x1; i < w; i++) {
402         int y = random_char ();
403         p->tmpline_u8[i] = y;
404       }
405       videotestsrc_blend_line (v, p->tmpline + x1 * 4, p->tmpline_u8 + x1,
406           &p->foreground_color, &p->background_color, w - x1);
407
408     }
409     videotestsrc_convert_tmpline (p, frame, j);
410
411   }
412 }
413
414 void
415 gst_video_test_src_smpte75 (GstVideoTestSrc * v, GstVideoFrame * frame)
416 {
417   int i;
418   int j;
419   paintinfo pi = PAINT_INFO_INIT;
420   paintinfo *p = &pi;
421   int w = frame->info.width, h = frame->info.height;
422
423   videotestsrc_setup_paintinfo (v, p, w, h);
424   if (v->info.colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT601) {
425     p->colors = vts_colors_bt601_ycbcr_75;
426   } else {
427     p->colors = vts_colors_bt709_ycbcr_75;
428   }
429
430   /* color bars */
431   for (j = 0; j < h; j++) {
432     for (i = 0; i < 7; i++) {
433       int x1 = i * w / 7;
434       int x2 = (i + 1) * w / 7;
435
436       p->color = p->colors + i;
437       p->paint_tmpline (p, x1, (x2 - x1));
438     }
439     videotestsrc_convert_tmpline (p, frame, j);
440   }
441 }
442
443 void
444 gst_video_test_src_smpte100 (GstVideoTestSrc * v, GstVideoFrame * frame)
445 {
446   int i;
447   int j;
448   paintinfo pi = PAINT_INFO_INIT;
449   paintinfo *p = &pi;
450   int w = frame->info.width, h = frame->info.height;
451
452   videotestsrc_setup_paintinfo (v, p, w, h);
453
454   /* color bars */
455   for (j = 0; j < h; j++) {
456     for (i = 0; i < 7; i++) {
457       int x1 = i * w / 7;
458       int x2 = (i + 1) * w / 7;
459
460       p->color = p->colors + i;
461       p->paint_tmpline (p, x1, (x2 - x1));
462     }
463     videotestsrc_convert_tmpline (p, frame, j);
464   }
465 }
466
467 void
468 gst_video_test_src_bar (GstVideoTestSrc * v, GstVideoFrame * frame)
469 {
470   int j;
471   paintinfo pi = PAINT_INFO_INIT;
472   paintinfo *p = &pi;
473   int w = frame->info.width, h = frame->info.height;
474
475   videotestsrc_setup_paintinfo (v, p, w, h);
476
477   for (j = 0; j < h; j++) {
478     /* use fixed size for now */
479     int x2 = w / 7;
480
481     p->color = &p->foreground_color;
482     p->paint_tmpline (p, 0, x2);
483     p->color = &p->background_color;
484     p->paint_tmpline (p, x2, (w - x2));
485     videotestsrc_convert_tmpline (p, frame, j);
486   }
487 }
488
489 void
490 gst_video_test_src_snow (GstVideoTestSrc * v, GstVideoFrame * frame)
491 {
492   int i;
493   int j;
494   paintinfo pi = PAINT_INFO_INIT;
495   paintinfo *p = &pi;
496   struct vts_color_struct color;
497   int w = frame->info.width, h = frame->info.height;
498
499   videotestsrc_setup_paintinfo (v, p, w, h);
500
501   color = p->colors[COLOR_BLACK];
502   p->color = &color;
503
504   for (j = 0; j < h; j++) {
505     for (i = 0; i < w; i++) {
506       int y = random_char ();
507       p->tmpline_u8[i] = y;
508     }
509     videotestsrc_blend_line (v, p->tmpline, p->tmpline_u8,
510         &p->foreground_color, &p->background_color, w);
511     videotestsrc_convert_tmpline (p, frame, j);
512   }
513 }
514
515 static void
516 gst_video_test_src_unicolor (GstVideoTestSrc * v, GstVideoFrame * frame,
517     int color_index)
518 {
519   int i;
520   paintinfo pi = PAINT_INFO_INIT;
521   paintinfo *p = &pi;
522   int w = frame->info.width, h = frame->info.height;
523
524   videotestsrc_setup_paintinfo (v, p, w, h);
525
526   p->color = p->colors + color_index;
527   if (color_index == COLOR_BLACK) {
528     p->color = &p->background_color;
529   }
530   if (color_index == COLOR_WHITE) {
531     p->color = &p->foreground_color;
532   }
533
534   for (i = 0; i < h; i++) {
535     p->paint_tmpline (p, 0, w);
536     videotestsrc_convert_tmpline (p, frame, i);
537   }
538 }
539
540 void
541 gst_video_test_src_black (GstVideoTestSrc * v, GstVideoFrame * frame)
542 {
543   gst_video_test_src_unicolor (v, frame, COLOR_BLACK);
544 }
545
546 void
547 gst_video_test_src_white (GstVideoTestSrc * v, GstVideoFrame * frame)
548 {
549   gst_video_test_src_unicolor (v, frame, COLOR_WHITE);
550 }
551
552 void
553 gst_video_test_src_red (GstVideoTestSrc * v, GstVideoFrame * frame)
554 {
555   gst_video_test_src_unicolor (v, frame, COLOR_RED);
556 }
557
558 void
559 gst_video_test_src_green (GstVideoTestSrc * v, GstVideoFrame * frame)
560 {
561   gst_video_test_src_unicolor (v, frame, COLOR_GREEN);
562 }
563
564 void
565 gst_video_test_src_blue (GstVideoTestSrc * v, GstVideoFrame * frame)
566 {
567   gst_video_test_src_unicolor (v, frame, COLOR_BLUE);
568 }
569
570 void
571 gst_video_test_src_blink (GstVideoTestSrc * v, GstVideoFrame * frame)
572 {
573   int i;
574   paintinfo pi = PAINT_INFO_INIT;
575   paintinfo *p = &pi;
576   int w = frame->info.width, h = frame->info.height;
577
578   videotestsrc_setup_paintinfo (v, p, w, h);
579
580   if (v->n_frames & 1) {
581     p->color = &p->foreground_color;
582   } else {
583     p->color = &p->background_color;
584   }
585
586   for (i = 0; i < h; i++) {
587     p->paint_tmpline (p, 0, w);
588     videotestsrc_convert_tmpline (p, frame, i);
589   }
590 }
591
592 void
593 gst_video_test_src_solid (GstVideoTestSrc * v, GstVideoFrame * frame)
594 {
595   int i;
596   paintinfo pi = PAINT_INFO_INIT;
597   paintinfo *p = &pi;
598   int w = frame->info.width, h = frame->info.height;
599
600   videotestsrc_setup_paintinfo (v, p, w, h);
601
602   p->color = &p->foreground_color;
603
604   for (i = 0; i < h; i++) {
605     p->paint_tmpline (p, 0, w);
606     videotestsrc_convert_tmpline (p, frame, i);
607   }
608 }
609
610 void
611 gst_video_test_src_checkers1 (GstVideoTestSrc * v, GstVideoFrame * frame)
612 {
613   int x, y;
614   paintinfo pi = PAINT_INFO_INIT;
615   paintinfo *p = &pi;
616   int w = frame->info.width, h = frame->info.height;
617
618   videotestsrc_setup_paintinfo (v, p, w, h);
619
620   for (y = 0; y < h; y++) {
621     for (x = 0; x < w; x++) {
622       if ((x ^ y) & 1) {
623         p->color = p->colors + COLOR_GREEN;
624       } else {
625         p->color = p->colors + COLOR_RED;
626       }
627       p->paint_tmpline (p, x, 1);
628     }
629     videotestsrc_convert_tmpline (p, frame, y);
630   }
631 }
632
633 void
634 gst_video_test_src_checkers2 (GstVideoTestSrc * v, GstVideoFrame * frame)
635 {
636   int x, y;
637   paintinfo pi = PAINT_INFO_INIT;
638   paintinfo *p = &pi;
639   int w = frame->info.width, h = frame->info.height;
640
641   videotestsrc_setup_paintinfo (v, p, w, h);
642
643   for (y = 0; y < h; y++) {
644     for (x = 0; x < w; x += 2) {
645       guint len = MIN (2, w - x);
646
647       if ((x ^ y) & 2) {
648         p->color = p->colors + COLOR_GREEN;
649       } else {
650         p->color = p->colors + COLOR_RED;
651       }
652       p->paint_tmpline (p, x, len);
653     }
654     videotestsrc_convert_tmpline (p, frame, y);
655   }
656 }
657
658 void
659 gst_video_test_src_checkers4 (GstVideoTestSrc * v, GstVideoFrame * frame)
660 {
661   int x, y;
662   paintinfo pi = PAINT_INFO_INIT;
663   paintinfo *p = &pi;
664   int w = frame->info.width, h = frame->info.height;
665
666   videotestsrc_setup_paintinfo (v, p, w, h);
667
668   for (y = 0; y < h; y++) {
669     for (x = 0; x < w; x += 4) {
670       guint len = MIN (4, w - x);
671
672       if ((x ^ y) & 4) {
673         p->color = p->colors + COLOR_GREEN;
674       } else {
675         p->color = p->colors + COLOR_RED;
676       }
677       p->paint_tmpline (p, x, len);
678     }
679     videotestsrc_convert_tmpline (p, frame, y);
680   }
681 }
682
683 void
684 gst_video_test_src_checkers8 (GstVideoTestSrc * v, GstVideoFrame * frame)
685 {
686   int x, y;
687   paintinfo pi = PAINT_INFO_INIT;
688   paintinfo *p = &pi;
689   int w = frame->info.width, h = frame->info.height;
690
691   videotestsrc_setup_paintinfo (v, p, w, h);
692
693   for (y = 0; y < h; y++) {
694     for (x = 0; x < w; x += 8) {
695       guint len = MIN (8, w - x);
696
697       if ((x ^ y) & 8) {
698         p->color = p->colors + COLOR_GREEN;
699       } else {
700         p->color = p->colors + COLOR_RED;
701       }
702       p->paint_tmpline (p, x, len);
703     }
704     videotestsrc_convert_tmpline (p, frame, y);
705   }
706 }
707
708 static const guint8 sine_table[256] = {
709   128, 131, 134, 137, 140, 143, 146, 149,
710   152, 156, 159, 162, 165, 168, 171, 174,
711   176, 179, 182, 185, 188, 191, 193, 196,
712   199, 201, 204, 206, 209, 211, 213, 216,
713   218, 220, 222, 224, 226, 228, 230, 232,
714   234, 236, 237, 239, 240, 242, 243, 245,
715   246, 247, 248, 249, 250, 251, 252, 252,
716   253, 254, 254, 255, 255, 255, 255, 255,
717   255, 255, 255, 255, 255, 255, 254, 254,
718   253, 252, 252, 251, 250, 249, 248, 247,
719   246, 245, 243, 242, 240, 239, 237, 236,
720   234, 232, 230, 228, 226, 224, 222, 220,
721   218, 216, 213, 211, 209, 206, 204, 201,
722   199, 196, 193, 191, 188, 185, 182, 179,
723   176, 174, 171, 168, 165, 162, 159, 156,
724   152, 149, 146, 143, 140, 137, 134, 131,
725   128, 124, 121, 118, 115, 112, 109, 106,
726   103, 99, 96, 93, 90, 87, 84, 81,
727   79, 76, 73, 70, 67, 64, 62, 59,
728   56, 54, 51, 49, 46, 44, 42, 39,
729   37, 35, 33, 31, 29, 27, 25, 23,
730   21, 19, 18, 16, 15, 13, 12, 10,
731   9, 8, 7, 6, 5, 4, 3, 3,
732   2, 1, 1, 0, 0, 0, 0, 0,
733   0, 0, 0, 0, 0, 0, 1, 1,
734   2, 3, 3, 4, 5, 6, 7, 8,
735   9, 10, 12, 13, 15, 16, 18, 19,
736   21, 23, 25, 27, 29, 31, 33, 35,
737   37, 39, 42, 44, 46, 49, 51, 54,
738   56, 59, 62, 64, 67, 70, 73, 76,
739   79, 81, 84, 87, 90, 93, 96, 99,
740   103, 106, 109, 112, 115, 118, 121, 124
741 };
742
743
744 void
745 gst_video_test_src_zoneplate (GstVideoTestSrc * v, GstVideoFrame * frame)
746 {
747   int i;
748   int j;
749   paintinfo pi = PAINT_INFO_INIT;
750   paintinfo *p = &pi;
751   struct vts_color_struct color;
752   int t = v->n_frames;
753   int w = frame->info.width, h = frame->info.height;
754   int xreset = -(w / 2) - v->xoffset;   /* starting values for x^2 and y^2, centering the ellipse */
755   int yreset = -(h / 2) - v->yoffset;
756
757   int x, y;
758   int accum_kx;
759   int accum_kxt;
760   int accum_ky;
761   int accum_kyt;
762   int accum_kxy;
763   int kt;
764   int kt2;
765   int ky2;
766   int delta_kxt = v->kxt * t;
767   int delta_kxy;
768   int scale_kxy = 0xffff / (w / 2);
769   int scale_kx2 = 0xffff / w;
770
771   videotestsrc_setup_paintinfo (v, p, w, h);
772
773   color = p->colors[COLOR_BLACK];
774   p->color = &color;
775
776   /* Zoneplate equation:
777    *
778    * phase = k0 + kx*x + ky*y + kt*t
779    *       + kxt*x*t + kyt*y*t + kxy*x*y
780    *       + kx2*x*x + ky2*y*y + Kt2*t*t
781    */
782
783 #if 0
784   for (j = 0, y = yreset; j < h; j++, y++) {
785     for (i = 0, x = xreset; i < w; i++, x++) {
786
787       /* zero order */
788       int phase = v->k0;
789
790       /* first order */
791       phase = phase + (v->kx * i) + (v->ky * j) + (v->kt * t);
792
793       /* cross term */
794       /* phase = phase + (v->kxt * i * t) + (v->kyt * j * t); */
795       /* phase = phase + (v->kxy * x * y) / (w/2); */
796
797       /*second order */
798       /*normalise x/y terms to rate of change of phase at the picture edge */
799       phase =
800           phase + ((v->kx2 * x * x) / w) + ((v->ky2 * y * y) / h) +
801           ((v->kt2 * t * t) >> 1);
802
803       color.Y = sine_table[phase & 0xff];
804
805       color.R = color.Y;
806       color.G = color.Y;
807       color.B = color.Y;
808       p->paint_tmpline (p, i, 1);
809     }
810   }
811 #endif
812
813   /* optimised version, with original code shown in comments */
814   accum_ky = 0;
815   accum_kyt = 0;
816   kt = v->kt * t;
817   kt2 = v->kt2 * t * t;
818   for (j = 0, y = yreset; j < h; j++, y++) {
819     accum_kx = 0;
820     accum_kxt = 0;
821     accum_ky += v->ky;
822     accum_kyt += v->kyt * t;
823     delta_kxy = v->kxy * y * scale_kxy;
824     accum_kxy = delta_kxy * xreset;
825     ky2 = (v->ky2 * y * y) / h;
826     for (i = 0, x = xreset; i < w; i++, x++) {
827
828       /* zero order */
829       int phase = v->k0;
830
831       /* first order */
832       accum_kx += v->kx;
833       /* phase = phase + (v->kx * i) + (v->ky * j) + (v->kt * t); */
834       phase = phase + accum_kx + accum_ky + kt;
835
836       /* cross term */
837       accum_kxt += delta_kxt;
838       accum_kxy += delta_kxy;
839       /* phase = phase + (v->kxt * i * t) + (v->kyt * j * t); */
840       phase = phase + accum_kxt + accum_kyt;
841
842       /* phase = phase + (v->kxy * x * y) / (w/2); */
843       /* phase = phase + accum_kxy / (w/2); */
844       phase = phase + (accum_kxy >> 16);
845
846       /*second order */
847       /*normalise x/y terms to rate of change of phase at the picture edge */
848       /*phase = phase + ((v->kx2 * x * x)/w) + ((v->ky2 * y * y)/h) + ((v->kt2 * t * t)>>1); */
849       phase = phase + ((v->kx2 * x * x * scale_kx2) >> 16) + ky2 + (kt2 >> 1);
850
851       p->tmpline_u8[i] = sine_table[phase & 0xff];
852     }
853     videotestsrc_blend_line (v, p->tmpline, p->tmpline_u8,
854         &p->foreground_color, &p->background_color, w);
855     videotestsrc_convert_tmpline (p, frame, j);
856   }
857 }
858
859 void
860 gst_video_test_src_chromazoneplate (GstVideoTestSrc * v, GstVideoFrame * frame)
861 {
862   int i;
863   int j;
864   paintinfo pi = PAINT_INFO_INIT;
865   paintinfo *p = &pi;
866   struct vts_color_struct color;
867   int t = v->n_frames;
868   int w = frame->info.width, h = frame->info.height;
869
870   int xreset = -(w / 2) - v->xoffset;   /* starting values for x^2 and y^2, centering the ellipse */
871   int yreset = -(h / 2) - v->yoffset;
872
873   int x, y;
874   int accum_kx;
875   int accum_kxt;
876   int accum_ky;
877   int accum_kyt;
878   int accum_kxy;
879   int kt;
880   int kt2;
881   int ky2;
882   int delta_kxt = v->kxt * t;
883   int delta_kxy;
884   int scale_kxy = 0xffff / (w / 2);
885   int scale_kx2 = 0xffff / w;
886
887   videotestsrc_setup_paintinfo (v, p, w, h);
888
889   color = p->colors[COLOR_BLACK];
890   p->color = &color;
891
892   /* Zoneplate equation:
893    *
894    * phase = k0 + kx*x + ky*y + kt*t
895    *       + kxt*x*t + kyt*y*t + kxy*x*y
896    *       + kx2*x*x + ky2*y*y + Kt2*t*t
897    */
898
899   /* optimised version, with original code shown in comments */
900   accum_ky = 0;
901   accum_kyt = 0;
902   kt = v->kt * t;
903   kt2 = v->kt2 * t * t;
904   for (j = 0, y = yreset; j < h; j++, y++) {
905     accum_kx = 0;
906     accum_kxt = 0;
907     accum_ky += v->ky;
908     accum_kyt += v->kyt * t;
909     delta_kxy = v->kxy * y * scale_kxy;
910     accum_kxy = delta_kxy * xreset;
911     ky2 = (v->ky2 * y * y) / h;
912     for (i = 0, x = xreset; i < w; i++, x++) {
913
914       /* zero order */
915       int phase = v->k0;
916
917       /* first order */
918       accum_kx += v->kx;
919       /* phase = phase + (v->kx * i) + (v->ky * j) + (v->kt * t); */
920       phase = phase + accum_kx + accum_ky + kt;
921
922       /* cross term */
923       accum_kxt += delta_kxt;
924       accum_kxy += delta_kxy;
925       /* phase = phase + (v->kxt * i * t) + (v->kyt * j * t); */
926       phase = phase + accum_kxt + accum_kyt;
927
928       /* phase = phase + (v->kxy * x * y) / (w/2); */
929       /* phase = phase + accum_kxy / (w/2); */
930       phase = phase + (accum_kxy >> 16);
931
932       /*second order */
933       /*normalise x/y terms to rate of change of phase at the picture edge */
934       /*phase = phase + ((v->kx2 * x * x)/w) + ((v->ky2 * y * y)/h) + ((v->kt2 * t * t)>>1); */
935       phase = phase + ((v->kx2 * x * x * scale_kx2) >> 16) + ky2 + (kt2 >> 1);
936
937       color.Y = 128;
938       color.U = sine_table[phase & 0xff];
939       color.V = sine_table[phase & 0xff];
940
941       color.R = 128;
942       color.G = 128;
943       color.B = color.V;
944
945       color.gray = color.Y << 8;
946       p->paint_tmpline (p, i, 1);
947     }
948     videotestsrc_convert_tmpline (p, frame, j);
949   }
950 }
951
952 #undef SCALE_AMPLITUDE
953 void
954 gst_video_test_src_circular (GstVideoTestSrc * v, GstVideoFrame * frame)
955 {
956   int i;
957   int j;
958   paintinfo pi = PAINT_INFO_INIT;
959   paintinfo *p = &pi;
960   double freq[8];
961   int w = frame->info.width, h = frame->info.height;
962
963   int d;
964
965   videotestsrc_setup_paintinfo (v, p, w, h);
966
967   for (i = 1; i < 8; i++) {
968     freq[i] = 200 * pow (2.0, -(i - 1) / 4.0);
969   }
970
971   for (j = 0; j < h; j++) {
972     for (i = 0; i < w; i++) {
973       double dist;
974       int seg;
975
976       dist =
977           sqrt ((2 * i - w) * (2 * i - w) + (2 * j - h) * (2 * j -
978               h)) / (2 * w);
979       seg = floor (dist * 16);
980       if (seg == 0 || seg >= 8) {
981         p->tmpline_u8[i] = 0;
982       } else {
983         d = floor (256 * dist * freq[seg] + 0.5);
984         p->tmpline_u8[i] = sine_table[d & 0xff];
985       }
986     }
987     videotestsrc_blend_line (v, p->tmpline, p->tmpline_u8,
988         &p->foreground_color, &p->background_color, w);
989     videotestsrc_convert_tmpline (p, frame, j);
990   }
991 }
992
993 void
994 gst_video_test_src_gamut (GstVideoTestSrc * v, GstVideoFrame * frame)
995 {
996   int x, y;
997   paintinfo pi = PAINT_INFO_INIT;
998   paintinfo *p = &pi;
999   struct vts_color_struct yuv_primary;
1000   struct vts_color_struct yuv_secondary;
1001   int w = frame->info.width, h = frame->info.height;
1002
1003   videotestsrc_setup_paintinfo (v, p, w, h);
1004
1005   for (y = 0; y < h; y++) {
1006     int region = (y * 4) / h;
1007
1008     switch (region) {
1009       case 0:                  /* black */
1010         yuv_primary = p->colors[COLOR_BLACK];
1011         yuv_secondary = p->colors[COLOR_BLACK];
1012         yuv_secondary.Y = 0;
1013         break;
1014       case 1:
1015         yuv_primary = p->colors[COLOR_WHITE];
1016         yuv_secondary = p->colors[COLOR_WHITE];
1017         yuv_secondary.Y = 255;
1018         break;
1019       case 2:
1020         yuv_primary = p->colors[COLOR_RED];
1021         yuv_secondary = p->colors[COLOR_RED];
1022         yuv_secondary.V = 255;
1023         break;
1024       case 3:
1025         yuv_primary = p->colors[COLOR_BLUE];
1026         yuv_secondary = p->colors[COLOR_BLUE];
1027         yuv_secondary.U = 255;
1028         break;
1029     }
1030
1031     for (x = 0; x < w; x += 8) {
1032       int len = MIN (8, w - x);
1033
1034       if ((x ^ y) & (1 << 4)) {
1035         p->color = &yuv_primary;
1036       } else {
1037         p->color = &yuv_secondary;
1038       }
1039       p->paint_tmpline (p, x, len);
1040     }
1041     videotestsrc_convert_tmpline (p, frame, y);
1042   }
1043 }
1044
1045 void
1046 gst_video_test_src_ball (GstVideoTestSrc * v, GstVideoFrame * frame)
1047 {
1048   int i;
1049   paintinfo pi = PAINT_INFO_INIT;
1050   paintinfo *p = &pi;
1051   int t = v->n_frames;
1052   double x, y;
1053   int radius = 20;
1054   int w = frame->info.width, h = frame->info.height;
1055
1056   videotestsrc_setup_paintinfo (v, p, w, h);
1057
1058   x = radius + (0.5 + 0.5 * sin (2 * G_PI * t / 200)) * (w - 2 * radius);
1059   y = radius + (0.5 + 0.5 * sin (2 * G_PI * sqrt (2) * t / 200)) * (h -
1060       2 * radius);
1061
1062   for (i = 0; i < h; i++) {
1063     if (i < y - radius || i > y + radius) {
1064       memset (p->tmpline_u8, 0, w);
1065     } else {
1066       int r = rint (sqrt (radius * radius - (i - y) * (i - y)));
1067       int x1, x2;
1068       int j;
1069
1070       x1 = 0;
1071       x2 = MAX (0, x - r);
1072       for (j = x1; j < x2; j++) {
1073         p->tmpline_u8[j] = 0;
1074       }
1075
1076       x1 = MAX (0, x - r);
1077       x2 = MIN (w, x + r + 1);
1078       for (j = x1; j < x2; j++) {
1079         double rr = radius - sqrt ((j - x) * (j - x) + (i - y) * (i - y));
1080
1081         rr *= 0.5;
1082         p->tmpline_u8[j] = CLAMP ((int) floor (256 * rr), 0, 255);
1083       }
1084
1085       x1 = MIN (w, x + r + 1);
1086       x2 = w;
1087       for (j = x1; j < x2; j++) {
1088         p->tmpline_u8[j] = 0;
1089       }
1090     }
1091     videotestsrc_blend_line (v, p->tmpline, p->tmpline_u8,
1092         &p->foreground_color, &p->background_color, w);
1093     videotestsrc_convert_tmpline (p, frame, i);
1094   }
1095 }
1096
1097 static void
1098 paint_tmpline_ARGB (paintinfo * p, int x, int w)
1099 {
1100   int offset;
1101   guint32 value;
1102
1103 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1104   value = (p->color->A << 0) | (p->color->R << 8) |
1105       (p->color->G << 16) | (p->color->B << 24);
1106 #else
1107   value = (p->color->A << 24) | (p->color->R << 16) |
1108       (p->color->G << 8) | (p->color->B << 0);
1109 #endif
1110
1111   offset = (x * 4);
1112   video_test_src_orc_splat_u32 (p->tmpline + offset, value, w);
1113 }
1114
1115 static void
1116 paint_tmpline_AYUV (paintinfo * p, int x, int w)
1117 {
1118   int offset;
1119   guint32 value;
1120
1121 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1122   value = (p->color->A << 0) | (p->color->Y << 8) |
1123       (p->color->U << 16) | (p->color->V << 24);
1124 #else
1125   value = (p->color->A << 24) | (p->color->Y << 16) |
1126       (p->color->U << 8) | (p->color->V << 0);
1127 #endif
1128
1129   offset = (x * 4);
1130   video_test_src_orc_splat_u32 (p->tmpline + offset, value, w);
1131 }
1132
1133 static void
1134 convert_hline_generic (paintinfo * p, GstVideoFrame * frame, int y)
1135 {
1136   const GstVideoFormatInfo *finfo, *uinfo;
1137   gint i, width = GST_VIDEO_FRAME_WIDTH (frame);
1138   gpointer src;
1139
1140   finfo = frame->info.finfo;
1141   uinfo = gst_video_format_get_info (finfo->unpack_format);
1142
1143   if (GST_VIDEO_FORMAT_INFO_DEPTH (uinfo, 0) == 16) {
1144     /* 16 bits */
1145     for (i = 0; i < width; i++) {
1146       p->tmpline_u16[i * 4 + 0] = TO_16 (p->tmpline[i * 4 + 0]);
1147       p->tmpline_u16[i * 4 + 1] = TO_16 (p->tmpline[i * 4 + 1]);
1148       p->tmpline_u16[i * 4 + 2] = TO_16 (p->tmpline[i * 4 + 2]);
1149       p->tmpline_u16[i * 4 + 3] = TO_16 (p->tmpline[i * 4 + 3]);
1150     }
1151     src = p->tmpline_u16;
1152   } else {
1153     src = p->tmpline;
1154   }
1155   finfo->pack_func (finfo, GST_VIDEO_PACK_FLAG_NONE,
1156       src, 0, frame->data, frame->info.stride,
1157       frame->info.chroma_site, y, width);
1158 }
1159
1160 static void
1161 convert_hline_bayer (paintinfo * p, GstVideoFrame * frame, int y)
1162 {
1163   int i;
1164   guint8 *data = GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
1165   guint8 *R = data + y * GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0);
1166   guint8 *argb = p->tmpline;
1167   gint width = GST_VIDEO_FRAME_WIDTH (frame);
1168   int x_inv = p->x_invert;
1169   int y_inv = p->y_invert;
1170
1171   if ((y ^ y_inv) & 1) {
1172     for (i = 0; i < width; i++) {
1173       if ((i ^ x_inv) & 1) {
1174         R[i] = argb[4 * i + 1];
1175       } else {
1176         R[i] = argb[4 * i + 2];
1177       }
1178     }
1179   } else {
1180     for (i = 0; i < width; i++) {
1181       if ((i ^ x_inv) & 1) {
1182         R[i] = argb[4 * i + 2];
1183       } else {
1184         R[i] = argb[4 * i + 3];
1185       }
1186     }
1187   }
1188 }