decodebin: Add autoplug-query signal to handle queries for yet unconnected elements
[platform/upstream/gstreamer.git] / gst / videoscale / vs_scanline.c
1 /*
2  * Image Scaling Functions
3  * Copyright (c) 2005 David A. Schleef <ds@schleef.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include "vs_scanline.h"
32
33 #include "gstvideoscaleorc.h"
34 #include <gst/gst.h>
35
36 #include <string.h>
37
38 /* greyscale, i.e., single componenet */
39
40 void
41 vs_scanline_downsample_Y (uint8_t * dest, uint8_t * src, int n)
42 {
43   video_scale_orc_downsample_u8 (dest, src, n);
44 }
45
46 void
47 vs_scanline_resample_nearest_Y (uint8_t * dest, uint8_t * src, int src_width,
48     int n, int *accumulator, int increment)
49 {
50   video_scale_orc_resample_nearest_u8 (dest, src, *accumulator, increment, n);
51
52   *accumulator += n * increment;
53 }
54
55 #include <glib.h>
56 void
57 vs_scanline_resample_linear_Y (uint8_t * dest, uint8_t * src, int src_width,
58     int n, int *accumulator, int increment)
59 {
60   video_scale_orc_resample_bilinear_u8 (dest, src, *accumulator, increment, n);
61
62   *accumulator += n * increment;
63 }
64
65 void
66 vs_scanline_merge_linear_Y (uint8_t * dest, uint8_t * src1, uint8_t * src2,
67     int n, int x)
68 {
69   uint32_t value = x >> 8;
70
71   if (value == 0) {
72     memcpy (dest, src1, n);
73   } else {
74     video_scale_orc_merge_linear_u8 (dest, src1, src2, value, n);
75   }
76 }
77
78 void
79 vs_scanline_downsample_Y16 (uint8_t * dest, uint8_t * src, int n)
80 {
81   video_scale_orc_downsample_u16 ((uint16_t *) dest, (uint16_t *) src, n);
82 }
83
84 void
85 vs_scanline_resample_nearest_Y16 (uint8_t * dest, uint8_t * src, int src_width,
86     int n, int *accumulator, int increment)
87 {
88   int acc = *accumulator;
89   int i;
90   int j;
91   int x;
92   uint16_t *d = (uint16_t *) dest, *s = (uint16_t *) src;
93
94   for (i = 0; i < n; i++) {
95     j = acc >> 16;
96     x = acc & 0xffff;
97     d[i] = (x < 32768 || j + 1 >= src_width) ? s[j] : s[j + 1];
98
99     acc += increment;
100   }
101
102   *accumulator = acc;
103 }
104
105 void
106 vs_scanline_resample_linear_Y16 (uint8_t * dest, uint8_t * src, int src_width,
107     int n, int *accumulator, int increment)
108 {
109   int acc = *accumulator;
110   int i;
111   int j;
112   int x;
113   uint16_t *d = (uint16_t *) dest, *s = (uint16_t *) src;
114
115   for (i = 0; i < n; i++) {
116     j = acc >> 16;
117     x = acc & 0xffff;
118
119     if (j + 1 < src_width)
120       d[i] = (s[j] * (65536 - x) + s[j + 1] * x) >> 16;
121     else
122       d[i] = s[j];
123
124     acc += increment;
125   }
126
127   *accumulator = acc;
128 }
129
130 void
131 vs_scanline_merge_linear_Y16 (uint8_t * dest, uint8_t * src1, uint8_t * src2,
132     int n, int x)
133 {
134   uint16_t *d = (uint16_t *) dest;
135   const uint16_t *s1 = (const uint16_t *) src1;
136   const uint16_t *s2 = (const uint16_t *) src2;
137
138   if (x == 0) {
139     memcpy (d, s1, n * 2);
140   } else {
141     video_scale_orc_merge_linear_u16 (d, s1, s2, 65536 - x, x, n);
142   }
143 }
144
145 /* RGBA */
146
147 void
148 vs_scanline_downsample_RGBA (uint8_t * dest, uint8_t * src, int n)
149 {
150   video_scale_orc_downsample_u32 (dest, src, n);
151 }
152
153 void
154 vs_scanline_resample_nearest_RGBA (uint8_t * dest, uint8_t * src, int src_width,
155     int n, int *accumulator, int increment)
156 {
157   video_scale_orc_resample_nearest_u32 (dest, src, *accumulator, increment, n);
158
159   *accumulator += n * increment;
160 }
161
162 void
163 vs_scanline_resample_linear_RGBA (uint8_t * dest, uint8_t * src, int src_width,
164     int n, int *accumulator, int increment)
165 {
166   video_scale_orc_resample_bilinear_u32 (dest, src, *accumulator, increment, n);
167
168   *accumulator += n * increment;
169 }
170
171 void
172 vs_scanline_merge_linear_RGBA (uint8_t * dest, uint8_t * src1, uint8_t * src2,
173     int n, int x)
174 {
175   uint32_t value = x >> 8;
176
177   if (value == 0) {
178     memcpy (dest, src1, n * 4);
179   } else {
180     video_scale_orc_merge_linear_u8 (dest, src1, src2, value, n * 4);
181   }
182 }
183
184
185 /* RGB */
186
187 void
188 vs_scanline_downsample_RGB (uint8_t * dest, uint8_t * src, int n)
189 {
190   int i;
191
192   for (i = 0; i < n; i++) {
193     dest[i * 3 + 0] = (src[i * 6 + 0] + src[i * 6 + 3]) / 2;
194     dest[i * 3 + 1] = (src[i * 6 + 1] + src[i * 6 + 4]) / 2;
195     dest[i * 3 + 2] = (src[i * 6 + 2] + src[i * 6 + 5]) / 2;
196   }
197 }
198
199 void
200 vs_scanline_resample_nearest_RGB (uint8_t * dest, uint8_t * src, int src_width,
201     int n, int *accumulator, int increment)
202 {
203   int acc = *accumulator;
204   int i;
205   int j;
206   int x;
207
208   for (i = 0; i < n; i++) {
209     j = acc >> 16;
210     x = acc & 0xffff;
211     dest[i * 3 + 0] = (x < 32768
212         || j + 1 >= src_width) ? src[j * 3 + 0] : src[j * 3 + 3];
213     dest[i * 3 + 1] = (x < 32768
214         || j + 1 >= src_width) ? src[j * 3 + 1] : src[j * 3 + 4];
215     dest[i * 3 + 2] = (x < 32768
216         || j + 1 >= src_width) ? src[j * 3 + 2] : src[j * 3 + 5];
217
218     acc += increment;
219   }
220
221   *accumulator = acc;
222 }
223
224 void
225 vs_scanline_resample_linear_RGB (uint8_t * dest, uint8_t * src, int src_width,
226     int n, int *accumulator, int increment)
227 {
228   int acc = *accumulator;
229   int i;
230   int j;
231   int x;
232
233   for (i = 0; i < n; i++) {
234     j = acc >> 16;
235     x = acc & 0xffff;
236
237     if (j + 1 < src_width) {
238       dest[i * 3 + 0] =
239           (src[j * 3 + 0] * (65536 - x) + src[j * 3 + 3] * x) >> 16;
240       dest[i * 3 + 1] =
241           (src[j * 3 + 1] * (65536 - x) + src[j * 3 + 4] * x) >> 16;
242       dest[i * 3 + 2] =
243           (src[j * 3 + 2] * (65536 - x) + src[j * 3 + 5] * x) >> 16;
244     } else {
245       dest[i * 3 + 0] = src[j * 3 + 0];
246       dest[i * 3 + 1] = src[j * 3 + 1];
247       dest[i * 3 + 2] = src[j * 3 + 2];
248     }
249
250     acc += increment;
251   }
252
253   *accumulator = acc;
254 }
255
256 void
257 vs_scanline_merge_linear_RGB (uint8_t * dest, uint8_t * src1, uint8_t * src2,
258     int n, int x)
259 {
260   uint32_t value = x >> 8;
261
262   if (value == 0) {
263     memcpy (dest, src1, n * 3);
264   } else {
265     video_scale_orc_merge_linear_u8 (dest, src1, src2, value, n * 3);
266   }
267 }
268
269
270 /* YUYV */
271
272 /* n is the number of pixels */
273 /* increment is per Y pixel */
274
275 void
276 vs_scanline_downsample_YUYV (uint8_t * dest, uint8_t * src, int n)
277 {
278   video_scale_orc_downsample_yuyv (dest, src, n);
279 }
280
281 void
282 vs_scanline_resample_nearest_YUYV (uint8_t * dest, uint8_t * src, int src_width,
283     int n, int *accumulator, int increment)
284 {
285   int acc = *accumulator;
286   int i;
287   int j;
288   int x;
289   int quads = (n + 1) / 2;
290
291   for (i = 0; i < quads; i++) {
292     j = acc >> 16;
293     x = acc & 0xffff;
294     dest[i * 4 + 0] = (x < 32768
295         || j + 1 >= src_width) ? src[j * 2 + 0] : src[j * 2 + 2];
296
297     j = acc >> 17;
298     x = acc & 0x1ffff;
299     dest[i * 4 + 1] = (x < 65536
300         || 2 * j + 2 >= src_width) ? src[j * 4 + 1] : src[j * 4 + 5];
301
302     if (2 * i + 1 < n && 2 * j + 1 < src_width)
303       dest[i * 4 + 3] = (x < 65536
304           || 2 * j + 3 >= src_width) ? src[j * 4 + 3] : src[j * 4 + 7];
305
306     acc += increment;
307
308     j = acc >> 16;
309     x = acc & 0xffff;
310
311     if (2 * i + 1 < n && j < src_width) {
312       dest[i * 4 + 2] = (x < 32768
313           || j + 1 >= src_width) ? src[j * 2 + 0] : src[j * 2 + 2];
314       acc += increment;
315     }
316   }
317
318   *accumulator = acc;
319 }
320
321 void
322 vs_scanline_resample_linear_YUYV (uint8_t * dest, uint8_t * src, int src_width,
323     int n, int *accumulator, int increment)
324 {
325   int acc = *accumulator;
326   int i;
327   int j;
328   int x;
329   int quads = (n + 1) / 2;
330
331   for (i = 0; i < quads; i++) {
332     j = acc >> 16;
333     x = acc & 0xffff;
334
335     if (j + 1 < src_width)
336       dest[i * 4 + 0] =
337           (src[j * 2 + 0] * (65536 - x) + src[j * 2 + 2] * x) >> 16;
338     else
339       dest[i * 4 + 0] = src[j * 2 + 0];
340
341     j = acc >> 17;
342     x = acc & 0x1ffff;
343
344     if (2 * j + 2 < src_width)
345       dest[i * 4 + 1] =
346           (src[j * 4 + 1] * (131072 - x) + src[j * 4 + 5] * x) >> 17;
347     else
348       dest[i * 4 + 1] = src[j * 4 + 1];
349
350     if (2 * i + 1 < n && 2 * j + 1 < src_width) {
351       if (2 * j + 3 < src_width)
352         dest[i * 4 + 3] =
353             (src[j * 4 + 3] * (131072 - x) + src[j * 4 + 7] * x) >> 17;
354       else
355         dest[i * 4 + 3] = src[j * 4 + 3];
356     }
357
358     acc += increment;
359
360     j = acc >> 16;
361     x = acc & 0xffff;
362
363     if (2 * i + 1 < n && j < src_width) {
364       if (j + 1 < src_width)
365         dest[i * 4 + 2] =
366             (src[j * 2 + 0] * (65536 - x) + src[j * 2 + 2] * x) >> 16;
367       else
368         dest[i * 4 + 2] = src[j * 2 + 0];
369       acc += increment;
370     }
371   }
372
373
374   *accumulator = acc;
375 }
376
377 void
378 vs_scanline_merge_linear_YUYV (uint8_t * dest, uint8_t * src1, uint8_t * src2,
379     int n, int x)
380 {
381   int quads = (n + 1) / 2;
382   uint32_t value = x >> 8;
383
384   if (value == 0) {
385     memcpy (dest, src1, quads * 4);
386   } else {
387     video_scale_orc_merge_linear_u8 (dest, src1, src2, value, quads * 4);
388   }
389 }
390
391
392 /* UYVY */
393
394 /* n is the number of bi-pixels */
395 /* increment is per Y pixel */
396
397 void
398 vs_scanline_downsample_UYVY (uint8_t * dest, uint8_t * src, int n)
399 {
400   int i;
401
402   for (i = 0; i < n; i++) {
403     dest[i * 4 + 0] = (src[i * 8 + 0] + src[i * 8 + 4]) / 2;
404     dest[i * 4 + 1] = (src[i * 8 + 1] + src[i * 8 + 3]) / 2;
405     dest[i * 4 + 2] = (src[i * 8 + 2] + src[i * 8 + 6]) / 2;
406     dest[i * 4 + 3] = (src[i * 8 + 5] + src[i * 8 + 7]) / 2;
407   }
408 }
409
410 void
411 vs_scanline_resample_nearest_UYVY (uint8_t * dest, uint8_t * src, int src_width,
412     int n, int *accumulator, int increment)
413 {
414   int acc = *accumulator;
415   int i;
416   int j;
417   int x;
418   int quads = (n + 1) / 2;
419
420   for (i = 0; i < quads; i++) {
421     j = acc >> 16;
422     x = acc & 0xffff;
423
424     dest[i * 4 + 1] = (x < 32768
425         || j + 1 >= src_width) ? src[j * 2 + 1] : src[j * 2 + 3];
426
427     j = acc >> 17;
428     x = acc & 0x1ffff;
429
430     dest[i * 4 + 0] = (x < 65536
431         || 2 * j + 2 >= src_width) ? src[j * 4 + 0] : src[j * 4 + 4];
432
433     if (2 * i + 1 < n && 2 * j + 1 < src_width)
434       dest[i * 4 + 2] = (x < 65536
435           || 2 * j + 3 >= src_width) ? src[j * 4 + 2] : src[j * 4 + 6];
436
437     acc += increment;
438
439     j = acc >> 16;
440     x = acc & 0xffff;
441
442     if (2 * i + 1 < n && j < src_width) {
443       dest[i * 4 + 3] = (x < 32768
444           || j + 1 >= src_width) ? src[j * 2 + 1] : src[j * 2 + 3];
445       acc += increment;
446     }
447   }
448
449   *accumulator = acc;
450 }
451
452 void
453 vs_scanline_resample_linear_UYVY (uint8_t * dest, uint8_t * src, int src_width,
454     int n, int *accumulator, int increment)
455 {
456   int acc = *accumulator;
457   int i;
458   int j;
459   int x;
460   int quads = (n + 1) / 2;
461
462   for (i = 0; i < quads; i++) {
463     j = acc >> 16;
464     x = acc & 0xffff;
465
466     if (j + 1 < src_width)
467       dest[i * 4 + 1] =
468           (src[j * 2 + 1] * (65536 - x) + src[j * 2 + 3] * x) >> 16;
469     else
470       dest[i * 4 + 1] = src[j * 2 + 1];
471
472     j = acc >> 17;
473     x = acc & 0x1ffff;
474     if (2 * j + 2 < src_width)
475       dest[i * 4 + 0] =
476           (src[j * 4 + 0] * (131072 - x) + src[j * 4 + 4] * x) >> 17;
477     else
478       dest[i * 4 + 0] = src[j * 4 + 0];
479
480     if (i * 2 + 1 < n && 2 * j + 1 < src_width) {
481       if (2 * j + 3 < src_width)
482         dest[i * 4 + 2] =
483             (src[j * 4 + 2] * (131072 - x) + src[j * 4 + 6] * x) >> 17;
484       else
485         dest[i * 4 + 2] = src[j * 4 + 2];
486     }
487
488     acc += increment;
489
490     j = acc >> 16;
491     x = acc & 0xffff;
492
493     if (2 * i + 1 < n && j < src_width) {
494       if (j + 1 < src_width)
495         dest[i * 4 + 3] =
496             (src[j * 2 + 1] * (65536 - x) + src[j * 2 + 3] * x) >> 16;
497       else
498         dest[i * 4 + 3] = src[j * 2 + 1];
499       acc += increment;
500     }
501   }
502
503   *accumulator = acc;
504 }
505
506 void
507 vs_scanline_merge_linear_UYVY (uint8_t * dest, uint8_t * src1,
508     uint8_t * src2, int n, int x)
509 {
510   int quads = (n + 1) / 2;
511   uint32_t value = x >> 8;
512
513   if (value == 0) {
514     memcpy (dest, src1, quads * 4);
515   } else {
516     video_scale_orc_merge_linear_u8 (dest, src1, src2, value, quads * 4);
517   }
518 }
519
520
521 /* NV12 */
522
523 /* n is the number of bi-pixels */
524
525 void
526 vs_scanline_downsample_NV12 (uint8_t * dest, uint8_t * src, int n)
527 {
528   int i;
529
530   for (i = 0; i < n; i++) {
531     dest[i * 2 + 0] = (src[i * 4 + 0] + src[i * 4 + 2]) / 2;
532     dest[i * 2 + 1] = (src[i * 4 + 1] + src[i * 4 + 3]) / 2;
533   }
534 }
535
536 void
537 vs_scanline_resample_nearest_NV12 (uint8_t * dest, uint8_t * src, int src_width,
538     int n, int *accumulator, int increment)
539 {
540   int acc = *accumulator;
541   int i;
542   int j;
543   int x;
544
545   for (i = 0; i < n; i++) {
546     j = acc >> 16;
547     x = acc & 0xffff;
548
549     dest[i * 2 + 0] = (x < 32768
550         || j + 1 >= src_width) ? src[j * 2 + 0] : src[j * 2 + 2];
551     dest[i * 2 + 1] = (x < 32768
552         || j + 1 >= src_width) ? src[j * 2 + 1] : src[j * 2 + 3];
553
554     acc += increment;
555   }
556
557   *accumulator = acc;
558 }
559
560 void
561 vs_scanline_resample_linear_NV12 (uint8_t * dest, uint8_t * src, int src_width,
562     int n, int *accumulator, int increment)
563 {
564   int acc = *accumulator;
565   int i;
566   int j;
567   int x;
568
569   for (i = 0; i < n; i++) {
570     j = acc >> 16;
571     x = acc & 0xffff;
572
573     if (j + 1 < src_width) {
574       dest[i * 2 + 0] =
575           (src[j * 2 + 0] * (65536 - x) + src[j * 2 + 2] * x) >> 16;
576       dest[i * 2 + 1] =
577           (src[j * 2 + 1] * (65536 - x) + src[j * 2 + 3] * x) >> 16;
578     } else {
579       dest[i * 4 + 0] = src[j * 2 + 0];
580       dest[i * 4 + 1] = src[j * 2 + 1];
581     }
582
583     acc += increment;
584   }
585
586   *accumulator = acc;
587 }
588
589 void
590 vs_scanline_merge_linear_NV12 (uint8_t * dest, uint8_t * src1,
591     uint8_t * src2, int n, int x)
592 {
593   uint32_t value = x >> 8;
594
595   if (value == 0) {
596     memcpy (dest, src1, n * 2);
597   } else {
598     video_scale_orc_merge_linear_u8 (dest, src1, src2, value, n * 2);
599   }
600 }
601
602
603 /* RGB565 */
604
605 /* note that src and dest are uint16_t, and thus endian dependent */
606
607 #define RGB565_R(x) (((x)&0xf800)>>8 | ((x)&0xf800)>>13)
608 #define RGB565_G(x) (((x)&0x07e0)>>3 | ((x)&0x07e0)>>9)
609 #define RGB565_B(x) (((x)&0x001f)<<3 | ((x)&0x001f)>>2)
610
611 #define RGB565(r,g,b) \
612   ((((r)<<8)&0xf800) | (((g)<<3)&0x07e0) | (((b)>>3)&0x001f))
613
614
615 void
616 vs_scanline_downsample_RGB565 (uint8_t * dest_u8, uint8_t * src_u8, int n)
617 {
618   uint16_t *dest = (uint16_t *) dest_u8;
619   uint16_t *src = (uint16_t *) src_u8;
620   int i;
621
622   for (i = 0; i < n; i++) {
623     dest[i] = RGB565 (
624         (RGB565_R (src[i * 2]) + RGB565_R (src[i * 2 + 1])) / 2,
625         (RGB565_G (src[i * 2]) + RGB565_G (src[i * 2 + 1])) / 2,
626         (RGB565_B (src[i * 2]) + RGB565_B (src[i * 2 + 1])) / 2);
627   }
628 }
629
630 void
631 vs_scanline_resample_nearest_RGB565 (uint8_t * dest_u8, uint8_t * src_u8,
632     int src_width, int n, int *accumulator, int increment)
633 {
634   uint16_t *dest = (uint16_t *) dest_u8;
635   uint16_t *src = (uint16_t *) src_u8;
636   int acc = *accumulator;
637   int i;
638   int j;
639   int x;
640
641   for (i = 0; i < n; i++) {
642     j = acc >> 16;
643     x = acc & 0xffff;
644     dest[i] = (x < 32768 || j + 1 >= src_width) ? src[j] : src[j + 1];
645
646     acc += increment;
647   }
648
649   *accumulator = acc;
650 }
651
652 void
653 vs_scanline_resample_linear_RGB565 (uint8_t * dest_u8, uint8_t * src_u8,
654     int src_width, int n, int *accumulator, int increment)
655 {
656   uint16_t *dest = (uint16_t *) dest_u8;
657   uint16_t *src = (uint16_t *) src_u8;
658   int acc = *accumulator;
659   int i;
660   int j;
661   int x;
662
663   for (i = 0; i < n; i++) {
664     j = acc >> 16;
665     x = acc & 0xffff;
666
667     if (j + 1 < src_width) {
668       dest[i] = RGB565 (
669           (RGB565_R (src[j]) * (65536 - x) + RGB565_R (src[j + 1]) * x) >> 16,
670           (RGB565_G (src[j]) * (65536 - x) + RGB565_G (src[j + 1]) * x) >> 16,
671           (RGB565_B (src[j]) * (65536 - x) + RGB565_B (src[j + 1]) * x) >> 16);
672     } else {
673       dest[i] = RGB565 (RGB565_R (src[j]),
674           RGB565_G (src[j]), RGB565_B (src[j]));
675     }
676
677     acc += increment;
678   }
679
680   *accumulator = acc;
681 }
682
683 void
684 vs_scanline_merge_linear_RGB565 (uint8_t * dest_u8, uint8_t * src1_u8,
685     uint8_t * src2_u8, int n, int x)
686 {
687   uint16_t *dest = (uint16_t *) dest_u8;
688   uint16_t *src1 = (uint16_t *) src1_u8;
689   uint16_t *src2 = (uint16_t *) src2_u8;
690   int i;
691
692   for (i = 0; i < n; i++) {
693     dest[i] = RGB565 (
694         (RGB565_R (src1[i]) * (65536 - x) + RGB565_R (src2[i]) * x) >> 16,
695         (RGB565_G (src1[i]) * (65536 - x) + RGB565_G (src2[i]) * x) >> 16,
696         (RGB565_B (src1[i]) * (65536 - x) + RGB565_B (src2[i]) * x) >> 16);
697   }
698 }
699
700
701 /* RGB555 */
702
703 /* note that src and dest are uint16_t, and thus endian dependent */
704
705 #define RGB555_R(x) (((x)&0x7c00)>>8 | ((x)&0x7c00)>>13)
706 #define RGB555_G(x) (((x)&0x03e0)>>3 | ((x)&0x03e0)>>9)
707 #define RGB555_B(x) (((x)&0x001f)<<3 | ((x)&0x001f)>>2)
708
709 #define RGB555(r,g,b) \
710   ((((r)<<7)&0x7c00) | (((g)<<3)&0x03e0) | (((b)>>3)&0x001f))
711
712
713 void
714 vs_scanline_downsample_RGB555 (uint8_t * dest_u8, uint8_t * src_u8, int n)
715 {
716   uint16_t *dest = (uint16_t *) dest_u8;
717   uint16_t *src = (uint16_t *) src_u8;
718   int i;
719
720   for (i = 0; i < n; i++) {
721     dest[i] = RGB555 (
722         (RGB555_R (src[i * 2]) + RGB555_R (src[i * 2 + 1])) / 2,
723         (RGB555_G (src[i * 2]) + RGB555_G (src[i * 2 + 1])) / 2,
724         (RGB555_B (src[i * 2]) + RGB555_B (src[i * 2 + 1])) / 2);
725   }
726 }
727
728 void
729 vs_scanline_resample_nearest_RGB555 (uint8_t * dest_u8, uint8_t * src_u8,
730     int src_width, int n, int *accumulator, int increment)
731 {
732   uint16_t *dest = (uint16_t *) dest_u8;
733   uint16_t *src = (uint16_t *) src_u8;
734   int acc = *accumulator;
735   int i;
736   int j;
737   int x;
738
739   for (i = 0; i < n; i++) {
740     j = acc >> 16;
741     x = acc & 0xffff;
742     dest[i] = (x < 32768 || j + 1 >= src_width) ? src[j] : src[j + 1];
743
744     acc += increment;
745   }
746
747   *accumulator = acc;
748 }
749
750 void
751 vs_scanline_resample_linear_RGB555 (uint8_t * dest_u8, uint8_t * src_u8,
752     int src_width, int n, int *accumulator, int increment)
753 {
754   uint16_t *dest = (uint16_t *) dest_u8;
755   uint16_t *src = (uint16_t *) src_u8;
756   int acc = *accumulator;
757   int i;
758   int j;
759   int x;
760
761   for (i = 0; i < n; i++) {
762     j = acc >> 16;
763     x = acc & 0xffff;
764
765     if (j + 1 < src_width) {
766       dest[i] = RGB555 (
767           (RGB555_R (src[j]) * (65536 - x) + RGB555_R (src[j + 1]) * x) >> 16,
768           (RGB555_G (src[j]) * (65536 - x) + RGB555_G (src[j + 1]) * x) >> 16,
769           (RGB555_B (src[j]) * (65536 - x) + RGB555_B (src[j + 1]) * x) >> 16);
770     } else {
771       dest[i] = RGB555 (RGB555_R (src[j]),
772           RGB555_G (src[j]), RGB555_B (src[j]));
773     }
774
775     acc += increment;
776   }
777
778   *accumulator = acc;
779 }
780
781 void
782 vs_scanline_merge_linear_RGB555 (uint8_t * dest_u8, uint8_t * src1_u8,
783     uint8_t * src2_u8, int n, int x)
784 {
785   uint16_t *dest = (uint16_t *) dest_u8;
786   uint16_t *src1 = (uint16_t *) src1_u8;
787   uint16_t *src2 = (uint16_t *) src2_u8;
788   int i;
789
790   for (i = 0; i < n; i++) {
791     dest[i] = RGB555 (
792         (RGB555_R (src1[i]) * (65536 - x) + RGB555_R (src2[i]) * x) >> 16,
793         (RGB555_G (src1[i]) * (65536 - x) + RGB555_G (src2[i]) * x) >> 16,
794         (RGB555_B (src1[i]) * (65536 - x) + RGB555_B (src2[i]) * x) >> 16);
795   }
796 }
797
798 void
799 vs_scanline_resample_nearest_AYUV64 (uint8_t * dest8, uint8_t * src8,
800     int src_width, int n, int *accumulator, int increment)
801 {
802   guint16 *dest = (guint16 *) dest8;
803   guint16 *src = (guint16 *) src8;
804   int acc = *accumulator;
805   int i;
806   int j;
807   int x;
808
809   for (i = 0; i < n; i++) {
810     j = acc >> 16;
811     x = acc & 0xffff;
812     dest[i * 4 + 0] = (x < 32768
813         || j + 1 >= src_width) ? src[j * 4 + 0] : src[j * 4 + 4];
814     dest[i * 4 + 1] = (x < 32768
815         || j + 1 >= src_width) ? src[j * 4 + 1] : src[j * 4 + 5];
816     dest[i * 4 + 2] = (x < 32768
817         || j + 1 >= src_width) ? src[j * 4 + 2] : src[j * 4 + 6];
818     dest[i * 4 + 3] = (x < 32768
819         || j + 1 >= src_width) ? src[j * 4 + 3] : src[j * 4 + 7];
820
821     acc += increment;
822   }
823
824   *accumulator = acc;
825 }
826
827 void
828 vs_scanline_resample_linear_AYUV64 (uint8_t * dest8, uint8_t * src8,
829     int src_width, int n, int *accumulator, int increment)
830 {
831   guint16 *dest = (guint16 *) dest8;
832   guint16 *src = (guint16 *) src8;
833   int acc = *accumulator;
834   int i;
835   int j;
836   int x;
837
838   for (i = 0; i < n; i++) {
839     j = acc >> 16;
840     x = (acc & 0xffff) >> 1;
841
842     if (j + 1 < src_width) {
843       dest[i * 4 + 0] =
844           (src[j * 3 + 0] * (32768 - x) + src[j * 4 + 4] * x) >> 15;
845       dest[i * 4 + 1] =
846           (src[j * 4 + 1] * (32768 - x) + src[j * 4 + 5] * x) >> 15;
847       dest[i * 4 + 2] =
848           (src[j * 4 + 2] * (32768 - x) + src[j * 4 + 6] * x) >> 15;
849       dest[i * 4 + 3] =
850           (src[j * 4 + 3] * (32768 - x) + src[j * 4 + 7] * x) >> 15;
851     } else {
852       dest[i * 4 + 0] = src[j * 4 + 0];
853       dest[i * 4 + 1] = src[j * 4 + 1];
854       dest[i * 4 + 2] = src[j * 4 + 2];
855       dest[i * 4 + 3] = src[j * 4 + 3];
856     }
857
858     acc += increment;
859   }
860
861   *accumulator = acc;
862 }